Permanently protected module
From Wikipedia, the free encyclopedia


local getArgs = require('Module:Arguments').getArgs

local yesno = require('Module:Yesno')



local rawData = mw.loadData('Module:Sanctions/data')

local data = rawData.sanctions

local aliasMap = rawData.aliases



local messageBox = require('Module:Message box')



-- Functions



local function tableContainsValue(needle, haystack)

	for _, v in pairs(haystack) do

		if v == needle then

			return true

		end

	end

	return false

end



local function _getTopicData(topicAlias)

	if datatopicAlias then

		return datatopicAlias

	elseif aliasMaptopicAlias then

		return dataaliasMaptopicAlias]]

	else

		return false

	end

end



-- Returns an invalid topic error, with a table of acceptable topics

local function syntaxHelp()

	return [[<span class="error">{{para|topic}} not specified. Available options:</span><div style="border-left: 5px dashed black; border-right: 5px dashed black; border-bottom: 5px dashed black; padding-left: 0.5em; padding-right: 0.5em; padding-bottom: 0.5em;">

	{{Gs/topics/table}}

	</div>]]

end



-- Topic class



local Topic = {}

Topic.__index = Topic



function Topic.new(topicCode, args)

	local obj = {}

	obj._args = args

	obj._topicData = _getTopicData(topicCode)

	

	return setmetatable(obj, Topic)

end



function Topic:get(arg)

	return self._topicDataarg

end



function Topic:exists()

	return ((self._topicData ~= nil) and (self._topicData ~= false))

end



function Topic:hasGlobalRestriction(type)

	return self._topicData.restrictionstype

end



function Topic:hasLocalRestriction(type)

	local localRestriction = self._argstype

	if localRestriction then

		if mw.ustring.find(type, '^restriction') ~= nil then

			return true

		else

			return yesno(localRestriction)

		end

	else

		return false

	end

end



function Topic:hasRestriction(type)

	return self:hasGlobalRestriction(type) or self:hasLocalRestriction(type)

end



function Topic:hasRestrictions(arr)

	for _, v in ipairs(arr) do

		if self:hasRestriction(v) then

			return true

		end

	end

	

	return false

end



function Topic:hasAnyRevertRestrictions()

	return self:hasRestrictions({'1rr', 'consensusrequired', 'brd'})

end



function Topic:hasAnyRestrictions()

	return self:hasAnyRevertRestrictions() or self:hasRestrictions({'restriction1'})

end



function Topic:getCustomRestrictions()

	local customRestrictions = {}

	local ri = 1

	local checkArr = self._topicData.restrictions

	local breakNext = false

	while true do

		if checkArr'restriction'..ri then

			table.insert(customRestrictions, checkArr'restriction'..ri])

			ri = ri + 1

		else

			if breakNext then

				break

			else

				ri = 1

				checkArr = self._args

				breakNext = true

			end

		end

	end

	

	return customRestrictions

end



-- End classes



-- This function builds a talk notice

-- TODO: split this up

--

-- @param frame

-- @param topic topic class instance

-- @param args arguments passed to wrapper template

-- @returns String representation of notice

