<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://www.interstellarrift.com/wiki/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://www.interstellarrift.com/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mr.+Stradivarius</id>
		<title>Interstellar Rift Wiki - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="http://www.interstellarrift.com/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mr.+Stradivarius"/>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Special:Contributions/Mr._Stradivarius"/>
		<updated>2026-04-05T14:36:21Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.23.2</generator>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Module:Protection_banner/config</id>
		<title>Module:Protection banner/config</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Module:Protection_banner/config"/>
				<updated>2014-08-14T05:00:48Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: remove Template:Pp-protected from the wrappers table, as it is now a redirect to Template:Pp&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module provides configuration data for [[Module:Protection banner]].&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--&lt;br /&gt;
--                                BANNER DATA&lt;br /&gt;
--&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Banner data consists of six fields:&lt;br /&gt;
-- * text - the main protection text that appears at the top of protection&lt;br /&gt;
--   banners.&lt;br /&gt;
-- * explanation - the text that appears below the main protection text, used&lt;br /&gt;
--   to explain the details of the protection.&lt;br /&gt;
-- * tooltip - the tooltip text you see when you move the mouse over a small&lt;br /&gt;
--   padlock icon.&lt;br /&gt;
-- * link - the page that the small padlock icon links to.&lt;br /&gt;
-- * alt - the alt text for the small padlock icon. This is also used as tooltip&lt;br /&gt;
--   text for the large protection banners.&lt;br /&gt;
-- * image - the padlock image used in both protection banners and small padlock&lt;br /&gt;
--   icons.&lt;br /&gt;
--&lt;br /&gt;
-- The module checks in three separate tables to find a value for each field.&lt;br /&gt;
-- First it checks the banners table, which has values specific to the reason&lt;br /&gt;
-- for the page being protected. Then the module checks the defaultBanners&lt;br /&gt;
-- table, which has values specific to each protection level. Finally, the&lt;br /&gt;
-- module checks the masterBanner table, which holds data for protection&lt;br /&gt;
-- templates to use if no data has been found in the previous two tables.&lt;br /&gt;
--&lt;br /&gt;
-- The values in the banner data can take parameters. These are specified&lt;br /&gt;
-- using ${TEXTLIKETHIS} (a dollar sign preceding a parameter name&lt;br /&gt;
-- enclosed in curly braces).&lt;br /&gt;
--&lt;br /&gt;
--                          Available parameters:&lt;br /&gt;
--&lt;br /&gt;
-- ${CURRENTVERSION} - a link to the page history or the move log, with the&lt;br /&gt;
-- display message &amp;quot;current-version-edit-display&amp;quot; or&lt;br /&gt;
-- &amp;quot;current-version-move-display&amp;quot;.&lt;br /&gt;
--&lt;br /&gt;
-- ${EDITREQUEST} - a link to create an edit request for the current page.&lt;br /&gt;
--&lt;br /&gt;
-- ${EXPIRY} - the protection expiry date in the format DD Month YYYY. If&lt;br /&gt;
-- protection is indefinite or is not set, this is the blank string.&lt;br /&gt;
--&lt;br /&gt;
-- ${EXPLANATIONBLURB} - an explanation blurb, e.g. &amp;quot;Please discuss any changes&lt;br /&gt;
-- on the talk page; you may submit a request to ask an administrator to make&lt;br /&gt;
-- an edit if it is minor or supported by consensus.&amp;quot;&lt;br /&gt;
--&lt;br /&gt;
-- ${IMAGELINK} - a link to set the image to, depending on the protection&lt;br /&gt;
-- action and protection level.&lt;br /&gt;
--&lt;br /&gt;
-- ${INTROBLURB} - the PROTECTIONBLURB parameter, plus the expiry if an expiry&lt;br /&gt;
-- is set. E.g. &amp;quot;Editing of this page by new or unregistered users is currently &lt;br /&gt;
-- disabled until dd Month YYYY.&amp;quot;&lt;br /&gt;
--&lt;br /&gt;
-- ${INTROFRAGMENT} - the same as ${INTROBLURB}, but without final punctuation&lt;br /&gt;
-- so that it can be used in run-on sentences.&lt;br /&gt;
--&lt;br /&gt;
-- ${PAGETYPE} - the type of the page, e.g. &amp;quot;article&amp;quot; or &amp;quot;template&amp;quot;.&lt;br /&gt;
-- Defined in the cfg.pagetypes table.&lt;br /&gt;
--&lt;br /&gt;
-- ${PROTECTIONBLURB} - a blurb explaining the protection level of the page, e.g.&lt;br /&gt;
-- &amp;quot;Editing of this page by new or unregistered users is currently disabled&amp;quot;&lt;br /&gt;
--&lt;br /&gt;
-- ${PROTECTIONDATE} - the protection date, if it has been supplied to the&lt;br /&gt;
-- template.&lt;br /&gt;
--&lt;br /&gt;
-- ${PROTECTIONLEVEL} - the protection level, e.g. &amp;quot;fully protected&amp;quot; or&lt;br /&gt;
-- &amp;quot;semi-protected&amp;quot;.&lt;br /&gt;
--&lt;br /&gt;
-- ${PROTECTIONLOG} - a link to the protection log or the pending changes log,&lt;br /&gt;
-- depending on the protection action.&lt;br /&gt;
--&lt;br /&gt;
-- ${TALKPAGE} - a link to the talk page. If a section is specified, links&lt;br /&gt;
-- straight to that talk page section.&lt;br /&gt;
--&lt;br /&gt;
-- ${TOOLTIPBLURB} - uses the PAGETYPE, PROTECTIONTYPE and EXPIRY parameters to&lt;br /&gt;
-- create a blurb like &amp;quot;This template is semi-protected&amp;quot;, or &amp;quot;This article is&lt;br /&gt;
-- move-protected until DD Month YYYY&amp;quot;.&lt;br /&gt;
--&lt;br /&gt;
-- ${VANDAL} - links for the specified username (or the root page name)&lt;br /&gt;
-- using Module:Vandal-m.&lt;br /&gt;
--&lt;br /&gt;
--                                 Functions&lt;br /&gt;
--&lt;br /&gt;
-- For advanced users, it is possible to use Lua functions instead of strings&lt;br /&gt;
-- in the banner config tables. Using functions gives flexibility that is not&lt;br /&gt;
-- possible just by using parameters. Functions take two arguments, the&lt;br /&gt;
-- protection object and the template arguments, and they must output a string.&lt;br /&gt;
--&lt;br /&gt;
-- For example:&lt;br /&gt;
--&lt;br /&gt;
-- text = function (protectionObj, args)&lt;br /&gt;
--     if protectionObj.level == 'autoconfirmed' then&lt;br /&gt;
--         return 'foo'&lt;br /&gt;
--     else&lt;br /&gt;
--         return 'bar'&lt;br /&gt;
--     end&lt;br /&gt;
-- end&lt;br /&gt;
--&lt;br /&gt;
-- Some protection object properties and methods that may be useful:&lt;br /&gt;
-- protectionObj.action - the protection action&lt;br /&gt;
-- protectionObj.level - the protection level&lt;br /&gt;
-- protectionObj.reason - the protection reason&lt;br /&gt;
-- protectionObj.expiry - the expiry. Nil if unset, the string &amp;quot;indef&amp;quot; if set&lt;br /&gt;
--     to indefinite, and the protection time in unix time if temporary.&lt;br /&gt;
-- protectionObj.protectionDate - the protection date in unix time, or nil if&lt;br /&gt;
--     unspecified.&lt;br /&gt;
-- protectionObj.bannerConfig - the banner config found by the module. Beware&lt;br /&gt;
--     of editing the config field used by the function, as it could create an&lt;br /&gt;
--     infinite loop.&lt;br /&gt;
-- protectionObj:isProtected - returns a boolean showing whether the page is&lt;br /&gt;
--     protected.&lt;br /&gt;
-- protectionObj:isTemporary - returns a boolean showing whether the expiry is&lt;br /&gt;
--     temporary.&lt;br /&gt;
-- protectionObj:isIncorrect - returns a boolean showing whether the protection&lt;br /&gt;
--     template is incorrect.&lt;br /&gt;
--]]&lt;br /&gt;
&lt;br /&gt;
-- The master banner data, used if no values have been found in banners or&lt;br /&gt;
-- defaultBanners.&lt;br /&gt;
masterBanner = {&lt;br /&gt;
	text = '${INTROBLURB}',&lt;br /&gt;
	explanation = '${EXPLANATIONBLURB}',&lt;br /&gt;
	tooltip = '${TOOLTIPBLURB}',&lt;br /&gt;
	link = '${IMAGELINK}',&lt;br /&gt;
	alt = 'Page ${PROTECTIONLEVEL}'&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
-- The default banner data. This holds banner data for different protection&lt;br /&gt;
-- levels.&lt;br /&gt;
-- *required* - this table needs edit, move, and autoreview subtables.&lt;br /&gt;
defaultBanners = {&lt;br /&gt;
	edit = {},&lt;br /&gt;
	move = {},&lt;br /&gt;
	autoreview = {&lt;br /&gt;
		autoconfirmed = {&lt;br /&gt;
			alt = 'Page protected with pending changes level 1',&lt;br /&gt;
			tooltip = 'All edits by unregistered and new users are subject to review',&lt;br /&gt;
			image = 'Padlock-silver-light.svg'&lt;br /&gt;
		},&lt;br /&gt;
		default = {&lt;br /&gt;
			alt = 'Page protected with pending changes level 2',&lt;br /&gt;
			tooltip = 'All edits by users who are not reviewers or administrators are'&lt;br /&gt;
				.. ' subject to review',&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
-- The banner data. This holds banner data for different protection reasons.&lt;br /&gt;
-- In fact, the reasons specified in this table control which reasons are&lt;br /&gt;
-- valid inputs to the first positional parameter.&lt;br /&gt;
--&lt;br /&gt;
-- There is also a non-standard &amp;quot;description&amp;quot; field that can be used for items&lt;br /&gt;
-- in this table. This is a description of the protection reason for use in the&lt;br /&gt;
-- module documentation.&lt;br /&gt;
--&lt;br /&gt;
-- *required* - this table needs edit, move, and autoreview subtables.&lt;br /&gt;
banners = {&lt;br /&gt;
	edit = {&lt;br /&gt;
		blp = {&lt;br /&gt;
			description = 'For pages protected to promote compliance with the'&lt;br /&gt;
				.. ' [[Wikipedia:Biographies of living persons'&lt;br /&gt;
				.. '|biographies of living persons]] policy.',&lt;br /&gt;
			text = '${INTROFRAGMENT} to promote compliance with'&lt;br /&gt;
				.. ' [[Wikipedia:Biographies of living persons'&lt;br /&gt;
				.. &amp;quot;|Wikipedia's&amp;amp;nbsp;policy on&amp;amp;nbsp;the&amp;amp;nbsp;biographies&amp;quot;&lt;br /&gt;
				.. ' of&amp;amp;nbsp;living&amp;amp;nbsp;people]].',&lt;br /&gt;
			tooltip = '${TOOLTIPFRAGMENT} to promote compliance with the policy on'&lt;br /&gt;
				.. ' biographies of living people',&lt;br /&gt;
		},&lt;br /&gt;
		dmca = {&lt;br /&gt;
			description = 'For pages protected by the Wikimedia Foundation'&lt;br /&gt;
				.. ' due to Digital Millennium Copyright Act takedown requests.',&lt;br /&gt;
			explanation = function (protectionObj, args)&lt;br /&gt;
				local ret = 'Pursuant to a rights owner notice under the Digital'&lt;br /&gt;
					.. ' Millennium Copyright Act (DMCA) regarding some content'&lt;br /&gt;
					.. ' in this article, the Wikimedia Foundation acted under'&lt;br /&gt;
					.. ' applicable law and took down and restricted the content'&lt;br /&gt;
					.. ' in question.'&lt;br /&gt;
				if args.notice then&lt;br /&gt;
					ret = ret .. ' A copy of the received notice can be found here: '&lt;br /&gt;
						.. args.notice .. '.'&lt;br /&gt;
				end&lt;br /&gt;
				ret = ret .. ' For more information, including websites discussing'&lt;br /&gt;
					.. ' how to file a counter-notice, please see'&lt;br /&gt;
					.. &amp;quot; [[Wikipedia:Office actions]] and the article's ${TALKPAGE}.&amp;quot;&lt;br /&gt;
					.. &amp;quot;'''Do not remove this template from the article until the&amp;quot;&lt;br /&gt;
					.. &amp;quot; restrictions are withdrawn'''.&amp;quot;&lt;br /&gt;
				return ret&lt;br /&gt;
			end,&lt;br /&gt;
			image = 'Padlock-black.svg',&lt;br /&gt;
		},&lt;br /&gt;
		dispute = {&lt;br /&gt;
			description = 'For pages protected due to editing disputes.',&lt;br /&gt;
			text = function (protectionObj, args)&lt;br /&gt;
				-- Find the value of &amp;quot;disputes&amp;quot;.&lt;br /&gt;
				local display = 'disputes'&lt;br /&gt;
				local disputes&lt;br /&gt;
				if args.section then&lt;br /&gt;
					disputes = string.format(&lt;br /&gt;
						'[[%s:%s#%s|%s]]',&lt;br /&gt;
						mw.site.namespaces[protectionObj.title.namespace].talk.name,&lt;br /&gt;
						protectionObj.title.text,&lt;br /&gt;
						args.section,&lt;br /&gt;
						display&lt;br /&gt;
					)&lt;br /&gt;
				else&lt;br /&gt;
					disputes = display&lt;br /&gt;
				end&lt;br /&gt;
&lt;br /&gt;
				-- Make the blurb, depending on the expiry.&lt;br /&gt;
				local msg&lt;br /&gt;
				if type(protectionObj.expiry) == 'number' then&lt;br /&gt;
					msg = '${INTROFRAGMENT} or until editing %s have been resolved.'&lt;br /&gt;
				else&lt;br /&gt;
					msg = '${INTROFRAGMENT} until editing %s have been resolved.'&lt;br /&gt;
				end&lt;br /&gt;
				return string.format(msg, disputes)&lt;br /&gt;
			end,&lt;br /&gt;
			explanation = &amp;quot;This protection is '''not''' an endorsement of the&amp;quot;&lt;br /&gt;
				.. ' ${CURRENTVERSION}. ${EXPLANATIONBLURB}',&lt;br /&gt;
			tooltip = '${TOOLTIPFRAGMENT} due to editing disputes',&lt;br /&gt;
		},&lt;br /&gt;
		mainpage = {&lt;br /&gt;
			description = 'For pages protected for being displayed on the [[Main Page]].',&lt;br /&gt;
			text = 'This file is currently'&lt;br /&gt;
				.. ' [[Wikipedia:This page is protected|protected]] from'&lt;br /&gt;
				.. ' editing because it is currently or will soon be displayed'&lt;br /&gt;
				.. ' on the [[Main Page]].',&lt;br /&gt;
			explanation = 'Images on the Main Page are protected due to their high'&lt;br /&gt;
				.. ' visibility. Please discuss any necessary changes on the ${TALKPAGE}.'&lt;br /&gt;
				.. '&amp;lt;br /&amp;gt;&amp;lt;span style=&amp;quot;font-size:90%;&amp;quot;&amp;gt;'&lt;br /&gt;
				.. &amp;quot;'''Administrators:''' Once this image is definitely off the Main Page,&amp;quot;&lt;br /&gt;
				.. ' please unprotect this file, or reduce to semi-protection,'&lt;br /&gt;
				.. ' as appropriate.&amp;lt;/span&amp;gt;',&lt;br /&gt;
		},&lt;br /&gt;
		office = {&lt;br /&gt;
			description = 'For pages protected by the Wikimedia Foundation.',&lt;br /&gt;
			text = function (protectionObj, args)&lt;br /&gt;
				local ret = 'This ${PAGETYPE} is currently under the'&lt;br /&gt;
					.. ' scrutiny of the'&lt;br /&gt;
					.. ' [[Wikipedia:Office actions|Wikimedia Foundation Office]]'&lt;br /&gt;
					.. ' and is protected.'&lt;br /&gt;
				if protectionObj.protectionDate then&lt;br /&gt;
					ret = ret .. ' It has been protected since ${PROTECTIONDATE}.'&lt;br /&gt;
				end&lt;br /&gt;
				return ret&lt;br /&gt;
			end,&lt;br /&gt;
			explanation = &amp;quot;If you can edit this page, please discuss all changes and&amp;quot;&lt;br /&gt;
				.. &amp;quot; additions on the ${TALKPAGE} first. '''Do not remove protection from this&amp;quot;&lt;br /&gt;
				.. &amp;quot; page unless you are authorized by the Wikimedia Foundation to do&amp;quot;&lt;br /&gt;
				.. &amp;quot; so.'''&amp;quot;,&lt;br /&gt;
			image = 'Padlock-black.svg',&lt;br /&gt;
		},&lt;br /&gt;
		reset = {&lt;br /&gt;
			description = 'For pages protected by the Wikimedia Foundation and'&lt;br /&gt;
				.. ' &amp;quot;reset&amp;quot; to a bare-bones version.',&lt;br /&gt;
 			text = 'This ${PAGETYPE} is currently under the'&lt;br /&gt;
					.. ' scrutiny of the'&lt;br /&gt;
					.. ' [[Wikipedia:Office actions|Wikimedia Foundation Office]]'&lt;br /&gt;
					.. ' and is protected.',&lt;br /&gt;
			explanation = function (protectionObj, args)&lt;br /&gt;
				local ret = ''&lt;br /&gt;
				if protectionObj.protectionDate then&lt;br /&gt;
					ret = ret .. 'On ${PROTECTIONDATE} this ${PAGETYPE} was'&lt;br /&gt;
				else&lt;br /&gt;
					ret = ret .. 'This ${PAGETYPE} has been'&lt;br /&gt;
				end&lt;br /&gt;
				ret = ret .. ' reduced to a'&lt;br /&gt;
				.. ' simplified, &amp;quot;bare bones&amp;quot; version so that it may be completely'&lt;br /&gt;
				.. ' rewritten to ensure it meets the policies of'&lt;br /&gt;
				.. ' [[WP:NPOV|Neutral Point of View]] and [[WP:V|Verifiability]].'&lt;br /&gt;
				.. ' Standard Wikipedia policies will apply to its rewriting—which'&lt;br /&gt;
				.. ' will eventually be open to all editors—and will be strictly'&lt;br /&gt;
				.. ' enforced. The ${PAGETYPE} has been ${PROTECTIONLEVEL} while'&lt;br /&gt;
				.. ' it is being rebuilt.\n\n'&lt;br /&gt;
				.. 'Any insertion of material directly from'&lt;br /&gt;
				.. ' pre-protection revisions of the ${PAGETYPE} will be removed, as'&lt;br /&gt;
				.. ' will any material added to the ${PAGETYPE} that is not properly'&lt;br /&gt;
				.. ' sourced. The associated talk page(s) were also cleared on the'&lt;br /&gt;
				.. &amp;quot; same date.\n\n&amp;quot;&lt;br /&gt;
				.. &amp;quot;If you can edit this page, please discuss all changes and&amp;quot;&lt;br /&gt;
				.. &amp;quot; additions on the ${TALKPAGE} first. '''Do not override&amp;quot;&lt;br /&gt;
				.. &amp;quot; this action, and do not remove protection from this page,&amp;quot;&lt;br /&gt;
				.. &amp;quot; unless you are authorized by the Wikimedia Foundation&amp;quot;&lt;br /&gt;
				.. &amp;quot; to do so. No editor may remove this notice.'''&amp;quot;&lt;br /&gt;
&lt;br /&gt;
				return ret&lt;br /&gt;
			end,&lt;br /&gt;
			image = 'Padlock-black.svg',&lt;br /&gt;
		},&lt;br /&gt;
		sock = {&lt;br /&gt;
			description = 'For pages protected due to'&lt;br /&gt;
				.. ' [[Wikipedia:Sock puppetry|sock puppetry]].',&lt;br /&gt;
			text = '${INTROFRAGMENT} to prevent [[Wikipedia:Sock puppetry|sock puppets]] of'&lt;br /&gt;
				.. ' [[Wikipedia:Blocking policy|blocked]] or'&lt;br /&gt;
				.. ' [[Wikipedia:List of banned users|banned users]]'&lt;br /&gt;
				.. ' from editing it.',&lt;br /&gt;
			tooltip = '${TOOLTIPFRAGMENT} to prevent sock puppets of blocked or banned users from'&lt;br /&gt;
				.. ' editing it',&lt;br /&gt;
		},&lt;br /&gt;
		template = {&lt;br /&gt;
			description = 'For [[Wikipedia:High-risk templates|high-risk]]'&lt;br /&gt;
				.. ' templates and Lua modules.',&lt;br /&gt;
			text = 'This is a permanently [[Help:Protection|protected]] ${PAGETYPE},'&lt;br /&gt;
				.. ' as it is [[Wikipedia:High-risk templates|high-risk]].',&lt;br /&gt;
			explanation = 'Please discuss any changes on the ${TALKPAGE}; you may'&lt;br /&gt;
				.. ' ${EDITREQUEST} to ask an'&lt;br /&gt;
				.. ' [[Wikipedia:Administrators|administrator]] or'&lt;br /&gt;
				.. ' [[Wikipedia:Template editor|template editor]] to make an edit if'&lt;br /&gt;
				.. ' it is [[Help:Minor edit#When to mark an edit as a minor edit'&lt;br /&gt;
				.. '|uncontroversial]] or supported by'&lt;br /&gt;
				.. ' [[Wikipedia:Consensus|consensus]]. You can also'&lt;br /&gt;
				.. ' [[Wikipedia:Requests for page protection|request]] that the page be'&lt;br /&gt;
				.. ' unprotected.',&lt;br /&gt;
			tooltip = 'This high-risk ${PAGETYPE} is permanently ${PROTECTIONLEVEL}'&lt;br /&gt;
				.. ' to prevent vandalism',&lt;br /&gt;
			alt = 'Permanently protected ${PAGETYPE}',&lt;br /&gt;
		},&lt;br /&gt;
		usertalk = {&lt;br /&gt;
			description = 'For pages protected against disruptive edits by a'&lt;br /&gt;
				.. ' particular user.',&lt;br /&gt;
			text = '${INTROFRAGMENT} to prevent ${VANDAL} from using it to make disruptive edits,'&lt;br /&gt;
				.. ' such as abusing the'&lt;br /&gt;
				.. ' &amp;amp;#123;&amp;amp;#123;[[Template:unblock|unblock]]&amp;amp;#125;&amp;amp;#125; template.',&lt;br /&gt;
			explanation = 'If you cannot edit this user talk page and you need to'&lt;br /&gt;
				.. ' make a change or leave a message, you can'&lt;br /&gt;
				.. ' [[Wikipedia:Requests for page protection'&lt;br /&gt;
				.. '#Current requests for edits to a protected page'&lt;br /&gt;
				.. '|request an edit]],'&lt;br /&gt;
				.. ' [[Wikipedia:Requests for page protection'&lt;br /&gt;
				.. '#Current requests for reduction in protection level'&lt;br /&gt;
				.. '|request unprotection]],'&lt;br /&gt;
				.. ' [[Special:Userlogin|log in]],'&lt;br /&gt;
				.. ' or [[Special:UserLogin/signup|create an account]].',&lt;br /&gt;
		},&lt;br /&gt;
		vandalism = {&lt;br /&gt;
			description = 'For pages protected against'&lt;br /&gt;
				.. ' [[Wikipedia:Vandalism|vandalism]].',&lt;br /&gt;
			text = '${INTROFRAGMENT} due to [[Wikipedia:Vandalism|vandalism]].',&lt;br /&gt;
			explanation = function (protectionObj, args)&lt;br /&gt;
				local ret = ''&lt;br /&gt;
				if protectionObj.level == 'sysop' then&lt;br /&gt;
					ret = ret .. &amp;quot;This protection is '''not''' an endorsement of the&amp;quot;&lt;br /&gt;
						.. ' ${CURRENTVERSION}. '&lt;br /&gt;
				end&lt;br /&gt;
				return ret .. '${EXPLANATIONBLURB}'&lt;br /&gt;
			end,&lt;br /&gt;
			tooltip = '${TOOLTIPFRAGMENT} due to vandalism',&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	move = {&lt;br /&gt;
		dispute = {&lt;br /&gt;
			description = 'For pages protected against page moves due to'&lt;br /&gt;
				.. ' disputes over the page title.',&lt;br /&gt;
			explanation = &amp;quot;This protection is '''not''' an endorsement of the&amp;quot;&lt;br /&gt;
				.. ' ${CURRENTVERSION}. ${EXPLANATIONBLURB}',&lt;br /&gt;
			image = 'Padlock-olive.svg'&lt;br /&gt;
		},&lt;br /&gt;
		vandalism = {&lt;br /&gt;
			description = 'For pages protected against'&lt;br /&gt;
				.. ' [[Wikipedia:Vandalism#Page-move vandalism'&lt;br /&gt;
				.. ' |page-move vandalism]].'&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	autoreview = {}&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--&lt;br /&gt;
--                            GENERAL DATA TABLES&lt;br /&gt;
--&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Protection blurbs&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This table produces the protection blurbs available with the&lt;br /&gt;
-- ${PROTECTIONBLURB} parameter. It is sorted by protection action and&lt;br /&gt;
-- protection level, and is checked by the module in the following order:&lt;br /&gt;
-- 1. page's protection action, page's protection level&lt;br /&gt;
-- 2. page's protection action, default protection level&lt;br /&gt;
-- 3. &amp;quot;edit&amp;quot; protection action, default protection level&lt;br /&gt;
--&lt;br /&gt;
-- It is possible to use banner parameters inside this table.&lt;br /&gt;
-- *required* - this table needs edit, move, and autoreview subtables.&lt;br /&gt;
protectionBlurbs = {&lt;br /&gt;
	edit = {&lt;br /&gt;
		default = 'This ${PAGETYPE} is currently [[Help:Protection|'&lt;br /&gt;
			.. 'protected]] from editing',&lt;br /&gt;
		autoconfirmed = 'Editing of this ${PAGETYPE} by [[Wikipedia:User access'&lt;br /&gt;
			.. ' levels#New users|new]] or [[Wikipedia:User access levels#Unregistered'&lt;br /&gt;
			.. ' users|unregistered]] users is currently [[Help:Protection|disabled]]'&lt;br /&gt;
	},&lt;br /&gt;
	move = {&lt;br /&gt;
		default = 'This ${PAGETYPE} is currently [[Help:Protection|protected]]'&lt;br /&gt;
			.. ' from [[Help:Moving a page|page moves]]'&lt;br /&gt;
	},&lt;br /&gt;
	autoreview = {&lt;br /&gt;
		autoconfirmed = 'All edits made to this ${PAGETYPE} by'&lt;br /&gt;
			.. ' [[Wikipedia:User access levels#New users|new]] or'&lt;br /&gt;
			.. ' [[Wikipedia:User access levels#Unregistered users|unregistered]]'&lt;br /&gt;
			.. ' users are currently'&lt;br /&gt;
			.. ' [[Wikipedia:Pending changes|subject to review]]',&lt;br /&gt;
		default = 'All edits made to this ${PAGETYPE} by users who are not'&lt;br /&gt;
			.. ' [[Wikipedia:Reviewing|reviewers]] or'&lt;br /&gt;
			.. ' [[Wikipedia:Administrators|administrators]] are currently'&lt;br /&gt;
			.. ' [[Wikipedia:Pending changes|subject to review]]'&lt;br /&gt;
	}&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Explanation blurbs&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This table produces the explanation blurbs available with the&lt;br /&gt;
-- ${EXPLANATIONBLURB} parameter. It is sorted by protection action,&lt;br /&gt;
-- protection level, and whether the page is a talk page or not. If the page is&lt;br /&gt;
-- a talk page it will have a talk key of &amp;quot;talk&amp;quot;; otherwise it will have a talk&lt;br /&gt;
-- key of &amp;quot;subject&amp;quot;. The table is checked in the following order:&lt;br /&gt;
-- 1. page's protection action, page's protection level, page's talk key&lt;br /&gt;
-- 2. page's protection action, page's protection level, default talk key&lt;br /&gt;
-- 3. page's protection action, default protection level, page's talk key&lt;br /&gt;
-- 4. page's protection action, default protection level, default talk key&lt;br /&gt;
--&lt;br /&gt;
-- It is possible to use banner parameters inside this table.&lt;br /&gt;
-- *required* - this table needs edit, move, and autoreview subtables.&lt;br /&gt;
explanationBlurbs = {&lt;br /&gt;
	edit = {&lt;br /&gt;
		autoconfirmed = {&lt;br /&gt;
			subject = 'See the [[Wikipedia:Protection policy|'&lt;br /&gt;
				.. 'protection policy]] and ${PROTECTIONLOG} for more details. If you'&lt;br /&gt;
				.. ' cannot edit this ${PAGETYPE} and you wish to make a change, you can'&lt;br /&gt;
				.. ' ${EDITREQUEST}, discuss changes on the ${TALKPAGE},'&lt;br /&gt;
				.. ' [[Wikipedia:Requests for page protection'&lt;br /&gt;
				.. '#Current requests for reduction in protection level'&lt;br /&gt;
				.. '|request unprotection]], [[Special:Userlogin|log in]], or'&lt;br /&gt;
				.. ' [[Special:UserLogin/signup|create an account]].',&lt;br /&gt;
			default = 'See the [[Wikipedia:Protection policy|'&lt;br /&gt;
				.. 'protection policy]] and ${PROTECTIONLOG} for more details. If you'&lt;br /&gt;
				.. ' cannot edit this ${PAGETYPE} and you wish to make a change, you can'&lt;br /&gt;
				.. ' [[Wikipedia:Requests for page protection'&lt;br /&gt;
				.. '#Current requests for reduction in protection level'&lt;br /&gt;
				.. '|request unprotection]], [[Special:Userlogin|log in]], or'&lt;br /&gt;
				.. ' [[Special:UserLogin/signup|create an account]].',&lt;br /&gt;
		},&lt;br /&gt;
		default = {&lt;br /&gt;
			subject = 'See the [[Wikipedia:Protection policy|'&lt;br /&gt;
				.. 'protection policy]] and ${PROTECTIONLOG} for more details.'&lt;br /&gt;
				.. ' Please discuss any changes on the ${TALKPAGE}; you'&lt;br /&gt;
				.. ' may ${EDITREQUEST} to ask an'&lt;br /&gt;
				.. ' [[Wikipedia:Administrators|administrator]] to make an edit if it'&lt;br /&gt;
				.. ' is [[Help:Minor edit#When to mark an edit as a minor edit'&lt;br /&gt;
				.. '|uncontroversial]] or supported by [[Wikipedia:Consensus'&lt;br /&gt;
				.. '|consensus]]. You may also [[Wikipedia:Requests for'&lt;br /&gt;
				.. ' page protection#Current requests for reduction in protection level'&lt;br /&gt;
				.. '|request]] that this page be unprotected.',&lt;br /&gt;
			default = 'See the [[Wikipedia:Protection policy|'&lt;br /&gt;
				.. 'protection policy]] and ${PROTECTIONLOG} for more details.'&lt;br /&gt;
				.. ' You may [[Wikipedia:Requests for page'&lt;br /&gt;
				.. ' protection#Current requests for edits to a protected page|request an'&lt;br /&gt;
				.. ' edit]] to this page, or [[Wikipedia:Requests for'&lt;br /&gt;
				.. ' page protection#Current requests for reduction in protection level'&lt;br /&gt;
				.. '|ask]] for it to be unprotected.'&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	move = {&lt;br /&gt;
		default = {&lt;br /&gt;
			subject = 'See the [[Wikipedia:Protection policy|'&lt;br /&gt;
				.. 'protection policy]] and ${PROTECTIONLOG} for more details.'&lt;br /&gt;
				.. ' The page may still be edited but cannot be moved'&lt;br /&gt;
				.. ' until unprotected. Please discuss any suggested moves on the'&lt;br /&gt;
				.. ' ${TALKPAGE} or at [[Wikipedia:Requested moves]]. You can also'&lt;br /&gt;
				.. ' [[Wikipedia:Requests for page protection|request]] that the page be'&lt;br /&gt;
				.. ' unprotected.',&lt;br /&gt;
			default = 'See the [[Wikipedia:Protection policy|'&lt;br /&gt;
				.. 'protection policy]] and ${PROTECTIONLOG} for more details.'&lt;br /&gt;
				.. ' The page may still be edited but cannot be moved'&lt;br /&gt;
				.. ' until unprotected. Please discuss any suggested moves at'&lt;br /&gt;
				.. ' [[Wikipedia:Requested moves]]. You can also'&lt;br /&gt;
				.. ' [[Wikipedia:Requests for page protection|request]] that the page be'&lt;br /&gt;
				.. ' unprotected.'&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	autoreview = {&lt;br /&gt;
		default = {&lt;br /&gt;
			reviewer = 'See the [[Wikipedia:Protection policy|'&lt;br /&gt;
				.. 'protection policy]] and ${PROTECTIONLOG} for more details.'&lt;br /&gt;
				.. ' Edits to this ${PAGETYPE} will not be visible to readers'&lt;br /&gt;
				.. ' until they are accepted by a reviewer or an administrator.'&lt;br /&gt;
				.. ' To avoid the need for your edits to be reviewed, you may'&lt;br /&gt;
				.. ' [[Wikipedia:Requests for page protection'&lt;br /&gt;
				.. '#Current requests for reduction in protection level'&lt;br /&gt;
				.. '|request unprotection]]. Experienced editors may also'&lt;br /&gt;
				.. ' request the [[Wikipedia:Reviewing|reviewer user right]].',&lt;br /&gt;
			default = 'See the [[Wikipedia:Protection policy|'&lt;br /&gt;
				.. 'protection policy]] and ${PROTECTIONLOG} for more details.'&lt;br /&gt;
				.. ' Edits to this ${PAGETYPE} by new and unregistered users'&lt;br /&gt;
				.. ' will not be visible to readers until they are accepted by'&lt;br /&gt;
				.. ' a reviewer. To avoid the need for your edits to be'&lt;br /&gt;
				.. ' reviewed, you may'&lt;br /&gt;
				.. ' [[Wikipedia:Requests for page protection'&lt;br /&gt;
				.. '#Current requests for reduction in protection level'&lt;br /&gt;
				.. '|request unprotection]], [[Special:Userlogin|log in]], or'&lt;br /&gt;
				.. ' [[Special:UserLogin/signup|create an account]].'&lt;br /&gt;
		},&lt;br /&gt;
	}&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Protection levels&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This table provides the data for the ${PROTECTIONLEVEL} parameter, which&lt;br /&gt;
-- produces a short label for different protection levels. It is sorted by&lt;br /&gt;
-- protection action and proteciton level, and is checked in the following&lt;br /&gt;
-- order:&lt;br /&gt;
-- 1. page's protection action, page's protection level&lt;br /&gt;
-- 2. page's protection action, default protection level&lt;br /&gt;
-- 3. &amp;quot;edit&amp;quot; protection action, default protection level&lt;br /&gt;
--&lt;br /&gt;
-- It is possible to use banner parameters inside this table.&lt;br /&gt;
-- *required* - this table needs edit, move, and autoreview subtables.&lt;br /&gt;
protectionLevels = {&lt;br /&gt;
	edit = {&lt;br /&gt;
		default = 'protected',&lt;br /&gt;
		templateeditor = 'template-protected',&lt;br /&gt;
		autoconfirmed = 'semi-protected',&lt;br /&gt;
	},&lt;br /&gt;
	move = {&lt;br /&gt;
		default = 'move-protected'&lt;br /&gt;
	},&lt;br /&gt;
	autoreview = {&lt;br /&gt;
	}&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Images&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This table lists different padlock images for each protection action and&lt;br /&gt;
-- protection level. It is used if an image is not specified in any of the&lt;br /&gt;
-- banner data tables, and if the page does not satisfy the conditions for using&lt;br /&gt;
-- the ['image-filename-indef'] image. It is checked in the following order:&lt;br /&gt;
-- 1. page's protection action, page's protection level&lt;br /&gt;
-- 2. page's protection action, default protection level&lt;br /&gt;
images = {&lt;br /&gt;
	edit = {&lt;br /&gt;
		default = 'Padlock.svg',&lt;br /&gt;
		templateeditor = 'Padlock-pink.svg',&lt;br /&gt;
		autoconfirmed = 'Padlock-silver.svg'&lt;br /&gt;
	},&lt;br /&gt;
	move = {&lt;br /&gt;
		default = 'Padlock-olive.svg',&lt;br /&gt;
	},&lt;br /&gt;
	autoreview = {&lt;br /&gt;
		autoconfirmed = 'Padlock-silver-light.svg',&lt;br /&gt;
		default = 'Padlock-orange.svg'&lt;br /&gt;
	}&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
-- Pages with a reason specified in this table will show the special &amp;quot;indef&amp;quot;&lt;br /&gt;
-- padlock, defined in the 'image-filename-indef' message, if no expiry is set.&lt;br /&gt;
indefImageReasons = {&lt;br /&gt;
	template = true&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Image links&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This table provides the data for the ${IMAGELINK} parameter, which gets&lt;br /&gt;
-- the image link for small padlock icons based on the page's protection action&lt;br /&gt;
-- and protection level. It is checked in the following order:&lt;br /&gt;
-- 1. page's protection action, page's protection level&lt;br /&gt;
-- 2. page's protection action, default protection level&lt;br /&gt;
-- 3. &amp;quot;edit&amp;quot; protection action, default protection level&lt;br /&gt;
--&lt;br /&gt;
-- It is possible to use banner parameters inside this table.&lt;br /&gt;
-- *required* - this table needs edit, move, and autoreview subtables.&lt;br /&gt;
imageLinks = {&lt;br /&gt;
	edit = {&lt;br /&gt;
		default = 'Wikipedia:Protection policy#full',&lt;br /&gt;
		templateeditor = 'Wikipedia:Protection policy#template',&lt;br /&gt;
		autoconfirmed = 'Wikipedia:Protection policy#semi'&lt;br /&gt;
	},&lt;br /&gt;
	move = {&lt;br /&gt;
		default = 'Wikipedia:Protection policy#move'&lt;br /&gt;
	},&lt;br /&gt;
	autoreview = {&lt;br /&gt;
		autoconfirmed = 'Wikipedia:Protection policy#pc1',&lt;br /&gt;
		reviewer = 'Wikipedia:Protection policy#pc2'&lt;br /&gt;
	}&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Padlock positions&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This table provides the data for the &amp;quot;right&amp;quot; CSS property for small padlock&lt;br /&gt;
-- icons, which determines where the icon appears on the top bar among the other&lt;br /&gt;
-- top icons. The data is stored by protection action. If no value is found for&lt;br /&gt;
-- the action, the default field is used.&lt;br /&gt;
padlockPositions = {&lt;br /&gt;
	autoreview = '85px',&lt;br /&gt;
	default = '55px'&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Protection categories&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- The protection categories are stored in the protectionCategories table.&lt;br /&gt;
-- Keys to this table are made up of the following strings:&lt;br /&gt;
--&lt;br /&gt;
-- 1. the expiry date&lt;br /&gt;
-- 2. the namespace&lt;br /&gt;
-- 3. the protection reason (e.g. &amp;quot;dispute&amp;quot; or &amp;quot;vandalism&amp;quot;)&lt;br /&gt;
-- 4. the protection level (e.g. &amp;quot;sysop&amp;quot; or &amp;quot;autoconfirmed&amp;quot;)&lt;br /&gt;
-- 5. the action (e.g. &amp;quot;edit&amp;quot; or &amp;quot;move&amp;quot;)&lt;br /&gt;
-- &lt;br /&gt;
-- When the module looks up a category in the table, first it will will check to&lt;br /&gt;
-- see a key exists that corresponds to all five parameters. For example, a&lt;br /&gt;
-- user page semi-protected from vandalism for two weeks would have the key&lt;br /&gt;
-- &amp;quot;temp-user-vandalism-autoconfirmed-edit&amp;quot;. If no match is found, the module&lt;br /&gt;
-- changes the first part of the key to &amp;quot;all&amp;quot; and checks the table again. It&lt;br /&gt;
-- keeps checking increasingly generic key combinations until it finds the&lt;br /&gt;
-- field, or until it reaches the key &amp;quot;all-all-all-all-all&amp;quot;.&lt;br /&gt;
--&lt;br /&gt;
-- The module uses a binary matrix to determine the order in which to search.&lt;br /&gt;
-- This is best demonstrated by a table. In this table, the &amp;quot;0&amp;quot; values&lt;br /&gt;
-- represent &amp;quot;all&amp;quot;, and the &amp;quot;1&amp;quot; values represent the original data (e.g.&lt;br /&gt;
-- &amp;quot;indef&amp;quot; or &amp;quot;file&amp;quot; or &amp;quot;vandalism&amp;quot;).&lt;br /&gt;
--&lt;br /&gt;
--        expiry    namespace reason   level     action&lt;br /&gt;
-- order&lt;br /&gt;
-- 1      1         1         1        1         1&lt;br /&gt;
-- 2      0         1         1        1         1&lt;br /&gt;
-- 3      1         0         1        1         1&lt;br /&gt;
-- 4      0         0         1        1         1&lt;br /&gt;
-- 5      1         1         0        1         1&lt;br /&gt;
-- 6      0         1         0        1         1&lt;br /&gt;
-- 7      1         0         0        1         1&lt;br /&gt;
-- 8      0         0         0        1         1&lt;br /&gt;
-- 9      1         1         1        0         1&lt;br /&gt;
-- 10     0         1         1        0         1&lt;br /&gt;
-- 11     1         0         1        0         1&lt;br /&gt;
-- 12     0         0         1        0         1&lt;br /&gt;
-- 13     1         1         0        0         1&lt;br /&gt;
-- 14     0         1         0        0         1&lt;br /&gt;
-- 15     1         0         0        0         1&lt;br /&gt;
-- 16     0         0         0        0         1&lt;br /&gt;
-- 17     1         1         1        1         0&lt;br /&gt;
-- 18     0         1         1        1         0&lt;br /&gt;
-- 19     1         0         1        1         0&lt;br /&gt;
-- 20     0         0         1        1         0&lt;br /&gt;
-- 21     1         1         0        1         0&lt;br /&gt;
-- 22     0         1         0        1         0&lt;br /&gt;
-- 23     1         0         0        1         0&lt;br /&gt;
-- 24     0         0         0        1         0&lt;br /&gt;
-- 25     1         1         1        0         0&lt;br /&gt;
-- 26     0         1         1        0         0&lt;br /&gt;
-- 27     1         0         1        0         0&lt;br /&gt;
-- 28     0         0         1        0         0&lt;br /&gt;
-- 29     1         1         0        0         0&lt;br /&gt;
-- 30     0         1         0        0         0&lt;br /&gt;
-- 31     1         0         0        0         0&lt;br /&gt;
-- 32     0         0         0        0         0&lt;br /&gt;
--&lt;br /&gt;
-- In this scheme the action has the highest priority, as it is the last&lt;br /&gt;
-- to change, and the expiry has the least priority, as it changes the most.&lt;br /&gt;
-- The priorities of the expiry, the protection level and the action are&lt;br /&gt;
-- fixed, but the priorities of the reason and the namespace can be swapped&lt;br /&gt;
-- through the use of the cfg.bannerDataNamespaceHasPriority table.&lt;br /&gt;
--]]&lt;br /&gt;
&lt;br /&gt;
-- If the reason specified to the template is listed in this table,&lt;br /&gt;
-- namespace data will take priority over reason data in the protectionCategories&lt;br /&gt;
-- table.&lt;br /&gt;
reasonsWithNamespacePriority = {&lt;br /&gt;
	vandalism = true,&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
-- The string to use as a namespace key for the protectionCategories table for each&lt;br /&gt;
-- namespace number.&lt;br /&gt;
categoryNamespaceKeys = {&lt;br /&gt;
	[  2] = 'user',&lt;br /&gt;
	[  3] = 'user',&lt;br /&gt;
	[  4] = 'project',&lt;br /&gt;
	[  6] = 'file',&lt;br /&gt;
	[  8] = 'mediawiki',&lt;br /&gt;
	[ 10] = 'template',&lt;br /&gt;
	[ 12] = 'project',&lt;br /&gt;
	[ 14] = 'category',&lt;br /&gt;
	[100] = 'portal',&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
protectionCategories = {&lt;br /&gt;
	['all|all|all|all|all']                  = 'Wikipedia protected pages',&lt;br /&gt;
	['all|all|office|all|all']               = 'Wikipedia Office-protected pages',&lt;br /&gt;
	['all|all|reset|all|all']                = 'Wikipedia Office-protected pages',&lt;br /&gt;
	['all|all|dmca|all|all']                 = 'Wikipedia Office-protected pages',&lt;br /&gt;
	['all|all|mainpage|all|all']             = 'Protected main page images',&lt;br /&gt;
	['all|template|all|all|edit']            = 'Wikipedia protected templates',&lt;br /&gt;
	['all|all|all|autoconfirmed|edit']       = 'Wikipedia semi-protected pages',&lt;br /&gt;
	['indef|all|all|autoconfirmed|edit']     = 'Wikipedia indefinitely semi-protected pages',&lt;br /&gt;
	['all|all|blp|autoconfirmed|edit']       = 'Wikipedia indefinitely semi-protected biographies of living people',&lt;br /&gt;
	['temp|all|blp|autoconfirmed|edit']      = 'Wikipedia temporarily semi-protected biographies of living people',&lt;br /&gt;
	['all|all|dispute|autoconfirmed|edit']   = 'Wikipedia pages semi-protected due to dispute',&lt;br /&gt;
	['all|all|sock|autoconfirmed|edit']      = 'Wikipedia pages semi-protected from banned users',&lt;br /&gt;
	['all|all|vandalism|autoconfirmed|edit'] = 'Wikipedia pages semi-protected against vandalism',&lt;br /&gt;
	['all|category|all|autoconfirmed|edit']  = 'Wikipedia semi-protected categories',&lt;br /&gt;
	['all|file|all|autoconfirmed|edit']      = 'Semi-protected images',&lt;br /&gt;
	['all|portal|all|autoconfirmed|edit']    = 'Semi-protected portals',&lt;br /&gt;
	['all|project|all|autoconfirmed|edit']   = 'Semi-protected project pages',&lt;br /&gt;
	['all|talk|all|autoconfirmed|edit']      = 'Semi-protected talk pages',&lt;br /&gt;
	['all|template|all|autoconfirmed|edit']  = 'Wikipedia semi-protected templates',&lt;br /&gt;
	['all|template|all|autoconfirmed|edit']  = 'Wikipedia semi-protected templates',&lt;br /&gt;
	['all|user|all|autoconfirmed|edit']      = 'Wikipedia semi-protected user and user talk pages',&lt;br /&gt;
	['all|all|blp|sysop|edit']               = 'Wikipedia indefinitely protected biographies of living people',&lt;br /&gt;
	['temp|all|blp|sysop|edit']              = 'Wikipedia temporarily protected biographies of living people',&lt;br /&gt;
	['all|all|dispute|sysop|edit']           = 'Wikipedia pages protected due to dispute',&lt;br /&gt;
	['all|all|sock|sysop|edit']              = 'Wikipedia pages protected from banned users',&lt;br /&gt;
	['all|all|vandalism|sysop|edit']         = 'Wikipedia pages protected against vandalism',&lt;br /&gt;
	['all|category|all|sysop|edit']          = 'Wikipedia protected categories',&lt;br /&gt;
	['all|file|all|sysop|edit']              = 'Protected images',&lt;br /&gt;
	['all|project|all|sysop|edit']           = 'Protected project pages',&lt;br /&gt;
	['all|talk|all|sysop|edit']              = 'Protected talk pages',&lt;br /&gt;
	['all|template|all|sysop|edit']          = 'Wikipedia protected templates',&lt;br /&gt;
	['all|user|all|sysop|edit']              = 'Wikipedia protected user and user talk pages',&lt;br /&gt;
	['all|all|all|sysop|move']               = 'Wikipedia move-protected pages',&lt;br /&gt;
	['indef|all|all|sysop|move']             = 'Wikipedia indefinitely move-protected pages',&lt;br /&gt;
	['all|all|dispute|sysop|move']           = 'Wikipedia pages move-protected due to dispute',&lt;br /&gt;
	['all|all|vandalism|sysop|move']         = 'Wikipedia pages move-protected due to vandalism',&lt;br /&gt;
	['all|portal|all|sysop|move']            = 'Wikipedia move-protected portals',&lt;br /&gt;
	['all|portal|all|sysop|move']            = 'Wikipedia move-protected portals',&lt;br /&gt;
	['all|project|all|sysop|move']           = 'Wikipedia move-protected project pages',&lt;br /&gt;
	['all|talk|all|sysop|move']              = 'Wikipedia move-protected talk pages',&lt;br /&gt;
	['all|template|all|sysop|move']          = 'Wikipedia move-protected templates',&lt;br /&gt;
	['all|user|all|sysop|move']              = 'Wikipedia move-protected user and user talk pages',&lt;br /&gt;
	['all|all|all|autoconfirmed|autoreview'] = 'Wikipedia pending changes protected pages (level 1)',&lt;br /&gt;
	['all|all|all|reviewer|autoreview']      = 'Wikipedia pending changes protected pages (level 2)',&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Expiry category config&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This table configures the expiry category behaviour for each protection&lt;br /&gt;
-- action.&lt;br /&gt;
-- * If set to true, setting that action will always categorise the page if&lt;br /&gt;
--   an expiry parameter is not set.&lt;br /&gt;
-- * If set to false, setting that action will never categorise the page.&lt;br /&gt;
-- * If set to nil, the module will categorise the page if:&lt;br /&gt;
--   1) an expiry parameter is not set, and&lt;br /&gt;
--   2) a reason is provided, and&lt;br /&gt;
--   3) the specified reason is not blacklisted in the reasonsWithoutExpiryCheck&lt;br /&gt;
--      table.&lt;br /&gt;
&lt;br /&gt;
expiryCheckActions = {&lt;br /&gt;
	edit = nil,&lt;br /&gt;
	move = false,&lt;br /&gt;
	autoreview = true&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
reasonsWithoutExpiryCheck = {&lt;br /&gt;
	blp = true,&lt;br /&gt;
	template = true,&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Pagetypes&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This table produces the page types available with the ${PAGETYPE} parameter.&lt;br /&gt;
-- Keys are namespace numbers, or the string &amp;quot;default&amp;quot; for the default value.&lt;br /&gt;
pagetypes = {&lt;br /&gt;
	[0] = 'article',&lt;br /&gt;
	[6] = 'file',&lt;br /&gt;
	[10] = 'template',&lt;br /&gt;
	[14] = 'category',&lt;br /&gt;
	[828] = 'module',&lt;br /&gt;
	default = 'page'&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Strings marking indefinite protection&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This table contains values passed to the expiry parameter that mean the page&lt;br /&gt;
-- is protected indefinitely.&lt;br /&gt;
indefStrings = {&lt;br /&gt;
	['indef'] = true,&lt;br /&gt;
	['indefinite'] = true,&lt;br /&gt;
	['indefinitely'] = true,&lt;br /&gt;
	['infinite'] = true,&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Wrapper templates and their default arguments&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This table contains wrapper templates used with the module, and their&lt;br /&gt;
-- default arguments. Templates specified in this table should contain the&lt;br /&gt;
-- following invocation, and no other template content:&lt;br /&gt;
--&lt;br /&gt;
-- {{#invoke:Protection banner|main}}&lt;br /&gt;
--&lt;br /&gt;
-- If other content is desired, it can be added between&lt;br /&gt;
-- &amp;lt;noinclude&amp;gt;...&amp;lt;/noinclude&amp;gt; tags.&lt;br /&gt;
--&lt;br /&gt;
-- When a user calls one of these wrapper templates, they will use the&lt;br /&gt;
-- default arguments automatically. The arguments cannot be overwritten by the&lt;br /&gt;
-- user.&lt;br /&gt;
wrappers = {&lt;br /&gt;
	['Template:Pp']                         = {},&lt;br /&gt;
	['Template:Pp-blp']                     = {'blp'},&lt;br /&gt;
	-- we don't need Template:Pp-create&lt;br /&gt;
	['Template:Pp-dispute']                 = {'dispute'},&lt;br /&gt;
	['Template:Pp-main-page']                = {'mainpage'},&lt;br /&gt;
	['Template:Pp-move']                    = {action = 'move'},&lt;br /&gt;
	['Template:Pp-move-dispute']            = {'dispute', action = 'move'},&lt;br /&gt;
	-- we don't need Template:Pp-move-indef&lt;br /&gt;
	['Template:Pp-move-vandalism']          = {'vandalism', action = 'move'},&lt;br /&gt;
	['Template:Pp-office']                  = {'office'},&lt;br /&gt;
	['Template:Pp-office-dmca']             = {'dmca'},&lt;br /&gt;
	['Template:Pp-pc1']                     = {action = 'autoreview', small = true},&lt;br /&gt;
	['Template:Pp-pc2']                     = {action = 'autoreview', small = true},&lt;br /&gt;
	['Template:Pp-reset']                   = {'reset'},&lt;br /&gt;
	['Template:Pp-semi-indef']              = {expiry = 'indef', small = true},&lt;br /&gt;
	['Template:Pp-sock']                    = {'sock'},&lt;br /&gt;
	['Template:Pp-template']                = {'template', small = true},&lt;br /&gt;
	['Template:Pp-usertalk']                = {'usertalk'},&lt;br /&gt;
	['Template:Pp-vandalism']               = {'vandalism'},&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- &lt;br /&gt;
--                                 MESSAGES&lt;br /&gt;
-- &lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
msg = {&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Intro blurb and intro fragment&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- These messages specify what is produced by the ${INTROBLURB} and&lt;br /&gt;
-- ${INTROFRAGMENT} parameters. If the protection is temporary they use the&lt;br /&gt;
-- intro-blurb-expiry or intro-fragment-expiry, and if not they use&lt;br /&gt;
-- intro-blurb-noexpiry or intro-fragment-noexpiry.&lt;br /&gt;
-- It is possible to use banner parameters in these messages.&lt;br /&gt;
['intro-blurb-expiry'] = '${PROTECTIONBLURB} until ${EXPIRY}.',&lt;br /&gt;
['intro-blurb-noexpiry'] = '${PROTECTIONBLURB}.',&lt;br /&gt;
['intro-fragment-expiry'] = '${PROTECTIONBLURB} until ${EXPIRY},',&lt;br /&gt;
['intro-fragment-noexpiry'] = '${PROTECTIONBLURB}',&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Tooltip blurb&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- These messages specify what is produced by the ${TOOLTIPBLURB} parameter.&lt;br /&gt;
-- If the protection is temporary the tooltip-blurb-expiry message is used, and&lt;br /&gt;
-- if not the tooltip-blurb-noexpiry message is used.&lt;br /&gt;
-- It is possible to use banner parameters in these messages.&lt;br /&gt;
['tooltip-blurb-expiry'] = 'This ${PAGETYPE} is ${PROTECTIONLEVEL} until ${EXPIRY}.',&lt;br /&gt;
['tooltip-blurb-noexpiry'] = 'This ${PAGETYPE} is ${PROTECTIONLEVEL}.',&lt;br /&gt;
['tooltip-fragment-expiry'] = 'This ${PAGETYPE} is ${PROTECTIONLEVEL} until ${EXPIRY},',&lt;br /&gt;
['tooltip-fragment-noexpiry'] = 'This ${PAGETYPE} is ${PROTECTIONLEVEL}',&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Special explanation blurb&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- An explanation blurb for pages that cannot be unprotected, e.g. for pages&lt;br /&gt;
-- in the MediaWiki namespace.&lt;br /&gt;
-- It is possible to use banner parameters in this message.&lt;br /&gt;
['explanation-blurb-nounprotect'] = 'See the [[Wikipedia:Protection policy|'&lt;br /&gt;
	.. 'protection policy]] and ${PROTECTIONLOG} for more details.'&lt;br /&gt;
	.. ' Please discuss any changes on the ${TALKPAGE}; you'&lt;br /&gt;
	.. ' may ${EDITREQUEST} to ask an'&lt;br /&gt;
	.. ' [[Wikipedia:Administrators|administrator]] to make an edit if it'&lt;br /&gt;
	.. ' is [[Help:Minor edit#When to mark an edit as a minor edit'&lt;br /&gt;
	.. '|uncontroversial]] or supported by [[Wikipedia:Consensus'&lt;br /&gt;
	.. '|consensus]].',&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Protection log display values&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- These messages determine the display values for the protection log link&lt;br /&gt;
-- or the pending changes log link produced by the ${PROTECTIONLOG} parameter.&lt;br /&gt;
-- It is possible to use banner parameters in these messages.&lt;br /&gt;
['protection-log-display'] = 'protection log',&lt;br /&gt;
['pc-log-display'] = 'pending changes log',&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Current version display values&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- These messages determine the display values for the page history link&lt;br /&gt;
-- or the move log link produced by the ${CURRENTVERSION} parameter.&lt;br /&gt;
-- It is possible to use banner parameters in these messages.&lt;br /&gt;
['current-version-move-display'] = 'current title',&lt;br /&gt;
['current-version-edit-display'] = 'current version',&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Talk page&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This message determines the display value of the talk page link produced&lt;br /&gt;
-- with the ${TALKPAGE} parameter.&lt;br /&gt;
-- It is possible to use banner parameters in this message.&lt;br /&gt;
['talk-page-link-display'] = 'talk page',&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Edit requests&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This message determines the display value of the edit request link produced&lt;br /&gt;
-- with the ${EDITREQUEST} parameter.&lt;br /&gt;
-- It is possible to use banner parameters in this message.&lt;br /&gt;
['edit-request-display'] = 'submit an edit request',&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Expiry date format&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This is the format for the blurb expiry date. It should be valid input for&lt;br /&gt;
-- the first parameter of the #time parser function.&lt;br /&gt;
['expiry-date-format'] = 'F j, Y',&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Tracking categories&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- These messages determine which tracking categories the module outputs.&lt;br /&gt;
['tracking-category-incorrect'] = 'Wikipedia pages with incorrect protection templates',&lt;br /&gt;
['tracking-category-expiry'] = 'Wikipedia protected pages without expiry',&lt;br /&gt;
['tracking-category-template'] = 'Wikipedia template-protected pages other than templates and modules',&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Images&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- These are images that are not defined by their protection action and protection level.&lt;br /&gt;
['image-filename-indef'] = 'Padlock-red.svg',&lt;br /&gt;
['image-filename-default'] = 'Transparent.gif',&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Error message blurb&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This is the blurb that is outputted with error messages produced by the&lt;br /&gt;
-- module. $1 is replaced with the error message text. The whole message is&lt;br /&gt;
-- turned into a large red error message, so there is no need to add HTML&lt;br /&gt;
-- styling.&lt;br /&gt;
['error-message-blurb'] = 'Error: $1 ([[Module:Protection banner#Errors|help]])'&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- End messages&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- End configuration&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Module:Effective_protection_level</id>
		<title>Module:Effective protection level</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Module:Effective_protection_level"/>
				<updated>2014-08-10T20:42:07Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: Changed protection level of Module:Effective protection level: High-risk Lua module ([Edit=Allow only template editors and admins] (indefinite) [Move=Allow only template editors and admins] (indefinite))&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;local p = {}&lt;br /&gt;
&lt;br /&gt;
-- Returns the permission required to perform a given action on a given title.&lt;br /&gt;
-- If no title is specified, the title of the page being displayed is used.&lt;br /&gt;
function p._main(action, pagename)&lt;br /&gt;
	local title&lt;br /&gt;
	if type(pagename) == 'table' and pagename.prefixedText then&lt;br /&gt;
		title = pagename&lt;br /&gt;
	elseif pagename then&lt;br /&gt;
		title = mw.title.new(pagename)&lt;br /&gt;
	else&lt;br /&gt;
		title = mw.title.getCurrentTitle()&lt;br /&gt;
	end&lt;br /&gt;
	pagename = title.prefixedText&lt;br /&gt;
	if action == 'autoreview' then&lt;br /&gt;
		local level = mw.getCurrentFrame():callParserFunction('PENDINGCHANGELEVEL', pagename)&lt;br /&gt;
		if level == 'review' then&lt;br /&gt;
			return 'reviewer'&lt;br /&gt;
		elseif level ~= '' then&lt;br /&gt;
			return level&lt;br /&gt;
		else&lt;br /&gt;
			return nil -- not '*'. a page not being PC-protected is distinct from it being PC-protected with anyone able to review. also not '', as that would mean PC-protected but nobody can review&lt;br /&gt;
		end&lt;br /&gt;
	elseif action ~= 'edit' and action ~= 'move' and action ~= 'create' and action ~= 'upload' then&lt;br /&gt;
		error( 'First parameter must be one of edit, move, create, upload, autoreview', 2 )&lt;br /&gt;
	end&lt;br /&gt;
	if title.namespace == 8 then -- MediaWiki namespace&lt;br /&gt;
		return 'sysop'&lt;br /&gt;
	elseif title.namespace == 2 and ( mw.ustring.find( pagename, '/.*%.js$') or mw.ustring.find( pagename, '/.*%.css$') ) then -- user .js or .css page&lt;br /&gt;
		return 'sysop'&lt;br /&gt;
	end&lt;br /&gt;
	local level = title.protectionLevels[action] and title.protectionLevels[action][1]&lt;br /&gt;
	if level == 'sysop' then&lt;br /&gt;
		return 'sysop'&lt;br /&gt;
	elseif mw.getCurrentFrame():callParserFunction('CASCADINGSOURCES', pagename) ~= '' then -- used by a cascading-protected page&lt;br /&gt;
		return 'sysop'&lt;br /&gt;
	elseif level == 'templateeditor' then&lt;br /&gt;
		return 'templateeditor'&lt;br /&gt;
	elseif action == 'move' then&lt;br /&gt;
		local blacklistentry = mw.ext.TitleBlacklist.test('edit', pagename) -- Testing action edit is correct, since this is for the source page. The target page name gets tested with action move.&lt;br /&gt;
		if blacklistentry and not blacklistentry.params.autoconfirmed then&lt;br /&gt;
			return 'accountcreator'&lt;br /&gt;
		elseif title.namespace == 6 then&lt;br /&gt;
			return 'filemover'&lt;br /&gt;
		else&lt;br /&gt;
			return 'autoconfirmed'&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local blacklistentry = mw.ext.TitleBlacklist.test(action, pagename)&lt;br /&gt;
	if blacklistentry then&lt;br /&gt;
		return blacklistentry.params.autoconfirmed and 'autoconfirmed' or 'accountcreator'&lt;br /&gt;
	elseif level then&lt;br /&gt;
		return level&lt;br /&gt;
	elseif action == 'upload' then&lt;br /&gt;
		return 'autoconfirmed'&lt;br /&gt;
	elseif action == 'create' and title.namespace % 2 == 0 and title.namespace ~= 118 then -- You need to be registered, but not autoconfirmed, to create non-talk pages other than drafts&lt;br /&gt;
		return 'user'&lt;br /&gt;
	else&lt;br /&gt;
		return '*'&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
setmetatable(p, { __index = function(t, k)&lt;br /&gt;
	return function(frame)&lt;br /&gt;
		return t._main(k, frame.args[1])&lt;br /&gt;
	end&lt;br /&gt;
end })&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Module:Protection_banner</id>
		<title>Module:Protection banner</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Module:Protection_banner"/>
				<updated>2014-08-10T17:25:15Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: allow user-specified args to overwrite default args; updated from sandbox&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module implements {{pp-meta}} and its daughter templates such as&lt;br /&gt;
-- {{pp-dispute}}, {{pp-vandalism}} and {{pp-sock}}.&lt;br /&gt;
&lt;br /&gt;
-- Initialise necessary modules.&lt;br /&gt;
require('Module:No globals')&lt;br /&gt;
local newFileLink = require('Module:File link').new&lt;br /&gt;
local effectiveProtectionLevel = require('Module:Effective protection level')._main&lt;br /&gt;
local yesno = require('Module:Yesno')&lt;br /&gt;
&lt;br /&gt;
-- Lazily initialise modules and objects we don't always need.&lt;br /&gt;
local getArgs, makeMessageBox, lang&lt;br /&gt;
&lt;br /&gt;
-- Set constants.&lt;br /&gt;
local CONFIG_MODULE = 'Module:Protection banner/config'&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Helper functions&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function makeCategoryLink(cat, sort)&lt;br /&gt;
	local nsText = mw.site.namespaces[14].name&lt;br /&gt;
	if cat and sort then&lt;br /&gt;
		return string.format(&lt;br /&gt;
			'[[%s:%s|%s]]',&lt;br /&gt;
			nsText,&lt;br /&gt;
			cat,&lt;br /&gt;
			sort&lt;br /&gt;
		)&lt;br /&gt;
	elseif cat then&lt;br /&gt;
		return string.format(&lt;br /&gt;
			'[[%s:%s]]',&lt;br /&gt;
			nsText,&lt;br /&gt;
			cat&lt;br /&gt;
		)&lt;br /&gt;
	else&lt;br /&gt;
		return ''&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Validation function for the expiry and the protection date&lt;br /&gt;
local function validateDate(dateString, dateType)&lt;br /&gt;
	lang = lang or mw.language.getContentLanguage()&lt;br /&gt;
	local success, result = pcall(lang.formatDate, lang, 'U', dateString)&lt;br /&gt;
	if success then&lt;br /&gt;
		result = tonumber(result)&lt;br /&gt;
		if result then&lt;br /&gt;
			return result&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	error(string.format(&lt;br /&gt;
		'invalid %s (&amp;quot;%s&amp;quot;)',&lt;br /&gt;
		dateType,&lt;br /&gt;
		tostring(dateString)&lt;br /&gt;
	), 0)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function makeFullUrl(page, query, display)&lt;br /&gt;
	return string.format(&lt;br /&gt;
		'[%s %s]',&lt;br /&gt;
		tostring(mw.uri.fullUrl(page, query)),&lt;br /&gt;
		display&lt;br /&gt;
	)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function toTableEnd(t, pos)&lt;br /&gt;
	-- Sends the value at position pos to the end of array t, and shifts the&lt;br /&gt;
	-- other items down accordingly.&lt;br /&gt;
	return table.insert(t, table.remove(t, pos))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Protection class&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local Protection = {}&lt;br /&gt;
Protection.__index = Protection&lt;br /&gt;
&lt;br /&gt;
Protection.supportedActions = {&lt;br /&gt;
	edit = true,&lt;br /&gt;
	move = true,&lt;br /&gt;
	autoreview = true&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Protection.bannerConfigFields = {&lt;br /&gt;
	'text',&lt;br /&gt;
	'explanation',&lt;br /&gt;
	'tooltip',&lt;br /&gt;
	'alt',&lt;br /&gt;
	'link',&lt;br /&gt;
	'image'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function Protection.new(args, cfg, title)&lt;br /&gt;
	local obj = {}&lt;br /&gt;
	obj._cfg = cfg&lt;br /&gt;
	obj.title = title or mw.title.getCurrentTitle()&lt;br /&gt;
&lt;br /&gt;
	-- Set action&lt;br /&gt;
	if not args.action then&lt;br /&gt;
		obj.action = 'edit'&lt;br /&gt;
	elseif Protection.supportedActions[args.action] then&lt;br /&gt;
		obj.action = args.action&lt;br /&gt;
	else&lt;br /&gt;
		error(string.format(&lt;br /&gt;
			'invalid action (&amp;quot;%s&amp;quot;)',&lt;br /&gt;
			tostring(args.action)&lt;br /&gt;
		), 0)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Set level&lt;br /&gt;
	obj.level = effectiveProtectionLevel(obj.action, obj.title)&lt;br /&gt;
	if obj.level == 'accountcreator' then&lt;br /&gt;
		-- Lump titleblacklisted pages in with template-protected pages,&lt;br /&gt;
		-- since templateeditors can do both.&lt;br /&gt;
		obj.level = 'templateeditor'&lt;br /&gt;
	elseif not obj.level or (obj.action == 'move' and obj.level == 'autoconfirmed') then&lt;br /&gt;
		-- Users need to be autoconfirmed to move pages anyway, so treat&lt;br /&gt;
		-- semi-move-protected pages as unprotected.&lt;br /&gt;
		obj.level = '*'&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Set expiry&lt;br /&gt;
	if args.expiry then&lt;br /&gt;
		if cfg.indefStrings[args.expiry] then&lt;br /&gt;
			obj.expiry = 'indef'&lt;br /&gt;
		elseif type(args.expiry) == 'number' then&lt;br /&gt;
			obj.expiry = args.expiry&lt;br /&gt;
		else&lt;br /&gt;
			obj.expiry = validateDate(args.expiry, 'expiry date')&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Set reason&lt;br /&gt;
	if args[1] then&lt;br /&gt;
		obj.reason = mw.ustring.lower(args[1])&lt;br /&gt;
		if obj.reason:find('|') then&lt;br /&gt;
			error('reasons cannot contain the pipe character (&amp;quot;|&amp;quot;)', 0)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Set protection date&lt;br /&gt;
	if args.date then&lt;br /&gt;
		obj.protectionDate = validateDate(args.date, 'protection date')&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Set banner config&lt;br /&gt;
	do&lt;br /&gt;
		obj.bannerConfig = {}&lt;br /&gt;
		local configTables = {}&lt;br /&gt;
		if cfg.banners[obj.action] then&lt;br /&gt;
			configTables[#configTables + 1] = cfg.banners[obj.action][obj.reason]&lt;br /&gt;
		end&lt;br /&gt;
		if cfg.defaultBanners[obj.action] then&lt;br /&gt;
			configTables[#configTables + 1] = cfg.defaultBanners[obj.action][obj.level]&lt;br /&gt;
			configTables[#configTables + 1] = cfg.defaultBanners[obj.action].default&lt;br /&gt;
		end&lt;br /&gt;
		configTables[#configTables + 1] = cfg.masterBanner&lt;br /&gt;
		for i, field in ipairs(Protection.bannerConfigFields) do&lt;br /&gt;
			for j, t in ipairs(configTables) do&lt;br /&gt;
				if t[field] then&lt;br /&gt;
					obj.bannerConfig[field] = t[field]&lt;br /&gt;
					break&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return setmetatable(obj, Protection)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Protection:isProtected()&lt;br /&gt;
	return self.level ~= '*'&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Protection:isTemporary()&lt;br /&gt;
	return type(self.expiry) == 'number'&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Protection:makeProtectionCategory()&lt;br /&gt;
	local cfg = self._cfg&lt;br /&gt;
	local title = self.title&lt;br /&gt;
	&lt;br /&gt;
	-- Exit if the page is not protected.&lt;br /&gt;
	if not self:isProtected() then&lt;br /&gt;
		return ''&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Get the expiry key fragment.&lt;br /&gt;
	local expiryFragment&lt;br /&gt;
	if self.expiry == 'indef' then&lt;br /&gt;
		expiryFragment = self.expiry&lt;br /&gt;
	elseif type(self.expiry) == 'number' then&lt;br /&gt;
		expiryFragment = 'temp'&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Get the namespace key fragment.&lt;br /&gt;
	local namespaceFragment&lt;br /&gt;
	do&lt;br /&gt;
		namespaceFragment = cfg.categoryNamespaceKeys[title.namespace]&lt;br /&gt;
		if not namespaceFragment and title.namespace % 2 == 1 then&lt;br /&gt;
				namespaceFragment = 'talk'&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
 &lt;br /&gt;
	-- Define the order that key fragments are tested in. This is done with an&lt;br /&gt;
	-- array of tables containing the value to be tested, along with its&lt;br /&gt;
	-- position in the cfg.protectionCategories table.&lt;br /&gt;
	local order = {&lt;br /&gt;
		{val = expiryFragment,    keypos = 1},&lt;br /&gt;
		{val = namespaceFragment, keypos = 2},&lt;br /&gt;
		{val = self.reason,       keypos = 3},&lt;br /&gt;
		{val = self.level,        keypos = 4},&lt;br /&gt;
		{val = self.action,       keypos = 5}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	--[[&lt;br /&gt;
	-- The old protection templates used an ad-hoc protection category system,&lt;br /&gt;
	-- with some templates prioritising namespaces in their categories, and&lt;br /&gt;
	-- others prioritising the protection reason. To emulate this in this module&lt;br /&gt;
	-- we use the config table cfg.reasonsWithNamespacePriority to set the&lt;br /&gt;
	-- reasons for which namespaces have priority over protection reason.&lt;br /&gt;
	-- If we are dealing with one of those reasons, move the namespace table to&lt;br /&gt;
	-- the end of the order table, i.e. give it highest priority. If not, the&lt;br /&gt;
	-- reason should have highest priority, so move that to the end of the table&lt;br /&gt;
	-- instead.&lt;br /&gt;
	--]]&lt;br /&gt;
	if self.reason and cfg.reasonsWithNamespacePriority[self.reason] then&lt;br /&gt;
		-- table.insert(order, 3, table.remove(order, 2))&lt;br /&gt;
		toTableEnd(order, 2)&lt;br /&gt;
	else&lt;br /&gt;
		toTableEnd(order, 3)&lt;br /&gt;
	end&lt;br /&gt;
 &lt;br /&gt;
	--[[&lt;br /&gt;
	-- Define the attempt order. Inactive subtables (subtables with nil &amp;quot;value&amp;quot;&lt;br /&gt;
	-- fields) are moved to the end, where they will later be given the key&lt;br /&gt;
	-- &amp;quot;all&amp;quot;. This is to cut down on the number of table lookups in&lt;br /&gt;
	-- cfg.protectionCategories, which grows exponentially with the number of&lt;br /&gt;
	-- non-nil keys. We keep track of the number of active subtables with the&lt;br /&gt;
	-- noActive parameter.&lt;br /&gt;
	--]]&lt;br /&gt;
	local noActive, attemptOrder&lt;br /&gt;
	do&lt;br /&gt;
		local active, inactive = {}, {}&lt;br /&gt;
		for i, t in ipairs(order) do&lt;br /&gt;
			if t.val then&lt;br /&gt;
				active[#active + 1] = t&lt;br /&gt;
			else&lt;br /&gt;
				inactive[#inactive + 1] = t&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		noActive = #active&lt;br /&gt;
		attemptOrder = active&lt;br /&gt;
		for i, t in ipairs(inactive) do&lt;br /&gt;
			attemptOrder[#attemptOrder + 1] = t&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
 &lt;br /&gt;
	--[[&lt;br /&gt;
	-- Check increasingly generic key combinations until we find a match. If a&lt;br /&gt;
	-- specific category exists for the combination of key fragments we are&lt;br /&gt;
	-- given, that match will be found first. If not, we keep trying different&lt;br /&gt;
	-- key fragment combinations until we match using the key&lt;br /&gt;
	-- &amp;quot;all-all-all-all-all&amp;quot;.&lt;br /&gt;
	--&lt;br /&gt;
	-- To generate the keys, we index the key subtables using a binary matrix&lt;br /&gt;
	-- with indexes i and j. j is only calculated up to the number of active&lt;br /&gt;
	-- subtables. For example, if there were three active subtables, the matrix&lt;br /&gt;
	-- would look like this, with 0 corresponding to the key fragment &amp;quot;all&amp;quot;, and&lt;br /&gt;
	-- 1 corresponding to other key fragments.&lt;br /&gt;
	-- &lt;br /&gt;
	--   j 1  2  3&lt;br /&gt;
	-- i  &lt;br /&gt;
	-- 1   1  1  1&lt;br /&gt;
	-- 2   0  1  1&lt;br /&gt;
	-- 3   1  0  1&lt;br /&gt;
	-- 4   0  0  1&lt;br /&gt;
	-- 5   1  1  0&lt;br /&gt;
	-- 6   0  1  0&lt;br /&gt;
	-- 7   1  0  0&lt;br /&gt;
	-- 8   0  0  0&lt;br /&gt;
	-- &lt;br /&gt;
	-- Values of j higher than the number of active subtables are set&lt;br /&gt;
	-- to the string &amp;quot;all&amp;quot;.&lt;br /&gt;
	--&lt;br /&gt;
	-- A key for cfg.protectionCategories is constructed for each value of i.&lt;br /&gt;
	-- The position of the value in the key is determined by the keypos field in&lt;br /&gt;
	-- each subtable.&lt;br /&gt;
	--]]&lt;br /&gt;
	local cats = cfg.protectionCategories&lt;br /&gt;
	for i = 1, 2^noActive do&lt;br /&gt;
		local key = {}&lt;br /&gt;
		for j, t in ipairs(attemptOrder) do&lt;br /&gt;
			if j &amp;gt; noActive then&lt;br /&gt;
				key[t.keypos] = 'all'&lt;br /&gt;
			else&lt;br /&gt;
				local quotient = i / 2 ^ (j - 1)&lt;br /&gt;
				quotient = math.ceil(quotient)&lt;br /&gt;
				if quotient % 2 == 1 then&lt;br /&gt;
					key[t.keypos] = t.val&lt;br /&gt;
				else&lt;br /&gt;
					key[t.keypos] = 'all'&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		key = table.concat(key, '|')&lt;br /&gt;
		local attempt = cats[key]&lt;br /&gt;
		if attempt then&lt;br /&gt;
			return makeCategoryLink(attempt, title.text)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return ''&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Protection:needsExpiry()&lt;br /&gt;
	local cfg = self._cfg&lt;br /&gt;
	local actionNeedsCheck = cfg.expiryCheckActions[self.action]&lt;br /&gt;
	return not self.expiry and (&lt;br /&gt;
		actionNeedsCheck or (&lt;br /&gt;
			actionNeedsCheck == nil&lt;br /&gt;
			and self.reason -- the old {{pp-protected}} didn't check for expiry&lt;br /&gt;
			and not cfg.reasonsWithoutExpiryCheck[self.reason]&lt;br /&gt;
		)&lt;br /&gt;
	)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Protection:isIncorrect()&lt;br /&gt;
	local expiry = self.expiry&lt;br /&gt;
	return not self:isProtected()&lt;br /&gt;
		or type(expiry) == 'number' and expiry &amp;lt; os.time()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Protection:isTemplateProtectedNonTemplate()&lt;br /&gt;
	local action, namespace = self.action, self.title.namespace&lt;br /&gt;
	return self.level == 'templateeditor'&lt;br /&gt;
		and (&lt;br /&gt;
			(action ~= 'edit' and action ~= 'move')&lt;br /&gt;
			or (namespace ~= 10 and namespace ~= 828)&lt;br /&gt;
		)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Protection:makeCategoryLinks()&lt;br /&gt;
	local msg = self._cfg.msg&lt;br /&gt;
	local ret = { self:makeProtectionCategory() }&lt;br /&gt;
	if self:needsExpiry() then&lt;br /&gt;
		ret[#ret + 1] = makeCategoryLink(&lt;br /&gt;
			msg['tracking-category-expiry'],&lt;br /&gt;
			self.title.text&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
	if self:isIncorrect() then&lt;br /&gt;
		ret[#ret + 1] = makeCategoryLink(&lt;br /&gt;
			msg['tracking-category-incorrect'],&lt;br /&gt;
			self.title.text&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
	if self:isTemplateProtectedNonTemplate() then&lt;br /&gt;
		ret[#ret + 1] = makeCategoryLink(&lt;br /&gt;
			msg['tracking-category-template'],&lt;br /&gt;
			self.title.text&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
	return table.concat(ret)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Blurb class&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local Blurb = {}&lt;br /&gt;
Blurb.__index = Blurb&lt;br /&gt;
&lt;br /&gt;
Blurb.bannerTextFields = {&lt;br /&gt;
	text = true,&lt;br /&gt;
	explanation = true,&lt;br /&gt;
	tooltip = true,&lt;br /&gt;
	alt = true,&lt;br /&gt;
	link = true&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function Blurb.new(protectionObj, args, cfg)&lt;br /&gt;
	return setmetatable({&lt;br /&gt;
		_cfg = cfg,&lt;br /&gt;
		_protectionObj = protectionObj,&lt;br /&gt;
		_args = args&lt;br /&gt;
	}, Blurb)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Private methods --&lt;br /&gt;
&lt;br /&gt;
function Blurb:_formatDate(num)&lt;br /&gt;
	-- Formats a Unix timestamp into dd Month, YYYY format.&lt;br /&gt;
	lang = lang or mw.language.getContentLanguage()&lt;br /&gt;
	local success, date = pcall(&lt;br /&gt;
		lang.formatDate,&lt;br /&gt;
		lang,&lt;br /&gt;
		self._cfg.msg['expiry-date-format'] or 'j F Y',&lt;br /&gt;
		'@' .. tostring(num)&lt;br /&gt;
	)&lt;br /&gt;
	if success then&lt;br /&gt;
		return date&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_getExpandedMessage(msgKey)&lt;br /&gt;
	return self:_substituteParameters(self._cfg.msg[msgKey])&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_substituteParameters(msg)&lt;br /&gt;
	if not self._params then&lt;br /&gt;
		local parameterFuncs = {}&lt;br /&gt;
&lt;br /&gt;
		parameterFuncs.CURRENTVERSION     = self._makeCurrentVersionParameter&lt;br /&gt;
		parameterFuncs.EDITREQUEST        = self._makeEditRequestParameter&lt;br /&gt;
		parameterFuncs.EXPIRY             = self._makeExpiryParameter&lt;br /&gt;
		parameterFuncs.EXPLANATIONBLURB   = self._makeExplanationBlurbParameter&lt;br /&gt;
		parameterFuncs.IMAGELINK          = self._makeImageLinkParameter&lt;br /&gt;
		parameterFuncs.INTROBLURB         = self._makeIntroBlurbParameter&lt;br /&gt;
		parameterFuncs.INTROFRAGMENT      = self._makeIntroFragmentParameter&lt;br /&gt;
		parameterFuncs.PAGETYPE           = self._makePagetypeParameter&lt;br /&gt;
		parameterFuncs.PROTECTIONBLURB    = self._makeProtectionBlurbParameter&lt;br /&gt;
		parameterFuncs.PROTECTIONDATE     = self._makeProtectionDateParameter&lt;br /&gt;
		parameterFuncs.PROTECTIONLEVEL    = self._makeProtectionLevelParameter&lt;br /&gt;
		parameterFuncs.PROTECTIONLOG      = self._makeProtectionLogParameter&lt;br /&gt;
		parameterFuncs.TALKPAGE           = self._makeTalkPageParameter&lt;br /&gt;
		parameterFuncs.TOOLTIPBLURB       = self._makeTooltipBlurbParameter&lt;br /&gt;
		parameterFuncs.TOOLTIPFRAGMENT    = self._makeTooltipFragmentParameter&lt;br /&gt;
		parameterFuncs.VANDAL             = self._makeVandalTemplateParameter&lt;br /&gt;
		&lt;br /&gt;
		self._params = setmetatable({}, {&lt;br /&gt;
			__index = function (t, k)&lt;br /&gt;
				local param&lt;br /&gt;
				if parameterFuncs[k] then&lt;br /&gt;
					param = parameterFuncs[k](self)&lt;br /&gt;
				end&lt;br /&gt;
				param = param or ''&lt;br /&gt;
				t[k] = param&lt;br /&gt;
				return param&lt;br /&gt;
			end&lt;br /&gt;
		})&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	msg = msg:gsub('${(%u+)}', self._params)&lt;br /&gt;
	return msg&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeCurrentVersionParameter()&lt;br /&gt;
	-- A link to the page history or the move log, depending on the kind of&lt;br /&gt;
	-- protection.&lt;br /&gt;
	local pagename = self._protectionObj.title.prefixedText&lt;br /&gt;
	if self._protectionObj.action == 'move' then&lt;br /&gt;
		-- We need the move log link.&lt;br /&gt;
		return makeFullUrl(&lt;br /&gt;
			'Special:Log',&lt;br /&gt;
			{type = 'move', page = pagename},&lt;br /&gt;
			self:_getExpandedMessage('current-version-move-display')&lt;br /&gt;
		)&lt;br /&gt;
	else&lt;br /&gt;
		-- We need the history link.&lt;br /&gt;
		return makeFullUrl(&lt;br /&gt;
			pagename,&lt;br /&gt;
			{action = 'history'},&lt;br /&gt;
			self:_getExpandedMessage('current-version-edit-display')&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeEditRequestParameter()&lt;br /&gt;
	local mEditRequest = require('Module:Submit an edit request')&lt;br /&gt;
	local action = self._protectionObj.action&lt;br /&gt;
	local level = self._protectionObj.level&lt;br /&gt;
	&lt;br /&gt;
	-- Get the edit request type.&lt;br /&gt;
	local requestType&lt;br /&gt;
	if action == 'edit' then&lt;br /&gt;
		if level == 'autoconfirmed' then&lt;br /&gt;
			requestType = 'semi'&lt;br /&gt;
		elseif level == 'templateeditor' then&lt;br /&gt;
			requestType = 'template'&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	requestType = requestType or 'full'&lt;br /&gt;
	&lt;br /&gt;
	-- Get the display value.&lt;br /&gt;
	local display = self:_getExpandedMessage('edit-request-display')&lt;br /&gt;
&lt;br /&gt;
	return mEditRequest._link{type = requestType, display = display}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeExpiryParameter()&lt;br /&gt;
	local expiry = self._protectionObj.expiry&lt;br /&gt;
	if type(expiry) == 'number' then&lt;br /&gt;
		return self:_formatDate(expiry)&lt;br /&gt;
	else&lt;br /&gt;
		return expiry&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeExplanationBlurbParameter()&lt;br /&gt;
	-- Cover special cases first.&lt;br /&gt;
	if self._protectionObj.title.namespace == 8 then&lt;br /&gt;
		-- MediaWiki namespace&lt;br /&gt;
		return self:_getExpandedMessage('explanation-blurb-nounprotect')&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Get explanation blurb table keys&lt;br /&gt;
	local action = self._protectionObj.action&lt;br /&gt;
	local level = self._protectionObj.level&lt;br /&gt;
	local talkKey = self._protectionObj.title.isTalkPage and 'talk' or 'subject'&lt;br /&gt;
&lt;br /&gt;
	-- Find the message in the explanation blurb table and substitute any&lt;br /&gt;
	-- parameters.&lt;br /&gt;
	local explanations = self._cfg.explanationBlurbs&lt;br /&gt;
	local msg&lt;br /&gt;
	if explanations[action][level] and explanations[action][level][talkKey] then&lt;br /&gt;
		msg = explanations[action][level][talkKey]&lt;br /&gt;
	elseif explanations[action][level] and explanations[action][level].default then&lt;br /&gt;
		msg = explanations[action][level].default&lt;br /&gt;
	elseif explanations[action].default and explanations[action].default[talkKey] then&lt;br /&gt;
		msg = explanations[action].default[talkKey]&lt;br /&gt;
	elseif explanations[action].default and explanations[action].default.default then&lt;br /&gt;
		msg = explanations[action].default.default&lt;br /&gt;
	else&lt;br /&gt;
		error(string.format(&lt;br /&gt;
			'could not find explanation blurb for action &amp;quot;%s&amp;quot;, level &amp;quot;%s&amp;quot; and talk key &amp;quot;%s&amp;quot;',&lt;br /&gt;
			action,&lt;br /&gt;
			level,&lt;br /&gt;
			talkKey&lt;br /&gt;
		))&lt;br /&gt;
	end&lt;br /&gt;
	return self:_substituteParameters(msg)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeImageLinkParameter()&lt;br /&gt;
	local imageLinks = self._cfg.imageLinks&lt;br /&gt;
	local action = self._protectionObj.action&lt;br /&gt;
	local level = self._protectionObj.level&lt;br /&gt;
	local msg&lt;br /&gt;
	if imageLinks[action][level] then&lt;br /&gt;
		msg = imageLinks[action][level]&lt;br /&gt;
	elseif imageLinks[action].default then&lt;br /&gt;
		msg = imageLinks[action].default&lt;br /&gt;
	else&lt;br /&gt;
		msg = imageLinks.edit.default&lt;br /&gt;
	end&lt;br /&gt;
	return self:_substituteParameters(msg)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeIntroBlurbParameter()&lt;br /&gt;
	if self._protectionObj:isTemporary() then&lt;br /&gt;
		return self:_getExpandedMessage('intro-blurb-expiry')&lt;br /&gt;
	else&lt;br /&gt;
		return self:_getExpandedMessage('intro-blurb-noexpiry')&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeIntroFragmentParameter()&lt;br /&gt;
	if self._protectionObj:isTemporary() then&lt;br /&gt;
		return self:_getExpandedMessage('intro-fragment-expiry')&lt;br /&gt;
	else&lt;br /&gt;
		return self:_getExpandedMessage('intro-fragment-noexpiry')&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makePagetypeParameter()&lt;br /&gt;
	local pagetypes = self._cfg.pagetypes&lt;br /&gt;
	return pagetypes[self._protectionObj.title.namespace]&lt;br /&gt;
		or pagetypes.default&lt;br /&gt;
		or error('no default pagetype defined')&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeProtectionBlurbParameter()&lt;br /&gt;
	local protectionBlurbs = self._cfg.protectionBlurbs&lt;br /&gt;
	local action = self._protectionObj.action&lt;br /&gt;
	local level = self._protectionObj.level&lt;br /&gt;
	local msg&lt;br /&gt;
	if protectionBlurbs[action][level] then&lt;br /&gt;
		msg = protectionBlurbs[action][level]&lt;br /&gt;
	elseif protectionBlurbs[action].default then&lt;br /&gt;
		msg = protectionBlurbs[action].default&lt;br /&gt;
	elseif protectionBlurbs.edit.default then&lt;br /&gt;
		msg = protectionBlurbs.edit.default&lt;br /&gt;
	else&lt;br /&gt;
		error('no protection blurb defined for protectionBlurbs.edit.default')&lt;br /&gt;
	end&lt;br /&gt;
	return self:_substituteParameters(msg)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeProtectionDateParameter()&lt;br /&gt;
	local protectionDate = self._protectionObj.protectionDate&lt;br /&gt;
	if type(protectionDate) == 'number' then&lt;br /&gt;
		return self:_formatDate(protectionDate)&lt;br /&gt;
	else&lt;br /&gt;
		return protectionDate&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeProtectionLevelParameter()&lt;br /&gt;
	local protectionLevels = self._cfg.protectionLevels&lt;br /&gt;
	local action = self._protectionObj.action&lt;br /&gt;
	local level = self._protectionObj.level&lt;br /&gt;
	local msg&lt;br /&gt;
	if protectionLevels[action][level] then&lt;br /&gt;
		msg = protectionLevels[action][level]&lt;br /&gt;
	elseif protectionLevels[action].default then&lt;br /&gt;
		msg = protectionLevels[action].default&lt;br /&gt;
	elseif protectionLevels.edit.default then&lt;br /&gt;
		msg = protectionLevels.edit.default&lt;br /&gt;
	else&lt;br /&gt;
		error('no protection level defined for protectionLevels.edit.default')&lt;br /&gt;
	end&lt;br /&gt;
	return self:_substituteParameters(msg)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeProtectionLogParameter()&lt;br /&gt;
	local pagename = self._protectionObj.title.prefixedText&lt;br /&gt;
	if self._protectionObj.action == 'autoreview' then&lt;br /&gt;
		-- We need the pending changes log.&lt;br /&gt;
		return makeFullUrl(&lt;br /&gt;
			'Special:Log',&lt;br /&gt;
			{type = 'stable', page = pagename},&lt;br /&gt;
			self:_getExpandedMessage('pc-log-display')&lt;br /&gt;
		)&lt;br /&gt;
	else&lt;br /&gt;
		-- We need the protection log.&lt;br /&gt;
		return makeFullUrl(&lt;br /&gt;
			'Special:Log',&lt;br /&gt;
			{type = 'protect', page = pagename},&lt;br /&gt;
			self:_getExpandedMessage('protection-log-display')&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeTalkPageParameter()&lt;br /&gt;
	return string.format(&lt;br /&gt;
		'[[%s:%s#%s|%s]]',&lt;br /&gt;
		mw.site.namespaces[self._protectionObj.title.namespace].talk.name,&lt;br /&gt;
		self._protectionObj.title.text,&lt;br /&gt;
		self._args.section or 'top',&lt;br /&gt;
		self:_getExpandedMessage('talk-page-link-display')&lt;br /&gt;
	)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeTooltipBlurbParameter()&lt;br /&gt;
	if self._protectionObj:isTemporary() then&lt;br /&gt;
		return self:_getExpandedMessage('tooltip-blurb-expiry')&lt;br /&gt;
	else&lt;br /&gt;
		return self:_getExpandedMessage('tooltip-blurb-noexpiry')&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeTooltipFragmentParameter()&lt;br /&gt;
	if self._protectionObj:isTemporary() then&lt;br /&gt;
		return self:_getExpandedMessage('tooltip-fragment-expiry')&lt;br /&gt;
	else&lt;br /&gt;
		return self:_getExpandedMessage('tooltip-fragment-noexpiry')&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeVandalTemplateParameter()&lt;br /&gt;
	return require('Module:Vandal-m')._main{&lt;br /&gt;
		self._args.user or self._protectionObj.title.baseText&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Public methods --&lt;br /&gt;
&lt;br /&gt;
function Blurb:makeBannerText(key)&lt;br /&gt;
	-- Validate input.&lt;br /&gt;
	if not key or not Blurb.bannerTextFields[key] then&lt;br /&gt;
		error(string.format(&lt;br /&gt;
			'&amp;quot;%s&amp;quot; is not a valid banner config field',&lt;br /&gt;
			tostring(key)&lt;br /&gt;
		), 2)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Generate the text.&lt;br /&gt;
	local msg = self._protectionObj.bannerConfig[key]&lt;br /&gt;
	if type(msg) == 'string' then&lt;br /&gt;
		return self:_substituteParameters(msg)&lt;br /&gt;
	elseif type(msg) == 'function' then&lt;br /&gt;
		msg = msg(self._protectionObj, self._args)&lt;br /&gt;
		if type(msg) ~= 'string' then&lt;br /&gt;
			error(string.format(&lt;br /&gt;
				'bad output from banner config function with key &amp;quot;%s&amp;quot;'&lt;br /&gt;
					.. ' (expected string, got %s)',&lt;br /&gt;
				tostring(key),&lt;br /&gt;
				type(msg)&lt;br /&gt;
			))&lt;br /&gt;
		end&lt;br /&gt;
		return self:_substituteParameters(msg)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- BannerTemplate class&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local BannerTemplate = {}&lt;br /&gt;
BannerTemplate.__index = BannerTemplate&lt;br /&gt;
&lt;br /&gt;
function BannerTemplate.new(protectionObj, cfg)&lt;br /&gt;
	local obj = {}&lt;br /&gt;
	obj._cfg = cfg&lt;br /&gt;
&lt;br /&gt;
	-- Set the image filename.&lt;br /&gt;
	local imageFilename = protectionObj.bannerConfig.image&lt;br /&gt;
	if imageFilename then&lt;br /&gt;
		obj._imageFilename = imageFilename&lt;br /&gt;
	else&lt;br /&gt;
		-- If an image filename isn't specified explicitly in the banner config,&lt;br /&gt;
		-- generate it from the protection status and the namespace.&lt;br /&gt;
		local action = protectionObj.action&lt;br /&gt;
		local level = protectionObj.level&lt;br /&gt;
		local namespace = protectionObj.title.namespace&lt;br /&gt;
		local reason = protectionObj.reason&lt;br /&gt;
		&lt;br /&gt;
		-- Deal with special cases first.&lt;br /&gt;
		if (&lt;br /&gt;
			namespace == 10&lt;br /&gt;
			or namespace == 828&lt;br /&gt;
			or reason and obj._cfg.indefImageReasons[reason]&lt;br /&gt;
			)&lt;br /&gt;
			and action == 'edit'&lt;br /&gt;
			and level == 'sysop'&lt;br /&gt;
			and not protectionObj:isTemporary()&lt;br /&gt;
		then&lt;br /&gt;
			-- Fully protected modules and templates get the special red &amp;quot;indef&amp;quot;&lt;br /&gt;
			-- padlock.&lt;br /&gt;
			obj._imageFilename = obj._cfg.msg['image-filename-indef']&lt;br /&gt;
		else&lt;br /&gt;
			-- Deal with regular protection types.&lt;br /&gt;
			local images = obj._cfg.images&lt;br /&gt;
			if images[action] then&lt;br /&gt;
				if images[action][level] then&lt;br /&gt;
					obj._imageFilename = images[action][level]&lt;br /&gt;
				elseif images[action].default then&lt;br /&gt;
					obj._imageFilename = images[action].default&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return setmetatable(obj, BannerTemplate)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function BannerTemplate:setImageWidth(width)&lt;br /&gt;
	self._imageWidth = width&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function BannerTemplate:setImageTooltip(tooltip)&lt;br /&gt;
	self._imageCaption = tooltip&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function BannerTemplate:renderImage()&lt;br /&gt;
	local filename = self._imageFilename&lt;br /&gt;
		or self._cfg.msg['image-filename-default']&lt;br /&gt;
		or 'Transparent.gif'&lt;br /&gt;
	return newFileLink(filename)&lt;br /&gt;
		:width(self._imageWidth or 20)&lt;br /&gt;
		:alt(self._imageAlt)&lt;br /&gt;
		:link(self._imageLink)&lt;br /&gt;
		:caption(self._imageCaption)&lt;br /&gt;
		:render()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Banner class&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local Banner = setmetatable({}, BannerTemplate)&lt;br /&gt;
Banner.__index = Banner&lt;br /&gt;
&lt;br /&gt;
function Banner.new(protectionObj, blurbObj, cfg)&lt;br /&gt;
	local obj = BannerTemplate.new(protectionObj, cfg) -- This doesn't need the blurb.&lt;br /&gt;
	obj:setImageWidth(40)&lt;br /&gt;
	obj:setImageTooltip(blurbObj:makeBannerText('alt')) -- Large banners use the alt text for the tooltip.&lt;br /&gt;
	obj._reasonText = blurbObj:makeBannerText('text')&lt;br /&gt;
	obj._explanationText = blurbObj:makeBannerText('explanation')&lt;br /&gt;
	obj._page = protectionObj.title.prefixedText -- Only makes a difference in testing.&lt;br /&gt;
	return setmetatable(obj, Banner)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Banner:__tostring()&lt;br /&gt;
	-- Renders the banner.&lt;br /&gt;
	makeMessageBox = makeMessageBox or require('Module:Message box').main&lt;br /&gt;
	local reasonText = self._reasonText or error('no reason text set')&lt;br /&gt;
	local explanationText = self._explanationText&lt;br /&gt;
	local mbargs = {&lt;br /&gt;
		page = self._page,&lt;br /&gt;
		type = 'protection',&lt;br /&gt;
		image = self:renderImage(),&lt;br /&gt;
		text = string.format(&lt;br /&gt;
			&amp;quot;'''%s'''%s&amp;quot;,&lt;br /&gt;
			reasonText,&lt;br /&gt;
			explanationText and '&amp;lt;br /&amp;gt;' .. explanationText or ''&lt;br /&gt;
		)&lt;br /&gt;
	}&lt;br /&gt;
	return makeMessageBox('mbox', mbargs)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Padlock class&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local Padlock = setmetatable({}, BannerTemplate)&lt;br /&gt;
Padlock.__index = Padlock&lt;br /&gt;
&lt;br /&gt;
function Padlock.new(protectionObj, blurbObj, cfg)&lt;br /&gt;
	local obj = BannerTemplate.new(protectionObj, cfg) -- This doesn't need the blurb.&lt;br /&gt;
	obj:setImageWidth(20)&lt;br /&gt;
	obj:setImageTooltip(blurbObj:makeBannerText('tooltip'))&lt;br /&gt;
	obj._imageAlt = blurbObj:makeBannerText('alt')&lt;br /&gt;
	obj._imageLink = blurbObj:makeBannerText('link')&lt;br /&gt;
	obj._right = cfg.padlockPositions[protectionObj.action]&lt;br /&gt;
		or cfg.padlockPositions.default&lt;br /&gt;
		or '55px'&lt;br /&gt;
	return setmetatable(obj, Padlock)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Padlock:__tostring()&lt;br /&gt;
	local root = mw.html.create('div')&lt;br /&gt;
	root&lt;br /&gt;
		:addClass('metadata topicon nopopups')&lt;br /&gt;
		:attr('id', 'protected-icon')&lt;br /&gt;
		:css{display = 'none', right = self._right}&lt;br /&gt;
		:wikitext(self:renderImage())&lt;br /&gt;
	return tostring(root)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Exports&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
function p._exportClasses()&lt;br /&gt;
	-- This is used for testing purposes.&lt;br /&gt;
	return {&lt;br /&gt;
		Protection = Protection,&lt;br /&gt;
		Blurb = Blurb,&lt;br /&gt;
		BannerTemplate = BannerTemplate,&lt;br /&gt;
		Banner = Banner,&lt;br /&gt;
		Padlock = Padlock,&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._main(args, cfg, title)&lt;br /&gt;
	args = args or {}&lt;br /&gt;
	cfg = cfg or require('Module:Protection banner/config')&lt;br /&gt;
&lt;br /&gt;
	-- Initialise the protection object and check for errors&lt;br /&gt;
	local protectionObjCreated, protectionObj = pcall(&lt;br /&gt;
		Protection.new,&lt;br /&gt;
		args,&lt;br /&gt;
		cfg,&lt;br /&gt;
		title&lt;br /&gt;
	)&lt;br /&gt;
	if not protectionObjCreated then&lt;br /&gt;
		local errorBlurb = cfg.msg['error-message-blurb'] or 'Error: $1.'&lt;br /&gt;
		local errorText = mw.message.newRawMessage(errorBlurb)&lt;br /&gt;
			:params(protectionObj) -- protectionObj is the error message&lt;br /&gt;
			:plain()&lt;br /&gt;
		return string.format(&lt;br /&gt;
			'&amp;lt;strong class=&amp;quot;error&amp;quot;&amp;gt;%s&amp;lt;/strong&amp;gt;%s',&lt;br /&gt;
			errorText,&lt;br /&gt;
			makeCategoryLink(&lt;br /&gt;
				cfg.msg['tracking-category-incorrect'],&lt;br /&gt;
				title and title.text or mw.title.getCurrentTitle().text&lt;br /&gt;
			)&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Initialise the blurb object&lt;br /&gt;
	local blurbObj = Blurb.new(protectionObj, args, cfg)&lt;br /&gt;
&lt;br /&gt;
	local ret = {}&lt;br /&gt;
&lt;br /&gt;
	-- Render the banner&lt;br /&gt;
	if protectionObj:isProtected() then&lt;br /&gt;
		ret[#ret + 1] = tostring(&lt;br /&gt;
			(yesno(args.small) and Padlock or Banner)&lt;br /&gt;
			.new(protectionObj, blurbObj, cfg)&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Render the categories&lt;br /&gt;
	if yesno(args.category) ~= false then&lt;br /&gt;
		ret[#ret + 1] = protectionObj:makeCategoryLinks()&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return table.concat(ret)	&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main(frame, cfg)&lt;br /&gt;
	cfg = cfg or require(CONFIG_MODULE)&lt;br /&gt;
&lt;br /&gt;
	-- Find default args, if any.&lt;br /&gt;
	local parentTitle = frame:getParent():getTitle()&lt;br /&gt;
	parentTitle = parentTitle:gsub('/sandbox$', '')&lt;br /&gt;
	local defaultArgs = cfg.wrappers[parentTitle] or {}&lt;br /&gt;
&lt;br /&gt;
	-- Find user args, and use the parent frame if we are being called from a&lt;br /&gt;
	-- wrapper template.&lt;br /&gt;
	getArgs = getArgs or require('Module:Arguments').getArgs&lt;br /&gt;
	local userArgs = getArgs(frame, {&lt;br /&gt;
		parentOnly = defaultArgs,&lt;br /&gt;
		frameOnly = not defaultArgs&lt;br /&gt;
	})&lt;br /&gt;
&lt;br /&gt;
	-- Build the args table. User-specified args overwrite default args.&lt;br /&gt;
	local args = {}&lt;br /&gt;
	for k, v in pairs(defaultArgs) do&lt;br /&gt;
		args[k] = v&lt;br /&gt;
	end&lt;br /&gt;
	for k, v in pairs(userArgs) do&lt;br /&gt;
		args[k] = v&lt;br /&gt;
	end&lt;br /&gt;
	return p._main(args, cfg)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Template:Pp-template</id>
		<title>Template:Pp-template</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Template:Pp-template"/>
				<updated>2014-08-05T17:17:27Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: convert this to use Module:Protection banner; see here for details&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{#invoke:Protection banner|main}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;!-- Categories go on the /doc subpage, and interwikis go on Wikidata. --&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Module:Category_handler</id>
		<title>Module:Category handler</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Module:Category_handler"/>
				<updated>2014-07-22T05:08:26Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: allow invocations specifying the page parameter to use the mw.loadData optimisations, and don't call mw.title.new every time&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--------------------------------------------------------------------------------&lt;br /&gt;
--                                                                            --&lt;br /&gt;
--                              CATEGORY HANDLER                              --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
--      This module implements the {{category handler}} template in Lua,      --&lt;br /&gt;
--      with a few improvements: all namespaces and all namespace aliases     --&lt;br /&gt;
--      are supported, and namespace names are detected automatically for     --&lt;br /&gt;
--      the local wiki. This module requires [[Module:Namespace detect]]      --&lt;br /&gt;
--      and [[Module:Yesno]] to be available on the local wiki. It can be     --&lt;br /&gt;
--      configured for different wikis by altering the values in              --&lt;br /&gt;
--      [[Module:Category handler/config]], and pages can be blacklisted      --&lt;br /&gt;
--      from categorisation by using [[Module:Category handler/blacklist]].   --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- Load required modules&lt;br /&gt;
local yesno = require('Module:Yesno')&lt;br /&gt;
&lt;br /&gt;
-- Lazily load things we don't always need&lt;br /&gt;
local mShared, mappings&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Helper functions&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function trimWhitespace(s, removeBlanks)&lt;br /&gt;
	if type(s) ~= 'string' then&lt;br /&gt;
		return s&lt;br /&gt;
	end&lt;br /&gt;
	s = s:match('^%s*(.-)%s*$')&lt;br /&gt;
	if removeBlanks then&lt;br /&gt;
		if s ~= '' then&lt;br /&gt;
			return s&lt;br /&gt;
		else&lt;br /&gt;
			return nil&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		return s&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- CategoryHandler class&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local CategoryHandler = {}&lt;br /&gt;
CategoryHandler.__index = CategoryHandler&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler.new(data, args)&lt;br /&gt;
	local obj = setmetatable({ _data = data, _args = args }, CategoryHandler)&lt;br /&gt;
	&lt;br /&gt;
	-- Set the title object&lt;br /&gt;
	do&lt;br /&gt;
		local pagename = obj:parameter('demopage')&lt;br /&gt;
		local success, titleObj&lt;br /&gt;
		if pagename then&lt;br /&gt;
			success, titleObj = pcall(mw.title.new, pagename)&lt;br /&gt;
		end&lt;br /&gt;
		if success and titleObj then&lt;br /&gt;
			obj.title = titleObj&lt;br /&gt;
			if titleObj == mw.title.getCurrentTitle() then&lt;br /&gt;
				obj._usesCurrentTitle = true&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			obj.title = mw.title.getCurrentTitle()&lt;br /&gt;
			obj._usesCurrentTitle = true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Set suppression parameter values&lt;br /&gt;
	for _, key in ipairs{'nocat', 'categories'} do&lt;br /&gt;
		local value = obj:parameter(key)&lt;br /&gt;
		value = trimWhitespace(value, true)&lt;br /&gt;
		obj['_' .. key] = yesno(value)&lt;br /&gt;
	end&lt;br /&gt;
	do&lt;br /&gt;
		local subpage = obj:parameter('subpage')&lt;br /&gt;
		local category2 = obj:parameter('category2')&lt;br /&gt;
		if type(subpage) == 'string' then&lt;br /&gt;
			subpage = mw.ustring.lower(subpage)&lt;br /&gt;
		end&lt;br /&gt;
		if type(category2) == 'string' then&lt;br /&gt;
			subpage = mw.ustring.lower(category2)&lt;br /&gt;
		end&lt;br /&gt;
		obj._subpage = trimWhitespace(subpage, true)&lt;br /&gt;
		obj._category2 = trimWhitespace(category2) -- don't remove blank values&lt;br /&gt;
	end&lt;br /&gt;
	return obj&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler:parameter(key)&lt;br /&gt;
	local parameterNames = self._data.parameters[key]&lt;br /&gt;
	local pntype = type(parameterNames)&lt;br /&gt;
	if pntype == 'string' or pntype == 'number' then&lt;br /&gt;
		return self._args[parameterNames]&lt;br /&gt;
	elseif pntype == 'table' then&lt;br /&gt;
		for _, name in ipairs(parameterNames) do&lt;br /&gt;
			local value = self._args[name]&lt;br /&gt;
			if value ~= nil then&lt;br /&gt;
				return value&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		return nil&lt;br /&gt;
	else&lt;br /&gt;
		error(string.format(&lt;br /&gt;
			'invalid config key &amp;quot;%s&amp;quot;',&lt;br /&gt;
			tostring(key)&lt;br /&gt;
		), 2)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler:isSuppressedByArguments()&lt;br /&gt;
	return&lt;br /&gt;
		-- See if a category suppression argument has been set.&lt;br /&gt;
		self._nocat == true&lt;br /&gt;
		or self._categories == false&lt;br /&gt;
		or (&lt;br /&gt;
			self._category2&lt;br /&gt;
			and self._category2 ~= self._data.category2Yes&lt;br /&gt;
			and self._category2 ~= self._data.category2Negative&lt;br /&gt;
		)&lt;br /&gt;
&lt;br /&gt;
		-- Check whether we are on a subpage, and see if categories are&lt;br /&gt;
		-- suppressed based on our subpage status.&lt;br /&gt;
		or self._subpage == self._data.subpageNo and self.title.isSubpage&lt;br /&gt;
		or self._subpage == self._data.subpageOnly and not self.title.isSubpage&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler:shouldSkipBlacklistCheck()&lt;br /&gt;
	-- Check whether the category suppression arguments indicate we&lt;br /&gt;
	-- should skip the blacklist check.&lt;br /&gt;
	return self._nocat == false&lt;br /&gt;
		or self._categories == true&lt;br /&gt;
		or self._category2 == self._data.category2Yes&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler:matchesBlacklist()&lt;br /&gt;
	if self._usesCurrentTitle then&lt;br /&gt;
		return self._data.currentTitleMatchesBlacklist&lt;br /&gt;
	else&lt;br /&gt;
		mShared = mShared or require('Module:Category handler/shared')&lt;br /&gt;
		return mShared.matchesBlacklist(&lt;br /&gt;
			self.title.prefixedText,&lt;br /&gt;
			mw.loadData('Module:Category handler/blacklist')&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler:isSuppressed()&lt;br /&gt;
	-- Find if categories are suppressed by either the arguments or by&lt;br /&gt;
	-- matching the blacklist.&lt;br /&gt;
	return self:isSuppressedByArguments()&lt;br /&gt;
		or not self:shouldSkipBlacklistCheck() and self:matchesBlacklist()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler:getNamespaceParameters()&lt;br /&gt;
	if self._usesCurrentTitle then&lt;br /&gt;
		return self._data.currentTitleNamespaceParameters&lt;br /&gt;
	else&lt;br /&gt;
		if not mappings then&lt;br /&gt;
			mShared = mShared or require('Module:Category handler/shared')&lt;br /&gt;
			mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData&lt;br /&gt;
		end&lt;br /&gt;
		return mShared.getNamespaceParameters(&lt;br /&gt;
			self.title,&lt;br /&gt;
			mappings&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler:namespaceParametersExist()&lt;br /&gt;
	-- Find whether any namespace parameters have been specified.&lt;br /&gt;
	-- We use the order &amp;quot;all&amp;quot; --&amp;gt; namespace params --&amp;gt; &amp;quot;other&amp;quot; as this is what&lt;br /&gt;
	-- the old template did.&lt;br /&gt;
	if self:parameter('all') then&lt;br /&gt;
		return true&lt;br /&gt;
	end&lt;br /&gt;
	if not mappings then&lt;br /&gt;
		mShared = mShared or require('Module:Category handler/shared')&lt;br /&gt;
		mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData&lt;br /&gt;
	end&lt;br /&gt;
	for ns, params in pairs(mappings) do&lt;br /&gt;
		for i, param in ipairs(params) do&lt;br /&gt;
			if self._args[param] then&lt;br /&gt;
				return true&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if self:parameter('other') then&lt;br /&gt;
		return true&lt;br /&gt;
	end&lt;br /&gt;
	return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler:getCategories()&lt;br /&gt;
	local params = self:getNamespaceParameters()&lt;br /&gt;
	local nsCategory&lt;br /&gt;
	for i, param in ipairs(params) do&lt;br /&gt;
		local value = self._args[param]&lt;br /&gt;
		if value ~= nil then&lt;br /&gt;
			nsCategory = value&lt;br /&gt;
			break&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if nsCategory ~= nil or self:namespaceParametersExist() then&lt;br /&gt;
		-- Namespace parameters exist - advanced usage.&lt;br /&gt;
		if nsCategory == nil then&lt;br /&gt;
			nsCategory = self:parameter('other')&lt;br /&gt;
		end&lt;br /&gt;
		local ret = {self:parameter('all')}&lt;br /&gt;
		local numParam = tonumber(nsCategory)&lt;br /&gt;
		if numParam and numParam &amp;gt;= 1 and math.floor(numParam) == numParam then&lt;br /&gt;
			-- nsCategory is an integer&lt;br /&gt;
			ret[#ret + 1] = self._args[numParam]&lt;br /&gt;
		else&lt;br /&gt;
			ret[#ret + 1] = nsCategory&lt;br /&gt;
		end&lt;br /&gt;
		if #ret &amp;lt; 1 then&lt;br /&gt;
			return nil&lt;br /&gt;
		else&lt;br /&gt;
			return table.concat(ret)&lt;br /&gt;
		end&lt;br /&gt;
	elseif self._data.defaultNamespaces[self.title.namespace] then&lt;br /&gt;
		-- Namespace parameters don't exist, simple usage.&lt;br /&gt;
		return self._args[1]&lt;br /&gt;
	end&lt;br /&gt;
	return nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Exports&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
function p._exportClasses()&lt;br /&gt;
	-- Used for testing purposes.&lt;br /&gt;
	return {&lt;br /&gt;
		CategoryHandler = CategoryHandler&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._main(args, data)&lt;br /&gt;
	data = data or mw.loadData('Module:Category handler/data')&lt;br /&gt;
	local handler = CategoryHandler.new(data, args)&lt;br /&gt;
	if handler:isSuppressed() then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	return handler:getCategories()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main(frame, data)&lt;br /&gt;
	data = data or mw.loadData('Module:Category handler/data')&lt;br /&gt;
	local args = require('Module:Arguments').getArgs(frame, {&lt;br /&gt;
		wrappers = data.wrappers,&lt;br /&gt;
		valueFunc = function (k, v)&lt;br /&gt;
			v = trimWhitespace(v)&lt;br /&gt;
			if type(k) == 'number' then&lt;br /&gt;
				if v ~= '' then&lt;br /&gt;
					return v&lt;br /&gt;
				else&lt;br /&gt;
					return nil&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				return v&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	})&lt;br /&gt;
	return p._main(args, data)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Module:Category_handler/blacklist</id>
		<title>Module:Category handler/blacklist</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Module:Category_handler/blacklist"/>
				<updated>2014-07-13T09:07:09Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: Protected Module:Category handler/blacklist: High-risk Lua module ([Edit=Allow only template editors and admins] (indefinite) [Move=Allow only template editors and admins] (indefinite))&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module contains the blacklist used by [[Module:Category handler]].&lt;br /&gt;
-- Pages that match Lua patterns in this list will not be categorised unless&lt;br /&gt;
-- categorisation is explicitly requested.&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
    '^Main Page$', -- don't categorise the main page.&lt;br /&gt;
 &lt;br /&gt;
    -- Don't categorise the following pages or their subpages.&lt;br /&gt;
    -- &amp;quot;%f[/\0]&amp;quot; matches if the next character is &amp;quot;/&amp;quot; or the end of the string.&lt;br /&gt;
    '^Wikipedia:Cascade%-protected items%f[/\0]',&lt;br /&gt;
    '^User:UBX%f[/\0]', -- The userbox &amp;quot;template&amp;quot; space.&lt;br /&gt;
    '^User talk:UBX%f[/\0]',&lt;br /&gt;
 &lt;br /&gt;
    -- Don't categorise subpages of these pages, but allow&lt;br /&gt;
    -- categorisation of the base page.&lt;br /&gt;
    '^Wikipedia:Template messages/.*$',&lt;br /&gt;
 &lt;br /&gt;
    '/[aA]rchive' -- Don't categorise archives.&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Module:Category_handler/shared</id>
		<title>Module:Category handler/shared</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Module:Category_handler/shared"/>
				<updated>2014-07-13T09:06:15Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: Protected Module:Category handler/shared: High-risk Lua module ([Edit=Allow only template editors and admins] (indefinite) [Move=Allow only template editors and admins] (indefinite))&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module contains shared functions used by [[Module:Category handler]]&lt;br /&gt;
-- and its submodules.&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
function p.matchesBlacklist(page, blacklist)&lt;br /&gt;
	for i, pattern in ipairs(blacklist) do&lt;br /&gt;
		local match = mw.ustring.match(page, pattern)&lt;br /&gt;
		if match then&lt;br /&gt;
			return true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.getParamMappings(useLoadData)&lt;br /&gt;
	local dataPage = 'Module:Namespace detect/data'&lt;br /&gt;
	if useLoadData then&lt;br /&gt;
		return mw.loadData(dataPage).mappings&lt;br /&gt;
	else&lt;br /&gt;
		return require(dataPage).mappings&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.getNamespaceParameters(titleObj, mappings)&lt;br /&gt;
	-- We don't use title.nsText for the namespace name because it adds&lt;br /&gt;
	-- underscores.&lt;br /&gt;
	local mappingsKey&lt;br /&gt;
	if titleObj.isTalkPage then&lt;br /&gt;
		mappingsKey = 'talk'&lt;br /&gt;
	else&lt;br /&gt;
		mappingsKey = mw.site.namespaces[titleObj.namespace].name&lt;br /&gt;
	end&lt;br /&gt;
	mappingsKey = mw.ustring.lower(mappingsKey)&lt;br /&gt;
	return mappings[mappingsKey] or {}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Module:Category_handler/data</id>
		<title>Module:Category handler/data</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Module:Category_handler/data"/>
				<updated>2014-07-13T09:05:55Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: Protected Module:Category handler/data: High-risk Lua module ([Edit=Allow only template editors and admins] (indefinite) [Move=Allow only template editors and admins] (indefinite))&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module assembles data to be passed to [[Module:Category handler]] using&lt;br /&gt;
-- mw.loadData. This includes the configuration data and whether the current&lt;br /&gt;
-- page matches the title blacklist.&lt;br /&gt;
&lt;br /&gt;
local data = require('Module:Category handler/config')&lt;br /&gt;
local mShared = require('Module:Category handler/shared')&lt;br /&gt;
local blacklist = require('Module:Category handler/blacklist')&lt;br /&gt;
local title = mw.title.getCurrentTitle()&lt;br /&gt;
&lt;br /&gt;
data.currentTitleMatchesBlacklist = mShared.matchesBlacklist(&lt;br /&gt;
	title.prefixedText,&lt;br /&gt;
	blacklist&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
data.currentTitleNamespaceParameters = mShared.getNamespaceParameters(&lt;br /&gt;
	title,&lt;br /&gt;
	mShared.getParamMappings()&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
return data&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Module:Category_handler/config</id>
		<title>Module:Category handler/config</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Module:Category_handler/config"/>
				<updated>2014-07-13T09:05:36Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: Protected Module:Category handler/config: High-risk Lua module ([Edit=Allow only template editors and admins] (indefinite) [Move=Allow only template editors and admins] (indefinite))&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--------------------------------------------------------------------------------&lt;br /&gt;
--            [[Module:Category handler]] configuration data                  --&lt;br /&gt;
--       Language-specific parameter names and values can be set here.        --&lt;br /&gt;
--       For blacklist config, see [[Module:Category handler/blacklist]].     --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local cfg = {} -- Don't edit this line.&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--                       Start configuration data                             --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--                              Parameter names                               --&lt;br /&gt;
-- These configuration items specify custom parameter names.                  --&lt;br /&gt;
-- To add one extra name, you can use this format:                            --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
-- foo = 'parameter name',                                                    --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
-- To add multiple names, you can use this format:                            --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
-- foo = {'parameter name 1', 'parameter name 2', 'parameter name 3'},        --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
cfg.parameters = {&lt;br /&gt;
	&lt;br /&gt;
	-- The nocat and categories parameter suppress&lt;br /&gt;
	-- categorisation. They are used with Module:Yesno, and work as follows:&lt;br /&gt;
	--&lt;br /&gt;
	-- cfg.nocat:&lt;br /&gt;
	-- Result of yesno()                        Effect&lt;br /&gt;
	-- true                                     Categorisation is suppressed&lt;br /&gt;
	-- false                                    Categorisation is allowed, and&lt;br /&gt;
	--                                          the blacklist check is skipped&lt;br /&gt;
	-- nil                                      Categorisation is allowed&lt;br /&gt;
	--&lt;br /&gt;
	-- cfg.categories:&lt;br /&gt;
	-- Result of yesno()                        Effect&lt;br /&gt;
	-- true                                     Categorisation is allowed, and&lt;br /&gt;
	--                                          the blacklist check is skipped&lt;br /&gt;
	-- false                                    Categorisation is suppressed&lt;br /&gt;
	-- nil                                      Categorisation is allowed&lt;br /&gt;
	nocat = 'nocat',&lt;br /&gt;
	categories = 'categories',&lt;br /&gt;
	&lt;br /&gt;
	-- The parameter name for the legacy &amp;quot;category2&amp;quot; parameter. This skips the&lt;br /&gt;
	-- blacklist if set to the cfg.category2Yes value, and suppresses&lt;br /&gt;
	-- categorisation if present but equal to anything other than&lt;br /&gt;
	-- cfg.category2Yes or cfg.category2Negative.&lt;br /&gt;
	category2 = 'category2',&lt;br /&gt;
	&lt;br /&gt;
	-- cfg.subpage is the parameter name to specify how to behave on subpages.&lt;br /&gt;
	subpage = 'subpage',&lt;br /&gt;
	&lt;br /&gt;
	-- The parameter for data to return in all namespaces.&lt;br /&gt;
	all = 'all',&lt;br /&gt;
	&lt;br /&gt;
	-- The parameter name for data to return if no data is specified for the&lt;br /&gt;
	-- namespace that is detected.&lt;br /&gt;
	other = 'other',&lt;br /&gt;
	&lt;br /&gt;
	-- The parameter name used to specify a page other than the current page;&lt;br /&gt;
	-- used for testing and demonstration.&lt;br /&gt;
	demopage = 'page',&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--                              Parameter values                              --&lt;br /&gt;
-- These are set values that can be used with certain parameters. Only one    --&lt;br /&gt;
-- value can be specified, like this:                                         --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
-- cfg.foo = 'value name'                                                     --                                               --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- The following settings are used with the cfg.category2 parameter. Setting&lt;br /&gt;
-- cfg.category2 to cfg.category2Yes skips the blacklist, and if cfg.category2&lt;br /&gt;
-- is present but equal to anything other than cfg.category2Yes or&lt;br /&gt;
-- cfg.category2Negative then it supresses cateogrisation.&lt;br /&gt;
cfg.category2Yes = 'yes'&lt;br /&gt;
cfg.category2Negative = '¬'&lt;br /&gt;
&lt;br /&gt;
-- The following settings are used with the cfg.subpage parameter.&lt;br /&gt;
-- cfg.subpageNo is the value to specify to not categorise on subpages;&lt;br /&gt;
-- cfg.subpageOnly is the value to specify to only categorise on subpages.&lt;br /&gt;
cfg.subpageNo = 'no'&lt;br /&gt;
cfg.subpageOnly = 'only'&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--                           Default namespaces                               --&lt;br /&gt;
-- This is a table of namespaces to categorise by default. The keys are the   --&lt;br /&gt;
-- namespace numbers.                                                         --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
cfg.defaultNamespaces = {&lt;br /&gt;
	[  0] = true, -- main&lt;br /&gt;
	[  6] = true, -- file&lt;br /&gt;
	[ 12] = true, -- help&lt;br /&gt;
	[ 14] = true, -- category&lt;br /&gt;
	[100] = true, -- portal&lt;br /&gt;
	[108] = true, -- book&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--                                Wrappers                                    --&lt;br /&gt;
-- This is a wrapper template or a list of wrapper templates to be passed to  --&lt;br /&gt;
-- [[Module:Arguments]].                                                      --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
cfg.wrappers = 'Template:Category handler'&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--                           End configuration data                           --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
return cfg -- Don't edit this line.&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Module:Arguments</id>
		<title>Module:Arguments</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Module:Arguments"/>
				<updated>2014-07-05T03:52:56Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: allow using both the frame and parent frame arguments with the wrappers option if specifically requested, per protected edit request by User:Jackmcbarn&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module provides easy processing of arguments passed to Scribunto from&lt;br /&gt;
-- #invoke. It is intended for use by other Lua modules, and should not be&lt;br /&gt;
-- called from #invoke directly.&lt;br /&gt;
&lt;br /&gt;
local libraryUtil = require('libraryUtil')&lt;br /&gt;
local checkType = libraryUtil.checkType&lt;br /&gt;
&lt;br /&gt;
local arguments = {}&lt;br /&gt;
&lt;br /&gt;
-- Generate four different tidyVal functions, so that we don't have to check the&lt;br /&gt;
-- options every time we call it.&lt;br /&gt;
&lt;br /&gt;
local function tidyValDefault(key, val)&lt;br /&gt;
	if type(val) == 'string' then&lt;br /&gt;
		val = val:match('^%s*(.-)%s*$')&lt;br /&gt;
		if val == '' then&lt;br /&gt;
			return nil&lt;br /&gt;
		else&lt;br /&gt;
			return val&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		return val&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function tidyValTrimOnly(key, val)&lt;br /&gt;
	if type(val) == 'string' then&lt;br /&gt;
		return val:match('^%s*(.-)%s*$')&lt;br /&gt;
	else&lt;br /&gt;
		return val&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function tidyValRemoveBlanksOnly(key, val)&lt;br /&gt;
	if type(val) == 'string' then&lt;br /&gt;
		if val:find('%S') then&lt;br /&gt;
			return val&lt;br /&gt;
		else&lt;br /&gt;
			return nil&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		return val&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function tidyValNoChange(key, val)&lt;br /&gt;
	return val&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function arguments.getArgs(frame, options)&lt;br /&gt;
	checkType('getArgs', 1, frame, 'table', true)&lt;br /&gt;
	checkType('getArgs', 2, options, 'table', true)&lt;br /&gt;
	frame = frame or {}&lt;br /&gt;
	options = options or {}&lt;br /&gt;
&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Get the argument tables. If we were passed a valid frame object, get the&lt;br /&gt;
	-- frame arguments (fargs) and the parent frame arguments (pargs), depending&lt;br /&gt;
	-- on the options set and on the parent frame's availability. If we weren't&lt;br /&gt;
	-- passed a valid frame object, we are being called from another Lua module&lt;br /&gt;
	-- or from the debug console, so assume that we were passed a table of args&lt;br /&gt;
	-- directly, and assign it to a new variable (luaArgs).&lt;br /&gt;
	--]]&lt;br /&gt;
	local fargs, pargs, luaArgs&lt;br /&gt;
	if type(frame.args) == 'table' and type(frame.getParent) == 'function' then&lt;br /&gt;
		if options.wrappers then&lt;br /&gt;
			--[[&lt;br /&gt;
			-- The wrappers option makes Module:Arguments look up arguments in&lt;br /&gt;
			-- either the frame argument table or the parent argument table, but&lt;br /&gt;
			-- not both. This means that users can use either the #invoke syntax&lt;br /&gt;
			-- or a wrapper template without the loss of performance associated&lt;br /&gt;
			-- with looking arguments up in both the frame and the parent frame.&lt;br /&gt;
			-- Module:Arguments will look up arguments in the parent frame&lt;br /&gt;
			-- if it finds the parent frame's title in options.wrapper;&lt;br /&gt;
			-- otherwise it will look up arguments in the frame object passed&lt;br /&gt;
			-- to getArgs.&lt;br /&gt;
			--]]&lt;br /&gt;
			local parent = frame:getParent()&lt;br /&gt;
			if not parent then&lt;br /&gt;
				fargs = frame.args&lt;br /&gt;
			else&lt;br /&gt;
				local title = parent:getTitle():gsub('/sandbox$', '')&lt;br /&gt;
				local found = false&lt;br /&gt;
				if type(options.wrappers) == 'table' then&lt;br /&gt;
					for _,v in pairs(options.wrappers) do&lt;br /&gt;
						if v == title then&lt;br /&gt;
							found = true&lt;br /&gt;
							break&lt;br /&gt;
						end&lt;br /&gt;
					end&lt;br /&gt;
				elseif options.wrappers == title then&lt;br /&gt;
					found = true&lt;br /&gt;
				end&lt;br /&gt;
				&lt;br /&gt;
				-- We test for false specifically here so that nil (the default) acts like true.&lt;br /&gt;
				if found or options.frameOnly == false then&lt;br /&gt;
					pargs = parent.args&lt;br /&gt;
				end&lt;br /&gt;
				if not found or options.parentOnly == false then&lt;br /&gt;
					fargs = frame.args&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			-- options.wrapper isn't set, so check the other options.&lt;br /&gt;
			if not options.parentOnly then&lt;br /&gt;
				fargs = frame.args&lt;br /&gt;
			end&lt;br /&gt;
			if not options.frameOnly then&lt;br /&gt;
				local parent = frame:getParent()&lt;br /&gt;
				pargs = parent and parent.args or nil&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if options.parentFirst then&lt;br /&gt;
			fargs, pargs = pargs, fargs&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		luaArgs = frame&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Set the order of precedence of the argument tables. If the variables are&lt;br /&gt;
	-- nil, nothing will be added to the table, which is how we avoid clashes&lt;br /&gt;
	-- between the frame/parent args and the Lua args.	&lt;br /&gt;
	local argTables = {fargs}&lt;br /&gt;
	argTables[#argTables + 1] = pargs&lt;br /&gt;
	argTables[#argTables + 1] = luaArgs&lt;br /&gt;
&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Generate the tidyVal function. If it has been specified by the user, we&lt;br /&gt;
	-- use that; if not, we choose one of four functions depending on the&lt;br /&gt;
	-- options chosen. This is so that we don't have to call the options table&lt;br /&gt;
	-- every time the function is called.&lt;br /&gt;
	--]]&lt;br /&gt;
	local tidyVal = options.valueFunc&lt;br /&gt;
	if tidyVal then&lt;br /&gt;
		if type(tidyVal) ~= 'function' then&lt;br /&gt;
			error(&lt;br /&gt;
				&amp;quot;bad value assigned to option 'valueFunc'&amp;quot;&lt;br /&gt;
					.. '(function expected, got '&lt;br /&gt;
					.. type(tidyVal)&lt;br /&gt;
					.. ')',&lt;br /&gt;
				2&lt;br /&gt;
			)&lt;br /&gt;
		end&lt;br /&gt;
	elseif options.trim ~= false then&lt;br /&gt;
		if options.removeBlanks ~= false then&lt;br /&gt;
			tidyVal = tidyValDefault&lt;br /&gt;
		else&lt;br /&gt;
			tidyVal = tidyValTrimOnly&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		if options.removeBlanks ~= false then&lt;br /&gt;
			tidyVal = tidyValRemoveBlanksOnly&lt;br /&gt;
		else&lt;br /&gt;
			tidyVal = tidyValNoChange&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Set up the args, metaArgs and nilArgs tables. args will be the one&lt;br /&gt;
	-- accessed from functions, and metaArgs will hold the actual arguments. Nil&lt;br /&gt;
	-- arguments are memoized in nilArgs, and the metatable connects all of them&lt;br /&gt;
	-- together.&lt;br /&gt;
	--]]&lt;br /&gt;
	local args, metaArgs, nilArgs, metatable = {}, {}, {}, {}&lt;br /&gt;
	setmetatable(args, metatable)&lt;br /&gt;
&lt;br /&gt;
	local function mergeArgs(iterator, tables)&lt;br /&gt;
		--[[&lt;br /&gt;
		-- Accepts multiple tables as input and merges their keys and values&lt;br /&gt;
		-- into one table using the specified iterator. If a value is already&lt;br /&gt;
		-- present it is not overwritten; tables listed earlier have precedence.&lt;br /&gt;
		-- We are also memoizing nil values, but those values can be&lt;br /&gt;
		-- overwritten.&lt;br /&gt;
		--]]&lt;br /&gt;
		for _, t in ipairs(tables) do&lt;br /&gt;
			for key, val in iterator(t) do&lt;br /&gt;
				if metaArgs[key] == nil then&lt;br /&gt;
					local tidiedVal = tidyVal(key, val)&lt;br /&gt;
					if tidiedVal == nil then&lt;br /&gt;
						nilArgs[key] = true&lt;br /&gt;
					else&lt;br /&gt;
						metaArgs[key] = tidiedVal&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Define metatable behaviour. Arguments are memoized in the metaArgs table,&lt;br /&gt;
	-- and are only fetched from the argument tables once. Fetching arguments&lt;br /&gt;
	-- from the argument tables is the most resource-intensive step in this&lt;br /&gt;
	-- module, so we try and avoid it where possible. For this reason, nil&lt;br /&gt;
	-- arguments are also memoized, in the nilArgs table. Also, we keep a record&lt;br /&gt;
	-- in the metatable of when pairs and ipairs have been called, so we do not&lt;br /&gt;
	-- run pairs and ipairs on the argument tables more than once. We also do&lt;br /&gt;
	-- not run ipairs on fargs and pargs if pairs has already been run, as all&lt;br /&gt;
	-- the arguments will already have been copied over.&lt;br /&gt;
	--]]&lt;br /&gt;
&lt;br /&gt;
	metatable.__index = function (t, key)&lt;br /&gt;
		--[[&lt;br /&gt;
		-- Fetches an argument when the args table is indexed. First we check&lt;br /&gt;
		-- to see if the value is memoized, and if not we try and fetch it from&lt;br /&gt;
		-- the argument tables. When we check memoization, we need to check&lt;br /&gt;
		-- metaArgs before nilArgs, as both can be non-nil at the same time.&lt;br /&gt;
		-- If the argument is not present in metaArgs, we also check whether&lt;br /&gt;
		-- pairs has been run yet. If pairs has already been run, we return nil.&lt;br /&gt;
		-- This is because all the arguments will have already been copied into&lt;br /&gt;
		-- metaArgs by the mergeArgs function, meaning that any other arguments&lt;br /&gt;
		-- must be nil.&lt;br /&gt;
		--]]&lt;br /&gt;
		local val = metaArgs[key]&lt;br /&gt;
		if val ~= nil then&lt;br /&gt;
			return val&lt;br /&gt;
		elseif metatable.donePairs or nilArgs[key] then&lt;br /&gt;
			return nil&lt;br /&gt;
		end&lt;br /&gt;
		for _, argTable in ipairs(argTables) do&lt;br /&gt;
			local argTableVal = tidyVal(key, argTable[key])&lt;br /&gt;
			if argTableVal == nil then&lt;br /&gt;
				nilArgs[key] = true&lt;br /&gt;
			else&lt;br /&gt;
				metaArgs[key] = argTableVal&lt;br /&gt;
				return argTableVal&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	metatable.__newindex = function (t, key, val)&lt;br /&gt;
		-- This function is called when a module tries to add a new value to the&lt;br /&gt;
		-- args table, or tries to change an existing value.&lt;br /&gt;
		if options.readOnly then&lt;br /&gt;
			error(&lt;br /&gt;
				'could not write to argument table key &amp;quot;'&lt;br /&gt;
					.. tostring(key)&lt;br /&gt;
					.. '&amp;quot;; the table is read-only',&lt;br /&gt;
				2&lt;br /&gt;
			)&lt;br /&gt;
		elseif options.noOverwrite and args[key] ~= nil then&lt;br /&gt;
			error(&lt;br /&gt;
				'could not write to argument table key &amp;quot;'&lt;br /&gt;
					.. tostring(key)&lt;br /&gt;
					.. '&amp;quot;; overwriting existing arguments is not permitted',&lt;br /&gt;
				2&lt;br /&gt;
			)&lt;br /&gt;
		elseif val == nil then&lt;br /&gt;
			--[[&lt;br /&gt;
			-- If the argument is to be overwritten with nil, we need to erase&lt;br /&gt;
			-- the value in metaArgs, so that __index, __pairs and __ipairs do&lt;br /&gt;
			-- not use a previous existing value, if present; and we also need&lt;br /&gt;
			-- to memoize the nil in nilArgs, so that the value isn't looked&lt;br /&gt;
			-- up in the argument tables if it is accessed again.&lt;br /&gt;
			--]]&lt;br /&gt;
			metaArgs[key] = nil&lt;br /&gt;
			nilArgs[key] = true&lt;br /&gt;
		else&lt;br /&gt;
			metaArgs[key] = val&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	metatable.__pairs = function ()&lt;br /&gt;
		-- Called when pairs is run on the args table.&lt;br /&gt;
		if not metatable.donePairs then&lt;br /&gt;
			mergeArgs(pairs, argTables)&lt;br /&gt;
			metatable.donePairs = true&lt;br /&gt;
			metatable.doneIpairs = true&lt;br /&gt;
		end&lt;br /&gt;
		return pairs(metaArgs)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	metatable.__ipairs = function ()&lt;br /&gt;
		-- Called when ipairs is run on the args table.&lt;br /&gt;
		if not metatable.doneIpairs then&lt;br /&gt;
			mergeArgs(ipairs, argTables)&lt;br /&gt;
			metatable.doneIpairs = true&lt;br /&gt;
		end&lt;br /&gt;
		return ipairs(metaArgs)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return args&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return arguments&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Module:Documentation</id>
		<title>Module:Documentation</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Module:Documentation"/>
				<updated>2014-07-04T14:26:55Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: Undid revision 615575005 by Technical 13 (talk) this puts the end box inside the main div, so we get one blue box inside another blue box; not really what we want&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module implements {{documentation}}.&lt;br /&gt;
&lt;br /&gt;
-- Get required modules.&lt;br /&gt;
local getArgs = require('Module:Arguments').getArgs&lt;br /&gt;
local htmlBuilder = require('Module:HtmlBuilder')&lt;br /&gt;
local messageBox = require('Module:Message box')&lt;br /&gt;
&lt;br /&gt;
-- Get the config table.&lt;br /&gt;
local cfg = mw.loadData('Module:Documentation/config')&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
-- Often-used functions.&lt;br /&gt;
local ugsub = mw.ustring.gsub&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
-- Helper functions&lt;br /&gt;
--&lt;br /&gt;
-- These are defined as local functions, but are made available in the p&lt;br /&gt;
-- table for testing purposes.&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function message(cfgKey, valArray, expectType)&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Gets a message from the cfg table and formats it if appropriate.&lt;br /&gt;
	-- The function raises an error if the value from the cfg table is not&lt;br /&gt;
	-- of the type expectType. The default type for expectType is 'string'.&lt;br /&gt;
	-- If the table valArray is present, strings such as $1, $2 etc. in the&lt;br /&gt;
	-- message are substituted with values from the table keys [1], [2] etc.&lt;br /&gt;
	-- For example, if the message &amp;quot;foo-message&amp;quot; had the value 'Foo $2 bar $1.',&lt;br /&gt;
	-- message('foo-message', {'baz', 'qux'}) would return &amp;quot;Foo qux bar baz.&amp;quot;&lt;br /&gt;
	--]]&lt;br /&gt;
	local msg = cfg[cfgKey]&lt;br /&gt;
	expectType = expectType or 'string'&lt;br /&gt;
	if type(msg) ~= expectType then&lt;br /&gt;
		error('message: type error in message cfg.' .. cfgKey .. ' (' .. expectType .. ' expected, got ' .. type(msg) .. ')', 2)&lt;br /&gt;
	end&lt;br /&gt;
	if not valArray then&lt;br /&gt;
		return msg&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local function getMessageVal(match)&lt;br /&gt;
		match = tonumber(match)&lt;br /&gt;
		return valArray[match] or error('message: no value found for key $' .. match .. ' in message cfg.' .. cfgKey, 4)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local ret = ugsub(msg, '$([1-9][0-9]*)', getMessageVal)&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
p.message = message&lt;br /&gt;
&lt;br /&gt;
local function makeWikilink(page, display)&lt;br /&gt;
	if display then&lt;br /&gt;
		return mw.ustring.format('[[%s|%s]]', page, display)&lt;br /&gt;
	else&lt;br /&gt;
		return mw.ustring.format('[[%s]]', page)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
p.makeWikilink = makeWikilink&lt;br /&gt;
&lt;br /&gt;
local function makeCategoryLink(cat, sort)&lt;br /&gt;
	local catns = mw.site.namespaces[14].name&lt;br /&gt;
	return makeWikilink(catns .. ':' .. cat, sort)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
p.makeCategoryLink = makeCategoryLink&lt;br /&gt;
&lt;br /&gt;
local function makeUrlLink(url, display)&lt;br /&gt;
	return mw.ustring.format('[%s %s]', url, display)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
p.makeUrlLink = makeUrlLink&lt;br /&gt;
&lt;br /&gt;
local function makeToolbar(...)&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	local lim = select('#', ...)&lt;br /&gt;
	if lim &amp;lt; 1 then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	for i = 1, lim do&lt;br /&gt;
		ret[#ret + 1] = select(i, ...)&lt;br /&gt;
	end&lt;br /&gt;
	return '&amp;lt;small style=&amp;quot;font-style: normal;&amp;quot;&amp;gt;(' .. table.concat(ret, ' &amp;amp;#124; ') .. ')&amp;lt;/small&amp;gt;'&lt;br /&gt;
end	&lt;br /&gt;
&lt;br /&gt;
p.makeToolbar = makeToolbar&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
-- Argument processing&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function makeInvokeFunc(funcName)&lt;br /&gt;
	return function (frame)&lt;br /&gt;
		local args = getArgs(frame, {&lt;br /&gt;
			valueFunc = function (key, value)&lt;br /&gt;
				if type(value) == 'string' then&lt;br /&gt;
					value = value:match('^%s*(.-)%s*$') -- Remove whitespace.&lt;br /&gt;
					if key == 'heading' or value ~= '' then&lt;br /&gt;
						return value&lt;br /&gt;
					else&lt;br /&gt;
						return nil&lt;br /&gt;
					end&lt;br /&gt;
				else&lt;br /&gt;
					return value&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		})&lt;br /&gt;
		return p[funcName](args)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
-- Main function&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
p.main = makeInvokeFunc('_main')&lt;br /&gt;
&lt;br /&gt;
function p._main(args)&lt;br /&gt;
	--[[&lt;br /&gt;
	-- This function defines logic flow for the module.&lt;br /&gt;
	-- @args - table of arguments passed by the user&lt;br /&gt;
	-- &lt;br /&gt;
	-- Messages:&lt;br /&gt;
	-- 'main-div-id' --&amp;gt; 'template-documentation'&lt;br /&gt;
	-- 'main-div-classes' --&amp;gt; 'template-documentation iezoomfix'&lt;br /&gt;
	--]]&lt;br /&gt;
	local env = p.getEnvironment(args)&lt;br /&gt;
	local root = htmlBuilder.create()&lt;br /&gt;
	root&lt;br /&gt;
		.wikitext(p.protectionTemplate(env))&lt;br /&gt;
		.wikitext(p.sandboxNotice(args, env))&lt;br /&gt;
		 -- This div tag is from {{documentation/start box}}, but moving it here&lt;br /&gt;
		 -- so that we don't have to worry about unclosed tags.&lt;br /&gt;
		.tag('div')&lt;br /&gt;
			.attr('id', message('main-div-id'))&lt;br /&gt;
			.addClass(message('main-div-classes'))&lt;br /&gt;
			.newline()&lt;br /&gt;
			.wikitext(p._startBox(args, env))&lt;br /&gt;
			.wikitext(p._content(args, env))&lt;br /&gt;
			.tag('div')&lt;br /&gt;
				.css('clear', 'both') -- So right or left floating items don't stick out of the doc box.&lt;br /&gt;
				.newline()&lt;br /&gt;
				.done()&lt;br /&gt;
			.done()&lt;br /&gt;
		.wikitext(p._endBox(args, env))&lt;br /&gt;
		.wikitext(p.addTrackingCategories(env))&lt;br /&gt;
	return tostring(root)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
-- Environment settings&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
function p.getEnvironment(args)&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Returns a table with information about the environment, including title objects and other namespace- or&lt;br /&gt;
	-- path-related data.&lt;br /&gt;
	-- @args - table of arguments passed by the user&lt;br /&gt;
	--&lt;br /&gt;
	-- Title objects include:&lt;br /&gt;
	-- env.title - the page we are making documentation for (usually the current title)&lt;br /&gt;
	-- env.templateTitle - the template (or module, file, etc.)&lt;br /&gt;
	-- env.docTitle - the /doc subpage.&lt;br /&gt;
	-- env.sandboxTitle - the /sandbox subpage.&lt;br /&gt;
	-- env.testcasesTitle - the /testcases subpage.&lt;br /&gt;
	-- env.printTitle - the print version of the template, located at the /Print subpage.&lt;br /&gt;
	--&lt;br /&gt;
	-- Data includes:&lt;br /&gt;
	-- env.protectionLevels - the protection levels table of the title object.&lt;br /&gt;
	-- env.subjectSpace - the number of the title's subject namespace.&lt;br /&gt;
	-- env.docSpace - the number of the namespace the title puts its documentation in.&lt;br /&gt;
	-- env.docpageBase - the text of the base page of the /doc, /sandbox and /testcases pages, with namespace.&lt;br /&gt;
	-- env.compareUrl - URL of the Special:ComparePages page comparing the sandbox with the template.&lt;br /&gt;
	-- &lt;br /&gt;
	-- All table lookups are passed through pcall so that errors are caught. If an error occurs, the value&lt;br /&gt;
	-- returned will be nil.&lt;br /&gt;
	--]]&lt;br /&gt;
	&lt;br /&gt;
	local env, envFuncs = {}, {}&lt;br /&gt;
&lt;br /&gt;
	-- Set up the metatable. If triggered we call the corresponding function in the envFuncs table. The value&lt;br /&gt;
	-- returned by that function is memoized in the env table so that we don't call any of the functions&lt;br /&gt;
	-- more than once. (Nils won't be memoized.)&lt;br /&gt;
	setmetatable(env, {&lt;br /&gt;
		__index = function (t, key)&lt;br /&gt;
			local envFunc = envFuncs[key]&lt;br /&gt;
			if envFunc then&lt;br /&gt;
				local success, val = pcall(envFunc)&lt;br /&gt;
				if success then&lt;br /&gt;
					env[key] = val -- Memoise the value.&lt;br /&gt;
					return val&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			return nil&lt;br /&gt;
		end&lt;br /&gt;
	})	&lt;br /&gt;
&lt;br /&gt;
	function envFuncs.title()&lt;br /&gt;
		-- The title object for the current page, or a test page passed with args.page.&lt;br /&gt;
		local title&lt;br /&gt;
		local titleArg = args.page&lt;br /&gt;
		if titleArg then&lt;br /&gt;
			title = mw.title.new(titleArg)&lt;br /&gt;
		else&lt;br /&gt;
			title = mw.title.getCurrentTitle()&lt;br /&gt;
		end&lt;br /&gt;
		return title&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	function envFuncs.templateTitle()&lt;br /&gt;
		--[[&lt;br /&gt;
		-- The template (or module, etc.) title object.&lt;br /&gt;
		-- Messages:&lt;br /&gt;
		-- 'sandbox-subpage' --&amp;gt; 'sandbox'&lt;br /&gt;
		-- 'testcases-subpage' --&amp;gt; 'testcases'&lt;br /&gt;
		--]]&lt;br /&gt;
		local subjectSpace = env.subjectSpace&lt;br /&gt;
		local title = env.title&lt;br /&gt;
		local subpage = title.subpageText&lt;br /&gt;
		if subpage == message('sandbox-subpage') or subpage == message('testcases-subpage') then&lt;br /&gt;
			return mw.title.makeTitle(subjectSpace, title.baseText)&lt;br /&gt;
		else&lt;br /&gt;
			return mw.title.makeTitle(subjectSpace, title.text)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	function envFuncs.docTitle()&lt;br /&gt;
		--[[&lt;br /&gt;
		-- Title object of the /doc subpage.&lt;br /&gt;
		-- Messages:&lt;br /&gt;
		-- 'doc-subpage' --&amp;gt; 'doc'&lt;br /&gt;
		--]]&lt;br /&gt;
		local title = env.title&lt;br /&gt;
		local docname = args[1] -- User-specified doc page.&lt;br /&gt;
		local docpage&lt;br /&gt;
		if docname then&lt;br /&gt;
			docpage = docname&lt;br /&gt;
		else&lt;br /&gt;
			docpage = env.docpageBase .. '/' .. message('doc-subpage')&lt;br /&gt;
		end&lt;br /&gt;
		return mw.title.new(docpage)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function envFuncs.sandboxTitle()&lt;br /&gt;
		--[[&lt;br /&gt;
		-- Title object for the /sandbox subpage.&lt;br /&gt;
		-- Messages:&lt;br /&gt;
		-- 'sandbox-subpage' --&amp;gt; 'sandbox'&lt;br /&gt;
		--]]&lt;br /&gt;
		return mw.title.new(env.docpageBase .. '/' .. message('sandbox-subpage'))&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function envFuncs.testcasesTitle()&lt;br /&gt;
		--[[&lt;br /&gt;
		-- Title object for the /testcases subpage.&lt;br /&gt;
		-- Messages:&lt;br /&gt;
		-- 'testcases-subpage' --&amp;gt; 'testcases'&lt;br /&gt;
		--]]&lt;br /&gt;
		return mw.title.new(env.docpageBase .. '/' .. message('testcases-subpage'))&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function envFuncs.printTitle()&lt;br /&gt;
		--[[&lt;br /&gt;
		-- Title object for the /Print subpage.&lt;br /&gt;
		-- Messages:&lt;br /&gt;
		-- 'print-subpage' --&amp;gt; 'Print'&lt;br /&gt;
		--]]&lt;br /&gt;
		return env.templateTitle:subPageTitle(message('print-subpage'))&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	function envFuncs.protectionLevels()&lt;br /&gt;
		-- The protection levels table of the title object.&lt;br /&gt;
		return env.title.protectionLevels&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	function envFuncs.subjectSpace()&lt;br /&gt;
		-- The subject namespace number.&lt;br /&gt;
		return mw.site.namespaces[env.title.namespace].subject.id&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	function envFuncs.docSpace()&lt;br /&gt;
		-- The documentation namespace number. For most namespaces this is the same as the&lt;br /&gt;
		-- subject namespace. However, pages in the Article, File, MediaWiki or Category&lt;br /&gt;
		-- namespaces must have their /doc, /sandbox and /testcases pages in talk space.&lt;br /&gt;
		local subjectSpace = env.subjectSpace&lt;br /&gt;
		if subjectSpace == 0 or subjectSpace == 6 or subjectSpace == 8 or subjectSpace == 14 then&lt;br /&gt;
			return subjectSpace + 1&lt;br /&gt;
		else&lt;br /&gt;
			return subjectSpace&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	function envFuncs.docpageBase()&lt;br /&gt;
		-- The base page of the /doc, /sandbox, and /testcases subpages.&lt;br /&gt;
		-- For some namespaces this is the talk page, rather than the template page.&lt;br /&gt;
		local templateTitle = env.templateTitle&lt;br /&gt;
		local docSpace = env.docSpace&lt;br /&gt;
		local docSpaceText = mw.site.namespaces[docSpace].name&lt;br /&gt;
		-- Assemble the link. docSpace is never the main namespace, so we can hardcode the colon.&lt;br /&gt;
		return docSpaceText .. ':' .. templateTitle.text&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function envFuncs.compareUrl()&lt;br /&gt;
		-- Diff link between the sandbox and the main template using [[Special:ComparePages]].&lt;br /&gt;
		local templateTitle = env.templateTitle&lt;br /&gt;
		local sandboxTitle = env.sandboxTitle&lt;br /&gt;
		if templateTitle.exists and sandboxTitle.exists then&lt;br /&gt;
			local compareUrl = mw.uri.fullUrl(&lt;br /&gt;
				'Special:ComparePages',&lt;br /&gt;
				{page1 = templateTitle.prefixedText, page2 = sandboxTitle.prefixedText}&lt;br /&gt;
			)&lt;br /&gt;
			return tostring(compareUrl)&lt;br /&gt;
		else&lt;br /&gt;
			return nil&lt;br /&gt;
		end&lt;br /&gt;
	end		&lt;br /&gt;
&lt;br /&gt;
	return env&lt;br /&gt;
end	&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
-- Auxiliary templates&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
function p.sandboxNotice(args, env)&lt;br /&gt;
	--[=[&lt;br /&gt;
	-- Generates a sandbox notice for display above sandbox pages.&lt;br /&gt;
	-- @args - a table of arguments passed by the user&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	-- &lt;br /&gt;
	-- Messages:&lt;br /&gt;
	-- 'sandbox-notice-image' --&amp;gt; '[[Image:Sandbox.svg|50px|alt=|link=]]'&lt;br /&gt;
	-- 'sandbox-notice-blurb' --&amp;gt; 'This is the $1 for $2.'&lt;br /&gt;
	-- 'sandbox-notice-diff-blurb' --&amp;gt; 'This is the $1 for $2 ($3).'&lt;br /&gt;
	-- 'sandbox-notice-pagetype-template' --&amp;gt; '[[Wikipedia:Template test cases|template sandbox]] page'&lt;br /&gt;
	-- 'sandbox-notice-pagetype-module' --&amp;gt; '[[Wikipedia:Template test cases|module sandbox]] page'&lt;br /&gt;
	-- 'sandbox-notice-pagetype-other' --&amp;gt; 'sandbox page'&lt;br /&gt;
	-- 'sandbox-notice-compare-link-display' --&amp;gt; 'diff'&lt;br /&gt;
	-- 'sandbox-notice-testcases-blurb' --&amp;gt; 'See also the companion subpage for $1.'&lt;br /&gt;
	-- 'sandbox-notice-testcases-link-display' --&amp;gt; 'test cases'&lt;br /&gt;
	-- 'sandbox-category' --&amp;gt; 'Template sandboxes'&lt;br /&gt;
	--]=]&lt;br /&gt;
	local title = env.title&lt;br /&gt;
	local sandboxTitle = env.sandboxTitle&lt;br /&gt;
	local templateTitle = env.templateTitle&lt;br /&gt;
	local subjectSpace = env.subjectSpace&lt;br /&gt;
	if not (subjectSpace and title and sandboxTitle and templateTitle and mw.title.equals(title, sandboxTitle)) then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	-- Build the table of arguments to pass to {{ombox}}. We need just two fields, &amp;quot;image&amp;quot; and &amp;quot;text&amp;quot;.&lt;br /&gt;
	local omargs = {}&lt;br /&gt;
	omargs.image = message('sandbox-notice-image')&lt;br /&gt;
	-- Get the text. We start with the opening blurb, which is something like&lt;br /&gt;
	-- &amp;quot;This is the template sandbox for [[Template:Foo]] (diff).&amp;quot;&lt;br /&gt;
	local text = ''&lt;br /&gt;
	local frame = mw.getCurrentFrame()&lt;br /&gt;
	local isPreviewing = frame:preprocess('{{REVISIONID}}') == '' -- True if the page is being previewed.&lt;br /&gt;
	local pagetype&lt;br /&gt;
	if subjectSpace == 10 then&lt;br /&gt;
		pagetype = message('sandbox-notice-pagetype-template')&lt;br /&gt;
	elseif subjectSpace == 828 then&lt;br /&gt;
		pagetype = message('sandbox-notice-pagetype-module')&lt;br /&gt;
	else&lt;br /&gt;
		pagetype = message('sandbox-notice-pagetype-other')&lt;br /&gt;
	end&lt;br /&gt;
	local templateLink = makeWikilink(templateTitle.prefixedText)&lt;br /&gt;
	local compareUrl = env.compareUrl&lt;br /&gt;
	if isPreviewing or not compareUrl then&lt;br /&gt;
		text = text .. message('sandbox-notice-blurb', {pagetype, templateLink})&lt;br /&gt;
	else&lt;br /&gt;
		local compareDisplay = message('sandbox-notice-compare-link-display')&lt;br /&gt;
		local compareLink = makeUrlLink(compareUrl, compareDisplay)&lt;br /&gt;
		text = text .. message('sandbox-notice-diff-blurb', {pagetype, templateLink, compareLink})&lt;br /&gt;
	end&lt;br /&gt;
	-- Get the test cases page blurb if the page exists. This is something like&lt;br /&gt;
	-- &amp;quot;See also the companion subpage for [[Template:Foo/testcases|test cases]].&amp;quot;&lt;br /&gt;
	local testcasesTitle = env.testcasesTitle&lt;br /&gt;
	if testcasesTitle and testcasesTitle.exists then&lt;br /&gt;
		if testcasesTitle.namespace == mw.site.namespaces.Module.id then&lt;br /&gt;
			local testcasesLinkDisplay = message('sandbox-notice-testcases-link-display')&lt;br /&gt;
			local testcasesRunLinkDisplay = message('sandbox-notice-testcases-run-link-display')&lt;br /&gt;
			local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)&lt;br /&gt;
			local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)&lt;br /&gt;
			text = text .. '&amp;lt;br /&amp;gt;' .. message('sandbox-notice-testcases-run-blurb', {testcasesLink, testcasesRunLink})&lt;br /&gt;
		else&lt;br /&gt;
			local testcasesLinkDisplay = message('sandbox-notice-testcases-link-display')&lt;br /&gt;
			local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)&lt;br /&gt;
			text = text .. '&amp;lt;br /&amp;gt;' .. message('sandbox-notice-testcases-blurb', {testcasesLink})&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	-- Add the sandbox to the sandbox category.&lt;br /&gt;
	text = text .. makeCategoryLink(message('sandbox-category'))&lt;br /&gt;
	omargs.text = text&lt;br /&gt;
	local ret = '&amp;lt;div style=&amp;quot;clear: both;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;'&lt;br /&gt;
	ret = ret .. messageBox.main('ombox', omargs)&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.protectionTemplate(env)&lt;br /&gt;
	-- Generates the padlock icon in the top right.&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	-- Messages:&lt;br /&gt;
	-- 'protection-template' --&amp;gt; 'pp-template'&lt;br /&gt;
	-- 'protection-template-args' --&amp;gt; {docusage = 'yes'}&lt;br /&gt;
	local title = env.title&lt;br /&gt;
	local protectionLevels&lt;br /&gt;
	local protectionTemplate = message('protection-template')&lt;br /&gt;
	local namespace = title.namespace&lt;br /&gt;
	if not (protectionTemplate and (namespace == 10 or namespace == 828)) then&lt;br /&gt;
		-- Don't display the protection template if we are not in the template or module namespaces.&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	protectionLevels = env.protectionLevels&lt;br /&gt;
	if not protectionLevels then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	local editLevels = protectionLevels.edit&lt;br /&gt;
	local moveLevels = protectionLevels.move&lt;br /&gt;
	if moveLevels and moveLevels[1] == 'sysop' or editLevels and editLevels[1] then&lt;br /&gt;
		-- The page is full-move protected, or full, template, or semi-protected.&lt;br /&gt;
		local frame = mw.getCurrentFrame()&lt;br /&gt;
		return frame:expandTemplate{title = protectionTemplate, args = message('protection-template-args', nil, 'table')}&lt;br /&gt;
	else&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
-- Start box&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
p.startBox = makeInvokeFunc('_startBox')&lt;br /&gt;
&lt;br /&gt;
function p._startBox(args, env)&lt;br /&gt;
	--[[&lt;br /&gt;
	-- This function generates the start box.&lt;br /&gt;
	-- @args - a table of arguments passed by the user&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	-- &lt;br /&gt;
	-- The actual work is done by p.makeStartBoxLinksData and p.renderStartBoxLinks which make&lt;br /&gt;
	-- the [view] [edit] [history] [purge] links, and by p.makeStartBoxData and p.renderStartBox&lt;br /&gt;
	-- which generate the box HTML.&lt;br /&gt;
	--]]&lt;br /&gt;
	env = env or p.getEnvironment(args)&lt;br /&gt;
	local links&lt;br /&gt;
	local content = args.content&lt;br /&gt;
	if not content then&lt;br /&gt;
		-- No need to include the links if the documentation is on the template page itself.&lt;br /&gt;
		local linksData = p.makeStartBoxLinksData(args, env)&lt;br /&gt;
		if linksData then&lt;br /&gt;
			links = p.renderStartBoxLinks(linksData)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	-- Generate the start box html.&lt;br /&gt;
	local data = p.makeStartBoxData(args, env, links)&lt;br /&gt;
	if data then&lt;br /&gt;
		return p.renderStartBox(data)&lt;br /&gt;
	else&lt;br /&gt;
		-- User specified no heading.&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.makeStartBoxLinksData(args, env)&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Does initial processing of data to make the [view] [edit] [history] [purge] links.&lt;br /&gt;
	-- @args - a table of arguments passed by the user&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	-- &lt;br /&gt;
	-- Messages:&lt;br /&gt;
	-- 'view-link-display' --&amp;gt; 'view'&lt;br /&gt;
	-- 'edit-link-display' --&amp;gt; 'edit'&lt;br /&gt;
	-- 'history-link-display' --&amp;gt; 'history'&lt;br /&gt;
	-- 'purge-link-display' --&amp;gt; 'purge'&lt;br /&gt;
	-- 'file-docpage-preload' --&amp;gt; 'Template:Documentation/preload-filespace'&lt;br /&gt;
	-- 'module-preload' --&amp;gt; 'Template:Documentation/preload-module-doc'&lt;br /&gt;
	-- 'docpage-preload' --&amp;gt; 'Template:Documentation/preload'&lt;br /&gt;
	-- 'create-link-display' --&amp;gt; 'create'&lt;br /&gt;
	--]]&lt;br /&gt;
	local subjectSpace = env.subjectSpace&lt;br /&gt;
	local title = env.title&lt;br /&gt;
	local docTitle = env.docTitle&lt;br /&gt;
	if not title or not docTitle then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local data = {}&lt;br /&gt;
	data.title = title&lt;br /&gt;
	data.docTitle = docTitle&lt;br /&gt;
	-- View, display, edit, and purge links if /doc exists.&lt;br /&gt;
	data.viewLinkDisplay = message('view-link-display')&lt;br /&gt;
	data.editLinkDisplay = message('edit-link-display')&lt;br /&gt;
	data.historyLinkDisplay = message('history-link-display')&lt;br /&gt;
	data.purgeLinkDisplay = message('purge-link-display')&lt;br /&gt;
	-- Create link if /doc doesn't exist.&lt;br /&gt;
	local preload = args.preload&lt;br /&gt;
	if not preload then&lt;br /&gt;
		if subjectSpace == 6 then -- File namespace&lt;br /&gt;
			preload = message('file-docpage-preload')&lt;br /&gt;
		elseif subjectSpace == 828 then -- Module namespace&lt;br /&gt;
			preload = message('module-preload')&lt;br /&gt;
		else&lt;br /&gt;
			preload = message('docpage-preload')&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	data.preload = preload&lt;br /&gt;
	data.createLinkDisplay = message('create-link-display')&lt;br /&gt;
	return data&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.renderStartBoxLinks(data)&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Generates the [view][edit][history][purge] or [create] links from the data table.&lt;br /&gt;
	-- @data - a table of data generated by p.makeStartBoxLinksData&lt;br /&gt;
	--]]&lt;br /&gt;
	&lt;br /&gt;
	local function escapeBrackets(s)&lt;br /&gt;
		-- Escapes square brackets with HTML entities.&lt;br /&gt;
		s = s:gsub('%[', '&amp;amp;#91;') -- Replace square brackets with HTML entities.&lt;br /&gt;
		s = s:gsub('%]', '&amp;amp;#93;')&lt;br /&gt;
		return s&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local ret&lt;br /&gt;
	local docTitle = data.docTitle&lt;br /&gt;
	local title = data.title&lt;br /&gt;
	if docTitle.exists then&lt;br /&gt;
		local viewLink = makeWikilink(docTitle.prefixedText, data.viewLinkDisplay)&lt;br /&gt;
		local editLink = makeUrlLink(docTitle:fullUrl{action = 'edit'}, data.editLinkDisplay)&lt;br /&gt;
		local historyLink = makeUrlLink(docTitle:fullUrl{action = 'history'}, data.historyLinkDisplay)&lt;br /&gt;
		local purgeLink = makeUrlLink(title:fullUrl{action = 'purge'}, data.purgeLinkDisplay)&lt;br /&gt;
		ret = '[%s] [%s] [%s] [%s]'&lt;br /&gt;
		ret = escapeBrackets(ret)&lt;br /&gt;
		ret = mw.ustring.format(ret, viewLink, editLink, historyLink, purgeLink)&lt;br /&gt;
	else&lt;br /&gt;
		local createLink = makeUrlLink(docTitle:fullUrl{action = 'edit', preload = data.preload}, data.createLinkDisplay)&lt;br /&gt;
		ret = '[%s]'&lt;br /&gt;
		ret = escapeBrackets(ret)&lt;br /&gt;
		ret = mw.ustring.format(ret, createLink)&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.makeStartBoxData(args, env, links)&lt;br /&gt;
	--[=[&lt;br /&gt;
	-- Does initial processing of data to pass to the start-box render function, p.renderStartBox.&lt;br /&gt;
	-- @args - a table of arguments passed by the user&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	-- @links - a string containing the [view][edit][history][purge] links - could be nil if there's an error.&lt;br /&gt;
	--&lt;br /&gt;
	-- Messages:&lt;br /&gt;
	-- 'documentation-icon-wikitext' --&amp;gt; '[[File:Test Template Info-Icon - Version (2).svg|50px|link=|alt=Documentation icon]]'&lt;br /&gt;
	-- 'template-namespace-heading' --&amp;gt; 'Template documentation'&lt;br /&gt;
	-- 'module-namespace-heading' --&amp;gt; 'Module documentation'&lt;br /&gt;
	-- 'file-namespace-heading' --&amp;gt; 'Summary'&lt;br /&gt;
	-- 'other-namespaces-heading' --&amp;gt; 'Documentation'&lt;br /&gt;
	-- 'start-box-linkclasses' --&amp;gt; 'mw-editsection-like plainlinks'&lt;br /&gt;
	-- 'start-box-link-id' --&amp;gt; 'doc_editlinks'&lt;br /&gt;
	-- 'testcases-create-link-display' --&amp;gt; 'create'&lt;br /&gt;
	--]=]&lt;br /&gt;
	local subjectSpace = env.subjectSpace&lt;br /&gt;
	if not subjectSpace then&lt;br /&gt;
		-- Default to an &amp;quot;other namespaces&amp;quot; namespace, so that we get at least some output&lt;br /&gt;
		-- if an error occurs.&lt;br /&gt;
		subjectSpace = 2&lt;br /&gt;
	end&lt;br /&gt;
	local data = {}&lt;br /&gt;
	&lt;br /&gt;
	-- Heading&lt;br /&gt;
	local heading = args.heading -- Blank values are not removed.&lt;br /&gt;
	if heading == '' then&lt;br /&gt;
		-- Don't display the start box if the heading arg is defined but blank.&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	if heading then&lt;br /&gt;
		data.heading = heading&lt;br /&gt;
	elseif subjectSpace == 10 then -- Template namespace&lt;br /&gt;
		data.heading = message('documentation-icon-wikitext') .. ' ' .. message('template-namespace-heading')&lt;br /&gt;
	elseif subjectSpace == 828 then -- Module namespace&lt;br /&gt;
		data.heading = message('documentation-icon-wikitext') .. ' ' .. message('module-namespace-heading')&lt;br /&gt;
	elseif subjectSpace == 6 then -- File namespace&lt;br /&gt;
		data.heading = message('file-namespace-heading')&lt;br /&gt;
	else&lt;br /&gt;
		data.heading = message('other-namespaces-heading')&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Heading CSS&lt;br /&gt;
	local headingStyle = args['heading-style']&lt;br /&gt;
	if headingStyle then&lt;br /&gt;
		data.headingStyleText = headingStyle&lt;br /&gt;
	elseif subjectSpace == 10 then&lt;br /&gt;
		-- We are in the template or template talk namespaces.&lt;br /&gt;
		data.headingFontWeight = 'bold'&lt;br /&gt;
		data.headingFontSize = '125%'&lt;br /&gt;
	else&lt;br /&gt;
		data.headingFontSize = '150%'&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Data for the [view][edit][history][purge] or [create] links.&lt;br /&gt;
	if links then&lt;br /&gt;
		data.linksClass = message('start-box-linkclasses')&lt;br /&gt;
		data.linksId = message('start-box-link-id')&lt;br /&gt;
		data.links = links&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return data&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.renderStartBox(data)&lt;br /&gt;
	-- Renders the start box html.&lt;br /&gt;
	-- @data - a table of data generated by p.makeStartBoxData.&lt;br /&gt;
	local sbox = htmlBuilder.create('div')&lt;br /&gt;
	sbox&lt;br /&gt;
		.css('padding-bottom', '3px')&lt;br /&gt;
		.css('border-bottom', '1px solid #aaa')&lt;br /&gt;
		.css('margin-bottom', '1ex')&lt;br /&gt;
		.newline()&lt;br /&gt;
		.tag('span')&lt;br /&gt;
			.cssText(data.headingStyleText)&lt;br /&gt;
			.css('font-weight', data.headingFontWeight)&lt;br /&gt;
			.css('font-size', data.headingFontSize)&lt;br /&gt;
			.wikitext(data.heading)&lt;br /&gt;
	local links = data.links&lt;br /&gt;
	if links then&lt;br /&gt;
		sbox.tag('span')&lt;br /&gt;
			.addClass(data.linksClass)&lt;br /&gt;
			.attr('id', data.linksId)&lt;br /&gt;
			.wikitext(links)&lt;br /&gt;
	end&lt;br /&gt;
	return tostring(sbox)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
-- Documentation content&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
p.content = makeInvokeFunc('_content')&lt;br /&gt;
&lt;br /&gt;
function p._content(args, env)&lt;br /&gt;
	-- Displays the documentation contents&lt;br /&gt;
	-- @args - a table of arguments passed by the user&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	env = env or p.getEnvironment(args)&lt;br /&gt;
	local docTitle = env.docTitle&lt;br /&gt;
	local content = args.content&lt;br /&gt;
	if not content and docTitle and docTitle.exists then&lt;br /&gt;
		content = args._content or mw.getCurrentFrame():expandTemplate{title = docTitle.prefixedText}&lt;br /&gt;
	end&lt;br /&gt;
	-- The line breaks below are necessary so that &amp;quot;=== Headings ===&amp;quot; at the start and end&lt;br /&gt;
	-- of docs are interpreted correctly.&lt;br /&gt;
	return '\n' .. (content or '') .. '\n' &lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
p.contentTitle = makeInvokeFunc('_contentTitle')&lt;br /&gt;
&lt;br /&gt;
function p._contentTitle(args, env)&lt;br /&gt;
	env = env or p.getEnvironment(args)&lt;br /&gt;
	local docTitle = env.docTitle&lt;br /&gt;
	if not args.content and docTitle and docTitle.exists then&lt;br /&gt;
		return docTitle.prefixedText&lt;br /&gt;
	else&lt;br /&gt;
		return ''&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
-- End box&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
p.endBox = makeInvokeFunc('_endBox')&lt;br /&gt;
&lt;br /&gt;
function p._endBox(args, env)&lt;br /&gt;
	--[=[&lt;br /&gt;
	-- This function generates the end box (also known as the link box).&lt;br /&gt;
	-- @args - a table of arguments passed by the user&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	-- &lt;br /&gt;
	-- Messages:&lt;br /&gt;
	-- 'fmbox-id' --&amp;gt; 'documentation-meta-data'&lt;br /&gt;
	-- 'fmbox-style' --&amp;gt; 'background-color: #ecfcf4'&lt;br /&gt;
	-- 'fmbox-textstyle' --&amp;gt; 'font-style: italic'&lt;br /&gt;
	-- &lt;br /&gt;
	-- The HTML is generated by the {{fmbox}} template, courtesy of [[Module:Message box]].&lt;br /&gt;
	--]=]&lt;br /&gt;
	&lt;br /&gt;
	-- Get environment data.&lt;br /&gt;
	env = env or p.getEnvironment(args)&lt;br /&gt;
	local subjectSpace = env.subjectSpace&lt;br /&gt;
	local docTitle = env.docTitle&lt;br /&gt;
	if not subjectSpace or not docTitle then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
		&lt;br /&gt;
	-- Check whether we should output the end box at all. Add the end&lt;br /&gt;
	-- box by default if the documentation exists or if we are in the&lt;br /&gt;
	-- user, module or template namespaces.&lt;br /&gt;
	local linkBox = args['link box']&lt;br /&gt;
	if linkBox == 'off'&lt;br /&gt;
		or not (&lt;br /&gt;
			docTitle.exists&lt;br /&gt;
			or subjectSpace == 2&lt;br /&gt;
			or subjectSpace == 828&lt;br /&gt;
			or subjectSpace == 10&lt;br /&gt;
		)&lt;br /&gt;
	then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Assemble the arguments for {{fmbox}}.&lt;br /&gt;
	local fmargs = {}&lt;br /&gt;
	fmargs.id = message('fmbox-id') -- Sets 'documentation-meta-data'&lt;br /&gt;
	fmargs.image = 'none'&lt;br /&gt;
	fmargs.style = message('fmbox-style') -- Sets 'background-color: #ecfcf4'&lt;br /&gt;
	fmargs.textstyle = message('fmbox-textstyle') -- 'font-style: italic;'&lt;br /&gt;
&lt;br /&gt;
	-- Assemble the fmbox text field.&lt;br /&gt;
	local text = ''&lt;br /&gt;
	if linkBox then&lt;br /&gt;
		text = text .. linkBox&lt;br /&gt;
	else&lt;br /&gt;
		text = text .. (p.makeDocPageBlurb(args, env) or '') -- &amp;quot;This documentation is transcluded from [[Foo]].&amp;quot; &lt;br /&gt;
		if subjectSpace == 2 or subjectSpace == 10 or subjectSpace == 828 then&lt;br /&gt;
			-- We are in the user, template or module namespaces.&lt;br /&gt;
			-- Add sandbox and testcases links.&lt;br /&gt;
			-- &amp;quot;Editors can experiment in this template's sandbox and testcases pages.&amp;quot;&lt;br /&gt;
			text = text .. p.makeExperimentBlurb(args, env)&lt;br /&gt;
			text = text .. '&amp;lt;br /&amp;gt;'&lt;br /&gt;
			if not args.content and not args[1] then&lt;br /&gt;
				-- &amp;quot;Please add categories to the /doc subpage.&amp;quot;&lt;br /&gt;
				-- Don't show this message with inline docs or with an explicitly specified doc page,&lt;br /&gt;
				-- as then it is unclear where to add the categories.&lt;br /&gt;
				text = text .. (p.makeCategoriesBlurb(args, env) or '')&lt;br /&gt;
			end&lt;br /&gt;
			text = text .. ' ' .. (p.makeSubpagesBlurb(args, env) or '') --&amp;quot;Subpages of this template&amp;quot;&lt;br /&gt;
			local printBlurb = p.makePrintBlurb(args, env) -- Two-line blurb about print versions of templates.&lt;br /&gt;
			if printBlurb then&lt;br /&gt;
				text = text .. '&amp;lt;br /&amp;gt;' .. printBlurb&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	fmargs.text = text&lt;br /&gt;
&lt;br /&gt;
	return messageBox.main('fmbox', fmargs)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.makeDocPageBlurb(args, env)&lt;br /&gt;
	--[=[&lt;br /&gt;
	-- Makes the blurb &amp;quot;This documentation is transcluded from [[Template:Foo]] (edit, history)&amp;quot;.&lt;br /&gt;
	-- @args - a table of arguments passed by the user&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	-- &lt;br /&gt;
	-- Messages:&lt;br /&gt;
	-- 'edit-link-display' --&amp;gt; 'edit'&lt;br /&gt;
	-- 'history-link-display' --&amp;gt; 'history'&lt;br /&gt;
	-- 'transcluded-from-blurb' --&amp;gt; &lt;br /&gt;
	-- 'The above [[Wikipedia:Template documentation|documentation]] &lt;br /&gt;
	-- is [[Wikipedia:Transclusion|transcluded]] from $1.'&lt;br /&gt;
	-- 'module-preload' --&amp;gt; 'Template:Documentation/preload-module-doc'&lt;br /&gt;
	-- 'create-link-display' --&amp;gt; 'create'&lt;br /&gt;
	-- 'create-module-doc-blurb' --&amp;gt;&lt;br /&gt;
	-- 'You might want to $1 a documentation page for this [[Wikipedia:Lua|Scribunto module]].'&lt;br /&gt;
	--]=]&lt;br /&gt;
	local docTitle = env.docTitle&lt;br /&gt;
	if not docTitle then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	local ret&lt;br /&gt;
	if docTitle.exists then&lt;br /&gt;
		-- /doc exists; link to it.&lt;br /&gt;
		local docLink = makeWikilink(docTitle.prefixedText)&lt;br /&gt;
		local editUrl = docTitle:fullUrl{action = 'edit'}&lt;br /&gt;
		local editDisplay = message('edit-link-display')&lt;br /&gt;
		local editLink = makeUrlLink(editUrl, editDisplay)&lt;br /&gt;
		local historyUrl = docTitle:fullUrl{action = 'history'}&lt;br /&gt;
		local historyDisplay = message('history-link-display')&lt;br /&gt;
		local historyLink = makeUrlLink(historyUrl, historyDisplay)&lt;br /&gt;
		ret = message('transcluded-from-blurb', {docLink})&lt;br /&gt;
			.. ' '&lt;br /&gt;
			.. makeToolbar(editLink, historyLink)&lt;br /&gt;
			.. '&amp;lt;br /&amp;gt;'&lt;br /&gt;
	elseif env.subjectSpace == 828 then&lt;br /&gt;
		-- /doc does not exist; ask to create it.&lt;br /&gt;
		local createUrl = docTitle:fullUrl{action = 'edit', preload = message('module-preload')}&lt;br /&gt;
		local createDisplay = message('create-link-display')&lt;br /&gt;
		local createLink = makeUrlLink(createUrl, createDisplay)&lt;br /&gt;
		ret = message('create-module-doc-blurb', {createLink})&lt;br /&gt;
			.. '&amp;lt;br /&amp;gt;'&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.makeExperimentBlurb(args, env)&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Renders the text &amp;quot;Editors can experiment in this template's sandbox (edit | diff) and testcases (edit) pages.&amp;quot;&lt;br /&gt;
	-- @args - a table of arguments passed by the user&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	-- &lt;br /&gt;
	-- Messages:&lt;br /&gt;
	-- 'sandbox-link-display' --&amp;gt; 'sandbox'&lt;br /&gt;
	-- 'sandbox-edit-link-display' --&amp;gt; 'edit'&lt;br /&gt;
	-- 'compare-link-display' --&amp;gt; 'diff'&lt;br /&gt;
	-- 'module-sandbox-preload' --&amp;gt; 'Template:Documentation/preload-module-sandbox'&lt;br /&gt;
	-- 'template-sandbox-preload' --&amp;gt; 'Template:Documentation/preload-sandbox'&lt;br /&gt;
	-- 'sandbox-create-link-display' --&amp;gt; 'create'&lt;br /&gt;
	-- 'mirror-edit-summary' --&amp;gt; 'Create sandbox version of $1'&lt;br /&gt;
	-- 'mirror-link-display' --&amp;gt; 'mirror'&lt;br /&gt;
	-- 'sandbox-link-display' --&amp;gt; 'sandbox'&lt;br /&gt;
	-- 'testcases-link-display' --&amp;gt; 'testcases'&lt;br /&gt;
	-- 'testcases-edit-link-display'--&amp;gt; 'edit'&lt;br /&gt;
	-- 'module-testcases-preload' --&amp;gt; 'Template:Documentation/preload-module-testcases'&lt;br /&gt;
	-- 'template-sandbox-preload' --&amp;gt; 'Template:Documentation/preload-sandbox'&lt;br /&gt;
	-- 'testcases-create-link-display' --&amp;gt; 'create'&lt;br /&gt;
	-- 'testcases-link-display' --&amp;gt; 'testcases'&lt;br /&gt;
	-- 'testcases-edit-link-display' --&amp;gt; 'edit'&lt;br /&gt;
	-- 'module-testcases-preload' --&amp;gt; 'Template:Documentation/preload-module-testcases'&lt;br /&gt;
	-- 'template-testcases-preload' --&amp;gt; 'Template:Documentation/preload-testcases'&lt;br /&gt;
	-- 'experiment-blurb-module' --&amp;gt; 'Editors can experiment in this module's $1 and $2 pages.'&lt;br /&gt;
	-- 'experiment-blurb-template' --&amp;gt; 'Editors can experiment in this template's $1 and $2 pages.'&lt;br /&gt;
	--]]&lt;br /&gt;
	local subjectSpace = env.subjectSpace&lt;br /&gt;
	local templateTitle = env.templateTitle&lt;br /&gt;
	local sandboxTitle = env.sandboxTitle&lt;br /&gt;
	local testcasesTitle = env.testcasesTitle&lt;br /&gt;
	local templatePage = templateTitle.prefixedText&lt;br /&gt;
	if not subjectSpace or not templateTitle or not sandboxTitle or not testcasesTitle then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	-- Make links.&lt;br /&gt;
	local sandboxLinks, testcasesLinks&lt;br /&gt;
	if sandboxTitle.exists then&lt;br /&gt;
		local sandboxPage = sandboxTitle.prefixedText&lt;br /&gt;
		local sandboxDisplay = message('sandbox-link-display')&lt;br /&gt;
		local sandboxLink = makeWikilink(sandboxPage, sandboxDisplay)&lt;br /&gt;
		local sandboxEditUrl = sandboxTitle:fullUrl{action = 'edit'}&lt;br /&gt;
		local sandboxEditDisplay = message('sandbox-edit-link-display')&lt;br /&gt;
		local sandboxEditLink = makeUrlLink(sandboxEditUrl, sandboxEditDisplay)&lt;br /&gt;
		local compareUrl = env.compareUrl&lt;br /&gt;
		local compareLink&lt;br /&gt;
		if compareUrl then&lt;br /&gt;
			local compareDisplay = message('compare-link-display')&lt;br /&gt;
			compareLink = makeUrlLink(compareUrl, compareDisplay)&lt;br /&gt;
		end&lt;br /&gt;
		sandboxLinks = sandboxLink .. ' ' .. makeToolbar(sandboxEditLink, compareLink)&lt;br /&gt;
	else&lt;br /&gt;
		local sandboxPreload&lt;br /&gt;
		if subjectSpace == 828 then&lt;br /&gt;
			sandboxPreload = message('module-sandbox-preload')&lt;br /&gt;
		else&lt;br /&gt;
			sandboxPreload = message('template-sandbox-preload')&lt;br /&gt;
		end&lt;br /&gt;
		local sandboxCreateUrl = sandboxTitle:fullUrl{action = 'edit', preload = sandboxPreload}&lt;br /&gt;
		local sandboxCreateDisplay = message('sandbox-create-link-display')&lt;br /&gt;
		local sandboxCreateLink = makeUrlLink(sandboxCreateUrl, sandboxCreateDisplay)&lt;br /&gt;
		local mirrorSummary = message('mirror-edit-summary', {makeWikilink(templatePage)})&lt;br /&gt;
		local mirrorUrl = sandboxTitle:fullUrl{action = 'edit', preload = templatePage, summary = mirrorSummary}&lt;br /&gt;
		local mirrorDisplay = message('mirror-link-display')&lt;br /&gt;
		local mirrorLink = makeUrlLink(mirrorUrl, mirrorDisplay)&lt;br /&gt;
		sandboxLinks = message('sandbox-link-display') .. ' ' .. makeToolbar(sandboxCreateLink, mirrorLink)&lt;br /&gt;
	end&lt;br /&gt;
	if testcasesTitle.exists then&lt;br /&gt;
		local testcasesPage = testcasesTitle.prefixedText&lt;br /&gt;
		local testcasesDisplay = message('testcases-link-display')&lt;br /&gt;
		local testcasesLink = makeWikilink(testcasesPage, testcasesDisplay)&lt;br /&gt;
		local testcasesEditUrl = testcasesTitle:fullUrl{action = 'edit'}&lt;br /&gt;
		local testcasesEditDisplay = message('testcases-edit-link-display')&lt;br /&gt;
		local testcasesEditLink = makeUrlLink(testcasesEditUrl, testcasesEditDisplay)&lt;br /&gt;
		testcasesLinks = testcasesLink .. ' ' .. makeToolbar(testcasesEditLink)&lt;br /&gt;
	else&lt;br /&gt;
		local testcasesPreload&lt;br /&gt;
		if subjectSpace == 828 then&lt;br /&gt;
			testcasesPreload = message('module-testcases-preload')&lt;br /&gt;
		else&lt;br /&gt;
			testcasesPreload = message('template-testcases-preload')&lt;br /&gt;
		end&lt;br /&gt;
		local testcasesCreateUrl = testcasesTitle:fullUrl{action = 'edit', preload = testcasesPreload}&lt;br /&gt;
		local testcasesCreateDisplay = message('testcases-create-link-display')&lt;br /&gt;
		local testcasesCreateLink = makeUrlLink(testcasesCreateUrl, testcasesCreateDisplay)&lt;br /&gt;
		testcasesLinks = message('testcases-link-display') .. ' ' .. makeToolbar(testcasesCreateLink)&lt;br /&gt;
	end&lt;br /&gt;
	local messageName&lt;br /&gt;
	if subjectSpace == 828 then&lt;br /&gt;
		messageName = 'experiment-blurb-module'&lt;br /&gt;
	else&lt;br /&gt;
		messageName = 'experiment-blurb-template'&lt;br /&gt;
	end&lt;br /&gt;
	return message(messageName, {sandboxLinks, testcasesLinks})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.makeCategoriesBlurb(args, env)&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Generates the text &amp;quot;Please add categories to the /doc subpage.&amp;quot;&lt;br /&gt;
	-- @args - a table of arguments passed by the user&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	-- Messages:&lt;br /&gt;
	-- 'doc-link-display' --&amp;gt; '/doc'&lt;br /&gt;
	-- 'add-categories-blurb' --&amp;gt; 'Please add categories to the $1 subpage.'&lt;br /&gt;
	--]]&lt;br /&gt;
	local docTitle = env.docTitle&lt;br /&gt;
	if not docTitle then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	local docPathLink = makeWikilink(docTitle.prefixedText, message('doc-link-display'))&lt;br /&gt;
	return message('add-categories-blurb', {docPathLink})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.makeSubpagesBlurb(args, env)&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Generates the &amp;quot;Subpages of this template&amp;quot; link.&lt;br /&gt;
	-- @args - a table of arguments passed by the user&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	&lt;br /&gt;
	-- Messages:&lt;br /&gt;
	-- 'template-pagetype' --&amp;gt; 'template'&lt;br /&gt;
	-- 'module-pagetype' --&amp;gt; 'module'&lt;br /&gt;
	-- 'default-pagetype' --&amp;gt; 'page'&lt;br /&gt;
	-- 'subpages-link-display' --&amp;gt; 'Subpages of this $1'&lt;br /&gt;
	--]]&lt;br /&gt;
	local subjectSpace = env.subjectSpace&lt;br /&gt;
	local templateTitle = env.templateTitle&lt;br /&gt;
	if not subjectSpace or not templateTitle then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	local pagetype&lt;br /&gt;
	if subjectSpace == 10 then&lt;br /&gt;
		pagetype = message('template-pagetype')&lt;br /&gt;
	elseif subjectSpace == 828 then&lt;br /&gt;
		pagetype = message('module-pagetype')&lt;br /&gt;
	else&lt;br /&gt;
		pagetype = message('default-pagetype')&lt;br /&gt;
	end&lt;br /&gt;
	local subpagesLink = makeWikilink(&lt;br /&gt;
		'Special:PrefixIndex/' .. templateTitle.prefixedText .. '/',&lt;br /&gt;
		message('subpages-link-display', {pagetype})&lt;br /&gt;
	)&lt;br /&gt;
	return message('subpages-blurb', {subpagesLink})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.makePrintBlurb(args, env)&lt;br /&gt;
	--[=[&lt;br /&gt;
	-- Generates the blurb displayed when there is a print version of the template available.&lt;br /&gt;
	-- @args - a table of arguments passed by the user&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	--&lt;br /&gt;
	-- Messages:&lt;br /&gt;
	-- 'print-link-display' --&amp;gt; '/Print'&lt;br /&gt;
	-- 'print-blurb' --&amp;gt; 'A [[Help:Books/for experts#Improving the book layout|print version]]'&lt;br /&gt;
	--		.. ' of this template exists at $1.'&lt;br /&gt;
	--		.. ' If you make a change to this template, please update the print version as well.'&lt;br /&gt;
	-- 'display-print-category' --&amp;gt; true&lt;br /&gt;
	-- 'print-category' --&amp;gt; 'Templates with print versions'&lt;br /&gt;
	--]=]&lt;br /&gt;
	local printTitle = env.printTitle&lt;br /&gt;
	if not printTitle then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	local ret&lt;br /&gt;
	if printTitle.exists then&lt;br /&gt;
		local printLink = makeWikilink(printTitle.prefixedText, message('print-link-display'))&lt;br /&gt;
		ret = message('print-blurb', {printLink})&lt;br /&gt;
		local displayPrintCategory = message('display-print-category', nil, 'boolean')&lt;br /&gt;
		if displayPrintCategory then&lt;br /&gt;
			ret = ret .. makeCategoryLink(message('print-category'))&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
-- Tracking categories&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
function p.addTrackingCategories(env)&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Check if {{documentation}} is transcluded on a /doc or /testcases page.&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	&lt;br /&gt;
	-- Messages:&lt;br /&gt;
	-- 'display-strange-usage-category' --&amp;gt; true&lt;br /&gt;
	-- 'doc-subpage' --&amp;gt; 'doc'&lt;br /&gt;
	-- 'testcases-subpage' --&amp;gt; 'testcases'&lt;br /&gt;
	-- 'strange-usage-category' --&amp;gt; 'Wikipedia pages with strange ((documentation)) usage'&lt;br /&gt;
	-- &lt;br /&gt;
	-- /testcases pages in the module namespace are not categorised, as they may have&lt;br /&gt;
	-- {{documentation}} transcluded automatically.&lt;br /&gt;
	--]]&lt;br /&gt;
	local title = env.title&lt;br /&gt;
	local subjectSpace = env.subjectSpace&lt;br /&gt;
	if not title or not subjectSpace then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	local subpage = title.subpageText&lt;br /&gt;
	local ret = ''&lt;br /&gt;
	if message('display-strange-usage-category', nil, 'boolean')&lt;br /&gt;
		and (&lt;br /&gt;
			subpage == message('doc-subpage')&lt;br /&gt;
			or subjectSpace ~= 828 and subpage == message('testcases-subpage')&lt;br /&gt;
		)&lt;br /&gt;
	then&lt;br /&gt;
		ret = ret .. makeCategoryLink(message('strange-usage-category'))&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Template:Documentation</id>
		<title>Template:Documentation</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Template:Documentation"/>
				<updated>2014-07-03T04:12:19Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: Changed protection level of Template:Documentation: Edit warring / content dispute: making this indef so that the template won't become unprotected accidentally ([Edit=Allow only administrators] (indefinite) [Move=Allow only adm&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#invoke:documentation|main|_content={{ {{#invoke:documentation|contentTitle}}}}}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- Categories go on the /doc subpage, and interwikis go on Wikidata. --&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Module:Infobox</id>
		<title>Module:Infobox</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Module:Infobox"/>
				<updated>2014-06-18T23:27:08Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: allow setting ids for rows, headers, labels and data fields, per protected edit request by User:Czarkoff&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--&lt;br /&gt;
-- This module implements {{Infobox}}&lt;br /&gt;
--&lt;br /&gt;
 &lt;br /&gt;
local p = {}&lt;br /&gt;
 &lt;br /&gt;
local HtmlBuilder = require('Module:HtmlBuilder')&lt;br /&gt;
 &lt;br /&gt;
local args = {}&lt;br /&gt;
local origArgs&lt;br /&gt;
local root&lt;br /&gt;
 &lt;br /&gt;
local function union(t1, t2)&lt;br /&gt;
    -- Returns the union of the values of two tables, as a sequence.&lt;br /&gt;
    local vals = {}&lt;br /&gt;
    for k, v in pairs(t1) do&lt;br /&gt;
        vals[v] = true&lt;br /&gt;
    end&lt;br /&gt;
    for k, v in pairs(t2) do&lt;br /&gt;
        vals[v] = true&lt;br /&gt;
    end&lt;br /&gt;
    local ret = {}&lt;br /&gt;
    for k, v in pairs(vals) do&lt;br /&gt;
        table.insert(ret, k)&lt;br /&gt;
    end&lt;br /&gt;
    return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getArgNums(prefix)&lt;br /&gt;
    -- Returns a table containing the numbers of the arguments that exist&lt;br /&gt;
    -- for the specified prefix. For example, if the prefix was 'data', and&lt;br /&gt;
    -- 'data1', 'data2', and 'data5' exist, it would return {1, 2, 5}.&lt;br /&gt;
    local nums = {}&lt;br /&gt;
    for k, v in pairs(args) do&lt;br /&gt;
        local num = tostring(k):match('^' .. prefix .. '([1-9]%d*)$')&lt;br /&gt;
        if num then table.insert(nums, tonumber(num)) end&lt;br /&gt;
    end&lt;br /&gt;
    table.sort(nums)&lt;br /&gt;
    return nums&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function addRow(rowArgs)&lt;br /&gt;
    -- Adds a row to the infobox, with either a header cell&lt;br /&gt;
    -- or a label/data cell combination.&lt;br /&gt;
    if rowArgs.header then&lt;br /&gt;
        root&lt;br /&gt;
            .tag('tr')&lt;br /&gt;
                .addClass(rowArgs.rowclass)&lt;br /&gt;
                .attr('id', rowArgs.rowid)&lt;br /&gt;
                .tag('th')&lt;br /&gt;
                    .attr('colspan', 2)&lt;br /&gt;
                    .attr('id', rowArgs.headerid)&lt;br /&gt;
                    .addClass(rowArgs.class)&lt;br /&gt;
                    .addClass(args.headerclass)&lt;br /&gt;
                    .css('text-align', 'center')&lt;br /&gt;
                    .cssText(args.headerstyle)&lt;br /&gt;
                    .wikitext(rowArgs.header)&lt;br /&gt;
    elseif rowArgs.data then&lt;br /&gt;
        local row = root.tag('tr')&lt;br /&gt;
        row.addClass(rowArgs.rowclass)&lt;br /&gt;
        row.attr('id', rowArgs.rowid)&lt;br /&gt;
        if rowArgs.label then&lt;br /&gt;
            row&lt;br /&gt;
                .tag('th')&lt;br /&gt;
                    .attr('scope', 'row')&lt;br /&gt;
                    .attr('id', rowArgs.labelid)&lt;br /&gt;
                    .css('text-align', 'left')&lt;br /&gt;
                    .cssText(args.labelstyle)&lt;br /&gt;
                    .wikitext(rowArgs.label)&lt;br /&gt;
                    .done()&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        local dataCell = row.tag('td')&lt;br /&gt;
        if not rowArgs.label then &lt;br /&gt;
            dataCell&lt;br /&gt;
                .attr('colspan', 2)&lt;br /&gt;
                .css('text-align', 'center') &lt;br /&gt;
        end&lt;br /&gt;
        dataCell&lt;br /&gt;
            .attr('id', rowArgs.dataid)&lt;br /&gt;
            .addClass(rowArgs.class)&lt;br /&gt;
            .cssText(rowArgs.datastyle)&lt;br /&gt;
            .newline()&lt;br /&gt;
            .wikitext(rowArgs.data)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function renderTitle()&lt;br /&gt;
    if not args.title then return end&lt;br /&gt;
&lt;br /&gt;
    root&lt;br /&gt;
        .tag('caption')&lt;br /&gt;
            .addClass(args.titleclass)&lt;br /&gt;
            .cssText(args.titlestyle)&lt;br /&gt;
            .wikitext(args.title)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function renderAboveRow()&lt;br /&gt;
    if not args.above then return end&lt;br /&gt;
    &lt;br /&gt;
    root&lt;br /&gt;
        .tag('tr')&lt;br /&gt;
            .tag('th')&lt;br /&gt;
                .attr('colspan', 2)&lt;br /&gt;
                .addClass(args.aboveclass)&lt;br /&gt;
                .css('text-align', 'center')&lt;br /&gt;
                .css('font-size', '125%')&lt;br /&gt;
                .css('font-weight', 'bold')&lt;br /&gt;
                .cssText(args.abovestyle)&lt;br /&gt;
                .wikitext(args.above)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function renderBelowRow()&lt;br /&gt;
    if not args.below then return end&lt;br /&gt;
    &lt;br /&gt;
    root&lt;br /&gt;
        .tag('tr')&lt;br /&gt;
            .tag('td')&lt;br /&gt;
                .attr('colspan', '2')&lt;br /&gt;
                .addClass(args.belowclass)&lt;br /&gt;
                .css('text-align', 'center')&lt;br /&gt;
                .cssText(args.belowstyle)&lt;br /&gt;
                .newline()&lt;br /&gt;
                .wikitext(args.below)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function renderSubheaders()&lt;br /&gt;
    if args.subheader then&lt;br /&gt;
        args.subheader1 = args.subheader&lt;br /&gt;
    end&lt;br /&gt;
    if args.subheaderrowclass then&lt;br /&gt;
        args.subheaderrowclass1 = args.subheaderrowclass&lt;br /&gt;
    end&lt;br /&gt;
    local subheadernums = getArgNums('subheader')&lt;br /&gt;
    for k, num in ipairs(subheadernums) do&lt;br /&gt;
        addRow({&lt;br /&gt;
            data = args['subheader' .. tostring(num)],&lt;br /&gt;
            datastyle = args.subheaderstyle or args['subheaderstyle' .. tostring(num)],&lt;br /&gt;
            class = args.subheaderclass,&lt;br /&gt;
            rowclass = args['subheaderrowclass' .. tostring(num)]&lt;br /&gt;
        })&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function renderImages()&lt;br /&gt;
    if args.image then&lt;br /&gt;
        args.image1 = args.image&lt;br /&gt;
    end&lt;br /&gt;
    if args.caption then&lt;br /&gt;
        args.caption1 = args.caption&lt;br /&gt;
    end&lt;br /&gt;
    local imagenums = getArgNums('image')&lt;br /&gt;
    for k, num in ipairs(imagenums) do&lt;br /&gt;
        local caption = args['caption' .. tostring(num)]&lt;br /&gt;
        local data = HtmlBuilder.create().wikitext(args['image' .. tostring(num)])&lt;br /&gt;
        if caption then&lt;br /&gt;
            data&lt;br /&gt;
                .tag('div')&lt;br /&gt;
                    .cssText(args.captionstyle)&lt;br /&gt;
                    .wikitext(caption)&lt;br /&gt;
        end&lt;br /&gt;
        addRow({&lt;br /&gt;
            data = tostring(data),&lt;br /&gt;
            datastyle = args.imagestyle,&lt;br /&gt;
            class = args.imageclass,&lt;br /&gt;
            rowclass = args['imagerowclass' .. tostring(num)]&lt;br /&gt;
        })&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function renderRows()&lt;br /&gt;
    -- Gets the union of the header and data argument numbers,&lt;br /&gt;
    -- and renders them all in order using addRow.&lt;br /&gt;
    local rownums = union(getArgNums('header'), getArgNums('data'))&lt;br /&gt;
    table.sort(rownums)&lt;br /&gt;
    for k, num in ipairs(rownums) do&lt;br /&gt;
        addRow({&lt;br /&gt;
            header = args['header' .. tostring(num)],&lt;br /&gt;
            label = args['label' .. tostring(num)],&lt;br /&gt;
            data = args['data' .. tostring(num)],&lt;br /&gt;
            datastyle = args.datastyle,&lt;br /&gt;
            class = args['class' .. tostring(num)],&lt;br /&gt;
            rowclass = args['rowclass' .. tostring(num)],&lt;br /&gt;
            dataid = args['dataid' .. tostring(num)],&lt;br /&gt;
            labelid = args['labelid' .. tostring(num)],&lt;br /&gt;
            headerid = args['headerid' .. tostring(num)],&lt;br /&gt;
            rowid = args['rowid' .. tostring(num)]&lt;br /&gt;
        })&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function renderNavBar()&lt;br /&gt;
    if not args.name then return end&lt;br /&gt;
    &lt;br /&gt;
    root&lt;br /&gt;
        .tag('tr')&lt;br /&gt;
            .tag('td')&lt;br /&gt;
                .attr('colspan', '2')&lt;br /&gt;
                .css('text-align', 'right')&lt;br /&gt;
                .wikitext(mw.getCurrentFrame():expandTemplate({ &lt;br /&gt;
                    title = 'navbar', &lt;br /&gt;
                    args = { args.name, mini = 1 }&lt;br /&gt;
                }))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function renderItalicTitle()&lt;br /&gt;
    local italicTitle = args['italic title'] and mw.ustring.lower(args['italic title'])&lt;br /&gt;
    if italicTitle == '' or italicTitle == 'force' or italicTitle == 'yes' then&lt;br /&gt;
        root.wikitext(mw.getCurrentFrame():expandTemplate({title = 'italic title'}))&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function renderTrackingCategories()&lt;br /&gt;
    if args.decat ~= 'yes' then&lt;br /&gt;
        if #(getArgNums('data')) == 0 and mw.title.getCurrentTitle().namespace == 0 then&lt;br /&gt;
            root.wikitext('[[Category:Articles which use infobox templates with no data rows]]')&lt;br /&gt;
        end&lt;br /&gt;
        if args.child == 'yes' and args.title then&lt;br /&gt;
            root.wikitext('[[Category:Articles which use embedded infobox templates with the title parameter]]')&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function _infobox()&lt;br /&gt;
    -- Specify the overall layout of the infobox, with special settings&lt;br /&gt;
    -- if the infobox is used as a 'child' inside another infobox.&lt;br /&gt;
    if args.child ~= 'yes' then&lt;br /&gt;
        root = HtmlBuilder.create('table')&lt;br /&gt;
        &lt;br /&gt;
        root&lt;br /&gt;
            .addClass('infobox')&lt;br /&gt;
            .addClass(args.bodyclass)&lt;br /&gt;
            .attr('cellspacing', 3)&lt;br /&gt;
            .css('border-spacing', '3px')&lt;br /&gt;
            &lt;br /&gt;
            if args.subbox == 'yes' then&lt;br /&gt;
                root&lt;br /&gt;
                    .css('padding', '0')&lt;br /&gt;
                    .css('border', 'none')&lt;br /&gt;
                    .css('margin', '-3px')&lt;br /&gt;
                    .css('width', 'auto')&lt;br /&gt;
                    .css('min-width', '100%')&lt;br /&gt;
                    .css('font-size', '100%')&lt;br /&gt;
                    .css('clear', 'none')&lt;br /&gt;
                    .css('float', 'none')&lt;br /&gt;
                    .css('background-color', 'transparent')&lt;br /&gt;
            else&lt;br /&gt;
                root&lt;br /&gt;
                    .css('width', '22em')&lt;br /&gt;
            end&lt;br /&gt;
        root&lt;br /&gt;
            .cssText(args.bodystyle)&lt;br /&gt;
    &lt;br /&gt;
        renderTitle()&lt;br /&gt;
        renderAboveRow()&lt;br /&gt;
    else&lt;br /&gt;
        root = HtmlBuilder.create()&lt;br /&gt;
        &lt;br /&gt;
        root&lt;br /&gt;
            .wikitext(args.title)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    renderSubheaders()&lt;br /&gt;
    renderImages() &lt;br /&gt;
    renderRows() &lt;br /&gt;
    renderBelowRow()  &lt;br /&gt;
    renderNavBar()&lt;br /&gt;
    renderItalicTitle()&lt;br /&gt;
    renderTrackingCategories()&lt;br /&gt;
    &lt;br /&gt;
    return tostring(root)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function preprocessSingleArg(argName)&lt;br /&gt;
    -- If the argument exists and isn't blank, add it to the argument table.&lt;br /&gt;
    -- Blank arguments are treated as nil to match the behaviour of ParserFunctions.&lt;br /&gt;
    if origArgs[argName] and origArgs[argName] ~= '' then&lt;br /&gt;
        args[argName] = origArgs[argName]&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function preprocessArgs(prefixTable, step)&lt;br /&gt;
    -- Assign the parameters with the given prefixes to the args table, in order, in batches&lt;br /&gt;
    -- of the step size specified. This is to prevent references etc. from appearing in the&lt;br /&gt;
    -- wrong order. The prefixTable should be an array containing tables, each of which has&lt;br /&gt;
    -- two possible fields, a &amp;quot;prefix&amp;quot; string and a &amp;quot;depend&amp;quot; table. The function always parses&lt;br /&gt;
    -- parameters containing the &amp;quot;prefix&amp;quot; string, but only parses parameters in the &amp;quot;depend&amp;quot;&lt;br /&gt;
    -- table if the prefix parameter is present and non-blank.&lt;br /&gt;
    if type(prefixTable) ~= 'table' then&lt;br /&gt;
        error(&amp;quot;Non-table value detected for the prefix table&amp;quot;, 2)&lt;br /&gt;
    end&lt;br /&gt;
    if type(step) ~= 'number' then&lt;br /&gt;
        error(&amp;quot;Invalid step value detected&amp;quot;, 2)&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    -- Get arguments without a number suffix, and check for bad input.&lt;br /&gt;
    for i,v in ipairs(prefixTable) do&lt;br /&gt;
        if type(v) ~= 'table' or type(v.prefix) ~= &amp;quot;string&amp;quot; or (v.depend and type(v.depend) ~= 'table') then&lt;br /&gt;
            error('Invalid input detected to preprocessArgs prefix table', 2)&lt;br /&gt;
        end&lt;br /&gt;
        preprocessSingleArg(v.prefix)&lt;br /&gt;
        -- Only parse the depend parameter if the prefix parameter is present and not blank.&lt;br /&gt;
        if args[v.prefix] and v.depend then&lt;br /&gt;
            for j, dependValue in ipairs(v.depend) do&lt;br /&gt;
                if type(dependValue) ~= 'string' then&lt;br /&gt;
                    error('Invalid &amp;quot;depend&amp;quot; parameter value detected in preprocessArgs')&lt;br /&gt;
                end&lt;br /&gt;
                preprocessSingleArg(dependValue)&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Get arguments with number suffixes.&lt;br /&gt;
    local a = 1 -- Counter variable.&lt;br /&gt;
    local moreArgumentsExist = true&lt;br /&gt;
    while moreArgumentsExist == true do&lt;br /&gt;
        moreArgumentsExist = false&lt;br /&gt;
        for i = a, a + step - 1 do&lt;br /&gt;
            for j,v in ipairs(prefixTable) do&lt;br /&gt;
                local prefixArgName = v.prefix .. tostring(i)&lt;br /&gt;
                if origArgs[prefixArgName] then&lt;br /&gt;
                    moreArgumentsExist = true -- Do another loop if any arguments are found, even blank ones.&lt;br /&gt;
                    preprocessSingleArg(prefixArgName)&lt;br /&gt;
                end&lt;br /&gt;
                -- Process the depend table if the prefix argument is present and not blank, or&lt;br /&gt;
                -- we are processing &amp;quot;prefix1&amp;quot; and &amp;quot;prefix&amp;quot; is present and not blank, and&lt;br /&gt;
                -- if the depend table is present.&lt;br /&gt;
                if v.depend and (args[prefixArgName] or (i == 1 and args[v.prefix])) then&lt;br /&gt;
                    for j,dependValue in ipairs(v.depend) do&lt;br /&gt;
                        local dependArgName = dependValue .. tostring(i)&lt;br /&gt;
                        preprocessSingleArg(dependArgName)&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        a = a + step&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
 &lt;br /&gt;
function p.infobox(frame)&lt;br /&gt;
    -- If called via #invoke, use the args passed into the invoking template.&lt;br /&gt;
    -- Otherwise, for testing purposes, assume args are being passed directly in.&lt;br /&gt;
    if frame == mw.getCurrentFrame() then&lt;br /&gt;
        origArgs = frame:getParent().args&lt;br /&gt;
    else&lt;br /&gt;
        origArgs = frame&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    -- Parse the data parameters in the same order that the old {{infobox}} did, so that&lt;br /&gt;
    -- references etc. will display in the expected places. Parameters that depend on&lt;br /&gt;
    -- another parameter are only processed if that parameter is present, to avoid&lt;br /&gt;
    -- phantom references appearing in article reference lists.&lt;br /&gt;
    preprocessSingleArg('child')&lt;br /&gt;
    preprocessSingleArg('bodyclass')&lt;br /&gt;
    preprocessSingleArg('subbox')&lt;br /&gt;
    preprocessSingleArg('bodystyle')&lt;br /&gt;
    preprocessSingleArg('title')&lt;br /&gt;
    preprocessSingleArg('titleclass')&lt;br /&gt;
    preprocessSingleArg('titlestyle')&lt;br /&gt;
    preprocessSingleArg('above')&lt;br /&gt;
    preprocessSingleArg('aboveclass')&lt;br /&gt;
    preprocessSingleArg('abovestyle')&lt;br /&gt;
    preprocessArgs({&lt;br /&gt;
        {prefix = 'subheader', depend = {'subheaderstyle', 'subheaderrowclass'}}&lt;br /&gt;
    }, 10)&lt;br /&gt;
    preprocessSingleArg('subheaderstyle')&lt;br /&gt;
    preprocessSingleArg('subheaderclass')&lt;br /&gt;
    preprocessArgs({&lt;br /&gt;
        {prefix = 'image', depend = {'caption', 'imagerowclass'}}&lt;br /&gt;
    }, 10)&lt;br /&gt;
    preprocessSingleArg('captionstyle')&lt;br /&gt;
    preprocessSingleArg('imagestyle')&lt;br /&gt;
    preprocessSingleArg('imageclass')&lt;br /&gt;
    preprocessArgs({&lt;br /&gt;
        {prefix = 'header'},&lt;br /&gt;
        {prefix = 'data', depend = {'label'}},&lt;br /&gt;
        {prefix = 'rowclass'},&lt;br /&gt;
        {prefix = 'class'},&lt;br /&gt;
        {prefix = 'dataid'},&lt;br /&gt;
        {prefix = 'labelid'},&lt;br /&gt;
        {prefix = 'headerid'},&lt;br /&gt;
        {prefix = 'rowid'}&lt;br /&gt;
    }, 50)&lt;br /&gt;
    preprocessSingleArg('headerclass')&lt;br /&gt;
    preprocessSingleArg('headerstyle')&lt;br /&gt;
    preprocessSingleArg('labelstyle')&lt;br /&gt;
    preprocessSingleArg('datastyle')&lt;br /&gt;
    preprocessSingleArg('below')&lt;br /&gt;
    preprocessSingleArg('belowclass')&lt;br /&gt;
    preprocessSingleArg('belowstyle')&lt;br /&gt;
    preprocessSingleArg('name')&lt;br /&gt;
    args['italic title'] = origArgs['italic title'] -- different behaviour if blank or absent&lt;br /&gt;
    preprocessSingleArg('decat')&lt;br /&gt;
 &lt;br /&gt;
    return _infobox()&lt;br /&gt;
end&lt;br /&gt;
 &lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Module:List</id>
		<title>Module:List</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Module:List"/>
				<updated>2014-06-12T09:21:46Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: remove li_style, ul_style and ol_style parameters, allow itemn_style and itemn_value parameters, and add a tracking category for item_stylen and item_valuen parameters&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module outputs different kinds of lists. At the moment, bulleted,&lt;br /&gt;
-- unbulleted, horizontal, ordered, and horizontal ordered lists are supported.&lt;br /&gt;
&lt;br /&gt;
local libUtil = require('libraryUtil')&lt;br /&gt;
local checkType = libUtil.checkType&lt;br /&gt;
local mTableTools = require('Module:TableTools')&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
local listTypes = {&lt;br /&gt;
	['bulleted'] = true,&lt;br /&gt;
	['unbulleted'] = true,&lt;br /&gt;
	['horizontal'] = true,&lt;br /&gt;
	['ordered'] = true,&lt;br /&gt;
	['horizontal_ordered'] = true&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function p.makeListData(listType, args)&lt;br /&gt;
	-- Constructs a data table to be passed to p.renderList.&lt;br /&gt;
	local data = {}&lt;br /&gt;
&lt;br /&gt;
	-- Classes&lt;br /&gt;
	data.classes = {}&lt;br /&gt;
	if listType == 'horizontal' or listType == 'horizontal_ordered' then&lt;br /&gt;
		table.insert(data.classes, 'hlist')&lt;br /&gt;
	elseif listType == 'unbulleted' then&lt;br /&gt;
		table.insert(data.classes, 'plainlist')&lt;br /&gt;
	end&lt;br /&gt;
	table.insert(data.classes, args.class)&lt;br /&gt;
&lt;br /&gt;
	-- Main div style&lt;br /&gt;
	data.style = args.style&lt;br /&gt;
&lt;br /&gt;
	-- Indent for horizontal lists&lt;br /&gt;
	if listType == 'horizontal' or listType == 'horizontal_ordered' then&lt;br /&gt;
		local indent = tonumber(args.indent)&lt;br /&gt;
		indent = indent and indent * 1.6 or 0&lt;br /&gt;
		if indent &amp;gt; 0 then&lt;br /&gt;
			data.marginLeft = indent .. 'em'&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- List style types for ordered lists&lt;br /&gt;
	-- This could be &amp;quot;1, 2, 3&amp;quot;, &amp;quot;a, b, c&amp;quot;, or a number of others. The list style&lt;br /&gt;
	-- type is either set by the &amp;quot;type&amp;quot; attribute or the &amp;quot;list-style-type&amp;quot; CSS&lt;br /&gt;
	-- property.&lt;br /&gt;
	if listType == 'ordered' or listType == 'horizontal_ordered' then &lt;br /&gt;
		data.listStyleType = args.list_style_type or args['list-style-type']&lt;br /&gt;
		data.type = args['type']&lt;br /&gt;
&lt;br /&gt;
		-- Detect invalid type attributes and attempt to convert them to&lt;br /&gt;
		-- list-style-type CSS properties.&lt;br /&gt;
		if data.type &lt;br /&gt;
			and not data.listStyleType&lt;br /&gt;
			and not tostring(data.type):find('^%s*[1AaIi]%s*$')&lt;br /&gt;
		then&lt;br /&gt;
			data.listStyleType = data.type&lt;br /&gt;
			data.type = nil&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- List tag type&lt;br /&gt;
	if listType == 'ordered' or listType == 'horizontal_ordered' then&lt;br /&gt;
		data.listTag = 'ol'&lt;br /&gt;
	else&lt;br /&gt;
		data.listTag = 'ul'&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Start number for ordered lists&lt;br /&gt;
	data.start = args.start&lt;br /&gt;
	if listType == 'horizontal_ordered' then&lt;br /&gt;
		-- Apply fix to get start numbers working with horizontal ordered lists.&lt;br /&gt;
		local startNum = tonumber(data.start)&lt;br /&gt;
		if startNum then&lt;br /&gt;
			data.counterReset = 'listitem ' .. tostring(startNum - 1)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- List style&lt;br /&gt;
	 -- ul_style and ol_style are included for backwards compatibility. No&lt;br /&gt;
	 -- distinction is made for ordered or unordered lists.&lt;br /&gt;
	data.listStyle = args.list_style&lt;br /&gt;
&lt;br /&gt;
	-- List items&lt;br /&gt;
	-- li_style is included for backwards compatibility. item_style was included&lt;br /&gt;
	-- to be easier to understand for non-coders.&lt;br /&gt;
	data.itemStyle = args.item_style or args.li_style&lt;br /&gt;
	data.items = {}&lt;br /&gt;
	for i, num in ipairs(mTableTools.numKeys(args)) do&lt;br /&gt;
		local item = {}&lt;br /&gt;
		item.content = args[num]&lt;br /&gt;
		item.style = args['item' .. tostring(num) .. '_style']&lt;br /&gt;
			or args['item_style' .. tostring(num)]&lt;br /&gt;
		item.value = args['item' .. tostring(num) .. '_value']&lt;br /&gt;
			or args['item_value' .. tostring(num)]&lt;br /&gt;
		table.insert(data.items, item)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return data&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.renderList(data)&lt;br /&gt;
	-- Renders the list HTML.&lt;br /&gt;
	&lt;br /&gt;
	-- Return the blank string if there are no list items.&lt;br /&gt;
	if type(data.items) ~= 'table' or #data.items &amp;lt; 1 then&lt;br /&gt;
		return ''&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Render the main div tag.&lt;br /&gt;
	local root = mw.html.create('div')&lt;br /&gt;
	for i, class in ipairs(data.classes or {}) do&lt;br /&gt;
		root:addClass(class)&lt;br /&gt;
	end&lt;br /&gt;
	root:css{['margin-left'] = data.marginLeft}&lt;br /&gt;
	if data.style then&lt;br /&gt;
		root:cssText(data.style)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Render the list tag.&lt;br /&gt;
	local list = root:tag(data.listTag or 'ul')&lt;br /&gt;
	list&lt;br /&gt;
		:attr{start = data.start, type = data.type}&lt;br /&gt;
		:css{&lt;br /&gt;
			['counter-reset'] = data.counterReset,&lt;br /&gt;
			['list-style-type'] = data.listStyleType&lt;br /&gt;
		}&lt;br /&gt;
	if data.listStyle then&lt;br /&gt;
		list:cssText(data.listStyle)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Render the list items&lt;br /&gt;
	for i, t in ipairs(data.items or {}) do&lt;br /&gt;
		local item = list:tag('li')&lt;br /&gt;
		if data.itemStyle then&lt;br /&gt;
			item:cssText(data.itemStyle)&lt;br /&gt;
		end&lt;br /&gt;
		if t.style then&lt;br /&gt;
			item:cssText(t.style)&lt;br /&gt;
		end&lt;br /&gt;
		item&lt;br /&gt;
			:attr{value = t.value}&lt;br /&gt;
			:wikitext(t.content)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return tostring(root)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.renderTrackingCategories(args)&lt;br /&gt;
	local isDeprecated = false -- Tracks deprecated parameters.&lt;br /&gt;
	for k, v in pairs(args) do&lt;br /&gt;
		k = tostring(k)&lt;br /&gt;
		if k:find('^item_style%d+$') or k:find('^item_value%d+$') then&lt;br /&gt;
			isDeprecated = true&lt;br /&gt;
			break&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local ret = ''&lt;br /&gt;
	if isDeprecated then&lt;br /&gt;
		ret = ret .. '[[Category:List templates with deprecated parameters]]'&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.makeList(listType, args)&lt;br /&gt;
	if not listType or not listTypes[listType] then&lt;br /&gt;
		error(string.format(&lt;br /&gt;
			&amp;quot;bad argument #1 to 'makeList' ('%s' is not a valid list type)&amp;quot;,&lt;br /&gt;
			tostring(listType)&lt;br /&gt;
		), 2)&lt;br /&gt;
	end&lt;br /&gt;
	checkType('makeList', 2, args, 'table')&lt;br /&gt;
	local data = p.makeListData(listType, args)&lt;br /&gt;
	local list = p.renderList(data)&lt;br /&gt;
	local trackingCategories = p.renderTrackingCategories(args)&lt;br /&gt;
	return list .. trackingCategories&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
for listType in pairs(listTypes) do&lt;br /&gt;
	p[listType] = function (frame)&lt;br /&gt;
		local mArguments = require('Module:Arguments')&lt;br /&gt;
		local origArgs = mArguments.getArgs(frame)&lt;br /&gt;
		-- Copy all the arguments to a new table, for faster indexing.&lt;br /&gt;
		local args = {}&lt;br /&gt;
		for k, v in pairs(origArgs) do&lt;br /&gt;
			args[k] = v&lt;br /&gt;
		end&lt;br /&gt;
		return p.makeList(listType, args)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Module:File_link</id>
		<title>Module:File link</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Module:File_link"/>
				<updated>2014-06-04T00:06:16Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: Undid revision 611451330 by Mr. Stradivarius (talk) whoops, that edit was supposed to be to the sandbox...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module provides a library for formatting file wikilinks.&lt;br /&gt;
&lt;br /&gt;
local libraryUtil = require('libraryUtil')&lt;br /&gt;
local checkType = libraryUtil.checkType&lt;br /&gt;
&lt;br /&gt;
local fileLink = {}&lt;br /&gt;
&lt;br /&gt;
function fileLink.new(filename)&lt;br /&gt;
	checkType('fileLink.new', 1, filename, 'string', true)&lt;br /&gt;
	local obj, data = {}, {}&lt;br /&gt;
	&lt;br /&gt;
	local checkSelf = libraryUtil.makeCheckSelfFunction(&lt;br /&gt;
		'fileLink',&lt;br /&gt;
		'fileLink',&lt;br /&gt;
		obj,&lt;br /&gt;
		'fileLink object'&lt;br /&gt;
	)&lt;br /&gt;
	&lt;br /&gt;
	-- Set the filename if we were passed it as an input to fileLink.new.&lt;br /&gt;
	if filename then&lt;br /&gt;
		data.theName = filename&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function data:name(s)&lt;br /&gt;
		checkSelf(self, 'name')&lt;br /&gt;
		checkType('fileLink:name', 1, s, 'string')&lt;br /&gt;
		data.theName = s&lt;br /&gt;
		return self&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function data:format(s, filename)&lt;br /&gt;
		checkSelf(self, 'format')&lt;br /&gt;
		checkType('fileLink:format', 1, s, 'string', true)&lt;br /&gt;
		checkType('fileLink:format', 2, format, 'string', true)&lt;br /&gt;
		local validFormats = {&lt;br /&gt;
			thumb = true,&lt;br /&gt;
			thumbnail = true,&lt;br /&gt;
			frame = true,&lt;br /&gt;
			framed = true,&lt;br /&gt;
			frameless = true&lt;br /&gt;
		}&lt;br /&gt;
		if s == nil or validFormats[s] then&lt;br /&gt;
			data.theFormat = s&lt;br /&gt;
			data.theFormatFilename = filename&lt;br /&gt;
		else&lt;br /&gt;
			error(string.format(&lt;br /&gt;
				&amp;quot;bad argument #1 to 'fileLink:format' ('%s' is not a valid format)&amp;quot;,&lt;br /&gt;
				s&lt;br /&gt;
			), 2)&lt;br /&gt;
		end&lt;br /&gt;
		return self&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local function sizeError(methodName)&lt;br /&gt;
		-- Used for formatting duplication errors in size-related methods.&lt;br /&gt;
		error(string.format(&lt;br /&gt;
			&amp;quot;duplicate size argument detected in '%s'&amp;quot;&lt;br /&gt;
			.. &amp;quot; ('upright' cannot be used in conjunction with height or width)&amp;quot;,&lt;br /&gt;
			methodName&lt;br /&gt;
		), 3)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function data:width(px)&lt;br /&gt;
		checkSelf(self, 'width')&lt;br /&gt;
		checkType('fileLink:width', 1, px, 'number', true)&lt;br /&gt;
		if px and data.isUpright then&lt;br /&gt;
			sizeError('fileLink:width')&lt;br /&gt;
		end&lt;br /&gt;
		data.theWidth = px&lt;br /&gt;
		return self&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function data:height(px)&lt;br /&gt;
		checkSelf(self, 'height')&lt;br /&gt;
		checkType('fileLink:height', 1, px, 'number', true)&lt;br /&gt;
		if px and data.isUpright then&lt;br /&gt;
			sizeError('fileLink:height')&lt;br /&gt;
		end&lt;br /&gt;
		data.theHeight = px&lt;br /&gt;
		return self&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function data:upright(isUpright, factor)&lt;br /&gt;
		checkSelf(self, 'upright')&lt;br /&gt;
		checkType('fileLink:upright', 1, isUpright, 'boolean', true)&lt;br /&gt;
		checkType('fileLink:upright', 2, factor, 'number', true)&lt;br /&gt;
		if isUpright and (data.theWidth or data.theHeight) then&lt;br /&gt;
			sizeError('fileLink:upright')&lt;br /&gt;
		end&lt;br /&gt;
		data.isUpright = isUpright&lt;br /&gt;
		data.uprightFactor = factor&lt;br /&gt;
		return self&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function data:resetSize()&lt;br /&gt;
		checkSelf(self, 'resetSize')&lt;br /&gt;
		for i, field in ipairs{'theWidth', 'theHeight', 'isUpright', 'uprightFactor'} do&lt;br /&gt;
			data[field] = nil&lt;br /&gt;
		end&lt;br /&gt;
		return self&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function data:location(s)&lt;br /&gt;
		checkSelf(self, 'location')&lt;br /&gt;
		checkType('fileLink:location', 1, s, 'string', true)&lt;br /&gt;
		local validLocations = {&lt;br /&gt;
			right = true,&lt;br /&gt;
			left = true,&lt;br /&gt;
			center = true,&lt;br /&gt;
			none = true&lt;br /&gt;
		}&lt;br /&gt;
		if s == nil or validLocations[s] then&lt;br /&gt;
			data.theLocation = s&lt;br /&gt;
		else&lt;br /&gt;
			error(string.format(&lt;br /&gt;
				&amp;quot;bad argument #1 to 'fileLink:location' ('%s' is not a valid location)&amp;quot;,&lt;br /&gt;
				s&lt;br /&gt;
			), 2)&lt;br /&gt;
		end&lt;br /&gt;
		return self&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function data:alignment(s)&lt;br /&gt;
		checkSelf(self, 'alignment')&lt;br /&gt;
		checkType('fileLink:alignment', 1, s, 'string', true)&lt;br /&gt;
		local validAlignments = {&lt;br /&gt;
			baseline = true,&lt;br /&gt;
			middle = true,&lt;br /&gt;
			sub = true,&lt;br /&gt;
			super = true,&lt;br /&gt;
			['text-top'] = true,&lt;br /&gt;
			['text-bottom'] = true,&lt;br /&gt;
			top = true,&lt;br /&gt;
			bottom = true&lt;br /&gt;
		}&lt;br /&gt;
		if s == nil or validAlignments[s] then&lt;br /&gt;
			data.theAlignment = s&lt;br /&gt;
		else&lt;br /&gt;
			error(string.format(&lt;br /&gt;
				&amp;quot;bad argument #1 to 'fileLink:alignment' ('%s' is not a valid alignment)&amp;quot;,&lt;br /&gt;
				s&lt;br /&gt;
			), 2)&lt;br /&gt;
		end&lt;br /&gt;
		return self&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function data:border(hasBorder)&lt;br /&gt;
		checkSelf(self, 'border')&lt;br /&gt;
		checkType('fileLink:border', 1, hasBorder, 'boolean', true)&lt;br /&gt;
		data.hasBorder = hasBorder&lt;br /&gt;
		return self&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function data:link(s)&lt;br /&gt;
		checkSelf(self, 'link')&lt;br /&gt;
		checkType('fileLink:link', 1, s, 'string', true)&lt;br /&gt;
		data.theLink = s&lt;br /&gt;
		return self&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function data:alt(s)&lt;br /&gt;
		checkSelf(self, 'alt')&lt;br /&gt;
		checkType('fileLink:alt', 1, s, 'string', true)&lt;br /&gt;
		data.theAlt = s&lt;br /&gt;
		return self&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function data:page(num)&lt;br /&gt;
		checkSelf(self, 'page')&lt;br /&gt;
		checkType('fileLink:page', 1, num, 'number', true)&lt;br /&gt;
		data.thePage = s&lt;br /&gt;
		return self&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function data:class(s)&lt;br /&gt;
		checkSelf(self, 'class')&lt;br /&gt;
		checkType('fileLink:class', 1, s, 'string', true)&lt;br /&gt;
		data.theClass = s&lt;br /&gt;
		return self&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function data:lang(s)&lt;br /&gt;
		checkSelf(self, 'lang')&lt;br /&gt;
		checkType('fileLink:lang', 1, s, 'string', true)&lt;br /&gt;
		data.theLang = s&lt;br /&gt;
		return self&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local function checkTypeStringOrNum(funcName, pos, arg)&lt;br /&gt;
		local argType = type(arg)&lt;br /&gt;
		if argType ~= 'nil' and argType ~= 'string' and argType ~= 'number' then&lt;br /&gt;
			error(string.format(&lt;br /&gt;
				&amp;quot;bad argument #%d to '%s' (string or number expected, got %s)&amp;quot;,&lt;br /&gt;
				pos,&lt;br /&gt;
				funcName,&lt;br /&gt;
				argType&lt;br /&gt;
			), 3)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function data:startTime(time)&lt;br /&gt;
		checkSelf(self, 'startTime')&lt;br /&gt;
		checkTypeStringOrNum('fileLink:startTime', 1, time)&lt;br /&gt;
		data.theStartTime = time&lt;br /&gt;
		return self&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function data:endTime(time)&lt;br /&gt;
		checkSelf(self, 'endTime')&lt;br /&gt;
		checkTypeStringOrNum('fileLink:endTime', 1, time)&lt;br /&gt;
		data.theEndTime = time&lt;br /&gt;
		return self&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function data:thumbTime(time)&lt;br /&gt;
		checkSelf(self, 'thumbTime')&lt;br /&gt;
		checkTypeStringOrNum('fileLink:thumbTime', 1, time)&lt;br /&gt;
		data.theThumbTime = time&lt;br /&gt;
		return self&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function data:caption(s)&lt;br /&gt;
		checkSelf(self, 'caption')&lt;br /&gt;
		checkType('fileLink:caption', 1, s, 'string', true)&lt;br /&gt;
		data.theCaption = s&lt;br /&gt;
		return self&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function data:render()&lt;br /&gt;
		checkSelf(self, 'render')&lt;br /&gt;
		local ret = {}&lt;br /&gt;
		&lt;br /&gt;
		-- Filename&lt;br /&gt;
		if not data.theName then&lt;br /&gt;
			error('fileLink:render: no filename was found')&lt;br /&gt;
		end&lt;br /&gt;
		ret[#ret + 1] = 'File:' .. data.theName&lt;br /&gt;
		&lt;br /&gt;
		-- Format&lt;br /&gt;
		if data.theFormat and data.theFormatFilename then&lt;br /&gt;
			ret[#ret + 1] = data.theFormat .. '=' .. data.theFormatFilename&lt;br /&gt;
		elseif data.theFormat then&lt;br /&gt;
			ret[#ret + 1] = data.theFormat&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		-- Border&lt;br /&gt;
		if data.hasBorder then&lt;br /&gt;
			ret[#ret + 1] = 'border'&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		-- Location&lt;br /&gt;
		ret[#ret + 1] = data.theLocation&lt;br /&gt;
&lt;br /&gt;
		-- Alignment&lt;br /&gt;
		ret[#ret + 1] = data.theAlignment&lt;br /&gt;
		&lt;br /&gt;
		-- Size&lt;br /&gt;
		if data.isUpright and data.uprightFactor then&lt;br /&gt;
			ret[#ret + 1] = 'upright=' .. tostring(data.uprightFactor)&lt;br /&gt;
		elseif data.isUpright then&lt;br /&gt;
			ret[#ret + 1] = 'upright'&lt;br /&gt;
		elseif data.theWidth and data.theHeight then&lt;br /&gt;
			ret[#ret + 1] = string.format('%dx%dpx', data.theWidth, data.theHeight)&lt;br /&gt;
		elseif data.theWidth then&lt;br /&gt;
			ret[#ret + 1] = tostring(data.theWidth) .. 'px'&lt;br /&gt;
		elseif data.theHeight then&lt;br /&gt;
			ret[#ret + 1] = string.format('x%dpx', data.theHeight)&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		-- Render named parameters.&lt;br /&gt;
		-- That includes link, alt, page, class, lang, start, end, and thumbtime.&lt;br /&gt;
		do&lt;br /&gt;
			local namedParameters = {&lt;br /&gt;
				{'link', 'theLink'},&lt;br /&gt;
				{'alt', 'theAlt'},&lt;br /&gt;
				{'page', 'thePage'},&lt;br /&gt;
				{'class', 'theClass'},&lt;br /&gt;
				{'lang', 'theLang'},&lt;br /&gt;
				{'start', 'theStartTime'},&lt;br /&gt;
				{'end', 'theEndTime'},&lt;br /&gt;
				{'thumbtime', 'theThumbTime'}&lt;br /&gt;
			}&lt;br /&gt;
			for i, t in ipairs(namedParameters) do&lt;br /&gt;
				local parameter = t[1]&lt;br /&gt;
				local value = data[t[2]]&lt;br /&gt;
				if value then&lt;br /&gt;
					ret[#ret + 1] = parameter .. '=' .. tostring(value)&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		-- Caption&lt;br /&gt;
		ret[#ret + 1] = data.theCaption&lt;br /&gt;
		&lt;br /&gt;
		return string.format('[[%s]]', table.concat(ret, '|'))&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local privateFields = {&lt;br /&gt;
		theName = true,&lt;br /&gt;
		theFormat = true,&lt;br /&gt;
		theFormatFilename = true,&lt;br /&gt;
		theWidth = true,&lt;br /&gt;
		theHeight = true,&lt;br /&gt;
		isUpright = true,&lt;br /&gt;
		uprightFactor = true,&lt;br /&gt;
		theLocation = true,&lt;br /&gt;
		theAlignment = true,&lt;br /&gt;
		hasBorder = true,&lt;br /&gt;
		theLink = true,&lt;br /&gt;
		theAlt = true,&lt;br /&gt;
		thePage = true,&lt;br /&gt;
		theClass = true,&lt;br /&gt;
		theLang = true,&lt;br /&gt;
		theCaption = true&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	local readOnlyFields = {}&lt;br /&gt;
	for field in pairs(data) do&lt;br /&gt;
		readOnlyFields[field] = true&lt;br /&gt;
	end&lt;br /&gt;
	readOnlyFields.theName = nil -- This is set if a filename is given to fileLink.new, so remove it.&lt;br /&gt;
	&lt;br /&gt;
	local function restrictedFieldError(key, restriction)&lt;br /&gt;
		error(string.format(&lt;br /&gt;
			&amp;quot;fileLink object field '%s' is %s&amp;quot;,&lt;br /&gt;
			tostring(key),&lt;br /&gt;
			restriction&lt;br /&gt;
		), 3)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	setmetatable(obj, {&lt;br /&gt;
		__index = function (t, key)&lt;br /&gt;
			if privateFields[key] then&lt;br /&gt;
				restrictedFieldError(key, 'private')&lt;br /&gt;
			else&lt;br /&gt;
				return data[key]&lt;br /&gt;
			end&lt;br /&gt;
		end,&lt;br /&gt;
		__newindex = function (t, key, value)&lt;br /&gt;
			if privateFields[key] then&lt;br /&gt;
				restrictedFieldError(key, 'private')&lt;br /&gt;
			elseif readOnlyFields[key] then&lt;br /&gt;
				restrictedFieldError(key, 'read-only')&lt;br /&gt;
			else&lt;br /&gt;
				data[key] = value&lt;br /&gt;
			end&lt;br /&gt;
		end,&lt;br /&gt;
		__tostring = function (t)&lt;br /&gt;
			return t:render()&lt;br /&gt;
		end,&lt;br /&gt;
		__pairs = function ()&lt;br /&gt;
			local temp = {}&lt;br /&gt;
			for k, v in pairs(data) do&lt;br /&gt;
				if not privateFields[k] then&lt;br /&gt;
					temp[k] = v&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			return pairs(temp)&lt;br /&gt;
		end&lt;br /&gt;
	})&lt;br /&gt;
	&lt;br /&gt;
	return obj&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return fileLink&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Module:Lua_banner</id>
		<title>Module:Lua banner</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Module:Lua_banner"/>
				<updated>2014-06-03T11:28:49Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: p.renderTrackingCategories fix - titleObj is already local&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module implements the {{lua}} template.&lt;br /&gt;
&lt;br /&gt;
local yesno = require('Module:Yesno')&lt;br /&gt;
local mList = require('Module:List')&lt;br /&gt;
local mTableTools = require('Module:TableTools')&lt;br /&gt;
local mMessageBox = require('Module:Message box')&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
function p.main(frame)&lt;br /&gt;
	local origArgs = frame:getParent().args&lt;br /&gt;
	local args = {}&lt;br /&gt;
	for k, v in pairs(origArgs) do&lt;br /&gt;
		v = v:match('^%s*(.-)%s*$')&lt;br /&gt;
		if v ~= '' then&lt;br /&gt;
			args[k] = v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return p._main(args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._main(args)&lt;br /&gt;
	local modules = mTableTools.compressSparseArray(args)&lt;br /&gt;
	local box = p.renderBox(modules)&lt;br /&gt;
	local trackingCategories = p.renderTrackingCategories(args, modules)&lt;br /&gt;
	return box .. trackingCategories&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.renderBox(modules)&lt;br /&gt;
	local boxArgs = {}&lt;br /&gt;
	if #modules &amp;lt; 1 then&lt;br /&gt;
		boxArgs.text = '&amp;lt;strong class=&amp;quot;error&amp;quot;&amp;gt;Error: no modules specified&amp;lt;/strong&amp;gt;'&lt;br /&gt;
	else&lt;br /&gt;
		local moduleLinks = {}&lt;br /&gt;
		for i, module in ipairs(modules) do&lt;br /&gt;
			moduleLinks[i] = string.format('[[:%s]]', module)&lt;br /&gt;
		end&lt;br /&gt;
		local moduleList = mList.makeList('bulleted', moduleLinks)&lt;br /&gt;
		boxArgs.text = 'Uses [[Wikipedia:Lua|Lua]]:\n' .. moduleList&lt;br /&gt;
	end&lt;br /&gt;
	boxArgs.type = 'notice'&lt;br /&gt;
	boxArgs.small = true&lt;br /&gt;
	boxArgs.image = '[[File:Lua-logo-nolabel.svg|30px|alt=Lua logo|link=Wikipedia:Lua]]'&lt;br /&gt;
	return mMessageBox.main('mbox', boxArgs)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.renderTrackingCategories(args, modules, titleObj)&lt;br /&gt;
	if yesno(args.nocat) then&lt;br /&gt;
		return ''&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local cats = {}&lt;br /&gt;
	&lt;br /&gt;
	-- Error category&lt;br /&gt;
	if #modules &amp;lt; 1 then&lt;br /&gt;
		cats[#cats + 1] = 'Lua templates with errors'&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Lua templates category&lt;br /&gt;
	titleObj = titleObj or mw.title.getCurrentTitle()&lt;br /&gt;
	local subpageBlacklist = {&lt;br /&gt;
		doc = true,&lt;br /&gt;
		sandbox = true,&lt;br /&gt;
		sandbox2 = true,&lt;br /&gt;
		testcases = true&lt;br /&gt;
	}&lt;br /&gt;
	if titleObj.namespace == 10 &lt;br /&gt;
		and not subpageBlacklist[titleObj.subpageText]&lt;br /&gt;
	then&lt;br /&gt;
		local category = args.category&lt;br /&gt;
		if not category then&lt;br /&gt;
			local categories = {&lt;br /&gt;
				['Module:String'] = 'Lua String-based templates',&lt;br /&gt;
				['Module:Math'] = 'Templates based on the Math Lua module',&lt;br /&gt;
				['Module:BaseConvert'] = 'Templates based on the BaseConvert Lua module',&lt;br /&gt;
				['Module:Citation'] = 'Lua-based citation templates'&lt;br /&gt;
			}&lt;br /&gt;
			categories['Module:Citation/CS1'] = categories['Module:Citation']&lt;br /&gt;
			category = modules[1] and categories[modules[1]]&lt;br /&gt;
			category = category or 'Lua-based templates'&lt;br /&gt;
		end&lt;br /&gt;
		cats[#cats + 1] = category&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	for i, cat in ipairs(cats) do&lt;br /&gt;
		cats[i] = string.format('[[Category:%s]]', cat)&lt;br /&gt;
	end&lt;br /&gt;
	return table.concat(cats)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Module:TableTools</id>
		<title>Module:TableTools</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Module:TableTools"/>
				<updated>2014-05-25T14:11:02Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: fix cleanPattern function - some of the character classes were still being magic even when they were inside the set, so escape them all&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--                               TableTools                                       --&lt;br /&gt;
--                                                                                --&lt;br /&gt;
-- This module includes a number of functions for dealing with Lua tables.        --&lt;br /&gt;
-- It is a meta-module, meant to be called from other Lua modules, and should     --&lt;br /&gt;
-- not be called directly from #invoke.                                           --&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
&lt;br /&gt;
local libraryUtil = require('libraryUtil')&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
-- Define often-used variables and functions.&lt;br /&gt;
local floor = math.floor&lt;br /&gt;
local infinity = math.huge&lt;br /&gt;
local checkType = libraryUtil.checkType&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- isPositiveInteger&lt;br /&gt;
--&lt;br /&gt;
-- This function returns true if the given value is a positive integer, and false&lt;br /&gt;
-- if not. Although it doesn't operate on tables, it is included here as it is&lt;br /&gt;
-- useful for determining whether a given table key is in the array part or the&lt;br /&gt;
-- hash part of a table.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.isPositiveInteger(v)&lt;br /&gt;
	if type(v) == 'number' and v &amp;gt;= 1 and floor(v) == v and v &amp;lt; infinity then&lt;br /&gt;
		return true&lt;br /&gt;
	else&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- isNan&lt;br /&gt;
--&lt;br /&gt;
-- This function returns true if the given number is a NaN value, and false&lt;br /&gt;
-- if not. Although it doesn't operate on tables, it is included here as it is&lt;br /&gt;
-- useful for determining whether a value can be a valid table key. Lua will&lt;br /&gt;
-- generate an error if a NaN is used as a table key.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.isNan(v)&lt;br /&gt;
	if type(v) == 'number' and tostring(v) == '-nan' then&lt;br /&gt;
		return true&lt;br /&gt;
	else&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- shallowClone&lt;br /&gt;
--&lt;br /&gt;
-- This returns a clone of a table. The value returned is a new table, but all&lt;br /&gt;
-- subtables and functions are shared. Metamethods are respected, but the returned&lt;br /&gt;
-- table will have no metatable of its own.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.shallowClone(t)&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for k, v in pairs(t) do&lt;br /&gt;
		ret[k] = v&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- removeDuplicates&lt;br /&gt;
--&lt;br /&gt;
-- This removes duplicate values from an array. Non-positive-integer keys are&lt;br /&gt;
-- ignored. The earliest value is kept, and all subsequent duplicate values are&lt;br /&gt;
-- removed, but otherwise the array order is unchanged.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.removeDuplicates(t)&lt;br /&gt;
	checkType('removeDuplicates', 1, t, 'table')&lt;br /&gt;
	local isNan = p.isNan&lt;br /&gt;
	local ret, exists = {}, {}&lt;br /&gt;
	for i, v in ipairs(t) do&lt;br /&gt;
		if isNan(v) then&lt;br /&gt;
			-- NaNs can't be table keys, and they are also unique, so we don't need to check existence.&lt;br /&gt;
			ret[#ret + 1] = v&lt;br /&gt;
		else&lt;br /&gt;
			if not exists[v] then&lt;br /&gt;
				ret[#ret + 1] = v&lt;br /&gt;
				exists[v] = true&lt;br /&gt;
			end&lt;br /&gt;
		end	&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end			&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- numKeys&lt;br /&gt;
--&lt;br /&gt;
-- This takes a table and returns an array containing the numbers of any numerical&lt;br /&gt;
-- keys that have non-nil values, sorted in numerical order.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.numKeys(t)&lt;br /&gt;
	checkType('numKeys', 1, t, 'table')&lt;br /&gt;
	local isPositiveInteger = p.isPositiveInteger&lt;br /&gt;
	local nums = {}&lt;br /&gt;
	for k, v in pairs(t) do&lt;br /&gt;
		if isPositiveInteger(k) then&lt;br /&gt;
			nums[#nums + 1] = k&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	table.sort(nums)&lt;br /&gt;
	return nums&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- affixNums&lt;br /&gt;
--&lt;br /&gt;
-- This takes a table and returns an array containing the numbers of keys with the&lt;br /&gt;
-- specified prefix and suffix. For example, for the table&lt;br /&gt;
-- {a1 = 'foo', a3 = 'bar', a6 = 'baz'} and the prefix &amp;quot;a&amp;quot;, affixNums will&lt;br /&gt;
-- return {1, 3, 6}.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.affixNums(t, prefix, suffix)&lt;br /&gt;
	checkType('affixNums', 1, t, 'table')&lt;br /&gt;
	checkType('affixNums', 2, prefix, 'string', true)&lt;br /&gt;
	checkType('affixNums', 3, suffix, 'string', true)&lt;br /&gt;
&lt;br /&gt;
	local function cleanPattern(s)&lt;br /&gt;
		-- Cleans a pattern so that the magic characters ()%.[]*+-?^$ are interpreted literally.&lt;br /&gt;
		s = s:gsub('([%(%)%%%.%[%]%*%+%-%?%^%$])', '%%%1')&lt;br /&gt;
		return s&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	prefix = prefix or ''&lt;br /&gt;
	suffix = suffix or ''&lt;br /&gt;
	prefix = cleanPattern(prefix)&lt;br /&gt;
	suffix = cleanPattern(suffix)&lt;br /&gt;
	local pattern = '^' .. prefix .. '([1-9]%d*)' .. suffix .. '$'&lt;br /&gt;
&lt;br /&gt;
	local nums = {}&lt;br /&gt;
	for k, v in pairs(t) do&lt;br /&gt;
		if type(k) == 'string' then			&lt;br /&gt;
			local num = mw.ustring.match(k, pattern)&lt;br /&gt;
			if num then&lt;br /&gt;
				nums[#nums + 1] = tonumber(num)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	table.sort(nums)&lt;br /&gt;
	return nums&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- numData&lt;br /&gt;
--&lt;br /&gt;
-- Given a table with keys like (&amp;quot;foo1&amp;quot;, &amp;quot;bar1&amp;quot;, &amp;quot;foo2&amp;quot;, &amp;quot;baz2&amp;quot;), returns a table&lt;br /&gt;
-- of subtables in the format &lt;br /&gt;
-- { [1] = {foo = 'text', bar = 'text'}, [2] = {foo = 'text', baz = 'text'} }&lt;br /&gt;
-- Keys that don't end with an integer are stored in a subtable named &amp;quot;other&amp;quot;.&lt;br /&gt;
-- The compress option compresses the table so that it can be iterated over with&lt;br /&gt;
-- ipairs.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.numData(t, compress)&lt;br /&gt;
	checkType('numData', 1, t, 'table')&lt;br /&gt;
	checkType('numData', 2, compress, 'boolean', true)&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for k, v in pairs(t) do&lt;br /&gt;
		local prefix, num = mw.ustring.match(tostring(k), '^([^0-9]*)([1-9][0-9]*)$')&lt;br /&gt;
		if num then&lt;br /&gt;
			num = tonumber(num)&lt;br /&gt;
			local subtable = ret[num] or {}&lt;br /&gt;
			if prefix == '' then&lt;br /&gt;
				-- Positional parameters match the blank string; put them at the start of the subtable instead.&lt;br /&gt;
				prefix = 1&lt;br /&gt;
			end&lt;br /&gt;
			subtable[prefix] = v&lt;br /&gt;
			ret[num] = subtable&lt;br /&gt;
		else&lt;br /&gt;
			local subtable = ret.other or {}&lt;br /&gt;
			subtable[k] = v&lt;br /&gt;
			ret.other = subtable&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if compress then&lt;br /&gt;
		local other = ret.other&lt;br /&gt;
		ret = p.compressSparseArray(ret)&lt;br /&gt;
		ret.other = other&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- compressSparseArray&lt;br /&gt;
--&lt;br /&gt;
-- This takes an array with one or more nil values, and removes the nil values&lt;br /&gt;
-- while preserving the order, so that the array can be safely traversed with&lt;br /&gt;
-- ipairs.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.compressSparseArray(t)&lt;br /&gt;
	checkType('compressSparseArray', 1, t, 'table')&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	local nums = p.numKeys(t)&lt;br /&gt;
	for _, num in ipairs(nums) do&lt;br /&gt;
		ret[#ret + 1] = t[num]&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- sparseIpairs&lt;br /&gt;
--&lt;br /&gt;
-- This is an iterator for sparse arrays. It can be used like ipairs, but can&lt;br /&gt;
-- handle nil values.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.sparseIpairs(t)&lt;br /&gt;
	checkType('sparseIpairs', 1, t, 'table')&lt;br /&gt;
	local nums = p.numKeys(t)&lt;br /&gt;
	local i = 0&lt;br /&gt;
	local lim = #nums&lt;br /&gt;
	return function ()&lt;br /&gt;
		i = i + 1&lt;br /&gt;
		if i &amp;lt;= lim then&lt;br /&gt;
			local key = nums[i]&lt;br /&gt;
			return key, t[key]&lt;br /&gt;
		else&lt;br /&gt;
			return nil, nil&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- size&lt;br /&gt;
--&lt;br /&gt;
-- This returns the size of a key/value pair table. It will also work on arrays,&lt;br /&gt;
-- but for arrays it is more efficient to use the # operator.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.size(t)&lt;br /&gt;
	checkType('size', 1, t, 'table')&lt;br /&gt;
	local i = 0&lt;br /&gt;
	for k in pairs(t) do&lt;br /&gt;
		i = i + 1&lt;br /&gt;
	end&lt;br /&gt;
	return i&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Module:Hatnote</id>
		<title>Module:Hatnote</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Module:Hatnote"/>
				<updated>2014-05-23T23:28:43Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: Undid revision 609825678 by SMcCandlish (talk) this change will have quite far-reaching consequences, so should be discussed first&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--------------------------------------------------------------------------------&lt;br /&gt;
--                              Module:Hatnote                                --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
-- This module produces hatnote links and links to related articles. It       --&lt;br /&gt;
-- implements the {{hatnote}} and {{format hatnote link}} meta-templates, and --&lt;br /&gt;
-- includes helper functions for other Lua hatnote modules.                   --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local libraryUtil = require('libraryUtil')&lt;br /&gt;
local checkType = libraryUtil.checkType&lt;br /&gt;
local mArguments -- lazily initialise [[Module:Arguments]]&lt;br /&gt;
local yesno -- lazily initialise [[Module:Yesno]]&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Helper functions&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function getArgs(frame)&lt;br /&gt;
	-- Fetches the arguments from the parent frame. Whitespace is trimmed and&lt;br /&gt;
	-- blanks are removed.&lt;br /&gt;
	mArguments = require('Module:Arguments')&lt;br /&gt;
	return mArguments.getArgs(frame, {parentOnly = true})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function removeInitialColon(s)&lt;br /&gt;
	-- Removes the initial colon from a string, if present.&lt;br /&gt;
	return s:match('^:?(.*)')&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.findNamespaceId(link, removeColon)&lt;br /&gt;
	-- Finds the namespace id (namespace number) of a link or a pagename. This&lt;br /&gt;
	-- function will not work if the link is enclosed in double brackets. Colons&lt;br /&gt;
	-- are trimmed from the start of the link by default. To skip colon&lt;br /&gt;
	-- trimming, set the removeColon parameter to true.&lt;br /&gt;
	checkType('findNamespaceId', 1, link, 'string')&lt;br /&gt;
	checkType('findNamespaceId', 2, removeColon, 'boolean', true)&lt;br /&gt;
	if removeColon ~= false then&lt;br /&gt;
		link = removeInitialColon(link)&lt;br /&gt;
	end&lt;br /&gt;
	local namespace = link:match('^(.-):')&lt;br /&gt;
	if namespace then&lt;br /&gt;
		local nsTable = mw.site.namespaces[namespace]&lt;br /&gt;
		if nsTable then&lt;br /&gt;
			return nsTable.id&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return 0&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.formatPages(...)&lt;br /&gt;
	-- Formats a list of pages using formatLink and returns it as an array. Nil&lt;br /&gt;
	-- values are not allowed.&lt;br /&gt;
	local pages = {...}&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for i, page in ipairs(pages) do&lt;br /&gt;
		ret[i] = p._formatLink(page)&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.formatPageTables(...)&lt;br /&gt;
	-- Takes a list of page/display tables and returns it as a list of&lt;br /&gt;
	-- formatted links. Nil values are not allowed.&lt;br /&gt;
	local pages = {...}&lt;br /&gt;
	local links = {}&lt;br /&gt;
	for i, t in ipairs(pages) do&lt;br /&gt;
		checkType('formatPageTables', i, t, 'table')&lt;br /&gt;
		local link = t[1]&lt;br /&gt;
		local display = t[2]&lt;br /&gt;
		links[i] = p._formatLink(link, display)&lt;br /&gt;
	end&lt;br /&gt;
	return links&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.makeWikitextError(msg, helpLink, addTrackingCategory)&lt;br /&gt;
	-- Formats an error message to be returned to wikitext. If&lt;br /&gt;
	-- addTrackingCategory is not false after being returned from&lt;br /&gt;
	-- [[Module:Yesno]], and if we are not on a talk page, a tracking category&lt;br /&gt;
	-- is added.&lt;br /&gt;
	checkType('makeWikitextError', 1, msg, 'string')&lt;br /&gt;
	checkType('makeWikitextError', 2, helpLink, 'string', true)&lt;br /&gt;
	yesno = require('Module:Yesno')&lt;br /&gt;
	local title = mw.title.getCurrentTitle()&lt;br /&gt;
	-- Make the help link text.&lt;br /&gt;
	local helpText&lt;br /&gt;
	if helpLink then&lt;br /&gt;
		helpText = ' ([[' .. helpLink .. '|help]])'&lt;br /&gt;
	else&lt;br /&gt;
		helpText = ''&lt;br /&gt;
	end&lt;br /&gt;
	-- Make the category text.&lt;br /&gt;
	local category&lt;br /&gt;
	if not title.isTalkPage and yesno(addTrackingCategory) ~= false then&lt;br /&gt;
		category = 'Hatnote templates with errors'&lt;br /&gt;
		category = string.format(&lt;br /&gt;
			'[[%s:%s]]',&lt;br /&gt;
			mw.site.namespaces[14].name,&lt;br /&gt;
			category&lt;br /&gt;
		)&lt;br /&gt;
	else&lt;br /&gt;
		category = ''&lt;br /&gt;
	end&lt;br /&gt;
	return string.format(&lt;br /&gt;
		'&amp;lt;strong class=&amp;quot;error&amp;quot;&amp;gt;Error: %s%s.&amp;lt;/strong&amp;gt;%s',&lt;br /&gt;
		msg,&lt;br /&gt;
		helpText,&lt;br /&gt;
		category&lt;br /&gt;
	)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Format link&lt;br /&gt;
--&lt;br /&gt;
-- Makes a wikilink from the given link and display values. Links are escaped&lt;br /&gt;
-- with colons if necessary, and links to sections are detected and displayed&lt;br /&gt;
-- with &amp;quot; § &amp;quot; as a separator rather than the standard MediaWiki &amp;quot;#&amp;quot;. Used in&lt;br /&gt;
-- the {{format hatnote link}} template.&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
function p.formatLink(frame)&lt;br /&gt;
	local args = getArgs(frame)&lt;br /&gt;
	local link = args[1]&lt;br /&gt;
	local display = args[2]&lt;br /&gt;
	if not link then&lt;br /&gt;
		return p.makeWikitextError(&lt;br /&gt;
			'no link specified',&lt;br /&gt;
			'Template:Format hatnote link#Errors',&lt;br /&gt;
			args.category&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
	return p._formatLink(link, display)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._formatLink(link, display)&lt;br /&gt;
	-- Find whether we need to use the colon trick or not. We need to use the&lt;br /&gt;
	-- colon trick for categories and files, as otherwise category links&lt;br /&gt;
	-- categorise the page and file links display the file.&lt;br /&gt;
	checkType('_formatLink', 1, link, 'string')&lt;br /&gt;
	checkType('_formatLink', 2, display, 'string', true)&lt;br /&gt;
	link = removeInitialColon(link)&lt;br /&gt;
	local namespace = p.findNamespaceId(link, false)&lt;br /&gt;
	local colon&lt;br /&gt;
	if namespace == 6 or namespace == 14 then&lt;br /&gt;
		colon = ':'&lt;br /&gt;
	else&lt;br /&gt;
		colon = ''&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Find the display value.&lt;br /&gt;
	if not display then&lt;br /&gt;
		local page, section = link:match('^(.-)#(.*)$')&lt;br /&gt;
		if page then&lt;br /&gt;
			display = page .. ' § ' .. section&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Assemble the link.&lt;br /&gt;
	if display then&lt;br /&gt;
		return string.format('[[%s%s|%s]]', colon, link, display)&lt;br /&gt;
	else&lt;br /&gt;
		return string.format('[[%s%s]]', colon, link)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Hatnote&lt;br /&gt;
--&lt;br /&gt;
-- Produces standard hatnote text. Implements the {{hatnote}} template.&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
function p.hatnote(frame)&lt;br /&gt;
	local args = getArgs(frame)&lt;br /&gt;
	local s = args[1]&lt;br /&gt;
	local options = {}&lt;br /&gt;
	if not s then&lt;br /&gt;
		return p.makeWikitextError(&lt;br /&gt;
			'no text specified',&lt;br /&gt;
			'Template:Hatnote#Errors',&lt;br /&gt;
			args.category&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
	options.extraclasses = args.extraclasses&lt;br /&gt;
	options.selfref = args.selfref&lt;br /&gt;
	return p._hatnote(s, options)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._hatnote(s, options)&lt;br /&gt;
	checkType('_hatnote', 1, s, 'string')&lt;br /&gt;
	checkType('_hatnote', 2, options, 'table', true)&lt;br /&gt;
	local classes = {'hatnote'}&lt;br /&gt;
	local extraclasses = options.extraclasses&lt;br /&gt;
	local selfref = options.selfref&lt;br /&gt;
	if type(extraclasses) == 'string' then&lt;br /&gt;
		classes[#classes + 1] = extraclasses&lt;br /&gt;
	end&lt;br /&gt;
	if selfref then&lt;br /&gt;
		classes[#classes + 1] = 'selfref'&lt;br /&gt;
	end&lt;br /&gt;
	return string.format(&lt;br /&gt;
		'&amp;lt;div class=&amp;quot;%s&amp;quot;&amp;gt;%s&amp;lt;/div&amp;gt;',&lt;br /&gt;
		table.concat(classes, ' '),&lt;br /&gt;
		s&lt;br /&gt;
	)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Module:Yesno</id>
		<title>Module:Yesno</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Module:Yesno"/>
				<updated>2014-04-18T10:35:42Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: use the Lua string.lower function instead of mw.ustring.lower; this makes the function around 25x faster&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- Function allowing for consistent treatment of boolean-like wikitext input.&lt;br /&gt;
-- It works similarly to the template {{yesno}}.&lt;br /&gt;
&lt;br /&gt;
return function (val, default)&lt;br /&gt;
	-- If your wiki uses non-ascii characters for any of &amp;quot;yes&amp;quot;, &amp;quot;no&amp;quot;, etc., you&lt;br /&gt;
	-- should replace &amp;quot;val:lower()&amp;quot; with &amp;quot;mw.ustring.lower(val)&amp;quot; in the&lt;br /&gt;
	-- following line.&lt;br /&gt;
	val = type(val) == 'string' and val:lower() or val&lt;br /&gt;
	if val == nil then&lt;br /&gt;
		return nil&lt;br /&gt;
	elseif val == true &lt;br /&gt;
		or val == 'yes'&lt;br /&gt;
		or val == 'y'&lt;br /&gt;
		or val == 'true'&lt;br /&gt;
		or tonumber(val) == 1&lt;br /&gt;
	then&lt;br /&gt;
		return true&lt;br /&gt;
	elseif val == false&lt;br /&gt;
		or val == 'no'&lt;br /&gt;
		or val == 'n'&lt;br /&gt;
		or val == 'false'&lt;br /&gt;
		or tonumber(val) == 0&lt;br /&gt;
	then&lt;br /&gt;
		return false&lt;br /&gt;
	else&lt;br /&gt;
		return default&lt;br /&gt;
	end&lt;br /&gt;
end&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Module:Message_box</id>
		<title>Module:Message box</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Module:Message_box"/>
				<updated>2014-04-08T04:39:12Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: Allow passing attributes per protected edit request by User:Jackmcbarn. Also remove undocumented &amp;quot;hidden&amp;quot; parameter and format the module so it mostly fits within 80 chars.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This is a meta-module for producing message box templates, including&lt;br /&gt;
-- {{mbox}}, {{ambox}}, {{imbox}}, {{tmbox}}, {{ombox}}, {{cmbox}} and {{fmbox}}.&lt;br /&gt;
&lt;br /&gt;
-- Require necessary modules.&lt;br /&gt;
local getArgs = require('Module:Arguments').getArgs&lt;br /&gt;
local htmlBuilder = require('Module:HtmlBuilder')&lt;br /&gt;
local categoryHandler = require('Module:Category handler').main&lt;br /&gt;
local yesno = require('Module:Yesno')&lt;br /&gt;
&lt;br /&gt;
-- Load the configuration page.&lt;br /&gt;
local cfgTables = mw.loadData('Module:Message box/configuration')&lt;br /&gt;
&lt;br /&gt;
-- Get a language object for formatDate and ucfirst.&lt;br /&gt;
local lang = mw.language.getContentLanguage()&lt;br /&gt;
&lt;br /&gt;
-- Set aliases for often-used functions to reduce table lookups.&lt;br /&gt;
local format = mw.ustring.format&lt;br /&gt;
local tinsert = table.insert&lt;br /&gt;
local tconcat = table.concat&lt;br /&gt;
local trim = mw.text.trim&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Helper functions&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function getTitleObject(page, ...)&lt;br /&gt;
	if type(page) == 'string' then&lt;br /&gt;
		-- Get the title object, passing the function through pcall &lt;br /&gt;
		-- in case we are over the expensive function count limit.&lt;br /&gt;
		local success, title = pcall(mw.title.new, page, ...)&lt;br /&gt;
		if success then&lt;br /&gt;
			return title&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function union(t1, t2)&lt;br /&gt;
	-- Returns the union of two arrays.&lt;br /&gt;
	local vals = {}&lt;br /&gt;
	for i, v in ipairs(t1) do&lt;br /&gt;
		vals[v] = true&lt;br /&gt;
	end&lt;br /&gt;
	for i, v in ipairs(t2) do&lt;br /&gt;
		vals[v] = true&lt;br /&gt;
	end&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for k in pairs(vals) do&lt;br /&gt;
		tinsert(ret, k)&lt;br /&gt;
	end&lt;br /&gt;
	table.sort(ret)&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getArgNums(args, prefix)&lt;br /&gt;
	local nums = {}&lt;br /&gt;
	for k, v in pairs(args) do&lt;br /&gt;
		local num = mw.ustring.match(tostring(k), '^' .. prefix .. '([1-9]%d*)$')&lt;br /&gt;
		if num then&lt;br /&gt;
			tinsert(nums, tonumber(num))&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	table.sort(nums)&lt;br /&gt;
	return nums&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Box class definition&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local box = {}&lt;br /&gt;
box.__index = box&lt;br /&gt;
&lt;br /&gt;
function box.new()&lt;br /&gt;
	local obj = {}&lt;br /&gt;
	setmetatable(obj, box)&lt;br /&gt;
	return obj&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function box.getNamespaceId(ns)&lt;br /&gt;
	if not ns then return end&lt;br /&gt;
	if type(ns) == 'string' then&lt;br /&gt;
		ns = lang:ucfirst(mw.ustring.lower(ns))&lt;br /&gt;
		if ns == 'Main' then&lt;br /&gt;
			ns = 0&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local nsTable = mw.site.namespaces[ns]&lt;br /&gt;
	if nsTable then&lt;br /&gt;
		return nsTable.id&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function box.getMboxType(nsid)&lt;br /&gt;
	-- Gets the mbox type from a namespace number.&lt;br /&gt;
	if nsid == 0 then&lt;br /&gt;
		return 'ambox' -- main namespace&lt;br /&gt;
	elseif nsid == 6 then&lt;br /&gt;
		return 'imbox' -- file namespace&lt;br /&gt;
	elseif nsid == 14 then&lt;br /&gt;
		return 'cmbox' -- category namespace&lt;br /&gt;
	else&lt;br /&gt;
		local nsTable = mw.site.namespaces[nsid]&lt;br /&gt;
		if nsTable and nsTable.isTalk then&lt;br /&gt;
			return 'tmbox' -- any talk namespace&lt;br /&gt;
		else&lt;br /&gt;
			return 'ombox' -- other namespaces or invalid input&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function box:addCat(ns, cat, sort)&lt;br /&gt;
	if type(cat) ~= 'string' then return end&lt;br /&gt;
	local nsVals = {'main', 'template', 'all'}&lt;br /&gt;
	local tname&lt;br /&gt;
	for i, val in ipairs(nsVals) do&lt;br /&gt;
		if ns == val then&lt;br /&gt;
			tname = ns .. 'Cats'&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if not tname then&lt;br /&gt;
		for i, val in ipairs(nsVals) do&lt;br /&gt;
			nsVals[i] = format('&amp;quot;%s&amp;quot;', val)&lt;br /&gt;
		end&lt;br /&gt;
		error(&lt;br /&gt;
			'invalid ns parameter passed to box:addCat; valid values are '&lt;br /&gt;
			.. mw.text.listToText(nsVals, nil, ' or ')&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
	self[tname] = self[tname] or {}&lt;br /&gt;
	if type(sort) == 'string' then&lt;br /&gt;
		tinsert(self[tname], format('[[Category:%s|%s]]', cat, sort))&lt;br /&gt;
	else&lt;br /&gt;
		tinsert(self[tname], format('[[Category:%s]]', cat))&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function box:addClass(class)&lt;br /&gt;
	if type(class) ~= 'string' then return end&lt;br /&gt;
	self.classes = self.classes or {}&lt;br /&gt;
	tinsert(self.classes, class)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function box:addAttr(attr, val)&lt;br /&gt;
	if type(attr) ~= 'string' or type(val) ~= 'string' then return end&lt;br /&gt;
	self.attrs = self.attrs or {}&lt;br /&gt;
	tinsert(self.attrs, attr)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function box:setTitle(args)&lt;br /&gt;
	-- Get the title object and the namespace.&lt;br /&gt;
	self.pageTitle = getTitleObject(args.page ~= '' and args.page)&lt;br /&gt;
	self.title = self.pageTitle or mw.title.getCurrentTitle()&lt;br /&gt;
	self.demospace = args.demospace ~= '' and args.demospace or nil&lt;br /&gt;
	self.nsid = box.getNamespaceId(self.demospace) or self.title.namespace&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function box:getConfig(boxType)&lt;br /&gt;
	-- Get the box config data from the data page.&lt;br /&gt;
	if boxType == 'mbox' then&lt;br /&gt;
		boxType = box.getMboxType(self.nsid)&lt;br /&gt;
	end&lt;br /&gt;
	local cfg = cfgTables[boxType]&lt;br /&gt;
	if not cfg then&lt;br /&gt;
		local boxTypes = {}&lt;br /&gt;
		for k, v in pairs(dataTables) do&lt;br /&gt;
			tinsert(boxTypes, format('&amp;quot;%s&amp;quot;', k))&lt;br /&gt;
		end&lt;br /&gt;
		tinsert(boxTypes, '&amp;quot;mbox&amp;quot;')&lt;br /&gt;
		error(format(&lt;br /&gt;
			'invalid message box type &amp;quot;%s&amp;quot;; valid types are %s',&lt;br /&gt;
			tostring(boxType),&lt;br /&gt;
			mw.text.listToText(boxTypes)&lt;br /&gt;
		), 2)&lt;br /&gt;
	end&lt;br /&gt;
	return cfg&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function box:removeBlankArgs(cfg, args)&lt;br /&gt;
	-- Only allow blank arguments for the parameter names listed in&lt;br /&gt;
	-- cfg.allowBlankParams.&lt;br /&gt;
	local newArgs = {}&lt;br /&gt;
	for k, v in pairs(args) do&lt;br /&gt;
		if v ~= '' then&lt;br /&gt;
			newArgs[k] = v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	for i, param in ipairs(cfg.allowBlankParams or {}) do&lt;br /&gt;
		newArgs[param] = args[param]&lt;br /&gt;
	end&lt;br /&gt;
	return newArgs&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function box:setBoxParameters(cfg, args)&lt;br /&gt;
	-- Get type data.&lt;br /&gt;
	self.type = args.type&lt;br /&gt;
	local typeData = cfg.types[self.type]&lt;br /&gt;
	self.invalidTypeError = cfg.showInvalidTypeError&lt;br /&gt;
		and self.type&lt;br /&gt;
		and not typeData&lt;br /&gt;
		and true&lt;br /&gt;
		or false&lt;br /&gt;
	typeData = typeData or cfg.types[cfg.default]&lt;br /&gt;
	self.typeClass = typeData.class&lt;br /&gt;
	self.typeImage = typeData.image&lt;br /&gt;
&lt;br /&gt;
	-- Find if the box has been wrongly substituted.&lt;br /&gt;
	if cfg.substCheck and args.subst == 'SUBST' then&lt;br /&gt;
		self.isSubstituted = true&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Find whether we are using a small message box.&lt;br /&gt;
	if cfg.allowSmall and (&lt;br /&gt;
		cfg.smallParam and args.small == cfg.smallParam&lt;br /&gt;
		or not cfg.smallParam and yesno(args.small)&lt;br /&gt;
	)&lt;br /&gt;
	then&lt;br /&gt;
		self.isSmall = true&lt;br /&gt;
	else&lt;br /&gt;
		self.isSmall = false&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Add attributes, classes and styles.&lt;br /&gt;
	if cfg.allowId then&lt;br /&gt;
		self.id = args.id&lt;br /&gt;
	end&lt;br /&gt;
	self:addClass(&lt;br /&gt;
		cfg.usePlainlinksParam and yesno(args.plainlinks or true) and 'plainlinks'&lt;br /&gt;
	)&lt;br /&gt;
	for _, class in ipairs(cfg.classes or {}) do&lt;br /&gt;
		self:addClass(class)&lt;br /&gt;
	end&lt;br /&gt;
	if self.isSmall then&lt;br /&gt;
		self:addClass(cfg.smallClass or 'mbox-small')&lt;br /&gt;
	end&lt;br /&gt;
	self:addClass(self.typeClass)&lt;br /&gt;
	self:addClass(args.class)&lt;br /&gt;
	self.style = args.style&lt;br /&gt;
	self.attrs = args.attrs&lt;br /&gt;
&lt;br /&gt;
	-- Set text style.&lt;br /&gt;
	self.textstyle = args.textstyle&lt;br /&gt;
&lt;br /&gt;
	-- Find if we are on the template page or not. This functionality is only&lt;br /&gt;
	-- used if useCollapsibleTextFields is set, or if both cfg.templateCategory&lt;br /&gt;
	-- and cfg.templateCategoryRequireName are set.&lt;br /&gt;
	self.useCollapsibleTextFields = cfg.useCollapsibleTextFields&lt;br /&gt;
	if self.useCollapsibleTextFields&lt;br /&gt;
		or cfg.templateCategory&lt;br /&gt;
		and cfg.templateCategoryRequireName&lt;br /&gt;
	then&lt;br /&gt;
		self.name = args.name&lt;br /&gt;
		if self.name then&lt;br /&gt;
			local templateName = mw.ustring.match(&lt;br /&gt;
				self.name,&lt;br /&gt;
				'^[tT][eE][mM][pP][lL][aA][tT][eE][%s_]*:[%s_]*(.*)$'&lt;br /&gt;
			) or self.name&lt;br /&gt;
			templateName = 'Template:' .. templateName&lt;br /&gt;
			self.templateTitle = getTitleObject(templateName)&lt;br /&gt;
		end&lt;br /&gt;
		self.isTemplatePage = self.templateTitle&lt;br /&gt;
			and mw.title.equals(self.title, self.templateTitle)&lt;br /&gt;
			or false&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Process data for collapsible text fields. At the moment these are only&lt;br /&gt;
	-- used in {{ambox}}.&lt;br /&gt;
	if self.useCollapsibleTextFields then&lt;br /&gt;
		-- Get the self.issue value.&lt;br /&gt;
		if self.isSmall and args.smalltext then&lt;br /&gt;
			self.issue = args.smalltext&lt;br /&gt;
		else&lt;br /&gt;
			local sect&lt;br /&gt;
			if args.sect == '' then&lt;br /&gt;
				sect = 'This ' .. (cfg.sectionDefault or 'page')&lt;br /&gt;
			elseif type(args.sect) == 'string' then&lt;br /&gt;
				sect = 'This ' .. args.sect&lt;br /&gt;
			end&lt;br /&gt;
			local issue = args.issue&lt;br /&gt;
			issue = type(issue) == 'string' and issue ~= '' and issue or nil&lt;br /&gt;
			local text = args.text&lt;br /&gt;
			text = type(text) == 'string' and text or nil&lt;br /&gt;
			local issues = {}&lt;br /&gt;
			tinsert(issues, sect)&lt;br /&gt;
			tinsert(issues, issue)&lt;br /&gt;
			tinsert(issues, text)&lt;br /&gt;
			self.issue = tconcat(issues, ' ')&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		-- Get the self.talk value.&lt;br /&gt;
		local talk = args.talk&lt;br /&gt;
		-- Show talk links on the template page or template subpages if the talk&lt;br /&gt;
		-- parameter is blank.&lt;br /&gt;
		if talk == ''&lt;br /&gt;
			and self.templateTitle &lt;br /&gt;
			and (&lt;br /&gt;
				mw.title.equals(self.templateTitle, self.title)&lt;br /&gt;
				or self.title:isSubpageOf(self.templateTitle)&lt;br /&gt;
			)&lt;br /&gt;
		then&lt;br /&gt;
			talk = '#'&lt;br /&gt;
		elseif talk == '' then&lt;br /&gt;
			talk = nil&lt;br /&gt;
		end&lt;br /&gt;
		if talk then&lt;br /&gt;
			-- If the talk value is a talk page, make a link to that page. Else&lt;br /&gt;
			-- assume that it's a section heading, and make a link to the talk&lt;br /&gt;
			-- page of the current page with that section heading.&lt;br /&gt;
			local talkTitle = getTitleObject(talk)&lt;br /&gt;
			local talkArgIsTalkPage = true&lt;br /&gt;
			if not talkTitle or not talkTitle.isTalkPage then&lt;br /&gt;
				talkArgIsTalkPage = false&lt;br /&gt;
				talkTitle = getTitleObject(&lt;br /&gt;
					self.title.text,&lt;br /&gt;
					mw.site.namespaces[self.title.namespace].talk.id&lt;br /&gt;
				)&lt;br /&gt;
			end&lt;br /&gt;
			if talkTitle and talkTitle.exists then&lt;br /&gt;
				local talkText = 'Relevant discussion may be found on'&lt;br /&gt;
				if talkArgIsTalkPage then&lt;br /&gt;
					talkText = format(&lt;br /&gt;
						'%s [[%s|%s]].',&lt;br /&gt;
						talkText,&lt;br /&gt;
						talk,&lt;br /&gt;
						talkTitle.prefixedText&lt;br /&gt;
					)&lt;br /&gt;
				else&lt;br /&gt;
					talkText = format(&lt;br /&gt;
						'%s the [[%s#%s|talk page]].',&lt;br /&gt;
						talkText,&lt;br /&gt;
						talkTitle.prefixedText,&lt;br /&gt;
						talk&lt;br /&gt;
					)&lt;br /&gt;
				end&lt;br /&gt;
				self.talk = talkText&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		-- Get other values.&lt;br /&gt;
		self.fix = args.fix ~= '' and args.fix or nil&lt;br /&gt;
		local date&lt;br /&gt;
		if args.date and args.date ~= '' then&lt;br /&gt;
			date = args.date&lt;br /&gt;
		elseif args.date == '' and self.isTemplatePage then&lt;br /&gt;
			date = lang:formatDate('F Y')&lt;br /&gt;
		end&lt;br /&gt;
		if date then&lt;br /&gt;
			self.date = format(&amp;quot; &amp;lt;small&amp;gt;''(%s)''&amp;lt;/small&amp;gt;&amp;quot;, date)&lt;br /&gt;
		end&lt;br /&gt;
		self.info = args.info&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Set the non-collapsible text field. At the moment this is used by all box&lt;br /&gt;
	-- types other than ambox, and also by ambox when small=yes.&lt;br /&gt;
	if self.isSmall then&lt;br /&gt;
		self.text = args.smalltext or args.text&lt;br /&gt;
	else&lt;br /&gt;
		self.text = args.text&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Set the below row.&lt;br /&gt;
	self.below = cfg.below and args.below&lt;br /&gt;
&lt;br /&gt;
	-- General image settings.&lt;br /&gt;
	self.imageCellDiv = not self.isSmall and cfg.imageCellDiv and true or false&lt;br /&gt;
	self.imageEmptyCell = cfg.imageEmptyCell&lt;br /&gt;
	if cfg.imageEmptyCellStyle then&lt;br /&gt;
		self.imageEmptyCellStyle = 'border:none;padding:0px;width:1px'&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Left image settings.&lt;br /&gt;
	local imageLeft = self.isSmall and args.smallimage or args.image&lt;br /&gt;
	if cfg.imageCheckBlank and imageLeft ~= 'blank' and imageLeft ~= 'none'&lt;br /&gt;
		or not cfg.imageCheckBlank and imageLeft ~= 'none'&lt;br /&gt;
	then&lt;br /&gt;
		self.imageLeft = imageLeft&lt;br /&gt;
		if not imageLeft then&lt;br /&gt;
			local imageSize = self.isSmall&lt;br /&gt;
				and (cfg.imageSmallSize or '30x30px')&lt;br /&gt;
				or '40x40px'&lt;br /&gt;
			self.imageLeft = format('[[File:%s|%s|link=|alt=]]', self.typeImage&lt;br /&gt;
				or 'Imbox notice.png', imageSize)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Right image settings.&lt;br /&gt;
	local imageRight = self.isSmall and args.smallimageright or args.imageright&lt;br /&gt;
	if not (cfg.imageRightNone and imageRight == 'none') then&lt;br /&gt;
		self.imageRight = imageRight&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Add mainspace categories. At the moment these are only used in {{ambox}}.&lt;br /&gt;
	if cfg.allowMainspaceCategories then&lt;br /&gt;
		if args.cat then&lt;br /&gt;
			args.cat1 = args.cat&lt;br /&gt;
		end&lt;br /&gt;
		self.catNums = getArgNums(args, 'cat')&lt;br /&gt;
		if args.category then&lt;br /&gt;
			args.category1 = args.category&lt;br /&gt;
		end&lt;br /&gt;
		self.categoryNums = getArgNums(args, 'category')&lt;br /&gt;
		if args.all then&lt;br /&gt;
			args.all1 = args.all&lt;br /&gt;
		end&lt;br /&gt;
		self.allNums = getArgNums(args, 'all')&lt;br /&gt;
		self.categoryParamNums = union(self.catNums, self.categoryNums)&lt;br /&gt;
		self.categoryParamNums = union(self.categoryParamNums, self.allNums)&lt;br /&gt;
		-- The following is roughly equivalent to the old {{Ambox/category}}.&lt;br /&gt;
		local date = args.date&lt;br /&gt;
		date = type(date) == 'string' and date&lt;br /&gt;
		local preposition = 'from'&lt;br /&gt;
		for _, num in ipairs(self.categoryParamNums) do&lt;br /&gt;
			local mainCat = args['cat' .. tostring(num)]&lt;br /&gt;
				or args['category' .. tostring(num)]&lt;br /&gt;
			local allCat = args['all' .. tostring(num)]&lt;br /&gt;
			mainCat = type(mainCat) == 'string' and mainCat&lt;br /&gt;
			allCat = type(allCat) == 'string' and allCat&lt;br /&gt;
			if mainCat and date and date ~= '' then&lt;br /&gt;
				local catTitle = format('%s %s %s', mainCat, preposition, date)&lt;br /&gt;
				self:addCat('main', catTitle)&lt;br /&gt;
				catTitle = getTitleObject('Category:' .. catTitle)&lt;br /&gt;
				if not catTitle or not catTitle.exists then&lt;br /&gt;
					self:addCat(&lt;br /&gt;
						'main',&lt;br /&gt;
						'Articles with invalid date parameter in template'&lt;br /&gt;
					)&lt;br /&gt;
				end&lt;br /&gt;
			elseif mainCat and (not date or date == '') then&lt;br /&gt;
				self:addCat('main', mainCat)&lt;br /&gt;
			end&lt;br /&gt;
			if allCat then&lt;br /&gt;
				self:addCat('main', allCat)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Add template-namespace categories.&lt;br /&gt;
	if cfg.templateCategory then&lt;br /&gt;
		if cfg.templateCategoryRequireName then&lt;br /&gt;
			if self.isTemplatePage then&lt;br /&gt;
				self:addCat('template', cfg.templateCategory)&lt;br /&gt;
			end&lt;br /&gt;
		elseif not self.title.isSubpage then&lt;br /&gt;
			self:addCat('template', cfg.templateCategory)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Add template error category.&lt;br /&gt;
	if cfg.templateErrorCategory then&lt;br /&gt;
		local templateErrorCategory = cfg.templateErrorCategory&lt;br /&gt;
		local templateCat, templateSort&lt;br /&gt;
		if not self.name and not self.title.isSubpage then&lt;br /&gt;
			templateCat = templateErrorCategory&lt;br /&gt;
		elseif self.isTemplatePage then&lt;br /&gt;
			local paramsToCheck = cfg.templateErrorParamsToCheck or {}&lt;br /&gt;
			local count = 0&lt;br /&gt;
			for i, param in ipairs(paramsToCheck) do&lt;br /&gt;
				if not args[param] then&lt;br /&gt;
					count = count + 1&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			if count &amp;gt; 0 then&lt;br /&gt;
				templateCat = templateErrorCategory&lt;br /&gt;
				templateSort = tostring(count)&lt;br /&gt;
			end&lt;br /&gt;
			if self.categoryNums and #self.categoryNums &amp;gt; 0 then&lt;br /&gt;
				templateCat = templateErrorCategory&lt;br /&gt;
				templateSort = 'C'&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		self:addCat('template', templateCat, templateSort)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Categories for all namespaces.&lt;br /&gt;
	if self.invalidTypeError then&lt;br /&gt;
		local allSort = (self.nsid == 0 and 'Main:' or '') .. self.title.prefixedText&lt;br /&gt;
		self:addCat('all', 'Wikipedia message box parameter needs fixing', allSort)&lt;br /&gt;
	end&lt;br /&gt;
	if self.isSubstituted then&lt;br /&gt;
		self:addCat('all', 'Pages with incorrectly substituted templates')&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Convert category tables to strings and pass them through&lt;br /&gt;
	-- [[Module:Category handler]].&lt;br /&gt;
	self.categories = categoryHandler{&lt;br /&gt;
		main = tconcat(self.mainCats or {}),&lt;br /&gt;
		template = tconcat(self.templateCats or {}),&lt;br /&gt;
		all = tconcat(self.allCats or {}),&lt;br /&gt;
		nocat = args.nocat,&lt;br /&gt;
		demospace = self.demospace,&lt;br /&gt;
		page = self.pageTitle and self.pageTitle.prefixedText or nil&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function box:export()&lt;br /&gt;
	local root = htmlBuilder.create()&lt;br /&gt;
&lt;br /&gt;
	-- Add the subst check error.&lt;br /&gt;
	if self.isSubstituted and self.name then&lt;br /&gt;
		root&lt;br /&gt;
			.tag('b')&lt;br /&gt;
				.addClass('error')&lt;br /&gt;
				.wikitext(format(&lt;br /&gt;
					'Template &amp;lt;code&amp;gt;%s[[Template:%s|%s]]%s&amp;lt;/code&amp;gt; has been incorrectly substituted.',&lt;br /&gt;
					mw.text.nowiki('{{'), self.name, self.name, mw.text.nowiki('}}')&lt;br /&gt;
				))&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Create the box table.&lt;br /&gt;
	local boxTable = root.tag('table')&lt;br /&gt;
	boxTable&lt;br /&gt;
		.attr('id', self.id)&lt;br /&gt;
	for i, class in ipairs(self.classes or {}) do&lt;br /&gt;
		boxTable&lt;br /&gt;
			.addClass(class)&lt;br /&gt;
	end&lt;br /&gt;
	boxTable&lt;br /&gt;
		.cssText(self.style)&lt;br /&gt;
		.attr('role', 'presentation')&lt;br /&gt;
	for attr, val in pairs(self.attrs or {}) do&lt;br /&gt;
		boxTable&lt;br /&gt;
			.attr(attr, val)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Add the left-hand image.&lt;br /&gt;
	local row = boxTable.tag('tr')&lt;br /&gt;
	if self.imageLeft then&lt;br /&gt;
		local imageLeftCell = row.tag('td').addClass('mbox-image')&lt;br /&gt;
		if self.imageCellDiv then&lt;br /&gt;
			-- If we are using a div, redefine imageLeftCell so that the image&lt;br /&gt;
			-- is inside it. Divs use style=&amp;quot;width: 52px;&amp;quot;, which limits the&lt;br /&gt;
			-- image width to 52px. If any images in a div are wider than that,&lt;br /&gt;
			-- they may overlap with the text or cause other display problems.&lt;br /&gt;
			imageLeftCell = imageLeftCell.tag('div').css('width', '52px') &lt;br /&gt;
		end&lt;br /&gt;
		imageLeftCell&lt;br /&gt;
			.wikitext(self.imageLeft)&lt;br /&gt;
	elseif self.imageEmptyCell then&lt;br /&gt;
		-- Some message boxes define an empty cell if no image is specified, and&lt;br /&gt;
		-- some don't. The old template code in templates where empty cells are&lt;br /&gt;
		-- specified gives the following hint: &amp;quot;No image. Cell with some width&lt;br /&gt;
		-- or padding necessary for text cell to have 100% width.&amp;quot;&lt;br /&gt;
		row.tag('td')&lt;br /&gt;
			.addClass('mbox-empty-cell') &lt;br /&gt;
			.cssText(self.imageEmptyCellStyle)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Add the text.&lt;br /&gt;
	local textCell = row.tag('td').addClass('mbox-text')&lt;br /&gt;
	if self.useCollapsibleTextFields then&lt;br /&gt;
		-- The message box uses advanced text parameters that allow things to be&lt;br /&gt;
		-- collapsible. At the moment, only ambox uses this.&lt;br /&gt;
		textCell&lt;br /&gt;
			.cssText(self.textstyle)&lt;br /&gt;
		local textCellSpan = textCell.tag('span')&lt;br /&gt;
		textCellSpan&lt;br /&gt;
			.addClass('mbox-text-span')&lt;br /&gt;
			.wikitext(self.issue)&lt;br /&gt;
		if not self.isSmall then&lt;br /&gt;
			textCellSpan&lt;br /&gt;
				.tag('span')&lt;br /&gt;
					.addClass('hide-when-compact')&lt;br /&gt;
					.wikitext(self.talk and ' ' .. self.talk)&lt;br /&gt;
					.wikitext(self.fix and ' ' .. self.fix)&lt;br /&gt;
		end&lt;br /&gt;
		textCellSpan&lt;br /&gt;
			.wikitext(self.date and ' ' .. self.date)&lt;br /&gt;
		if not self.isSmall then&lt;br /&gt;
			textCellSpan&lt;br /&gt;
				.tag('span')&lt;br /&gt;
				.addClass('hide-when-compact')&lt;br /&gt;
				.wikitext(self.info and ' ' .. self.info)&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		-- Default text formatting - anything goes.&lt;br /&gt;
		textCell&lt;br /&gt;
			.cssText(self.textstyle)&lt;br /&gt;
			.wikitext(self.text)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Add the right-hand image.&lt;br /&gt;
	if self.imageRight then&lt;br /&gt;
		local imageRightCell = row.tag('td').addClass('mbox-imageright')&lt;br /&gt;
		if self.imageCellDiv then&lt;br /&gt;
			-- If we are using a div, redefine imageRightCell so that the image&lt;br /&gt;
			-- is inside it.&lt;br /&gt;
			imageRightCell = imageRightCell.tag('div').css('width', '52px')&lt;br /&gt;
		end&lt;br /&gt;
		imageRightCell&lt;br /&gt;
			.wikitext(self.imageRight)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Add the below row.&lt;br /&gt;
	if self.below then&lt;br /&gt;
		boxTable.tag('tr')&lt;br /&gt;
			.tag('td')&lt;br /&gt;
				.attr('colspan', self.imageRight and '3' or '2')&lt;br /&gt;
				.addClass('mbox-text')&lt;br /&gt;
				.cssText(self.textstyle)&lt;br /&gt;
				.wikitext(self.below)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Add error message for invalid type parameters.&lt;br /&gt;
	if self.invalidTypeError then&lt;br /&gt;
		root&lt;br /&gt;
			.tag('div')&lt;br /&gt;
				.css('text-align', 'center')&lt;br /&gt;
				.wikitext(format(&lt;br /&gt;
					'This message box is using an invalid &amp;quot;type=%s&amp;quot; parameter and needs fixing.',&lt;br /&gt;
					self.type or ''&lt;br /&gt;
				))&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Add categories.&lt;br /&gt;
	root&lt;br /&gt;
		.wikitext(self.categories)&lt;br /&gt;
&lt;br /&gt;
	return tostring(root)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function main(boxType, args)&lt;br /&gt;
	local outputBox = box.new()&lt;br /&gt;
	outputBox:setTitle(args)&lt;br /&gt;
	local cfg = outputBox:getConfig(boxType)&lt;br /&gt;
	args = outputBox:removeBlankArgs(cfg, args)&lt;br /&gt;
	outputBox:setBoxParameters(cfg, args)&lt;br /&gt;
	return outputBox:export()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function makeWrapper(boxType)&lt;br /&gt;
	return function (frame)&lt;br /&gt;
		local args = getArgs(frame, {trim = false, removeBlanks = false})&lt;br /&gt;
		return main(boxType, args)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local p = {&lt;br /&gt;
	main = main,&lt;br /&gt;
	mbox = makeWrapper('mbox')&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
for boxType in pairs(cfgTables) do&lt;br /&gt;
	p[boxType] = makeWrapper(boxType)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Module:Namespace_detect/config</id>
		<title>Module:Namespace detect/config</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Module:Namespace_detect/config"/>
				<updated>2014-04-05T17:03:49Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: use cfg.demopage rather than cfg.page now that the default parameter has been changed on the /data page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--------------------------------------------------------------------------------&lt;br /&gt;
--                    Namespace detect configuration data                     --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
-- This module stores configuration data for Module:Namespace detect. Here    --&lt;br /&gt;
-- you can localise the module to your wiki's language.                       --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
-- To activate a configuration item, you need to uncomment it. This means     --&lt;br /&gt;
-- that you need to remove the text &amp;quot;-- &amp;quot; at the start of the line.           --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local cfg = {} -- Don't edit this line.&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--                              Parameter names                               --&lt;br /&gt;
-- These configuration items specify custom parameter names. Values added     --&lt;br /&gt;
-- here will work in addition to the default English parameter names.         --&lt;br /&gt;
-- To add one extra name, you can use this format:                            --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
-- cfg.foo = 'parameter name'                                                 --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
-- To add multiple names, you can use this format:                            --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
-- cfg.foo = {'parameter name 1', 'parameter name 2', 'parameter name 3'}     --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
---- This parameter displays content for the main namespace:&lt;br /&gt;
-- cfg.main = 'main'&lt;br /&gt;
&lt;br /&gt;
---- This parameter displays in talk namespaces:&lt;br /&gt;
-- cfg.talk = 'talk'&lt;br /&gt;
&lt;br /&gt;
---- This parameter displays content for &amp;quot;other&amp;quot; namespaces (namespaces for which&lt;br /&gt;
---- parameters have not been specified):&lt;br /&gt;
-- cfg.other = 'other'&lt;br /&gt;
&lt;br /&gt;
---- This parameter makes talk pages behave as though they are the corresponding&lt;br /&gt;
---- subject namespace. Note that this parameter is used with [[Module:Yesno]].&lt;br /&gt;
---- Edit that module to change the default values of &amp;quot;yes&amp;quot;, &amp;quot;no&amp;quot;, etc.&lt;br /&gt;
-- cfg.subjectns = 'subjectns'&lt;br /&gt;
&lt;br /&gt;
---- This parameter sets a demonstration namespace:&lt;br /&gt;
-- cfg.demospace = 'demospace'&lt;br /&gt;
&lt;br /&gt;
---- This parameter sets a specific page to compare:&lt;br /&gt;
cfg.demopage = 'page'&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--                           Table configuration                              --&lt;br /&gt;
-- These configuration items allow customisation of the &amp;quot;table&amp;quot; function,     --&lt;br /&gt;
-- used to generate a table of possible parameters in the module              --&lt;br /&gt;
-- documentation.                                                             --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
---- The header for the namespace column in the wikitable containing the list of&lt;br /&gt;
---- possible subject-space parameters.&lt;br /&gt;
-- cfg.wikitableNamespaceHeader = 'Namespace'&lt;br /&gt;
&lt;br /&gt;
---- The header for the wikitable containing the list of possible subject-space&lt;br /&gt;
---- parameters.&lt;br /&gt;
-- cfg.wikitableAliasesHeader = 'Aliases'&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--                        End of configuration data                           --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
return cfg -- Don't edit this line.&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Module:Namespace_detect/data</id>
		<title>Module:Namespace detect/data</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Module:Namespace_detect/data"/>
				<updated>2014-04-05T17:02:16Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: bug fix - use the demospace parameter as both key and value in the argKeys table&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--------------------------------------------------------------------------------&lt;br /&gt;
--                          Namespace detect data                             --&lt;br /&gt;
-- This module holds data for [[Module:Namespace detect]] to be loaded per    --&lt;br /&gt;
-- page, rather than per #invoke, for performance reasons.                    --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local cfg = require('Module:Namespace detect/config')&lt;br /&gt;
&lt;br /&gt;
local function addKey(t, key, defaultKey)&lt;br /&gt;
	if key ~= defaultKey then&lt;br /&gt;
		t[#t + 1] = key&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get a table of parameters to query for each default parameter name.&lt;br /&gt;
-- This allows wikis to customise parameter names in the cfg table while&lt;br /&gt;
-- ensuring that default parameter names will always work. The cfg table&lt;br /&gt;
-- values can be added as a string, or as an array of strings.&lt;br /&gt;
&lt;br /&gt;
local defaultKeys = {&lt;br /&gt;
	'main',&lt;br /&gt;
	'talk',&lt;br /&gt;
	'other',&lt;br /&gt;
	'subjectns',&lt;br /&gt;
	'demospace',&lt;br /&gt;
	'demopage'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local argKeys = {}&lt;br /&gt;
for i, defaultKey in ipairs(defaultKeys) do&lt;br /&gt;
	argKeys[defaultKey] = {defaultKey}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
for defaultKey, t in pairs(argKeys) do&lt;br /&gt;
	local cfgValue = cfg[defaultKey]&lt;br /&gt;
	local cfgValueType = type(cfgValue)&lt;br /&gt;
	if cfgValueType == 'string' then&lt;br /&gt;
		addKey(t, cfgValue, defaultKey)&lt;br /&gt;
	elseif cfgValueType == 'table' then&lt;br /&gt;
		for i, key in ipairs(cfgValue) do&lt;br /&gt;
			addKey(t, key, defaultKey)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	cfg[defaultKey] = nil -- Free the cfg value as we don't need it any more.&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getParamMappings()&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Returns a table of how parameter names map to namespace names. The keys&lt;br /&gt;
	-- are the actual namespace names, in lower case, and the values are the&lt;br /&gt;
	-- possible parameter names for that namespace, also in lower case. The&lt;br /&gt;
	-- table entries are structured like this:&lt;br /&gt;
	-- {&lt;br /&gt;
	--   [''] = {'main'},&lt;br /&gt;
	--   ['wikipedia'] = {'wikipedia', 'project', 'wp'},&lt;br /&gt;
	--   ...&lt;br /&gt;
	-- }&lt;br /&gt;
	--]]&lt;br /&gt;
	local mappings = {}&lt;br /&gt;
	local mainNsName = mw.site.subjectNamespaces[0].name&lt;br /&gt;
	mainNsName = mw.ustring.lower(mainNsName)&lt;br /&gt;
	mappings[mainNsName] = mw.clone(argKeys.main)&lt;br /&gt;
	mappings['talk'] = mw.clone(argKeys.talk)&lt;br /&gt;
	for nsid, ns in pairs(mw.site.subjectNamespaces) do&lt;br /&gt;
		if nsid ~= 0 then -- Exclude main namespace.&lt;br /&gt;
			local nsname = mw.ustring.lower(ns.name)&lt;br /&gt;
			local canonicalName = mw.ustring.lower(ns.canonicalName)&lt;br /&gt;
			mappings[nsname] = {nsname}&lt;br /&gt;
			if canonicalName ~= nsname then&lt;br /&gt;
				table.insert(mappings[nsname], canonicalName)&lt;br /&gt;
			end&lt;br /&gt;
			for _, alias in ipairs(ns.aliases) do&lt;br /&gt;
				table.insert(mappings[nsname], mw.ustring.lower(alias))&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return mappings&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
	argKeys = argKeys,&lt;br /&gt;
	cfg = cfg,&lt;br /&gt;
	mappings = getParamMappings()&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Module:Message_box/configuration</id>
		<title>Module:Message box/configuration</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Module:Message_box/configuration"/>
				<updated>2014-01-27T01:07:32Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: allow the hidden arg to be blank, and allow tmbox to have an id attribute, per protected edit request by User:Technical 13&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;local ambox = {&lt;br /&gt;
	types = {&lt;br /&gt;
		speedy = {&lt;br /&gt;
			class = 'ambox-speedy',&lt;br /&gt;
			image = 'Ambox speedy deletion.png'&lt;br /&gt;
		},&lt;br /&gt;
		delete = {&lt;br /&gt;
			class = 'ambox-delete',&lt;br /&gt;
			image = 'Ambox deletion.png'&lt;br /&gt;
		},&lt;br /&gt;
		content = {&lt;br /&gt;
			class = 'ambox-content',&lt;br /&gt;
			image = 'Ambox content.png'&lt;br /&gt;
		},&lt;br /&gt;
		style = {&lt;br /&gt;
			class = 'ambox-style',&lt;br /&gt;
			image = 'Edit-clear.svg'&lt;br /&gt;
		},&lt;br /&gt;
		move = {&lt;br /&gt;
			class = 'ambox-move',&lt;br /&gt;
			image = 'Ambox move.png'&lt;br /&gt;
		},&lt;br /&gt;
		protection = {&lt;br /&gt;
			class = 'ambox-protection',&lt;br /&gt;
			image = 'Ambox protection.png'&lt;br /&gt;
		},&lt;br /&gt;
		notice = {&lt;br /&gt;
			class = 'ambox-notice',&lt;br /&gt;
			image = 'Ambox notice.png'&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	default                     = 'notice',&lt;br /&gt;
	allowBlankParams            = {'talk', 'sect', 'date', 'issue', 'fix', 'subst', 'hidden'},&lt;br /&gt;
	allowSmall                  = true,&lt;br /&gt;
	smallParam                  = 'left',&lt;br /&gt;
	smallClass                  = 'mbox-small-left',&lt;br /&gt;
	substCheck                  = true,&lt;br /&gt;
	classes                     = {'metadata', 'plainlinks', 'ambox'},&lt;br /&gt;
	imageEmptyCell              = true,&lt;br /&gt;
	imageCheckBlank             = true,&lt;br /&gt;
	imageSmallSize              = '20x20px',&lt;br /&gt;
	imageCellDiv                = true,&lt;br /&gt;
	useCollapsibleTextFields    = true,&lt;br /&gt;
	imageRightNone              = true,&lt;br /&gt;
	sectionDefault              = 'article',&lt;br /&gt;
	allowMainspaceCategories    = true,&lt;br /&gt;
	templateCategory            = 'Article message templates',&lt;br /&gt;
        templateCategoryRequireName = true,&lt;br /&gt;
	templateErrorCategory       = 'Article message templates with missing parameters',&lt;br /&gt;
	templateErrorParamsToCheck  = {'issue', 'fix', 'subst'}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local cmbox = {&lt;br /&gt;
	types = {&lt;br /&gt;
		speedy = {&lt;br /&gt;
			class = 'cmbox-speedy',&lt;br /&gt;
			image = 'Cmbox deletion.png'&lt;br /&gt;
		},&lt;br /&gt;
		delete = {&lt;br /&gt;
			class = 'cmbox-delete',&lt;br /&gt;
			image = 'Cmbox deletion.png'&lt;br /&gt;
		},&lt;br /&gt;
		content = {&lt;br /&gt;
			class = 'cmbox-content',&lt;br /&gt;
			image = 'Cmbox content.png'&lt;br /&gt;
		},&lt;br /&gt;
		style = {&lt;br /&gt;
			class = 'cmbox-style',&lt;br /&gt;
			image = 'Edit-clear.svg'&lt;br /&gt;
		},&lt;br /&gt;
		move = {&lt;br /&gt;
			class = 'cmbox-move',&lt;br /&gt;
			image = 'Cmbox move.png'&lt;br /&gt;
		},&lt;br /&gt;
		protection = {&lt;br /&gt;
			class = 'cmbox-protection',&lt;br /&gt;
			image = 'Cmbox protection.png'&lt;br /&gt;
		},&lt;br /&gt;
		notice = {&lt;br /&gt;
			class = 'cmbox-notice',&lt;br /&gt;
			image = 'Cmbox notice.png'&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	default              = 'notice',&lt;br /&gt;
	showInvalidTypeError = true,&lt;br /&gt;
	classes              = {'plainlinks', 'cmbox'},&lt;br /&gt;
	imageEmptyCell       = true&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local fmbox = {&lt;br /&gt;
	types = {&lt;br /&gt;
		warning = {&lt;br /&gt;
			class = 'fmbox-warning',&lt;br /&gt;
			image = 'Cmbox deletion.png'&lt;br /&gt;
		},&lt;br /&gt;
		editnotice = {&lt;br /&gt;
			class = 'fmbox-editnotice',&lt;br /&gt;
			image = 'Imbox notice.png'&lt;br /&gt;
		},&lt;br /&gt;
		system = {&lt;br /&gt;
			class = 'fmbox-system',&lt;br /&gt;
			image = 'Imbox notice.png'&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	default              = 'system',&lt;br /&gt;
	showInvalidTypeError = true,&lt;br /&gt;
	allowId                = true,&lt;br /&gt;
	classes              = {'plainlinks', 'fmbox'},&lt;br /&gt;
	imageEmptyCell       = false,&lt;br /&gt;
	imageRightNone       = false&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local imbox = {&lt;br /&gt;
	types = {&lt;br /&gt;
		speedy = {&lt;br /&gt;
			class = 'imbox-speedy',&lt;br /&gt;
			image = 'Imbox speedy deletion.png'&lt;br /&gt;
		},&lt;br /&gt;
		delete = {&lt;br /&gt;
			class = 'imbox-delete',&lt;br /&gt;
			image = 'Imbox deletion.png'&lt;br /&gt;
		},&lt;br /&gt;
		content = {&lt;br /&gt;
			class = 'imbox-content',&lt;br /&gt;
			image = 'Imbox content.png'&lt;br /&gt;
		},&lt;br /&gt;
		style = {&lt;br /&gt;
			class = 'imbox-style',&lt;br /&gt;
			image = 'Edit-clear.svg'&lt;br /&gt;
		},&lt;br /&gt;
		move = {&lt;br /&gt;
			class = 'imbox-move',&lt;br /&gt;
			image = 'Imbox move.png'&lt;br /&gt;
		},&lt;br /&gt;
		protection = {&lt;br /&gt;
			class = 'imbox-protection',&lt;br /&gt;
			image = 'Imbox protection.png'&lt;br /&gt;
		},&lt;br /&gt;
		license = {&lt;br /&gt;
			class = 'imbox-license',&lt;br /&gt;
			image = 'Imbox license.png'&lt;br /&gt;
		},&lt;br /&gt;
		featured = {&lt;br /&gt;
			class = 'imbox-featured',&lt;br /&gt;
			image = 'Imbox featured.png'&lt;br /&gt;
		},&lt;br /&gt;
		notice = {&lt;br /&gt;
			class = 'imbox-notice',&lt;br /&gt;
			image = 'Imbox notice.png'&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	default              = 'notice',&lt;br /&gt;
	showInvalidTypeError = true,&lt;br /&gt;
	classes              = {'imbox'},&lt;br /&gt;
	usePlainlinksParam   = true,&lt;br /&gt;
	imageEmptyCell       = true,&lt;br /&gt;
	below                = true,&lt;br /&gt;
	templateCategory     = 'File message boxes'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local ombox = {&lt;br /&gt;
	types = {&lt;br /&gt;
		speedy = {&lt;br /&gt;
			class = 'ombox-speedy',&lt;br /&gt;
			image = 'Imbox speedy deletion.png'&lt;br /&gt;
		},&lt;br /&gt;
		delete = {&lt;br /&gt;
			class = 'ombox-delete',&lt;br /&gt;
			image = 'Imbox deletion.png'&lt;br /&gt;
		},&lt;br /&gt;
		content = {&lt;br /&gt;
			class = 'ombox-content',&lt;br /&gt;
			image = 'Imbox content.png'&lt;br /&gt;
		},&lt;br /&gt;
		style = {&lt;br /&gt;
			class = 'ombox-style',&lt;br /&gt;
			image = 'Edit-clear.svg'&lt;br /&gt;
		},&lt;br /&gt;
		move = {&lt;br /&gt;
			class = 'ombox-move',&lt;br /&gt;
			image = 'Imbox move.png'&lt;br /&gt;
		},&lt;br /&gt;
		protection = {&lt;br /&gt;
			class = 'ombox-protection',&lt;br /&gt;
			image = 'Imbox protection.png'&lt;br /&gt;
		},&lt;br /&gt;
		notice = {&lt;br /&gt;
			class = 'ombox-notice',&lt;br /&gt;
			image = 'Imbox notice.png'&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	default              = 'notice',&lt;br /&gt;
	showInvalidTypeError = true,&lt;br /&gt;
	classes              = {'plainlinks', 'ombox'},&lt;br /&gt;
	allowSmall           = true,&lt;br /&gt;
	imageEmptyCell       = true,&lt;br /&gt;
	imageRightNone       = true&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local tmbox = {&lt;br /&gt;
	types = {&lt;br /&gt;
		speedy = {&lt;br /&gt;
			class = 'tmbox-speedy',&lt;br /&gt;
			image = 'Imbox speedy deletion.png'&lt;br /&gt;
		},&lt;br /&gt;
		delete = {&lt;br /&gt;
			class = 'tmbox-delete',&lt;br /&gt;
			image = 'Imbox deletion.png'&lt;br /&gt;
		},&lt;br /&gt;
		content = {&lt;br /&gt;
			class = 'tmbox-content',&lt;br /&gt;
			image = 'Imbox content.png'&lt;br /&gt;
		},&lt;br /&gt;
		style = {&lt;br /&gt;
			class = 'tmbox-style',&lt;br /&gt;
			image = 'Edit-clear.svg '&lt;br /&gt;
		},&lt;br /&gt;
		move = {&lt;br /&gt;
			class = 'tmbox-move',&lt;br /&gt;
			image = 'Imbox move.png'&lt;br /&gt;
		},&lt;br /&gt;
		protection = {&lt;br /&gt;
			class = 'tmbox-protection',&lt;br /&gt;
			image = 'Imbox protection.png'&lt;br /&gt;
		},&lt;br /&gt;
		notice = {&lt;br /&gt;
			class = 'tmbox-notice',&lt;br /&gt;
			image = 'Imbox notice.png'&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	default              = 'notice',&lt;br /&gt;
	showInvalidTypeError = true,&lt;br /&gt;
	classes              = {'plainlinks', 'tmbox'},&lt;br /&gt;
	allowId              = true,&lt;br /&gt;
	allowSmall           = true,&lt;br /&gt;
	imageRightNone       = true,&lt;br /&gt;
	imageEmptyCell       = true,&lt;br /&gt;
	imageEmptyCellStyle  = true,&lt;br /&gt;
	templateCategory     = 'Talk message boxes'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
	ambox = ambox,&lt;br /&gt;
	cmbox = cmbox,&lt;br /&gt;
	fmbox = fmbox,&lt;br /&gt;
	imbox = imbox,&lt;br /&gt;
	ombox = ombox,&lt;br /&gt;
	tmbox = tmbox&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Template:Ombox</id>
		<title>Template:Ombox</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Template:Ombox"/>
				<updated>2013-10-20T12:45:08Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: switch to Lua version&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#invoke:Message box|ombox}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;!-- Categories go on the /doc subpage, and interwikis go on Wikidata. --&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	<entry>
		<id>http://www.interstellarrift.com/wiki/index.php?title=Module:HtmlBuilder</id>
		<title>Module:HtmlBuilder</title>
		<link rel="alternate" type="text/html" href="http://www.interstellarrift.com/wiki/index.php?title=Module:HtmlBuilder"/>
				<updated>2013-09-18T15:22:39Z</updated>
		
		<summary type="html">&lt;p&gt;Mr. Stradivarius: don't add attributes with no values, plus a couple of minor tweaks&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- Module for building complex HTML (e.g. infoboxes, navboxes) using a fluent interface.&lt;br /&gt;
&lt;br /&gt;
local HtmlBuilder = {}&lt;br /&gt;
&lt;br /&gt;
local metatable = {}&lt;br /&gt;
&lt;br /&gt;
metatable.__index = function(t, key)&lt;br /&gt;
    local ret = rawget(t, key)&lt;br /&gt;
    if ret then&lt;br /&gt;
        return ret&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    ret = metatable[key]&lt;br /&gt;
    if type(ret) == 'function' then&lt;br /&gt;
        return function(...) &lt;br /&gt;
            return ret(t, ...) &lt;br /&gt;
        end &lt;br /&gt;
    else&lt;br /&gt;
        return ret&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
metatable.__tostring = function(t)&lt;br /&gt;
    local ret = {}&lt;br /&gt;
    t._build(ret)&lt;br /&gt;
    return table.concat(ret)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
metatable._build = function(t, ret)&lt;br /&gt;
    if t.tagName then &lt;br /&gt;
        table.insert(ret, '&amp;lt;' .. t.tagName)&lt;br /&gt;
        for i, attr in ipairs(t.attributes) do&lt;br /&gt;
            table.insert(ret, ' ' .. attr.name .. '=&amp;quot;' .. attr.val .. '&amp;quot;') &lt;br /&gt;
        end&lt;br /&gt;
        if #t.styles &amp;gt; 0 then&lt;br /&gt;
            table.insert(ret, ' style=&amp;quot;')&lt;br /&gt;
            for i, prop in ipairs(t.styles) do&lt;br /&gt;
                if type(prop) == 'string' then -- added with cssText()&lt;br /&gt;
                    table.insert(ret, prop .. ';')&lt;br /&gt;
                else -- added with css()&lt;br /&gt;
                    table.insert(ret, prop.name .. ':' .. prop.val .. ';')&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
            table.insert(ret, '&amp;quot;')&lt;br /&gt;
        end&lt;br /&gt;
        if t.selfClosing then&lt;br /&gt;
            table.insert(ret, ' /')&lt;br /&gt;
        end&lt;br /&gt;
        table.insert(ret, '&amp;gt;') &lt;br /&gt;
    end&lt;br /&gt;
    for i, node in ipairs(t.nodes) do&lt;br /&gt;
        if node then&lt;br /&gt;
            if type(node) == 'table' then&lt;br /&gt;
                node._build(ret)&lt;br /&gt;
            else&lt;br /&gt;
                table.insert(ret, tostring(node))&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if t.tagName and not t.unclosed and not t.selfClosing then&lt;br /&gt;
        table.insert(ret, '&amp;lt;/' .. t.tagName .. '&amp;gt;')&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
metatable.node = function(t, builder)&lt;br /&gt;
    if builder then&lt;br /&gt;
        table.insert(t.nodes, builder)&lt;br /&gt;
    end&lt;br /&gt;
    return t&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
metatable.wikitext = function(t, ...) &lt;br /&gt;
    local vals = {...}&lt;br /&gt;
    for i = 1, #vals do&lt;br /&gt;
        if vals[i] then&lt;br /&gt;
            table.insert(t.nodes, vals[i])&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return t&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
metatable.newline = function(t)&lt;br /&gt;
    table.insert(t.nodes, '\n')&lt;br /&gt;
    return t&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
metatable.tag = function(t, tagName, args)&lt;br /&gt;
    args = args or {}&lt;br /&gt;
    args.parent = t&lt;br /&gt;
    local builder = HtmlBuilder.create(tagName, args)&lt;br /&gt;
    table.insert(t.nodes, builder)&lt;br /&gt;
    return builder&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getAttr(t, name)&lt;br /&gt;
    for i, attr in ipairs(t.attributes) do&lt;br /&gt;
        if attr.name == name then&lt;br /&gt;
            return attr&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
metatable.attr = function(t, name, val)&lt;br /&gt;
    if type(val) == 'string' or type(val) == 'number' then&lt;br /&gt;
        -- if caller sets the style attribute explicitly, then replace all styles previously added with css() and cssText()&lt;br /&gt;
        if name == 'style' then&lt;br /&gt;
            t.styles = {val}&lt;br /&gt;
            return t&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        local attr = getAttr(t, name)&lt;br /&gt;
        if attr then&lt;br /&gt;
            attr.val = val&lt;br /&gt;
        else&lt;br /&gt;
            table.insert(t.attributes, {name = name, val = val})&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    return t&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
metatable.addClass = function(t, class)&lt;br /&gt;
    if class then&lt;br /&gt;
        local attr = getAttr(t, 'class')&lt;br /&gt;
        if attr then&lt;br /&gt;
            attr.val = attr.val .. ' ' .. class&lt;br /&gt;
        else&lt;br /&gt;
            t.attr('class', class)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    return t&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
metatable.css = function(t, name, val)&lt;br /&gt;
    if type(val) == 'string' or type(val) == 'number' then&lt;br /&gt;
        for i, prop in ipairs(t.styles) do&lt;br /&gt;
            if prop.name == name then&lt;br /&gt;
                prop.val = val&lt;br /&gt;
                return t&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        table.insert(t.styles, {name = name, val = val})&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    return t&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
metatable.cssText = function(t, css)&lt;br /&gt;
    if css then&lt;br /&gt;
        table.insert(t.styles, css)&lt;br /&gt;
    end&lt;br /&gt;
    return t&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
metatable.done = function(t)&lt;br /&gt;
    return t.parent or t&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
metatable.allDone = function(t)&lt;br /&gt;
    while t.parent do&lt;br /&gt;
        t = t.parent&lt;br /&gt;
    end&lt;br /&gt;
    return t&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function HtmlBuilder.create(tagName, args)&lt;br /&gt;
    args = args or {}&lt;br /&gt;
    local builder = {}&lt;br /&gt;
    setmetatable(builder, metatable)&lt;br /&gt;
    builder.nodes = {}&lt;br /&gt;
    builder.attributes = {}&lt;br /&gt;
    builder.styles = {}&lt;br /&gt;
    builder.tagName = tagName&lt;br /&gt;
    builder.parent = args.parent&lt;br /&gt;
    builder.unclosed = args.unclosed or false&lt;br /&gt;
    builder.selfClosing = args.selfClosing or false&lt;br /&gt;
    return builder&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return HtmlBuilder&lt;/div&gt;</summary>
		<author><name>Mr. Stradivarius</name></author>	</entry>

	</feed>