Navigation Menu

Skip to content

Commit

Permalink
fix(packages): Stricter color parsing and improved color documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
Omikhleia authored and Didier Willis committed Jul 8, 2022
1 parent 2c4d3d5 commit f7b919a
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 13 deletions.
27 changes: 19 additions & 8 deletions core/colorparser.lua
Expand Up @@ -151,27 +151,38 @@ local colorsRGB = {

local colorparser = function (col)
local r, g, b, c, m, y, k, l
if colorsRGB[col] then
c = colorsRGB[col]
return { r = c[1] / 255, g = c[2] / 255, b = c[3] / 255 }
if not col or type(col) ~= "string" then
SU.error("Not a color specification string ("..tostring(col)..")")
end
r, g, b = col:match("#(%x%x)(%x%x)(%x%x)")
local named = colorsRGB[string.lower(col)]
if named then
return { r = named[1] / 255, g = named[2] / 255, b = named[3] / 255 }
end
r, g, b = col:match("^#(%x%x)(%x%x)(%x%x)$")
if r then
return { r = tonumber("0x"..r)/255, g = tonumber("0x"..g)/255, b = tonumber("0x"..b)/255 }
end
r, g, b = col:match("#(%x)(%x)(%x)")
r, g, b = col:match("^#(%x)(%x)(%x)$")
if r then
return { r = tonumber("0x"..r)/15, g = tonumber("0x"..g)/15, b = tonumber("0x"..b)/15 }
end
c, m, y, k = col:match("(%d+%.?%d*)%s+(%d+%.?%d*)%s+(%d+%.?%d*)%s+(%d+%.?%d*)")
c, m, y, k = col:match("^(%d+%.?%d*)%s+(%d+%.?%d*)%s+(%d+%.?%d*)%s+(%d+%.?%d*)$")
if c then
return { c = tonumber(c)/255, m = tonumber(m)/255, y = tonumber(y)/255, k = tonumber(k)/255 }
end
r, g, b = col:match("(%d+%.?%d*)%s+(%d+%.?%d*)%s+(%d+%.?%d*)")
c, m, y, k = col:match("^(%d+%.?%d*)%%%s+(%d+%.?%d*)%%%s+(%d+%.?%d*)%%%s+(%d+%.?%d*)%%$")
if c then
return { c = tonumber(c)/100, m = tonumber(m)/100, y = tonumber(y)/100, k = tonumber(k)/100 }
end
r, g, b = col:match("^(%d+%.?%d*)%s+(%d+%.?%d*)%s+(%d+%.?%d*)$")
if r then
return { r = tonumber(r)/255, g = tonumber(g)/255, b = tonumber(b)/255 }
end
l = col:match("(%d+.?%d*)")
r, g, b = col:match("^(%d+%.?%d*)%%%s+(%d+%.?%d*)%%%s+(%d+%.?%d*)%%$")
if r then
return { r = tonumber(r)/100, g = tonumber(g)/100, b = tonumber(b)/100 }
end
l = col:match("^(%d+.?%d*)$")
if l then
return { l = tonumber(l)/255 }
end
Expand Down
20 changes: 15 additions & 5 deletions packages/color/init.lua
Expand Up @@ -20,12 +20,22 @@ The \autodoc:package{color} package allows you to temporarily change the color o
(virtual) ink that SILE uses to output text and rules. The package provides
a \autodoc:command{\color} command which takes one parameter,
\autodoc:parameter{color=<color specification>}, and typesets
its argument in that color. The color specification is the same as HTML:
it can be a RGB color value in \code{#xxx} or \code{#xxxxxx} format, where \code{x}
represents a hexadecimal digit (\code{#000} is black, \code{#fff} is white,
\code{#f00} is red and so on), or it can be one of the HTML and CSS named colors.
its argument in that color.
\note{The HTML and CSS named colors can be found at \code{http://dev.w3.org/csswg/css-color/#named-colors}.}
The color specification is one of the following:
\begin{itemize}
\item{A RGB color in \code{#xxx} or \code{#xxxxxx} format, where \code{x}
represents a hexadecimal digit, as often seen in HTML/CSS (\code{#000} is
black, \code{#fff} is white, \code{#f00} is red and so on);}
\item{A RGB color as a series of three numeric values between 0 and 255
(e.g. \code{0 0 139} is a dark blue) or as three percentages;}
\item{A CMYK color as a series of four numeric values between 0 and 255
or as four percentages;}
\item{A grayscale color as a numeric value between 0 and 255;}
\item{A (case-insensitive) named color, as one of the 148 keywords defined
in the CSS Color Module Level 4. (Named colors resolve to RGB
in the actual output.)}
\end{itemize}
So, for example, \color[color=red]{this text is typeset with \autodoc:command{\color[color=red]{…}}}.
Expand Down
43 changes: 43 additions & 0 deletions spec/colorparser_spec.lua
@@ -0,0 +1,43 @@
SILE = require("core.sile")
SU.warn = function () end

describe("The color parser", function()
local parse = SILE.colorparser
local rebecca = {
b = 0.6,
g = 0.2,
r = 0.4
}
local reddish = {
c = 0,
k = 0.3,
m = 0.81,
y = 0.81
}
it("should return the correct RGB values for a named color", function()
assert.is.same(parse("rebeccapurple"), rebecca)
assert.is.same(parse("RebeccaPurple"), rebecca)
end)
it("should return the correct RGB values for a hexadecimal specification", function()
assert.is.same(parse("#663399"), rebecca)
assert.is.same(parse("#639"), rebecca)
end)
it("should return the correct RGB values for a series of 3 numbers or percentages", function()
assert.is.same(parse("102 51 153"), rebecca)
assert.is.same(parse("40% 20% 60%"), rebecca)
end)
it("should return the correct CMYK values for a series of 4 numbers or percentages", function()
assert.is.same(parse("0% 81% 81% 30%"), reddish)
assert.is.same(parse("0 206.55 206.55 76.5"), reddish)
end)
it("should return the correct grayscale value for single number", function()
assert.is.same(parse("204"), { l = 0.8 })
end)

it("error if unable to parse", function()
assert.has.errors(function () parse("not_a_color") end)
assert.has.errors(function () parse(nil) end)
assert.has.errors(function () parse("") end)
end)
end)

0 comments on commit f7b919a

Please sign in to comment.