local function buildTalkNotice(frame, topic, args)

	local type = args'type' or args2 or 'mini'

	local out = mw.html.create('')

	local hasRestrictions = topic:hasAnyRestrictions()

	local hasRevertRestrictions = topic:hasAnyRevertRestrictions()

	

	if hasRestrictions then

		type = 'long' -- force long displaywhere custom restrictions are applicable



		out

			:tag('span')

				:css('font-size', '120%')

				:wikitext("'''WARNING: ACTIVE COMMUNITY SANCTIONS'''")

	end



	if hasRestrictions then

		out

			:tag('p')

				:wikitext("The article [[:{{SUBJECTPAGENAME}}]], along with other pages relating to "..topic:get('scope')..", is designated by the community as a '''[[Wikipedia:Contentious topics|contentious topic]]'''. The current restrictions are:")

	else

		out

			:tag('p')

				:wikitext("<strong>The use of the [[Wikipedia:Contentious topics|contentious topics procedure]] has been authorised by the community for pages related to ".. topic:get('scope') ..", including this page.</strong>" .. (type == 'mini' and ' Editors who repeatedly or seriously fail to adhere to the [[Wikipedia:Five_pillars|purpose of Wikipedia]], any expected [[Wikipedia:Etiquette|standards of behaviour]], or any [[Wikipedia:List_of_policies|normal editorial process]] may be sanctioned.' or ''))

	end



	if not (type == 'mini') then

		local restrictionList = mw.html.create('ul')



		-- 1RR

		if topic:hasRestriction('1rr') then

			restrictionList

				:tag('li')

					:wikitext("'''Limit of one revert in 24 hours:''' This article is under [[Wikipedia:Edit warring#Other revert rules|WP:1RR]] (one [[Wikipedia:Reverting|revert]] per editor per article ''per 24-hour period'')")

		end



		-- Text for boilerplate/predefined restrictions

		if topic:hasRestriction('consensusrequired') then

			restrictionList

				:tag('li')

					:wikitext("'''Consensus required:''' All editors must obtain [[WP:Consensus|consensus]] on the talk page of this article before reinstating ''any edits that have been challenged (via reversion).'' This includes making edits similar to the ones that have been challenged. If in doubt, do not make the edit.")

		end



		if topic:hasRestriction('brd') then

			restrictionList

				:tag('li')

					:wikitext("'''24-hr [[Wikipedia:BOLD, revert, discuss cycle|BRD cycle]]:''' If a change you make to this article is reverted, you may not reinstate that change unless you discuss the issue on the talk page and wait 24 hours (from the time of the original edit). Partial reverts/reinstatements that reasonably address objections of other editors [[Wikipedia:BOLD, revert, discuss cycle#WP:BRR|are preferable]] to wholesale reverts.")

		end

		

		local customRestrictions = topic:getCustomRestrictions()

		for _, v in ipairs(customRestrictions) do

			restrictionList

				:tag('li')

					:wikitext(v)

		end

		

		if hasRestrictions then

			out:node(restrictionList)

		end



		out

			:tag('p')

				:wikitext("Editors who repeatedly or seriously fail to adhere to the [[Wikipedia:Five_pillars|purpose of Wikipedia]], any expected [[Wikipedia:Etiquette|standards of behaviour]], or any [[Wikipedia:List_of_policies|normal editorial process]] may be sanctioned.")

			

		-- Further info box

		if hasRestrictions then

			local furtherInfo = mw.html.create('')



			-- Enforcement procedures

			furtherInfo

				:tag('p')

					:wikitext('Enforcement procedures:')

					:done()



			local enforcementProcedures = mw.html.create('ul')



			if hasRestrictions then

				enforcementProcedures

					:tag('li')

						:wikitext("Violations of any restrictions " .. (hasRevertRestrictions and "(excluding 1RR/reverting violations) " or "") .. "and other conduct issues should be reported to the [[Wikipedia:Administrators' noticeboard/Incidents|administrators' incidents noticeboard]]." .. (hasRevertRestrictions and " Violations of revert restrictions should be reported to the [[Wikipedia:Administrators' noticeboard/Edit warring|administrators' edit warring noticeboard]]." or ""))

						:done()

					:tag('li')

						:wikitext("Editors who violate any listed restrictions may be blocked by any uninvolved administrator, even on a first offense.")

						:done()

			else

				enforcementProcedures

					:tag('li')

						:wikitext("Problems should be reported to the [[Wikipedia:Administrators' noticeboard/Incidents|administrators' incidents noticeboard]].")

						:done()

			end



			enforcementProcedures

				:tag('li')

					:wikitext("An editor must be [[Wikipedia:Contentious topics#Awareness of contentious topics|aware]] before they can be sanctioned.")

					:allDone()

			furtherInfo:node(enforcementProcedures)



			if hasRevertRestrictions then

				furtherInfo

					:tag('p')

						:wikitext("With respect to any reverting restrictions:")

						:done()

					:tag('ul')

						:tag('li')

							:wikitext("Edits made solely to enforce any clearly established consensus are exempt from all edit-warring restrictions. In order to be considered \"clearly established\" the consensus must be proven by prior talk-page discussion.")

							:done()

						:tag('li')

							:wikitext("Edits made which remove or otherwise change any material placed by clearly established consensus, without first obtaining consensus to do so, may be treated in the same manner as clear vandalism.")

							:done()

						:tag('li')

							:wikitext("Clear vandalism of any origin may be reverted without restriction.")

							:done()

						:tag('li')

							:wikitext("Reverts of edits made by anonymous (IP) editors that are not vandalism are exempt from the 1RR but are subject to [[Wikipedia:Edit warring|the usual rules on edit warring]]. If you are in doubt, contact an administrator for assistance.")

							:allDone()

					:tag('p')

							:wikitext("If you are unsure if your edit is appropriate, discuss it here on this talk page first. <strong>Remember: When in doubt, don't revert!</strong>")

			end



			local collapsed = frame:expandTemplate{ title = 'collapse', args = {

				tostring(furtherInfo),

				'<span style="color:red">Remedy instructions and exemptions</span>',

				'bg' = '#EEE8AA'

			}}

			

			out

				:newline()

				:node(collapsed)

		end

		-- End further info box

	end



	local box = messageBox.main( 'tmbox', {

		type = 'notice',

		image = type == 'long' and '[[File:Commons-emblem-issue.svg|50px]]' or '[[File:Commons-emblem-hand-orange.svg|40px]]',

		text = frame:preprocess(tostring(out))

    })



    return box

