Skip to content

Commit 24010e6

Browse files
committed
support 'none' in hsl colors
1 parent 371cf70 commit 24010e6

5 files changed

Lines changed: 127 additions & 32 deletions

File tree

src/main/java/org/htmlunit/cssparser/dom/HSLColorImpl.java

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,22 +53,36 @@ public HSLColorImpl(final String function, final LexicalUnit lu) throws DOMExcep
5353
function_ = functionLC;
5454

5555
LexicalUnit next = lu;
56+
if (next == null) {
57+
throw new DOMException(DOMException.SYNTAX_ERR, function_ + " requires at least three values.");
58+
}
5659
hue_ = new CSSValueImpl(next, true);
5760

5861
next = next.getNextLexicalUnit();
5962
if (next == null) {
6063
throw new DOMException(DOMException.SYNTAX_ERR, function_ + " requires at least three values.");
6164
}
6265

63-
commaSeparated_ = next.getLexicalUnitType() == LexicalUnitType.OPERATOR_COMMA;
66+
commaSeparated_ = LexicalUnitType.OPERATOR_COMMA == next.getLexicalUnitType();
6467
if (commaSeparated_) {
68+
if (hue_.getLexicalUnitType() == LexicalUnitType.NONE) {
69+
throw new DOMException(DOMException.SYNTAX_ERR,
70+
function_ + " has to use blank as separator if none is used.");
71+
}
72+
6573
next = next.getNextLexicalUnit();
6674
if (next == null) {
6775
throw new DOMException(DOMException.SYNTAX_ERR, function_ + " requires at least three values.");
6876
}
6977

70-
if (LexicalUnitType.PERCENTAGE != next.getLexicalUnitType()) {
71-
throw new DOMException(DOMException.SYNTAX_ERR, "Saturation part has to be percentage.");
78+
if (LexicalUnitType.NONE == next.getLexicalUnitType()) {
79+
throw new DOMException(DOMException.SYNTAX_ERR,
80+
function_ + " has to use blank as separator if none is used.");
81+
}
82+
else {
83+
if (LexicalUnitType.PERCENTAGE != next.getLexicalUnitType()) {
84+
throw new DOMException(DOMException.SYNTAX_ERR, "Saturation part has to be percentage.");
85+
}
7286
}
7387
saturation_ = new CSSValueImpl(next, true);
7488

@@ -77,7 +91,7 @@ public HSLColorImpl(final String function, final LexicalUnit lu) throws DOMExcep
7791
throw new DOMException(DOMException.SYNTAX_ERR, function_ + " requires at least three values.");
7892
}
7993

80-
if (next.getLexicalUnitType() != LexicalUnitType.OPERATOR_COMMA) {
94+
if (LexicalUnitType.OPERATOR_COMMA != next.getLexicalUnitType()) {
8195
throw new DOMException(DOMException.SYNTAX_ERR, function_ + " parameters must be separated by ','.");
8296
}
8397

@@ -86,6 +100,10 @@ public HSLColorImpl(final String function, final LexicalUnit lu) throws DOMExcep
86100
throw new DOMException(DOMException.SYNTAX_ERR, function_ + "b requires at least three values.");
87101
}
88102

103+
if (LexicalUnitType.NONE == next.getLexicalUnitType()) {
104+
throw new DOMException(DOMException.SYNTAX_ERR,
105+
function_ + " has to use blank as separator if none is used.");
106+
}
89107
if (LexicalUnitType.PERCENTAGE != next.getLexicalUnitType()) {
90108
throw new DOMException(DOMException.SYNTAX_ERR, "Lightness part has to be percentage.");
91109
}
@@ -96,14 +114,19 @@ public HSLColorImpl(final String function, final LexicalUnit lu) throws DOMExcep
96114
return;
97115
}
98116

