Edge Rewrite
// HTMLRewriter · presentation

This page was redesigned at the edge.

Cloudflare fetched the original article and streamed it through HTMLRewriter to apply an entirely new visual system without rebuilding the source page.

Jump to content

Module:Storm categories/demo

From Wikipedia, the free encyclopedia

--
-- This module handles demonstration and list of possible values for all storm
-- category templates! Please test this module on [[Module:Storm categories/demo/doc]]
-- before publishing to avoid errros. Thank you!
--
local colorRatio = require("Module:Color contrast")._ratio
local TableTools = require("Module:TableTools")
local stormcats = require("Module:Storm categories")
local cats = require("Module:Storm categories/categories").cats
local colors = require("Module:Storm categories/colors").colors
local icons = require("Module:Storm categories/icons").icons
local p = {}

local customKeys = {}
for k, v in pairs(colors) do
	table.insert(customKeys, k)
end
for k, v in pairs(icons) do
	table.insert(customKeys, k)
end
TableTools.removeDuplicates(customKeys)

function tableEmpty(_table)
	for k, v in pairs(_table) do
		return false
	end
	return true
end

--- Generates and renderds the demo table.
-- @param frame The Scribunto frame.
function p.demo(frame)
	local plain = (frame.args["plain"] or frame:getParent().args["plain"] or "") ~= ""
	local verbose = (frame.args["verbose"] or frame:getParent().args["verbose"] or "") ~= ""
	
	local legend = setmetatable({}, { refgroupname = "" })
	local errors = setmetatable({}, { refgroupname = "E" })
	local warnings = setmetatable({}, { refgroupname = "W" })
	
	--- Builds the entire reflist
	-- @param _group The group to build for. Uses `legend` by default.
	function buildReflist(_group)
		group = _group or legend
		return frame:expandTemplate{ title = 'reflist', args = {
			group = getmetatable(group)["refgroupname"]
		} }
	end
	
	--- Returns a single <ref> tag containing the legend provided and
	-- attaches the note definition to the list of notes.
	-- @param details The details of the legend.
	-- @param _group The group to write in. Uses `legend` by default.
	function createLegend(details, _group)
		hash = string.sub(mw.hash.hashValue("md5", details), 0, 8)
		group = _group or legend
		if group[hash] == nil then
			group[hash] = plain and "" or frame:extensionTag{ 
				-- <ref name="hash">details</ref>
				name = 'ref',
				content = mw.ustring.gsub(details, "%[%[File:([^%|]+)[^%]]*%]%]", "[[:File:%1]]"),
				args = { 
					name = hash, 
					group = getmetatable(group)["refgroupname"]
				}
			}
		end
		
		-- <ref name="hash"/>
		return plain and "" or frame:extensionTag{ name = 'ref', args = { 
			name = hash,
			group = getmetatable(group)["refgroupname"]
		} }
	end
	
	--- Checks for color contrast issues and tags accordingly.
	-- Returns the refernce tag, so this should be used in conjunction with an
	-- HTML node's :wikitext function.
	function contrastCheck(color)
		local catColorBlackRatio = colorRatio({ "#" .. color, "black" })
		local catColorLinkRatio = colorRatio({ "#" .. color, "#0645ad" })
		local catColorVisitedLinkRatio = colorRatio({ "#" .. color, "#0b0080" })
		
		local finalWikitext = ""
		if catColorBlackRatio == "?" or catColorLinkRatio == "?" or catColorVisitedLinkRatio == "?" then
			finalWikitext = finalWikitext ..
				createLegend("This color must be a hexadecimal color.", errors)
		else
			if catColorBlackRatio < 4.5 then
				finalWikitext = finalWikitext ..
					createLegend("This color has [[MOS:COLOR|contrast issues]] with black (not WCAG 2.0 AA-compatible). It will be unusable on all infoboxes and storm season summaries.", errors)
			end
			if catColorLinkRatio < 4.5 then
				finalWikitext = finalWikitext ..
					createLegend("This color has [[MOS:COLOR|contrast issues]] with links (not WCAG 2.0 AA-compatible). It should not be used in conjunction with a link.", warnings)
			end
			if catColorVisitedLinkRatio < 4.5 then
				finalWikitext = finalWikitext ..
					createLegend("This color has [[MOS:COLOR|contrast issues]] with visited links (not WCAG 2.0 AA-compatible with #0b0080). It should not be used in conjunction with a visited link.", warnings)
			end
			if actualCat == "c0c0c0" and cat[sortkey] ~= 0 then
				finalWikitext = finalWikitext ..
					createLegend("This category is using a color reserved specifically for the \"unknown\" category.", warnings)
			end
		end
		return finalWikitext
	end
	
	function colorInfo(color, verbose, extra)
		local catColorBlackRatio = colorRatio({ "#" .. color, "black" })
		local catColorLinkRatio = colorRatio({ "#" .. color, "#0645ad" })
		local catColorVisitedLinkRatio = colorRatio({ "#" .. color, "#0b0080" })
		
		local nc = tostring(mw.html.create("abbr")
			:wikitext("NC")
			:attr("title", "Does not satisfy the minimum WCAG 2.1 compliance level for color contrast (AA)")
		);
		local aa = tostring(mw.html.create("abbr")
			:wikitext("AA")
			:attr("title", "WCAG 2.1 Level AA: Acceptable compliance")
		);
		local aaa = tostring(mw.html.create("abbr")
			:wikitext("AAA")
			:attr("title", "WCAG 2.1 Level AAA: Optimal compliance")
		);
		
		function contrastLevel(contrast)
			return contrast >= 7 and aaa or (contrast >= 4.5 and aa or nc)
		end
		
		return mw.html.create("td")
			:attr("data-sort-value", math.min(catColorBlackRatio))
			:wikitext(
				"#" .. color .. (extra or "") .. contrastCheck(color) .. (verbose and ("<br/>"
				.. tostring(
					mw.html.create("abbr")
						:attr("title", "Contrast to black")
						:wikitext("CTB")
				) .. ": " .. string.format("%.2f", catColorBlackRatio) .. " (" .. contrastLevel(catColorBlackRatio) .. ")<br/>"
				.. tostring(
					mw.html.create("abbr")
						:attr("title", "Contrast to links")
						:wikitext("CTL")
				) .. ": " .. string.format("%.2f", catColorLinkRatio) .. " (" .. contrastLevel(catColorLinkRatio) .. ")<br/>"
				.. tostring(
					mw.html.create("abbr")
						:attr("title", "Contrast to visited links")
						:wikitext("CTVL")
				) .. ": " .. string.format("%.2f", catColorVisitedLinkRatio) .. " (" .. contrastLevel(catColorVisitedLinkRatio) .. ")") or "")
			)
	end
	
	local categoryTable = mw.html.create("table")
		:addClass("wikitable")
		:addClass("sortable")
		:attr("style", "width: 100%")
		
	categoryTable
		:node(
			mw.html.create("tr")
				:node(mw.html.create("th"):wikitext("Icon")
					:attr("class", "unsortable")
					:attr("rowspan", "2")
					:css("width", "0"))
				:node(mw.html.create("th"):wikitext("ID")
					:attr("rowspan", "2"))
				:node(mw.html.create("th"):wikitext("Name")
					:attr("colspan", "2"))
				:node(mw.html.create("th"):wikitext("Color")
					:attr("rowspan", "2")
					:attr("colspan", "2"))
				:node(mw.html.create("th"):wikitext("Sortkey")
					:attr("colspan", "2"))
		):node(
			mw.html.create("tr")
				:node(mw.html.create("th"):wikitext("Basin"))
				:node(mw.html.create("th"):wikitext("Name"))
				:node(mw.html.create("th"):wikitext("Basin"))
				:node(mw.html.create("th"):wikitext("Sortkey")
					:attr("data-sort-type", "number"))
		)
	
	for name, cat in TableTools.sortedPairs(cats) do
		local rows = { mw.html.create("tr") }
		local row = rows[1]
		
		local actualIcon = stormcats._icon(name)
		local icon = mw.html.create("td")
			:wikitext(actualIcon)
		if cat["icon"] ~= nil and actualIcon ~= cat["icon"] then
			icon:wikitext(
				createLegend("Overriden from original icon (" .. cat["icon"] .. ")")
			)
		end
			
		local id = mw.html.create("td")
			:wikitext(name)
		local actualColor = stormcats._color(name)
		local colorPreview = mw.html.create("td")
			:attr("style", "background-color: #" .. actualColor .. "; color:inherit; padding: 0; width: 1.8em")
		local color = colorInfo(
			actualColor,
			verbose,
			actualColor ~= cat["color"] and createLegend(
				"Overriden from original color ({{color box|#"
				.. cat["color"]
				.. "}} #"
				.. cat["color"]
				.. ")"
			) or ""
		):css("width", "0"):css("white-space", "nowrap")
		
		local sortkeyCategory = mw.html.create("td")
			:attr("data-sort-value", cat["sortkey"])
		local sortkey = mw.html.create("td")
			:attr("data-sort-value", cat["sortkey"])
			:wikitext(cat["sortkey"])
			
		if cat["sortkey"] < 0 then
			sortkeyCategory:wikitext("Invalid")
		elseif cat["sortkey"] < 20000 then
			sortkeyCategory:wikitext("Global")
		elseif cat["sortkey"] < 30000 then
			sortkeyCategory:wikitext("Historical")
		elseif cat["sortkey"] < 40000 then
			sortkeyCategory:wikitext("SWIO")
		elseif cat["sortkey"] < 50000 then
			sortkeyCategory:wikitext("Aus/Fiji")
		elseif cat["sortkey"] < 60000 then
			sortkeyCategory:wikitext("NIO")
		elseif cat["sortkey"] < 80000 then
			sortkeyCategory:wikitext("WPAC")
		elseif cat["sortkey"] < 90000 then
			sortkeyCategory:wikitext("Atl/EPac/SAtl")
		elseif cat["sortkey"] < 100000 then
			sortkeyCategory:attr("style", "color: gray")
			sortkeyCategory:wikitext("''Global''")
		else
			sortkeyCategory:wikitext("Invalid")
		end
		
		if type(cat["name"]) == "string" then
			local name = mw.html.create("td")
				:attr("colspan", "2")
				:wikitext(cat["name"])
			row:node(icon)
			row:node(id)
			row:node(name)
		else
			local nameTableLength = TableTools.size(cat["name"])
			icon:attr("rowspan", nameTableLength)
			id:attr("rowspan", nameTableLength)
			colorPreview:attr("rowspan", nameTableLength)
			color:attr("rowspan", nameTableLength)
			sortkeyCategory:attr("rowspan", nameTableLength)
			sortkey:attr("rowspan", nameTableLength)
			
			row:node(icon)
			row:node(id)
			local firstDone = false
			for key, basinName in TableTools.sortedPairs(cat["name"]) do
				if firstDone then
					local nameRow = mw.html.create("tr")
					
					nameRow
						:node(mw.html.create("td"):wikitext(key))
						:node(mw.html.create("td"):wikitext(basinName))
						
					table.insert(rows, nameRow)	
				else
					firstDone = true
					row
						:node(mw.html.create("td"):wikitext(key))
						:node(mw.html.create("td"):wikitext(basinName))
				end
			end
		end
		
		row:node(colorPreview)
		row:node(color)
		row:node(sortkeyCategory)
		row:node(sortkey)
		
		for _, _row in TableTools.sortedPairs(rows) do
			categoryTable:node(_row)
		end
	end
	
	for name, _ in TableTools.sortedPairs(TableTools.listToSet(customKeys)) do
		if cats[name] == nil then
			local row = mw.html.create("tr")
			
			local icon = stormcats._icon(name, true)
			row
				:node(mw.html.create("td")
					:wikitext(
						icon ~= nil
						and icon
						or "''<span style=\"color:gray\">N/A</span>''"
					))
				:node(mw.html.create("td"):wikitext(name))
			
			local color = stormcats._color(name, true)
			-- Add more conditions eventually
			if color ~= nil then
				row
					:node(mw.html.create("td")
						:attr("colspan", "2")
						:wikitext("''<span style=\"color:gray\">not available</span>''"))
					:node(mw.html.create("td")
						:attr("style", "background-color: #" .. color .. "; color:inherit; padding: 0; width: 1.8em"))
					:node(colorInfo(color, verbose))
						:css("width", "0")
						:css("white-space", "nowrap")
					:node(mw.html.create("td")
						:attr("colspan", "2")
						:wikitext("''<span style=\"color:gray\">not available</span>''"))
			else
				row
					:node(mw.html.create("td")
						:attr("colspan", "6")
						:wikitext("''<span style=\"color:gray\">not available</span>''"))
			end
			categoryTable:node(row)
		end
	end
	
	out = ""
	if not plain and not tableEmpty(errors) then
		out = out
			.. tostring(mw.html.create("h4"):wikitext("Error"))
		    .. tostring(mw.html.create("p"):wikitext("This table contains errors than need to be addressed immediately, as it may cause errors on a large amount of pages."))
		    .. buildReflist(errors)
	end
	if not plain and not tableEmpty(legend) then
		out = out
			.. tostring(mw.html.create("h4"):wikitext("Legend"))
		    .. buildReflist(legend)
	end
	out = out .. tostring(categoryTable)
	if not plain and not tableEmpty(warnings) then
		out = out
			.. tostring(mw.html.create("h4"):wikitext("Warnings"))
		    .. tostring(mw.html.create("p"):wikitext("This table contains warnings than should be addressed. Please note that some warnings cannot be fully addressed without changes that would require consensus."))
		    .. buildReflist(warnings)
	end
	
	return mw.text.trim(out)
end

return p