end



-- Builds an alert notice

--

-- @param frame

-- @param topic topic class instance

-- @returns String representation of notice

local function buildAlert(frame, topic, sig)

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

		:addClass('gs-alert')

		:cssText("border: 1px solid #AAA; background-color: #E5F8FF; padding: 0.5em; width: 100%; margin-bottom: 1em")



	out

		:tag('tr')

			:tag('td')

				:cssText("vertical-align:middle; padding-left:1px; padding-right:0.5em;")

				:wikitext("[[File:Commons-emblem-notice.svg|50px]]")

				:done()

			:tag('td')

				:wikitext("This is a standard message to notify contributors about an administrative ruling in effect. ''It does '''not''' imply that there are any issues with your contributions to date.''")

				:newline()

				:wikitext("You have shown interest in ".. topic:get('scope') ..". Due to past disruption in this topic area, the community has authorised uninvolved administrators to impose [[Wikipedia:Contentious topics|contentious topics restrictions]]—such as [[Wikipedia:Editing restrictions#Types of restrictions|editing restrictions]], [[Wikipedia:Banning policy#Types of bans|bans]], or [[WP:Blocking policy|blocks]]—on editors who do not strictly follow [[Wikipedia:List of policies|Wikipedia's policies]], expected [[Wikipedia:Etiquette|standards of behaviour]], or the [[Wikipedia:Contentious topics#Standard set|page-specific restrictions]], when making edits related to the topic.")

				:newline()

				:wikitext("For additional information, please see the [[".. topic:get('wikilink') .."|guidance on these sanctions]]. If you have any questions, or any doubts regarding what edits are appropriate, you are welcome to discuss them with me or any other editor." .. (sig and ' '..sig or ''))



	return frame:preprocess(tostring(out))

end



-- Builds an edit notice

local function buildEditNotice(frame, topic, args)

	local enHeader = mw.html.create('')

	local restrictionMsgs = {}

	

	if topic:hasRestriction('1rr') then

		table.insert(restrictionMsgs, "Editors must not make more than one [[Help:Reverting|revert]] per 24 hours (subject to [[Wikipedia:Edit warring#Exemptions|exceptions]])")

	end

	

	if topic:hasRestriction('consensusrequired') then

		table.insert(restrictionMsgs, "Editors must not reinstate any challenged edits (via reversion) without first obtaining [[Wikipedia:Consensus|consensus]] on the talk page of this article")

	end



	local customRestrictions = topic:getCustomRestrictions()

	for _, v in ipairs(customRestrictions) do

		table.insert(restrictionMsgs, v)

	end



	if #restrictionMsgs == 0 then

		return frame:preprocess(syntaxHelp())

	else

		local list = mw.html.create('ul')

		for _,v in ipairs(restrictionMsgs) do

			list

				:tag('li')

					:wikitext(v)

					:done()

		end

		enHeader:wikitext(tostring(list))

	end



	local enText = mw.html.create('')

	enText

		:tag('p')

			:wikitext("<strong>Breaching the restriction on this page may result in a block or other sanctions.</strong> In addition, please note that because this topic area has been disrupted in the past, the community has [["..topic:get('wikilink').."|authorised]] administrators to take [[Wikipedia:Contentious topics|appropriate steps]] to ensure the smooth running of all pages related to "..topic:get('scope')..". Conduct which does not adhere to our policies and [[Wikipedia:Etiquette|standards of behaviour]] may be met with sanctions. Please edit carefully.")

			:done()



	local editnotice = frame:expandTemplate{ title = 'editnotice', args = {

		expiry = "indefinite",

		headerstyle = "font-size: 120%;",

		style = "background: ivory;",

		image = "Commons-emblem-issue.svg",

		imagesize = "50px",

		header = tostring(enHeader),

		text = tostring(enText)

	}}



	return editnotice

