Module:Color: Difference between revisions

From Zelda Wiki, the Zelda encyclopedia
Jump to navigation Jump to search
(simplification - was too fancy for no reason)
(more documentation)
Line 188: Line 188:
{"SSHD Blue", "Demise"},
{"SSHD Blue", "Demise"},
{"invalid color", "foo"},
{"invalid color", "foo"},
{"SSHD Blue ", "Demise"},
{
desc = "This template no longer supports arbitrary web colors. Use [[Template:Web Color]] instead. Name all in-game colors at [[Module:Color/Data]].",
args = {"#f2a1b5", "custom color"},
},
{
desc = "Leading/trailing whitespace is not allowed in the color name." ,
args = {"SSHD Blue ", "Demise"},
},
{"SSHD\nBlue", "Demise"},
{"SSHD\nBlue", "Demise"},
{"", "missing color"},
{
desc = "Both parameters are required.",
args = {"", "missing color"},
},
{"missing text"},
{"missing text"},
{""},
{""},
{},
{},
{"deprecated color", "bar"},
{
desc = "Color names can be discontinued.",
args = {"deprecated color", "bar"},
},
{"replaced color", "bar"},
{"replaced color", "bar"},
}
}

Revision as of 17:11, 16 September 2022

Lua error in Module:Documentation/Module at line 334: attempt to call field 'Schemas' (a table value).


local utilsError = require("Module:UtilsError")
local utilsString = require("Module:UtilsString")

local Constants = mw.loadData("Module:Constants/Data")
local data = mw.loadData("Module:Color/Data")

local p = {}

local CAT_DEPRECATED_COLORS = "Category:Articles Using Deprecated Colors"

function p.Main(frame)
	local args = frame:getParent().args
	local coloredText, errorCategories = p.color(args[1], args[2])
	return coloredText .. (errorCategories or "")
end

function p.List(frame)
	local args = frame:getParent().args
	return p.listColors(args[1])
end

-- @return the colored text as a sring
-- @return any error categories as a string, or nil
function p.color(colorId, text)
	if text == nil or text == "" then
		utilsError.warn("<code>text</code> parameter is required.")
		return text or "", "[[Category:"..Constants.catInvalidArgs.."]]"
	end
	if colorId == nil or colorId == "" then
		utilsError.warn("<code>color</code> parameter is required.")
		return text, "[[Category:"..Constants.catInvalidArgs.."]]"
	end
	if string.find(colorId, "\n", 1, true) or string.find(colorId, "\r", 1, true) or utilsString.startsWith(colorId, " ") or utilsString.endsWith(colorId, " ") then
		utilsError.warn("<code>color</code> argument contains invalid whitespace such as newlines or leading/trailing spaces.")
		return text, "[[Category:"..Constants.catInvalidArgs.."]]"
	end
	
	local colorData = data.colors[colorId]
	-- Backwards compatibility for inputting any valid HTML color
	-- In articles we should only allow defined game colors, but we can keep support for any HTML color on user and talk pages to avoid breaking user signatures that use the template this way
	if colorData == nil and (mw.title.getCurrentTitle().isTalkPage or mw.title.getCurrentTitle().nsText == "User" or mw.title.getCurrentTitle().nsText == "Zelda_Wiki") then
		html = mw.html.create("span")
			:css("color", colorId)
			:wikitext(text)
		return tostring(html)
	elseif colorData == nil then
		utilsError.warn(string.format("<code>%s</code> is not a valid color name. See [[Template:Color]] for a list of supported colors.", colorId))
		return text, "[[Category:Articles Using Invalid Color Names]]"
	end
	local colorValue = colorData.color
	local html = mw.html.create("span")
		:addClass("colored-text")
		:wikitext(text)
	if utilsString.startsWith(colorValue, "linear-gradient") then
		-- It's OK to use inline styles here because the color is a "fixed" part of the quote and applies to all Zelda Wiki skins
		-- This enables colors to be defined in one place in module data, which is easier to maintain
		html:css({
			["background-image"] = colorValue,
			["color"] = "transparent",
			["background-clip"] = "text",
			["-webkit-background-clip"] = "text"
		})
	else
		html:css("color", colorValue)
	end
	local result = tostring(html)
	if colorData.deprecated then
		local action = ""
		if type(colorData.deprecated) == "string" then
			action = string.format("Use <code>%s</code> instead.", colorData.deprecated)
		else
			action = "See [[Template:Color]] for a list of supported colors."
		end
		utilsError.warn(string.format("Color <code>%s</code> is being discontinued. %s", colorId, action))
		return result, "[["..CAT_DEPRECATED_COLORS.."]]"
	end
	return result
end

