Module:Color: Difference between revisions
Jump to navigation
Jump to search
PhantomCaleb (talk | contribs) No edit summary |
PhantomCaleb (talk | contribs) No edit summary |
||
(16 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
local | local p = {} | ||
local h = {} | |||
local data = mw.loadData("Module:Color/Data") | |||
local utilsString = require("Module:UtilsString") | local utilsString = require("Module:UtilsString") | ||
local | local CAT_INVALID_ARGS = "[[Category:"..require("Module:Constants/category/invalidArgs").."]]" | ||
local | local CAT_INVALID_COLOR = "[[Category:Articles using invalid color names]]" | ||
local | function h.warn(msg) | ||
local utilsError = require("Module:UtilsError") | |||
utilsError.warn(msg) | |||
end | |||
local | function h.invalidColor(colorId) | ||
local TransclusionArguments = require("Module:Transclusion Arguments") | |||
h.warn(string.format("<code>%s</code> is not a valid color name. See [[Template:Color]] for a list of supported colors.", colorId)) | |||
-- We only store invalid colors for performance reasons | |||
-- Storing all template usages seems to break pages that use the template a lot | |||
TransclusionArguments.store({ | |||
module = "Module:Color", | |||
args = { | |||
[1] = colorId, | |||
[2] = text, | |||
}, | |||
isValid = false, | |||
}) | |||
end | |||
function p.Main(frame) | function p.Main(frame) | ||
Line 24: | Line 43: | ||
function p.color(colorId, text) | function p.color(colorId, text) | ||
if text == nil or text == "" then | if text == nil or text == "" then | ||
h.warn("<code>text</code> parameter is required.") | |||
return text or "", | return text or "", CAT_INVALID_ARGS | ||
end | end | ||
if colorId == nil or colorId == "" then | if colorId == nil or colorId == "" then | ||
h.warn("<code>color</code> parameter is required.") | |||
return text, | return text, CAT_INVALID_ARGS | ||
end | end | ||
if string.find(colorId, "\n", 1, true) or string.find(colorId, "\r", 1, true) or utilsString.startsWith(colorId, " ") or utilsString.endsWith(colorId, " ") then | if string.find(colorId, "\n", 1, true) or string.find(colorId, "\r", 1, true) or utilsString.startsWith(colorId, " ") or utilsString.endsWith(colorId, " ") then | ||
h.warn("<code>color</code> argument contains invalid whitespace such as newlines or leading/trailing spaces.") | |||
return text, | return text, CAT_INVALID_ARGS | ||
end | end | ||
local colorData = data.colors[colorId] | local colorData = data.colors[colorId] | ||
if colorData == nil then | if colorData == nil then | ||
h.invalidColor(colorId) | |||
return text, | return text, CAT_INVALID_COLOR | ||
end | end | ||
local colorValue = colorData.color | local colorValue = colorData.color | ||
local html = mw.html.create("span") | local html = mw.html.create("span") | ||
:addClass(" | :addClass("zw-color") | ||
:wikitext(text) | :wikitext(text) | ||
if utilsString.startsWith(colorValue, "linear-gradient") then | if utilsString.startsWith(colorValue, "linear-gradient") then | ||
Line 65: | Line 84: | ||
action = "See [[Template:Color]] for a list of supported colors." | action = "See [[Template:Color]] for a list of supported colors." | ||
end | end | ||
h.warn(string.format("Color <code>%s</code> is being discontinued. %s", colorId, action)) | |||
return result, | return result, CAT_INVALID_COLOR | ||
end | end | ||
return result | return result | ||
Line 92: | Line 111: | ||
} | } | ||
} | } | ||
local games = game and {game} or Franchise.enum({ | local games = game and {game} or Franchise.enum({includeNonfiction = true}) | ||
local listAllGames = game == nil | local listAllGames = game == nil | ||
local colorKeys = utilsTable.keys(data.colors) | local colorKeys = utilsTable.keys(data.colors) | ||
Line 225: | Line 244: | ||
} | } | ||
p.Schemas | function p.Schemas() | ||
return { | |||
-- For auto-generated doc at Module:Color/Documentation | |||
color = { | |||
colorName = { | |||
type = "string", | |||
required = true, | |||
desc = "The name of a color from [[Module:Color/Data]]", | |||
}, | |||
text = { | |||
type = "string", | |||
required = true, | |||
desc = "The text to color", | |||
}, | |||
}, | }, | ||
-- For auto-generated doc at Module:Color/Data/Documentation | |||
type = " | Data = { | ||
type = "record", | |||
required = true, | 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 = "isDefault", | |||
type = "boolean", | |||
desc = "Set this to <code>true</code> when the color is the game's default dialogue color. Used by [[Module:Cite]] to set the default text color for citations." | |||
}, | |||
{ | |||
name = "defaultFor", | |||
type = "array", | |||
name = "notes", | items = { type = "string" }, | ||
desc = "A list of wiki page names referring to the characters and/or interfaces whose text uses the color by default. Used by [[Module:Cite]] to set the default text color for citations." | |||
}, | |||
{ | |||
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", | |||
oneOf = { | |||
{ | |||
type = "string" | |||
}, | |||
{ | |||
type = "boolean" | |||
}, | |||
}, | }, | ||
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>.", | |||
}, | }, | ||
} | } | ||
} | } | ||
Line 282: | Line 314: | ||
} | } | ||
} | } | ||
end | |||
p.Documentation | function p.Documentation() | ||
return { | |||
color = { | |||
params = {"colorName", "text"}, | params = {"colorName", "text"}, | ||
returns = { | returns = { | ||
Line 294: | Line 327: | ||
{ | { | ||
args = {"TMC Blue", "guy in green tights"}, | args = {"TMC Blue", "guy in green tights"}, | ||
expect = {'<span class=" | expect = {'<span class="zw-color" style="color:#37acbe">guy in green tights</span>', nil}, | ||
}, | }, | ||
{ | { | ||
args = {"notAColor", "foo"}, | args = {"notAColor", "foo"}, | ||
expect = {"foo", "[[Category:Articles | expect = {"foo", "[[Category:Articles using invalid color names]]"}, | ||
}, | }, | ||
}, | }, | ||
}, | }, | ||
} | } | ||
end | |||
return p | return p |
Latest revision as of 01:50, 21 July 2023
This is the main module for the following templates:
In addition, this module exports the following functions.
color
color(colorName, text)
Parameters
colorName
- The name of a color from Module:Color/Data
text
- The text to color
Returns
- Colored text
- Error categories, or
nil
if no errors occurred
Examples
# | Input | Output | Result | Status |
---|---|---|---|---|
1 | color("TMC Blue", "guy in green tights")
| '<span class="zw-color" style="color:#37acbe">guy in green tights</span>'
| guy in green tights | |
nil
| ||||
2 | color("notAColor", "foo")
| "foo"
| foo | |
"[[Category:Articles using invalid color names]]"
|
local p = {}
local h = {}
local data = mw.loadData("Module:Color/Data")
local utilsString = require("Module:UtilsString")
local CAT_INVALID_ARGS = "[[Category:"..require("Module:Constants/category/invalidArgs").."]]"
local CAT_INVALID_COLOR = "[[Category:Articles using invalid color names]]"
function h.warn(msg)
local utilsError = require("Module:UtilsError")
utilsError.warn(msg)
end
function h.invalidColor(colorId)
local TransclusionArguments = require("Module:Transclusion Arguments")
h.warn(string.format("<code>%s</code> is not a valid color name. See [[Template:Color]] for a list of supported colors.", colorId))
-- We only store invalid colors for performance reasons
-- Storing all template usages seems to break pages that use the template a lot
TransclusionArguments.store({
module = "Module:Color",
args = {
[1] = colorId,
[2] = text,
},
isValid = false,
})
end
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 string
-- @return any error categories as a string, or nil
function p.color(colorId, text)
if text == nil or text == "" then
h.warn("<code>text</code> parameter is required.")
return text or "", CAT_INVALID_ARGS
end
if colorId == nil or colorId == "" then
h.warn("<code>color</code> parameter is required.")
return text, CAT_INVALID_ARGS
end
if string.find(colorId, "\n", 1, true) or string.find(colorId, "\r", 1, true) or utilsString.startsWith(colorId, " ") or utilsString.endsWith(colorId, " ") then
h.warn("<code>color</code> argument contains invalid whitespace such as newlines or leading/trailing spaces.")
return text, CAT_INVALID_ARGS
end
local colorData = data.colors[colorId]
if colorData == nil then
h.invalidColor(colorId)
return text, CAT_INVALID_COLOR
end
local colorValue = colorData.color
local html = mw.html.create("span")
:addClass("zw-color")
: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
h.warn(string.format("Color <code>%s</code> is being discontinued. %s", colorId, action))
return result, CAT_INVALID_COLOR
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({includeNonfiction = 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 = "colorId",
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"},
}
}
}
function p.Schemas()
return {
-- For auto-generated doc at Module:Color/Documentation
color = {
colorName = {
type = "string",
required = true,
desc = "The name of a color from [[Module:Color/Data]]",
},
text = {
type = "string",
required = true,
desc = "The text to color",
},
},
-- For auto-generated doc at Module:Color/Data/Documentation
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 = "isDefault",
type = "boolean",
desc = "Set this to <code>true</code> when the color is the game's default dialogue color. Used by [[Module:Cite]] to set the default text color for citations."
},
{
name = "defaultFor",
type = "array",
items = { type = "string" },
desc = "A list of wiki page names referring to the characters and/or interfaces whose text uses the color by default. Used by [[Module:Cite]] to set the default text color for citations."
},
{
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",
oneOf = {
{
type = "string"
},
{
type = "boolean"
},
},
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>.",
},
}
}
}
}
}
}
end
function p.Documentation()
return {
color = {
params = {"colorName", "text"},
returns = {
"Colored text",
"Error categories, or <code>nil</code> if no errors occurred",
},
cases = {
{
args = {"TMC Blue", "guy in green tights"},
expect = {'<span class="zw-color" style="color:#37acbe">guy in green tights</span>', nil},
},
{
args = {"notAColor", "foo"},
expect = {"foo", "[[Category:Articles using invalid color names]]"},
},
},
},
}
end
return p