end



--/////////--

-- EXPORTS

--/////////--

local p = {}



-- Returns a talk notice

-- For documentation, see [[Template:Gs/talk notice]]

function p.talknotice(frame)

	local args = getArgs(frame, {

		wrappers = {

			'Template:Gs/talk notice',

			'Template:Gs/talk notice/sandbox'

		}

	})



	local topic = Topic.new(args'topic' or args1], args)



	if not topic:exists() then

		return frame:preprocess(syntaxHelp())

	end

	

	return buildTalkNotice(frame, topic, args)

end



-- Returns an alert

-- For documentation, see [[Template:Gs/alert]]

function p.alert(frame)

	local args = getArgs(frame, {

		wrappers = {

			'Template:Gs/alert',

			'Template:Gs/alert/sandbox',

		}

	})



	local topic = Topic.new(args'topic' or args1], args)

	if not topic:exists() then

		return frame:preprocess(syntaxHelp())

	elseif not topic:hasRestriction('ds') then

		return frame:preprocess('<span class="error">This topic area is not designated as a contentious topic. Alert is not required.</span>')

	end

	

	return buildAlert(frame, topic, args'sig'])

end



-- Returns an edit notice

-- For documentation, see [[Template:Gs/editnotice]]

function p.editnotice(frame)

	local args = getArgs(frame, {

		wrappers = {

			'Template:Gs/editnotice',

			'Template:Gs/editnotice/sandbox'

		}

	})



	local topic = Topic.new(args'topic' or args1], args)

	if not topic:exists() then

		return frame:preprocess(syntaxHelp())

	elseif not topic:hasAnyRestrictions() then

		return frame:preprocess('<span class="error">Page sanctions are not authorised for this topic area. Edit notice is not required.</span>[[Category:Pages with sanctions errors]]')

	end



	return buildEditNotice(frame, topic, args)

end



function p.table(frame)

	local args = getArgs(frame, {

		wrappers = {

			'Template:Gs/topics/table',

			'Template:Gs/topics/table/sandbox',

		}

	})



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

		:addClass('wikitable')

		:css('font-size', '9pt')

		:css('background', 'transparent')



	-- Headers

	tbl:tag('tr')

		:tag('th')

			:wikitext("Topic code")

			:done()

		:tag('th')

			:wikitext("Area of conflict")

			:done()

		:tag('th')

			:wikitext("Decision linked to")

			:allDone()

	

	-- sort alphabetically

	local sortedTable = {}

	for n in pairs(data) do

		table.insert(sortedTable, n)

	end

	table.sort(sortedTable)



	for _,v in ipairs(sortedTable) do

		local sanction = datav

		local title = mw.title.new(sanction.wikilink).redirectTarget			-- probably unnecessarily expensive; just add to config

		tbl:tag('tr')

			:tag('td')

				:wikitext(frame:preprocess("{{tlx"..(args'subst' and "s" or "").."|{{#ifeq:{{BASEPAGENAME}}|Gs|{{PAGENAME}}|{{BASEPAGENAME}}}}|<nowiki>topic=</nowiki><b>"..(sanction.palias or v).."</b>}}"))

				:done()

			:tag('td')

				:wikitext(sanction.scope)

				:done()

			:tag('td')

				:wikitext("[["..title.fullText.."]]")

				:allDone()

	end



	return tostring(tbl)

end



function p.topicsHelper(frame)

	local args = getArgs(frame, {

		wrappers = {

			'Template:Gs/topics',

			'Template:Gs/topics/sandbox'

		}

	})



	if args'sanctions scope' and dataargs'sanctions scope']] then

		return _getTopicData(args'sanctions scope']).scope

	elseif args'sanctions link' and dataargs'sanctions link']] then

		return mw.title.new(_getTopicData(args'sanctions link']).wikilink).redirectTarget

	else

		return "" -- ?

	end

end



-- Returns true if the given topic name is a valid topic area

function p.checkIfValidTopic(topicName)

	local topic = Topic.new(topicName, nil)

	if topic:exists() then

		return true

	else

		return false

	end

end



return p
Permanently protected module
From Wikipedia, the free encyclopedia