-- lists colors for one game, or all games if game is nil
function p.listColors(game)
	-- Perfomance optimization; only loading dependencies on the documentation pages where they're needed
	local Franchise = require("Module:Franchise")
	local utilsLayout = require("Module:UtilsLayout")
	local utilsString = require("Module:UtilsString")
	local utilsTable = require("Module:UtilsTable")
	
	local tableRows = {
		{
			header = true,
			{
				content = "Color",
				styles = {
					width = "150px"
				},
			},
			"Name",
			"Notes",
		}
	}
	local games = game and {game} or Franchise.enum({includeCompilations = true})
	local listAllGames = game == nil
	local colorKeys = utilsTable.keys(data.colors)
	
	-- Remove deprecated colors
	colorKeys = utilsTable.filter(colorKeys, function(colorKey)
		return not data.colors[colorKey].deprecated
	end)
	
	local seenColorKeys = {}
	for _, game in ipairs(games) do -- "game" here could also be a book like Encyclopedia
		-- The added " " is for doing a whole-word match. e,g. SS should match "SS Green" but not "SSHD Green"
		local gameColorKeys = utilsTable.filter(colorKeys, utilsString._startsWith(game .. " "))
		table.sort(gameColorKeys)
		if listAllGames and #gameColorKeys > 0 then
			table.insert(tableRows, {
				header = true,
				{
					colspan = 3,
					content = string.format('<span id="%s">[[#%s|%s]]</span>', game, game, Franchise.display(game)), -- creates section links to each game
				}
			})
		end
		p.addRows(tableRows, gameColorKeys)
		seenColorKeys = utilsTable.concat(seenColorKeys, gameColorKeys)
	end

	local remainingColorKeys = utilsTable.difference(colorKeys, seenColorKeys)
	if listAllGames and #remainingColorKeys > 0 then
		table.insert(tableRows, {
			header = true,
			{
				colspan = 3,
				content = string.format("[[#Other|Other]]</span>"),
			}
		})
		p.addRows(tableRows, remainingColorKeys)
	end 
	return utilsLayout.table({
		caption = "Text Colors",
		rows = tableRows,
		hideEmptyColumns = true,
	})
end
function p.addRows(tableRows, gameColorKeys)
	for _, colorKey in ipairs(gameColorKeys) do
		local colorData = data.colors[colorKey]
		if not colorData.deprecated then
			table.insert(tableRows, {
				{
					content = " ", -- using whitespace so the cell isn't treated as being empty by utilsLayout
					styles = {
						["background"] = colorData.color,
					}
				},
				"<b><code>"..colorKey.."</code></b>",
				colorData.notes or ""
			})
		end
	end
end

-- For auto-generated doc at Module:Colors/Data/Documentation
function p.Data()
	return p.listColors()
end

p.Templates = {
	["Color"] = {
		purpose = "This template allows text to be colored such that quotes from games (e.g. [[Template:Cite]]) or other media have the same color highlights as the source text. These colors convey meaningful empasis and are essential to Zelda Wiki's [[Guidelines:Terminology|terminology guidelines]].",
		format = "inline",
		params = {
			[1] = {
				name = "color",
				required = true,
				type = "string",
				desc = "The name of the color - see supported colors below"
			},
			[2] = {
				name = "text",
				required = true,
				type = "string",
				desc = "The text to color"
			}
		},
		examples = {
			{"TWWHD Vermilion", "merchant's oath"},
			{"SSHD Blue", "Demise"},
			{"invalid color", "foo"},
			{
				desc = "This template no longer supports arbitrary web colors. Use [[Template:Web Color]] instead. Name all in-game colors at [[Module:Color/Data]].",
				args = {"#f2a1b5", "custom color"},
			},
			{
				desc = "Leading/trailing whitespace is not allowed in the color name." ,
				args = {"SSHD Blue ", "Demise"},
			},
			{"SSHD\nBlue", "Demise"},
			{
				desc = "Both parameters are required.",
				args = {"", "missing color"},
			},
			{"missing text"},
			{""},
			{},
			{
				desc = "Color names can be discontinued.",
				args = {"deprecated color", "bar"},
			},
			{"replaced color", "bar"},
		}
	},
	["Color/List"] = {
		purpose = "This template lists the colors that [[Template:Color]] supports.",
		format = "inline",
		params = {
			[1] = {
				name = "game",
				type = "string",
				enum = {
					reference = "[[Data:Franchise]]" 
				},
				desc = "If specified, the template will output the colors for the given game only. Otherwise, all colors will be listed.",
				canOmit = true,
			}
		},
		examples = {
			{"BotW"},
			{"E"},
		}
	}
}

-- For auto-generated doc at Module:Colors/Data/Documentation
p.Schemas = {
	Data = {
		type = "record",
		required = true,
		properties = {
			{
				name = "colors",
				required = true,
				type = "map",
				keys = {
					type = "string",
				},
				values = {
					type = "record",
					properties = {
						{
							name = "color",
							required = true,
							type = "string",
							desc = "A [https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color hex color] (with preceding #) or a [https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient linear-gradient].",
						},
						{
							name = "notes",
							type = "string",
							desc = "Anything that editors should know about the color – the context in which it appears, other colors it could be confused with, etc.",
						},
						{
							name = "deprecated",
							type = "string",
							desc = "The name of the color that should be used instead of this color going forward. If multiple colors apply, just put <code>true</code>. Pages using the deprecated color are added to [[:"..CAT_DEPRECATED_COLORS.."]]."
						}
					}
				}
			}
		}
	}
}

return p