99-
if (next.getLexicalUnitType() != LexicalUnitType.OPERATOR_COMMA) {
117+
if (LexicalUnitType.OPERATOR_COMMA != next.getLexicalUnitType()) {
100118
throw new DOMException(DOMException.SYNTAX_ERR, function_ + " parameters must be separated by ','.");
101119
}
120+
102121
next = next.getNextLexicalUnit();
103122
if (next == null) {
104123
throw new DOMException(DOMException.SYNTAX_ERR, "Missing alpha value.");
105124
}
106125

126+
if (LexicalUnitType.NONE == next.getLexicalUnitType()) {
127+
throw new DOMException(DOMException.SYNTAX_ERR,
128+
function_ + " has to use blank as separator if none is used.");
129+
}
107130
if (LexicalUnitType.INTEGER != next.getLexicalUnitType()
108131
&& LexicalUnitType.REAL != next.getLexicalUnitType()
109132
&& LexicalUnitType.PERCENTAGE != next.getLexicalUnitType()) {
@@ -117,7 +140,8 @@ public HSLColorImpl(final String function, final LexicalUnit lu) throws DOMExcep
117140
return;
118141
}
119142

120-
if (LexicalUnitType.PERCENTAGE != next.getLexicalUnitType()) {
143+
if (LexicalUnitType.NONE != next.getLexicalUnitType()
144+
&& LexicalUnitType.PERCENTAGE != next.getLexicalUnitType()) {
121145
throw new DOMException(DOMException.SYNTAX_ERR, "Saturation part has to be percentage.");
122146
}
123147
saturation_ = new CSSValueImpl(next, true);
@@ -131,7 +155,8 @@ public HSLColorImpl(final String function, final LexicalUnit lu) throws DOMExcep
131155
function_ + " requires consitent separators (blank or comma).");
132156
}
133157

134-
if (LexicalUnitType.PERCENTAGE != next.getLexicalUnitType()) {
158+
if (LexicalUnitType.NONE != next.getLexicalUnitType()
159+
&& LexicalUnitType.PERCENTAGE != next.getLexicalUnitType()) {
135160
throw new DOMException(DOMException.SYNTAX_ERR, "Lightness part has to be percentage.");
136161
}
137162
lightness_ = new CSSValueImpl(next, true);

src/main/java/org/htmlunit/cssparser/dom/RGBColorImpl.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@ public RGBColorImpl(final String function, final LexicalUnit lu) throws DOMExcep
6464
throw new DOMException(DOMException.SYNTAX_ERR, function_ + " requires at least three values.");
6565
}
6666