local getArgs = require('Module:Arguments').getArgs

local yesno = require('Module:Yesno')



local rawData = mw.loadData('Module:Sanctions/data')

local data = rawData.sanctions

local aliasMap = rawData.aliases



local messageBox = require('Module:Message box')



-- Functions



local function tableContainsValue(needle, haystack)

	for _, v in pairs(haystack) do

		if v == needle then

			return true

		end

	end

	return false

end



local function _getTopicData(topicAlias)

	if datatopicAlias then

		return datatopicAlias

	elseif aliasMaptopicAlias then

		return dataaliasMaptopicAlias]]

	else

		return false

	end

end



-- Returns an invalid topic error, with a table of acceptable topics

local function syntaxHelp()

	return [[<span class="error">{{para|topic}} not specified. Available options:</span><div style="border-left: 5px dashed black; border-right: 5px dashed black; border-bottom: 5px dashed black; padding-left: 0.5em; padding-right: 0.5em; padding-bottom: 0.5em;">

	{{Gs/topics/table}}

	</div>]]

end



-- Topic class



local Topic = {}

Topic.__index = Topic



function Topic.new(topicCode, args)

	local obj = {}

	obj._args = args

	obj._topicData = _getTopicData(topicCode)

	

	return setmetatable(obj, Topic)

end



function Topic:get(arg)

	return self._topicDataarg

end



function Topic:exists()

	return ((self._topicData ~= nil) and (self._topicData ~= false))

end



function Topic:hasGlobalRestriction(type)

	return self._topicData.restrictionstype

end



function Topic:hasLocalRestriction(type)

	local localRestriction = self._argstype

	if localRestriction then

		if mw.ustring.find(type, '^restriction') ~= nil then

			return true

		else

			return yesno(localRestriction)

		end

	else

		return false

	end

end



function Topic:hasRestriction(type)

	return self:hasGlobalRestriction(type) or self:hasLocalRestriction(type)

end



function Topic:hasRestrictions(arr)

	for _, v in ipairs(arr) do

		if self:hasRestriction(v) then

			return true

		end

	end

	

	return false

end



function Topic:hasAnyRevertRestrictions()

	return self:hasRestrictions({'1rr', 'consensusrequired', 'brd'})

end



function Topic:hasAnyRestrictions()

	return self:hasAnyRevertRestrictions() or self:hasRestrictions({'restriction1'})

end



function Topic:getCustomRestrictions()

	local customRestrictions = {}

	local ri = 1

	local checkArr = self._topicData.restrictions

	local breakNext = false

	while true do

		if checkArr'restriction'..ri then

			table.insert(customRestrictions, checkArr'restriction'..ri])

			ri = ri + 1

		else

			if breakNext then

				break

			else

				ri = 1

				checkArr = self._args

				breakNext = true

			end

		end

	end

	

	return customRestrictions

end



-- End classes



-- This function builds a talk notice

-- TODO: split this up

--

-- @param frame

-- @param topic topic class instance

-- @param args arguments passed to wrapper template

-- @returns String representation of notice

