Skip to content

Commit f8b34df

Browse files
committed
Support for the dimensions 'ch', 'vw', 'vh', 'vmin' and 'vmax' added
Minus sign no longer supported inside unknown dimensions. This fixes a problem when parsing calc terms without whitespace around the minus like in calc(42vh-16.4em).
1 parent c8e39c2 commit f8b34df

File tree

8 files changed

+530
-10
lines changed

8 files changed

+530
-10
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
<dependency>
4242
<groupId>net.java.dev.javacc</groupId>
4343
<artifactId>javacc</artifactId>
44-
<version>7.0.9</version>
44+
<version>7.0.4</version>
4545
</dependency>
4646
</dependencies>
4747
</plugin>

src/main/java/com/gargoylesoftware/css/dom/CSSValueImpl.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,21 @@ public enum CSSPrimitiveValueType {
6868
/** CSS_EXS. */
6969
CSS_EXS,
7070

71+
/** CSS_CH. */
72+
CSS_CH,
73+
74+
/** CSS_VW. */
75+
CSS_VW,
76+
77+
/** CSS_VH. */
78+
CSS_VH,
79+
80+
/** CSS_VMIN. */
81+
CSS_VMIN,
82+
83+
/** CSS_VMAX. */
84+
CSS_VMAX,
85+
7186
/** CSS_PX. */
7287
CSS_PX,
7388

@@ -298,6 +313,16 @@ public CSSPrimitiveValueType getPrimitiveType() {
298313
return CSSPrimitiveValueType.CSS_UNKNOWN;
299314
case EX:
300315
return CSSPrimitiveValueType.CSS_EXS;
316+
case CH:
317+
return CSSPrimitiveValueType.CSS_CH;
318+
case VW:
319+
return CSSPrimitiveValueType.CSS_VW;
320+
case VH:
321+
return CSSPrimitiveValueType.CSS_VH;
322+
case VMIN:
323+
return CSSPrimitiveValueType.CSS_VMIN;
324+
case VMAX:
325+
return CSSPrimitiveValueType.CSS_VMAX;
301326
case PIXEL:
302327
return CSSPrimitiveValueType.CSS_PX;
303328
case INCH:

src/main/java/com/gargoylesoftware/css/parser/LexicalUnit.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ enum LexicalUnitType {
4343
EM,
4444
REM,
4545
EX,
46+
CH,
47+
VW,
48+
VH,
49+
VMIN,
50+
VMAX,
4651
PIXEL,
4752
INCH,
4853
CENTIMETER,

src/main/java/com/gargoylesoftware/css/parser/LexicalUnitImpl.java

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,16 @@ public String getDimensionUnitText() {
231231
return "rem";
232232
case EX:
233233
return "ex";
234+
case CH:
235+
return "ch";
236+
case VW:
237+
return "vw";
238+
case VH:
239+
return "vh";
240+
case VMIN:
241+
return "vmin";
242+
case VMAX:
243+
return "vmax";
234244
case PIXEL:
235245
return "px";
236246
case INCH:
@@ -344,6 +354,11 @@ public String getCssText() {
344354
case EM:
345355
case REM:
346356
case EX:
357+
case CH:
358+
case VW:
359+
case VH:
360+
case VMIN:
361+
case VMAX:
347362
case PIXEL:
348363
case INCH:
349364
case CENTIMETER:
@@ -512,6 +527,36 @@ public String toDebugString() {
512527
.append(getDimensionUnitText())
513528
.append(")");
514529
break;
530+
case CH:
531+
sb.append("CH(")
532+
.append(getTrimedDoubleValue())
533+
.append(getDimensionUnitText())
534+
.append(")");
535+
break;
536+
case VW:
537+
sb.append("VW(")
538+
.append(getTrimedDoubleValue())
539+
.append(getDimensionUnitText())
540+
.append(")");
541+
break;
542+
case VH:
543+
sb.append("VH(")
544+
.append(getTrimedDoubleValue())
545+
.append(getDimensionUnitText())
546+
.append(")");
547+
break;
548+
case VMIN:
549+
sb.append("VMIN(")
550+
.append(getTrimedDoubleValue())
551+
.append(getDimensionUnitText())
552+
.append(")");
553+
break;
554+
case VMAX:
555+
sb.append("VMAX(")
556+
.append(getTrimedDoubleValue())
557+
.append(getDimensionUnitText())
558+
.append(")");
559+
break;
515560
case PIXEL:
516561
sb.append("PIXEL(")
517562
.append(getTrimedDoubleValue())
@@ -806,6 +851,51 @@ public static LexicalUnit createEx(final LexicalUnit prev, final double d) {
806851
return new LexicalUnitImpl(prev, LexicalUnitType.EX, d);
807852
}
808853

854+
/**
855+
* @param prev the previous LexicalUnit
856+
* @param d the double value
857+
* @return lexical unit with type ch
858+
*/
859+
public static LexicalUnit createCh(final LexicalUnit prev, final double d) {
860+
return new LexicalUnitImpl(prev, LexicalUnitType.CH, d);
861+
}
862+
863+
/**
864+
* @param prev the previous LexicalUnit
865+
* @param d the double value
866+
* @return lexical unit with type vw
867+
*/
868+
public static LexicalUnit createVw(final LexicalUnit prev, final double d) {
869+
return new LexicalUnitImpl(prev, LexicalUnitType.VW, d);
870+
}
871+
872+
/**
873+
* @param prev the previous LexicalUnit
874+
* @param d the double value
875+
* @return lexical unit with type vh
876+
*/
877+
public static LexicalUnit createVh(final LexicalUnit prev, final double d) {
878+
return new LexicalUnitImpl(prev, LexicalUnitType.VH, d);
879+
}
880+
881+
/**
882+
* @param prev the previous LexicalUnit
883+
* @param d the double value
884+
* @return lexical unit with type vmin
885+
*/
886+
public static LexicalUnit createVMin(final LexicalUnit prev, final double d) {
887+
return new LexicalUnitImpl(prev, LexicalUnitType.VMIN, d);
888+
}
889+
890+
/**
891+
* @param prev the previous LexicalUnit
892+
* @param d the double value
893+
* @return lexical unit with type vmax
894+
*/
895+
public static LexicalUnit createVMax(final LexicalUnit prev, final double d) {
896+
return new LexicalUnitImpl(prev, LexicalUnitType.VMAX, d);
897+
}
898+
809899
/**
810900
* @param prev the previous LexicalUnit
811901
* @param d the double value

src/main/javacc/CSS3Parser.jj

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -240,9 +240,6 @@ TOKEN_MGR_DECLS :
240240
// U v|\\0{0,4}(55|76)(\r\n|[ \t\r\n\f])?|\\v
241241
| < #U_LETTER: "u" | "\\" ("0")? ("0")? ("0")? ("0")? ( "55" | "75" ) ( "\r\n" | [ " ", "\t", "\r", "\n", "\f"])? | "\\" "u" >
242242

243-
// V v|\\0{0,4}(56|76)(\r\n|[ \t\r\n\f])?|\\v
244-
| < #V_LETTER: "v" | "\\" ("0")? ("0")? ("0")? ("0")? ( "56" | "76" ) ( "\r\n" | [ " ", "\t", "\r", "\n", "\f"])? | "\\" "v" >
245-
246243
// X x|\\0{0,4}(58|78)(\r\n|[ \t\r\n\f])?|\\x
247244
| < #X_LETTER: "x" | "\\" ("0")? ("0")? ("0")? ("0")? ( "58" | "78" ) ( "\r\n" | [ " ", "\t", "\r", "\n", "\f"])? | "\\" "x" >
248245

@@ -324,11 +321,26 @@ TOKEN_MGR_DECLS :
324321
| < EMS: <NUM> <E_LETTER> <M_LETTER> > { matchedToken.image = ParserUtils.trimBy(image, 0, 2); }
325322

326323
// {num}{R}{E}{M} {return REM;}
327-
| < REM: <NUM> <R_LETTER> <E_LETTER> <M_LETTER> > { matchedToken.image = ParserUtils.trimBy(image, 0, 3); }
324+
| < REM: <NUM> "rem" > { matchedToken.image = ParserUtils.trimBy(image, 0, 3); }
328325

329326
// {num}{E}{X} {return EXS;}
330327
| < EXS: <NUM> <E_LETTER> <X_LETTER> > { matchedToken.image = ParserUtils.trimBy(image, 0, 2); }
331328

329+
// {num}{C}{H} {return CH;}
330+
| < CH: <NUM> "ch" > { matchedToken.image = ParserUtils.trimBy(image, 0, 2); }
331+
332+
// {num}{V}{W} {return VW;}
333+
| < VW: <NUM> "vw" > { matchedToken.image = ParserUtils.trimBy(image, 0, 2); }
334+
335+
// {num}{V}{H} {return VH;}
336+
| < VH: <NUM> "vh" > { matchedToken.image = ParserUtils.trimBy(image, 0, 2); }
337+
338+
// {num}{V}{M}{I}{N} {return VMIN;}
339+
| < VMIN: <NUM> "vmin" > { matchedToken.image = ParserUtils.trimBy(image, 0, 4); }
340+
341+
// {num}{V}{M}{I}{N} {return VMAX;}
342+
| < VMAX: <NUM> "vmax" > { matchedToken.image = ParserUtils.trimBy(image, 0, 4); }
343+
332344
// {num}{P}{X} {return LENGTH;}
333345
| < LENGTH_PX: <NUM> <P_LETTER> <X_LETTER> > { matchedToken.image = ParserUtils.trimBy(image, 0, 2); }
334346

@@ -378,7 +390,7 @@ TOKEN_MGR_DECLS :
378390
| < PERCENTAGE: <NUM> "%" > { matchedToken.image = ParserUtils.trimBy(image, 0, 1); }
379391

380392
// {num}{ident} {return DIMENSION;}
381-
| < DIMENSION: <NUM> <IDENT> >
393+
| < DIMENSION: <NUM> <NMSTART> ( ["a"-"z","0"-"9"] | <NONASCII> | <ESCAPE> )* >
382394

383395
| < #H_PLACEHOLDER: (<H> | "?"){1,6} >
384396
| < UNICODE_RANGE: "u+" <H_PLACEHOLDER > (< MINUS > < H_PLACEHOLDER >)? >
@@ -2000,6 +2012,11 @@ LexicalUnit dimension(LexicalUnit prev, char op) :
20002012
| t = <EMS> { value = LexicalUnitImpl.createEm(prev, doubleValue(op, t.image)); }
20012013
| t = <REM> { value = LexicalUnitImpl.createRem(prev, doubleValue(op, t.image)); }
20022014
| t = <EXS> { value = LexicalUnitImpl.createEx(prev, doubleValue(op, t.image)); }
2015+
| t = <CH> { value = LexicalUnitImpl.createCh(prev, doubleValue(op, t.image)); }
2016+
| t = <VW> { value = LexicalUnitImpl.createVw(prev, doubleValue(op, t.image)); }
2017+
| t = <VH> { value = LexicalUnitImpl.createVh(prev, doubleValue(op, t.image)); }
2018+
| t = <VMIN> { value = LexicalUnitImpl.createVMin(prev, doubleValue(op, t.image)); }
2019+
| t = <VMAX> { value = LexicalUnitImpl.createVMax(prev, doubleValue(op, t.image)); }
20032020
| t = <ANGLE_DEG> { value = LexicalUnitImpl.createDegree(prev, doubleValue(op, t.image)); }
20042021
| t = <ANGLE_RAD> { value = LexicalUnitImpl.createRadian(prev, doubleValue(op, t.image)); }
20052022
| t = <ANGLE_GRAD> { value = LexicalUnitImpl.createGradian(prev, doubleValue(op, t.image)); }
@@ -2113,6 +2130,26 @@ void appendUnit(Token t, StringBuilder sb) {
21132130
sb.append("ex");
21142131
return;
21152132
}
2133+
if (t.kind == CH) {
2134+
sb.append("ch");
2135+
return;
2136+
}
2137+
if (t.kind == VW) {
2138+
sb.append("vw");
2139+
return;
2140+
}
2141+
if (t.kind == VH) {
2142+
sb.append("vh");
2143+
return;
2144+
}
2145+
if (t.kind == VMIN) {
2146+
sb.append("vmin");
2147+
return;
2148+
}
2149+
if (t.kind == VMAX) {
2150+
sb.append("vmax");
2151+
return;
2152+
}
21162153
if (t.kind == LENGTH_PX) {
21172154
sb.append("px");
21182155
return;

src/test/java/com/gargoylesoftware/css/dom/CSSValueImplTest.java

Lines changed: 106 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ public void dimension() throws Exception {
132132
* @throws Exception if any error occurs
133133
*/
134134
@Test
135-
public void em() throws Exception {
135+
public void ems() throws Exception {
136136
final LexicalUnit lu = LexicalUnitImpl.createEm(null, 1.2f);
137137
final CSSValueImpl value = new CSSValueImpl(lu, false);
138138

@@ -546,6 +546,111 @@ public void rem() throws Exception {
546546
}
547547
}
548548

549+
/**
550+
* @throws Exception if any error occurs
551+
*/
552+
@Test
553+
public void ch() throws Exception {
554+
final LexicalUnit lu = LexicalUnitImpl.createCh(null, 1.2f);
555+
final CSSValueImpl value = new CSSValueImpl(lu, false);
556+
557+
Assert.assertEquals("1.2ch", value.getCssText());
558+
Assert.assertEquals(CSSPrimitiveValueType.CSS_CH, value.getPrimitiveType());
559+
Assert.assertEquals(LexicalUnit.LexicalUnitType.CH, value.getLexicalUnitType());
560+
Assert.assertEquals(1.2, value.getDoubleValue(), 0.00001);
561+
try {
562+
value.getStringValue();
563+
Assert.fail("DomException expected");
564+
}
565+
catch (final DOMException e) {
566+
// expected
567+
}
568+
}
569+
570+
/**
571+
* @throws Exception if any error occurs
572+
*/
573+
@Test
574+
public void vw() throws Exception {
575+
final LexicalUnit lu = LexicalUnitImpl.createVw(null, 1.2f);
576+
final CSSValueImpl value = new CSSValueImpl(lu, false);
577+
578+
Assert.assertEquals("1.2vw", value.getCssText());
579+
Assert.assertEquals(CSSPrimitiveValueType.CSS_VW, value.getPrimitiveType());
580+
Assert.assertEquals(LexicalUnit.LexicalUnitType.VW, value.getLexicalUnitType());
581+
Assert.assertEquals(1.2, value.getDoubleValue(), 0.00001);
582+
try {
583+
value.getStringValue();
584+
Assert.fail("DomException expected");
585+
}
586+
catch (final DOMException e) {
587+
// expected
588+
}
589+
}
590+
591+
/**
592+
* @throws Exception if any error occurs
593+
*/
594+
@Test
595+
public void vh() throws Exception {
596+
final LexicalUnit lu = LexicalUnitImpl.createVh(null, 1.2f);
597+
final CSSValueImpl value = new CSSValueImpl(lu, false);
598+
599+
Assert.assertEquals("1.2vh", value.getCssText());
600+
Assert.assertEquals(CSSPrimitiveValueType.CSS_VH, value.getPrimitiveType());
601+
Assert.assertEquals(LexicalUnit.LexicalUnitType.VH, value.getLexicalUnitType());
602+
Assert.assertEquals(1.2, value.getDoubleValue(), 0.00001);
603+
try {
604+
value.getStringValue();
605+
Assert.fail("DomException expected");
606+
}
607+
catch (final DOMException e) {
608+
// expected
609+
}
610+
}
611+
612+
/**
613+
* @throws Exception if any error occurs
614+
*/
615+
@Test
616+
public void vmin() throws Exception {
617+
final LexicalUnit lu = LexicalUnitImpl.createVMin(null, 1.2f);
618+
final CSSValueImpl value = new CSSValueImpl(lu, false);
619+
620+
Assert.assertEquals("1.2vmin", value.getCssText());
621+
Assert.assertEquals(CSSPrimitiveValueType.CSS_VMIN, value.getPrimitiveType());
622+
Assert.assertEquals(LexicalUnit.LexicalUnitType.VMIN, value.getLexicalUnitType());
623+
Assert.assertEquals(1.2, value.getDoubleValue(), 0.00001);
624+
try {
625+
value.getStringValue();
626+
Assert.fail("DomException expected");
627+
}
628+
catch (final DOMException e) {
629+
// expected
630+
}
631+
}
632+
633+
/**
634+
* @throws Exception if any error occurs
635+
*/
636+
@Test
637+
public void vmax() throws Exception {
638+
final LexicalUnit lu = LexicalUnitImpl.createVMax(null, 1.2f);
639+
final CSSValueImpl value = new CSSValueImpl(lu, false);
640+
641+
Assert.assertEquals("1.2vmax", value.getCssText());
642+
Assert.assertEquals(CSSPrimitiveValueType.CSS_VMAX, value.getPrimitiveType());
643+
Assert.assertEquals(LexicalUnit.LexicalUnitType.VMAX, value.getLexicalUnitType());
644+
Assert.assertEquals(1.2, value.getDoubleValue(), 0.00001);
645+
try {
646+
value.getStringValue();
647+
Assert.fail("DomException expected");
648+
}
649+
catch (final DOMException e) {
650+
// expected
651+
}
652+
}
653+
549654
/**
550655
* @throws Exception if any error occurs
551656
*/

0 commit comments

Comments
 (0)