67-
commaSeparated_ = next.getLexicalUnitType() == LexicalUnitType.OPERATOR_COMMA;
67+
commaSeparated_ = LexicalUnitType.OPERATOR_COMMA == next.getLexicalUnitType();
6868
if (commaSeparated_) {
69-
if (red_.getLexicalUnitType() == LexicalUnitType.NONE) {
69+
if (LexicalUnitType.NONE == red_.getLexicalUnitType()) {
7070
throw new DOMException(DOMException.SYNTAX_ERR,
7171
function_ + " has to use blank as separator if none is used.");
7272
}
@@ -76,18 +76,18 @@ public RGBColorImpl(final String function, final LexicalUnit lu) throws DOMExcep
7676
throw new DOMException(DOMException.SYNTAX_ERR, function_ + " requires at least three values.");
7777
}
7878

79-
green_ = getPart(next);
80-
if (green_.getLexicalUnitType() == LexicalUnitType.NONE) {
79+
if (LexicalUnitType.NONE == next.getLexicalUnitType()) {
8180
throw new DOMException(DOMException.SYNTAX_ERR,
8281
function_ + " has to use blank as separator if none is used.");
8382
}
83+
green_ = getPart(next);
8484

8585
next = next.getNextLexicalUnit();
8686
if (next == null) {
8787
throw new DOMException(DOMException.SYNTAX_ERR, function_ + " requires at least three values.");
8888
}
8989

90-
if (next.getLexicalUnitType() != LexicalUnitType.OPERATOR_COMMA) {
90+
if (LexicalUnitType.OPERATOR_COMMA != next.getLexicalUnitType()) {
9191
throw new DOMException(DOMException.SYNTAX_ERR, function_ + " parameters must be separated by ','.");
9292
}
9393

@@ -96,30 +96,30 @@ public RGBColorImpl(final String function, final LexicalUnit lu) throws DOMExcep
9696
throw new DOMException(DOMException.SYNTAX_ERR, function_ + "b requires at least three values.");
9797
}
9898

99-
blue_ = getPart(next);
100-
if (blue_.getLexicalUnitType() == LexicalUnitType.NONE) {
99+
if (LexicalUnitType.NONE == next.getLexicalUnitType()) {
101100
throw new DOMException(DOMException.SYNTAX_ERR,
102101
function_ + " has to use blank as separator if none is used.");
103102
}
103+
blue_ = getPart(next);
104104

105105
next = next.getNextLexicalUnit();
106106
if (next == null) {
107107
return;
108108
}
109109

110-
if (next.getLexicalUnitType() != LexicalUnitType.OPERATOR_COMMA) {
110+
if (LexicalUnitType.OPERATOR_COMMA != next.getLexicalUnitType()) {
111111
throw new DOMException(DOMException.SYNTAX_ERR, function_ + " parameters must be separated by ','.");
112112
}
113113
next = next.getNextLexicalUnit();
114114
if (next == null) {
115115
throw new DOMException(DOMException.SYNTAX_ERR, "Missing alpha value");
116116
}
117117

118-
alpha_ = getPart(next);
119-
if (alpha_.getLexicalUnitType() == LexicalUnitType.NONE) {
118+
if (LexicalUnitType.NONE == next.getLexicalUnitType()) {
120119
throw new DOMException(DOMException.SYNTAX_ERR,
121120
function_ + " has to use blank as separator if none is used.");
122121
}
122+
alpha_ = getPart(next);
123123

124124
next = next.getNextLexicalUnit();
125125
if (next != null) {

src/main/javacc/CSS3Parser.jj

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2028,7 +2028,8 @@ LexicalUnit hslColor(LexicalUnit prev) :
20282028
(
20292029
(op = unaryOperator() )?
20302030
(
2031-
param = number(null, op)
2031+
<NONE> { param = LexicalUnitImpl.createNone(null); }
2032+
| param = number(null, op)
20322033
| t = <ANGLE_DEG> { param = LexicalUnitImpl.createDegree(null, doubleValue(op, t.image)); }
20332034
| t = <ANGLE_RAD> { param = LexicalUnitImpl.createRadian(null, doubleValue(op, t.image)); }
20342035
| t = <ANGLE_GRAD> { param = LexicalUnitImpl.createGradian(null, doubleValue(op, t.image)); }
@@ -2046,7 +2047,8 @@ LexicalUnit hslColor(LexicalUnit prev) :
20462047
(
20472048
(op = unaryOperator() )?
20482049
(
2049-
next = percentage(next, op)
2050+
<NONE> { next = LexicalUnitImpl.createNone(next); }
2051+
| next = percentage(next, op)
20502052
)
20512053
)
20522054
{ op = ' '; }
@@ -2060,7 +2062,8 @@ LexicalUnit hslColor(LexicalUnit prev) :
20602062
(
20612063
(op = unaryOperator() )?
20622064
(
2063-
next = percentage(next, op)
2065+
<NONE> { next = LexicalUnitImpl.createNone(next); }
2066+
| next = percentage(next, op)
20642067
)
20652068
)
20662069
{ op = ' '; }
@@ -2077,7 +2080,8 @@ LexicalUnit hslColor(LexicalUnit prev) :
20772080

20782081
(op = unaryOperator() )?
20792082
(
2080-
next = number(next, op)
2083+
<NONE> { next = LexicalUnitImpl.createNone(next); }
2084+
| next = number(next, op)
20812085
| next = percentage(next, op)
20822086
)
20832087

src/test/java/org/htmlunit/cssparser/dom/HSLColorImplTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ public void constructByLU() throws Exception {
5353
*/
5454
@Test
5555
public void constructByLUException() throws Exception {
56+
try {
57+
new HSLColorImpl("hsl", null);
58+
fail("DOMException expected");
59+
}
60+
catch (final DOMException e) {
61+
assertEquals("hsl requires at least three values.", e.getMessage());
62+
}
63+
5664
LexicalUnit hslLU = LexicalUnitImpl.createNumber(null, 10);
5765
LexicalUnit lu = LexicalUnitImpl.createComma(hslLU);
5866
LexicalUnitImpl.createDivide(lu);

src/test/java/org/htmlunit/cssparser/parser/CSS3ParserTest.java

Lines changed: 69 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,6 +1128,10 @@ public void hslComma() throws Exception {
11281128
color("foreground: hsl(255grad, 0%, 15.37%)", "foreground: hsl(2.55e2grad, 0e0%, 1537e-2%)");
11291129
color("foreground: hsl(255turn, 0%, 15.37%)", "foreground: hsl(2.55e2turn, 0e0%, 1537e-2%)");
11301130

1131+
color("foreground: hsl(none 0% 60%)", "foreground: hsl(none 0% 60%)");
1132+
color("foreground: hsl(100deg none 60%)", "foreground: hsl(100deg none 60%)");
1133+
color("foreground: hsl(100deg 0% none)", "foreground: hsl(100deg 0% none)");
1134+
11311135
// alpha
11321136
color("foreground: hsl(270, 60%, 70%, 0.1)", "foreground: hsl(270,60%,70%,0.1)");
11331137
color("foreground: hsl(-270, 60%, 70%, 0.1)", "foreground: hsl(-270, 60%, 70%, 0.1)");
@@ -1160,6 +1164,18 @@ public void hslBlank() throws Exception {
11601164
color("foreground: hsl(-270 60% 70% / 10%)", "foreground: hsl(-270 60% 70% / 10%)");
11611165
}
11621166

1167+
/**
1168+
* @throws Exception in case of failure
1169+
*/
1170+
@Test
1171+
public void hslMixed() throws Exception {
1172+
color("foreground: hsl(42, 128%, 255%)", "foreground: hsl(42, 128%, 255%)");
1173+
color("foreground: hsl(42deg, 128%, 255%)", "foreground: hsl(42deg, 128%, 255%)");
1174+
1175+
color("foreground: hsl(42 128% 255%)", "foreground: hsl(42 128% 255%)");
1176+
color("foreground: hsl(42rad 128% 255%)", "foreground: hsl(42rad 128% 255%)");
1177+
}
1178+
11631179
/**
11641180
* @throws Exception in case of failure
11651181
*/
@@ -1210,6 +1226,18 @@ public void hslaBlank() throws Exception {
12101226
color("foreground: hsla(-270 60% 70% / 10%)", "foreground: hsla(-270 60% 70% / 10%)");
12111227
}
12121228

1229+
/**
1230+
* @throws Exception in case of failure
1231+
*/
1232+
@Test
1233+
public void hslaMixed() throws Exception {
1234+
color("foreground: hsla(42, 128%, 255%)", "foreground: hsla(42, 128%, 255%)");
1235+
color("foreground: hsla(42deg, 128%, 255%)", "foreground: hsla(42deg, 128%, 255%)");
1236+
1237+
color("foreground: hsla(42 128% 255%)", "foreground: hsla(42 128% 255%)");
1238+
color("foreground: hsla(42rad 128% 255%)", "foreground: hsla(42rad 128% 255%)");
1239+
}
1240+
12131241
/**
12141242
* @throws Exception in case of failure
12151243
*/
@@ -1218,17 +1246,47 @@ public void hslVariousErrors() throws Exception {
12181246
color(1, "DOM exception: 'hsl parameters must be separated by ','.'", "foreground: hsl(10, 20% 30%)");
12191247
color(1, "DOM exception: 'hsl requires consitent separators (blank or comma).'", "foreground: hsl(10 20%, 30%)");
12201248

1221-
color(1, "Error in expression. (Invalid token \"10\". "
1222-
+ "Was expecting one of: <S>, <NUMBER>, \"-\", \"+\", <ANGLE_DEG>, <ANGLE_RAD>, <ANGLE_GRAD>, <ANGLE_TURN>.)",
1223-
"foreground: hsl('10', 20% 30%)");
1224-
color(1, "Error in expression. (Invalid token \"10\". "
1225-
+ "Was expecting one of: <S>, <NUMBER>, \"-\", \"+\", <ANGLE_DEG>, <ANGLE_RAD>, <ANGLE_GRAD>, <ANGLE_TURN>.)",
1226-
"foreground: hsl(10px, 20% 30%)");
1227-
1228-
color(1, "Error in expression. (Invalid token \"20\". Was expecting one of: <S>, \"-\", \"+\", <PERCENTAGE>.)",
1229-
"foreground: hsl(10, 20, 30%)");
1230-
color(1, "Error in expression. (Invalid token \"30\". Was expecting one of: <S>, \"-\", \"+\", <PERCENTAGE>.)",
1231-
"foreground: hsl(10, 20%, 30)");
1249+
color(1, "DOM exception: 'hsl alpha value must be separated by '/'.'", "foreground: hsl(10 20% 30% 40)");
1250+
1251+
color(1, "DOM exception: 'hsl has to use blank as separator if none is used.'", "foreground: hsl(none, 20%, 30%)");
1252+
color(1, "DOM exception: 'hsl has to use blank as separator if none is used.'", "foreground: hsl(10, none, 30%)");
1253+
color(1, "DOM exception: 'hsl has to use blank as separator if none is used.'", "foreground: hsl(10, 20%, none)");
1254+
color(1, "DOM exception: 'hsl has to use blank as separator if none is used.'", "foreground: hsl(10, 20%, 30%, none)");
1255+
1256+
// mixing numbers and percentages is supported by current browsers
1257+
// color(1, "DOM exception: 'hsl mixing numbers and percentages.'", "foreground: hsl(10rad, 20, 30)");
1258+
// color(1, "DOM exception: 'hsl mixing numbers and percentages.'", "foreground: hsl(10rad, 20%, 30)");
1259+
// color(1, "DOM exception: 'hsl mixing numbers and percentages.'", "foreground: hsl(10, 20%, 30)");
1260+
// color(1, "DOM exception: 'hsl mixing numbers and percentages.'", "foreground: hsl(10, 20%, 30%)");
1261+
// color(1, "DOM exception: 'hsl mixing numbers and percentages.'", "foreground: hsl(10, 20, 30%)");
1262+
// color(1, "DOM exception: 'hsl mixing numbers and percentages.'", "foreground: hsl(10rad, 20, 30%)");
1263+
//
1264+
// color(1, "DOM exception: 'hsl mixing numbers and percentages.'", "foreground: hsl(10rad 20 30)");
1265+
// color(1, "DOM exception: 'hsl mixing numbers and percentages.'", "foreground: hsl(10rad 20% 30)");
1266+
// color(1, "DOM exception: 'hsl mixing numbers and percentages.'", "foreground: hsl(10 20% 30)");
1267+
// color(1, "DOM exception: 'hsl mixing numbers and percentages.'", "foreground: hsl(10 20% 30%)");
1268+
// color(1, "DOM exception: 'hsl mixing numbers and percentages.'", "foreground: hsl(10 20 30%)");
1269+
// color(1, "DOM exception: 'hsl mixing numbers and percentages.'", "foreground: hsl(10rad 20 30%)");
1270+
1271+
color(1, "Error in expression. (Invalid token \")\". Was expecting one of: <S>, <NUMBER>, \"none\", \"-\", \"+\", <ANGLE_DEG>, <ANGLE_RAD>, <ANGLE_GRAD>, <ANGLE_TURN>.)",
1272+
"foreground: hsl()");
1273+
color(1, "Error in expression. (Invalid token \")\". Was expecting one of: <S>, \"none\", \"-\", \"+\", \",\", <PERCENTAGE>.)",
1274+
"foreground: hsl(10)");
1275+
color(1, "Error in expression. (Invalid token \")\". Was expecting one of: <S>, \"none\", \"-\", \"+\", \",\", <PERCENTAGE>.)",
1276+
"foreground: hsl(10 20%)");
1277+
1278+
color(1, "Error in expression. (Invalid token \")\". Was expecting one of: <S>, <NUMBER>, \"none\", \"-\", \"+\", <PERCENTAGE>.)",
1279+
"foreground: hsl(10, 20%, 30%,)");
1280+
color(1, "Error in expression. (Invalid token \")\". Was expecting one of: <S>, <NUMBER>, \"none\", \"-\", \"+\", <PERCENTAGE>.)",
1281+
"foreground: hsl(10, 20%, 30%/)");
1282+
1283+
color(1, "Error in expression. (Invalid token \"20\". Was expecting one of: <S>, \"none\", \"-\", \"+\", <PERCENTAGE>.)",
1284+
"foreground: hsl(10, 20px, 30)");
1285+
color(1, "Error in expression. (Invalid token \"20\". Was expecting one of: <S>, \"none\", \"-\", \"+\", \",\", <PERCENTAGE>.)",
1286+
"foreground: hsl(10 20px 30)");
1287+
1288+
color(1, "Error in expression. (Invalid token \"10\". Was expecting one of: <S>, <NUMBER>, \"none\", \"-\", \"+\", <ANGLE_DEG>, <ANGLE_RAD>, <ANGLE_GRAD>, <ANGLE_TURN>.)",
1289+
"foreground: hsl('10', 20, 30,)");
12321290
}
12331291

12341292
private void color(final String expected, final String cssText) throws Exception {

0 commit comments

Comments
 (0)