local function buildTalkNotice(frame, topic, args)

	local type = args'type' or args2 or 'mini'

	local out = mw.html.create('')

	local hasRestrictions = topic:hasAnyRestrictions()

	local hasRevertRestrictions = topic:hasAnyRevertRestrictions()

	

	if hasRestrictions then

		type = 'long' -- force long displaywhere custom restrictions are applicable



		out

			:tag('span')

				:css('font-size', '120%')

				:wikitext("'''WARNING: ACTIVE COMMUNITY SANCTIONS'''")

	end



	if hasRestrictions then

		out

			:tag('p')

				:wikitext("The article [[:{{SUBJECTPAGENAME}}]], along with other pages relating to "..topic:get('scope')..", is designated by the community as a '''[[Wikipedia:Contentious topics|contentious topic]]'''. The current restrictions are:")

	else

		out

			:tag('p')

				:wikitext("<strong>The use of the [[Wikipedia:Contentious topics|contentious topics procedure]] has been authorised by the community for pages related to ".. topic:get('scope') ..", including this page.</strong>" .. (type == 'mini' and ' Editors who repeatedly or seriously fail to adhere to the [[Wikipedia:Five_pillars|purpose of Wikipedia]], any expected [[Wikipedia:Etiquette|standards of behaviour]], or any [[Wikipedia:List_of_policies|normal editorial process]] may be sanctioned.' or ''))

	end



	if not (type == 'mini') then

		local restrictionList = mw.html.create('ul')



		-- 1RR

		if topic:hasRestriction('1rr') then

			restrictionList

				:tag('li')

					:wikitext("'''Limit of one revert in 24 hours:''' This article is under [[Wikipedia:Edit warring#Other revert rules|WP:1RR]] (one [[Wikipedia:Reverting|revert]] per editor per article ''per 24-hour period'')")

		end



		-- Text for boilerplate/predefined restrictions

		if topic:hasRestriction('consensusrequired') then

			restrictionList

				:tag('li')

					:wikitext("'''Consensus required:''' All editors must obtain [[WP:Consensus|consensus]] on the talk page of this article before reinstating ''any edits that have been challenged (via reversion).'' This includes making edits similar to the ones that have been challenged. If in doubt, do not make the edit.")

		end



		if topic:hasRestriction('brd') then

			restrictionList

				:tag('li')

					:wikitext("'''24-hr [[Wikipedia:BOLD, revert, discuss cycle|BRD cycle]]:''' If a change you make to this article is reverted, you may not reinstate that change unless you discuss the issue on the talk page and wait 24 hours (from the time of the original edit). Partial reverts/reinstatements that reasonably address objections of other editors [[Wikipedia:BOLD, revert, discuss cycle#WP:BRR|are preferable]] to wholesale reverts.")

		end

		

		local customRestrictions = topic:getCustomRestrictions()

		for _, v in ipairs(customRestrictions) do

			restrictionList

				:tag('li')

					:wikitext(v)

		end

		

		if hasRestrictions then

			out:node(restrictionList)

		end



		out

			:tag('p')

				:wikitext("Editors who repeatedly or seriously fail to adhere to the [[Wikipedia:Five_pillars|purpose of Wikipedia]], any expected [[Wikipedia:Etiquette|standards of behaviour]], or any [[Wikipedia:List_of_policies|normal editorial process]] may be sanctioned.")

			

		-- Further info box

		if hasRestrictions then

			local furtherInfo = mw.html.create('')



			-- Enforcement procedures

			furtherInfo

				:tag('p')

					:wikitext('Enforcement procedures:')

					:done()



			local enforcementProcedures = mw.html.create('ul')



			if hasRestrictions then

				enforcementProcedures

					:tag('li')

						:wikitext("Violations of any restrictions " .. (hasRevertRestrictions and "(excluding 1RR/reverting violations) " or "") .. "and other conduct issues should be reported to the [[Wikipedia:Administrators' noticeboard/Incidents|administrators' incidents noticeboard]]." .. (hasRevertRestrictions and " Violations of revert restrictions should be reported to the [[Wikipedia:Administrators' noticeboard/Edit warring|administrators' edit warring noticeboard]]." or ""))

						:done()

					:tag('li')

						:wikitext("Editors who violate any listed restrictions may be blocked by any uninvolved administrator, even on a first offense.")

						:done()

			else

				enforcementProcedures

					:tag('li')

						:wikitext("Problems should be reported to the [[Wikipedia:Administrators' noticeboard/Incidents|administrators' incidents noticeboard]].")

						:done()

			end



			enforcementProcedures

				:tag('li')

					:wikitext("An editor must be [[Wikipedia:Contentious topics#Awareness of contentious topics|aware]] before they can be sanctioned.")

					:allDone()

			furtherInfo:node(enforcementProcedures)



			if hasRevertRestrictions then

				furtherInfo

					:tag('p')

						:wikitext("With respect to any reverting restrictions:")

						:done()

					:tag('ul')

						:tag('li')

							:wikitext("Edits made solely to enforce any clearly established consensus are exempt from all edit-warring restrictions. In order to be considered \"clearly established\" the consensus must be proven by prior talk-page discussion.")

							:done()

						:tag('li')

							:wikitext("Edits made which remove or otherwise change any material placed by clearly established consensus, without first obtaining consensus to do so, may be treated in the same manner as clear vandalism.")

							:done()

						:tag('li')

							:wikitext("Clear vandalism of any origin may be reverted without restriction.")

							:done()

						:tag('li')

							:wikitext("Reverts of edits made by anonymous (IP) editors that are not vandalism are exempt from the 1RR but are subject to [[Wikipedia:Edit warring|the usual rules on edit warring]]. If you are in doubt, contact an administrator for assistance.")

							:allDone()

					:tag('p')

							:wikitext("If you are unsure if your edit is appropriate, discuss it here on this talk page first. <strong>Remember: When in doubt, don't revert!</strong>")

			end



			local collapsed = frame:expandTemplate{ title = 'collapse', args = {

				tostring(furtherInfo),

				'<span style="color:red">Remedy instructions and exemptions</span>',

				'bg' = '#EEE8AA'

			}}

			

			out

				:newline()

				:node(collapsed)

		end

		-- End further info box

	end



	local box = messageBox.main( 'tmbox', {

		type = 'notice',

		image = type == 'long' and '[[File:Commons-emblem-issue.svg|50px]]' or '[[File:Commons-emblem-hand-orange.svg|40px]]',

		text = frame:preprocess(tostring(out))

    })



    return box

end



-- Builds an alert notice

--

-- @param frame

-- @param topic topic class instance

-- @returns String representation of notice

local function buildAlert(frame, topic, sig)

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

		:addClass('gs-alert')

		:cssText("border: 1px solid #AAA; background-color: #E5F8FF; padding: 0.5em; width: 100%; margin-bottom: 1em")



	out

		:tag('tr')

			:tag('td')

				:cssText("vertical-align:middle; padding-left:1px; padding-right:0.5em;")

				:wikitext("[[File:Commons-emblem-notice.svg|50px]]")

				:done()

			:tag('td')

				:wikitext("This is a standard message to notify contributors about an administrative ruling in effect. ''It does '''not''' imply that there are any issues with your contributions to date.''")

				:newline()

				:wikitext("You have shown interest in ".. topic:get('scope') ..". Due to past disruption in this topic area, the community has authorised uninvolved administrators to impose [[Wikipedia:Contentious topics|contentious topics restrictions]]—such as [[Wikipedia:Editing restrictions#Types of restrictions|editing restrictions]], [[Wikipedia:Banning policy#Types of bans|bans]], or [[WP:Blocking policy|blocks]]—on editors who do not strictly follow [[Wikipedia:List of policies|Wikipedia's policies]], expected [[Wikipedia:Etiquette|standards of behaviour]], or the [[Wikipedia:Contentious topics#Standard set|page-specific restrictions]], when making edits related to the topic.")

				:newline()

				:wikitext("For additional information, please see the [[".. topic:get('wikilink') .."|guidance on these sanctions]]. If you have any questions, or any doubts regarding what edits are appropriate, you are welcome to discuss them with me or any other editor." .. (sig and ' '..sig or ''))



	return frame:preprocess(tostring(out))

end



-- Builds an edit notice

local function buildEditNotice(frame, topic, args)

	local enHeader = mw.html.create('')

	local restrictionMsgs = {}

	

	if topic:hasRestriction('1rr') then

		table.insert(restrictionMsgs, "Editors must not make more than one [[Help:Reverting|revert]] per 24 hours (subject to [[Wikipedia:Edit warring#Exemptions|exceptions]])")

	end

	

	if topic:hasRestriction('consensusrequired') then

		table.insert(restrictionMsgs, "Editors must not reinstate any challenged edits (via reversion) without first obtaining [[Wikipedia:Consensus|consensus]] on the talk page of this article")

	end



	local customRestrictions = topic:getCustomRestrictions()

	for _, v in ipairs(customRestrictions) do

		table.insert(restrictionMsgs, v)

	end



	if #restrictionMsgs == 0 then

		return frame:preprocess(syntaxHelp())

	else

		local list = mw.html.create('ul')

		for _,v in ipairs(restrictionMsgs) do

			list

				:tag('li')

					:wikitext(v)

					:done()

		end

		enHeader:wikitext(tostring(list))

	end



	local enText = mw.html.create('')

	enText

		:tag('p')

			:wikitext("<strong>Breaching the restriction on this page may result in a block or other sanctions.</strong> In addition, please note that because this topic area has been disrupted in the past, the community has [["..topic:get('wikilink').."|authorised]] administrators to take [[Wikipedia:Contentious topics|appropriate steps]] to ensure the smooth running of all pages related to "..topic:get('scope')..". Conduct which does not adhere to our policies and [[Wikipedia:Etiquette|standards of behaviour]] may be met with sanctions. Please edit carefully.")

			:done()



	local editnotice = frame:expandTemplate{ title = 'editnotice', args = {

		expiry = "indefinite",

		headerstyle = "font-size: 120%;",

		style = "background: ivory;",

		image = "Commons-emblem-issue.svg",

		imagesize = "50px",

		header = tostring(enHeader),

		text = tostring(enText)

	}}



	return editnotice

end



--/////////--

-- EXPORTS

--/////////--

local p = {}



-- Returns a talk notice

-- For documentation, see [[Template:Gs/talk notice]]

function p.talknotice(frame)

	local args = getArgs(frame, {

		wrappers = {

			'Template:Gs/talk notice',

			'Template:Gs/talk notice/sandbox'

		}

	})



	local topic = Topic.new(args'topic' or args1], args)



	if not topic:exists() then

		return frame:preprocess(syntaxHelp())

	end

	

	return buildTalkNotice(frame, topic, args)

end



-- Returns an alert

-- For documentation, see [[Template:Gs/alert]]

function p.alert(frame)

	local args = getArgs(frame, {

		wrappers = {

			'Template:Gs/alert',

			'Template:Gs/alert/sandbox',

		}

	})



	local topic = Topic.new(args'topic' or args1], args)

	if not topic:exists() then

		return frame:preprocess(syntaxHelp())

	elseif not topic:hasRestriction('ds') then

		return frame:preprocess('<span class="error">This topic area is not designated as a contentious topic. Alert is not required.</span>')

	end

	

	return buildAlert(frame, topic, args'sig'])

end



-- Returns an edit notice

-- For documentation, see [[Template:Gs/editnotice]]

function p.editnotice(frame)

	local args = getArgs(frame, {

		wrappers = {

			'Template:Gs/editnotice',

			'Template:Gs/editnotice/sandbox'

		}

	})



	local topic = Topic.new(args'topic' or args1], args)

	if not topic:exists() then

		return frame:preprocess(syntaxHelp())

	elseif not topic:hasAnyRestrictions() then

		return frame:preprocess('<span class="error">Page sanctions are not authorised for this topic area. Edit notice is not required.</span>[[Category:Pages with sanctions errors]]')

	end



	return buildEditNotice(frame, topic, args)

end



function p.table(frame)

	local args = getArgs(frame, {

		wrappers = {

			'Template:Gs/topics/table',

			'Template:Gs/topics/table/sandbox',

		}

	})



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

		:addClass('wikitable')

		:css('font-size', '9pt')

		:css('background', 'transparent')



	-- Headers

	tbl:tag('tr')

		:tag('th')

			:wikitext("Topic code")

			:done()

		:tag('th')

			:wikitext("Area of conflict")

			:done()

		:tag('th')

			:wikitext("Decision linked to")

			:allDone()

	

	-- sort alphabetically

	local sortedTable = {}

	for n in pairs(data) do

		table.insert(sortedTable, n)

	end

	table.sort(sortedTable)



	for _,v in ipairs(sortedTable) do

		local sanction = datav

		local title = mw.title.new(sanction.wikilink).redirectTarget			-- probably unnecessarily expensive; just add to config

		tbl:tag('tr')

			:tag('td')

				:wikitext(frame:preprocess("{{tlx"..(args'subst' and "s" or "").."|{{#ifeq:{{BASEPAGENAME}}|Gs|{{PAGENAME}}|{{BASEPAGENAME}}}}|<nowiki>topic=</nowiki><b>"..(sanction.palias or v).."</b>}}"))

				:done()

			:tag('td')

				:wikitext(sanction.scope)

				:done()

			:tag('td')

				:wikitext("[["..title.fullText.."]]")

				:allDone()

	end



	return tostring(tbl)

end



function p.topicsHelper(frame)

	local args = getArgs(frame, {

		wrappers = {

			'Template:Gs/topics',

			'Template:Gs/topics/sandbox'

		}

	})



	if args'sanctions scope' and dataargs'sanctions scope']] then

		return _getTopicData(args'sanctions scope']).scope

	elseif args'sanctions link' and dataargs'sanctions link']] then

		return mw.title.new(_getTopicData(args'sanctions link']).wikilink).redirectTarget

	else

		return "" -- ?

	end

end



-- Returns true if the given topic name is a valid topic area

function p.checkIfValidTopic(topicName)

	local topic = Topic.new(topicName, nil)

	if topic:exists() then

		return true

	else

		return false

	end

end



return p

Videos

Youtube | Vimeo | Bing

Websites

Google | Yahoo | Bing

Encyclopedia

Google | Yahoo | Bing

Facebook