Skip to content

Commit 66e8adf

Browse files
committed
check page pseudo selectors
1 parent e519860 commit 66e8adf

File tree

5 files changed

+76
-32
lines changed

5 files changed

+76
-32
lines changed

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.net.URL;
2020
import java.text.MessageFormat;
2121
import java.util.HashMap;
22+
import java.util.Locale;
2223

2324
import org.w3c.dom.DOMException;
2425

@@ -77,6 +78,9 @@ public abstract class AbstractCSSParser {
7778
parserMessages_.put("invalidExprColon", "Error in expression; '':'' found after identifier \"{0}\".");
7879
parserMessages_.put("invalidPrio", "Error in priority.");
7980

81+
parserMessages_.put("invalidPagePseudoClass",
82+
"Invalid page pseudo class \"{0}\"; valid values are \"blank\", \"first\", \"left\", and \"right\".");
83+
8084
parserMessages_.put("ignoringRule", "Ignoring the whole rule.");
8185
parserMessages_.put("ignoringFollowingDeclarations", "Ignoring the following declarations in this rule.");
8286

@@ -1086,4 +1090,19 @@ private static int hexval(final char c) {
10861090
return -1;
10871091
}
10881092
}
1093+
1094+
protected String normalizeAndValidatePagePseudoClass(final Token t) {
1095+
final String pseudo = unescape(t.image, false);
1096+
final String pseudoLC = pseudo.toLowerCase(Locale.ROOT);
1097+
if ("blank".equals(pseudoLC)
1098+
|| "left".equals(pseudoLC)
1099+
|| "first".equals(pseudoLC)
1100+
|| "right".equals(pseudoLC)) {
1101+
return pseudoLC;
1102+
}
1103+
1104+
final String pattern = getParserMessage("invalidPagePseudoClass");
1105+
throw new CSSParseException(MessageFormat.format(pattern, pseudo),
1106+
getInputSource().getURI(), t.beginLine, t.beginColumn);
1107+
}
10891108
}

src/main/javacc/CSS3Parser.jj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,7 @@ String pseudoPage() :
925925
Token t;
926926
}
927927
{
928-
<COLON> t = <IDENT> { return ":" + unescape(t.image, false); }
928+
<COLON> t = <IDENT> { return ":" + normalizeAndValidatePagePseudoClass(t); }
929929
}
930930

931931
//

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

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@
1515
package com.gargoylesoftware.css.dom;
1616

1717
import static org.junit.jupiter.api.Assertions.assertEquals;
18+
import static org.junit.jupiter.api.Assertions.assertTrue;
19+
import static org.junit.jupiter.api.Assertions.fail;
1820

1921
import java.io.StringReader;
2022

2123
import org.junit.jupiter.api.Test;
24+
import org.w3c.dom.DOMException;
2225

2326
import com.gargoylesoftware.css.parser.CSSOMParser;
2427
import com.gargoylesoftware.css.parser.InputSource;
@@ -51,9 +54,9 @@ public void setCssText() throws Exception {
5154
assertEquals("@page { size: 21cm 29.7cm; }", value.getCssText());
5255
assertEquals("@page { size: 21cm 29.7cm; }", value.toString());
5356

54-
value.setCssText("@page :pseudo { color: blue }");
55-
assertEquals("@page :pseudo { color: blue; }", value.getCssText());
56-
assertEquals("@page :pseudo { color: blue; }", value.toString());
57+
value.setCssText("@page :left { color: blue }");
58+
assertEquals("@page :left { color: blue; }", value.getCssText());
59+
assertEquals("@page :left { color: blue; }", value.toString());
5760

5861
}
5962

@@ -65,8 +68,8 @@ public void getSelectorText() throws Exception {
6568
CSSPageRuleImpl value = parsePageRule("@page { size: 21.0cm 29.7cm; }");
6669
assertEquals("", value.getSelectorText());
6770

68-
value = parsePageRule("@page :pseudo {color: blue}");
69-
assertEquals(":pseudo", value.getSelectorText());
71+
value = parsePageRule("@page :first {color: blue}");
72+
assertEquals(":first", value.getSelectorText());
7073
}
7174

7275
/**
@@ -77,11 +80,33 @@ public void setSelectorText() throws Exception {
7780
final CSSPageRuleImpl value = parsePageRule("@page { color: blue; }");
7881
assertEquals("", value.getSelectorText());
7982

80-
value.setSelectorText(":pseudo");
81-
assertEquals("@page :pseudo { color: blue; }", value.getCssText());
82-
assertEquals("@page :pseudo { color: blue; }", value.toString());
83+
value.setSelectorText(":right");
84+
assertEquals(":right", value.getSelectorText());
85+
assertEquals("@page :right { color: blue; }", value.getCssText());
86+
assertEquals("@page :right { color: blue; }", value.toString());
8387

8488
value.setSelectorText("");
89+
assertEquals("", value.getSelectorText());
90+
assertEquals("@page { color: blue; }", value.getCssText());
91+
assertEquals("@page { color: blue; }", value.toString());
92+
}
93+
94+
/**
95+
* @throws Exception if any error occurs
96+
*/
97+
@Test
98+
public void setSelectorTextInvalid() throws Exception {
99+
final CSSPageRuleImpl value = parsePageRule("@page { color: blue; }");
100+
assertEquals("", value.getSelectorText());
101+
102+
try {
103+
value.setSelectorText(":invalid");
104+
fail("DOMException expected");
105+
}
106+
catch (final DOMException e) {
107+
assertTrue(e.getMessage().startsWith("The text does not represent a page rule (null)"), e.getMessage());
108+
}
109+
assertEquals("", value.getSelectorText());
85110
assertEquals("@page { color: blue; }", value.getCssText());
86111
assertEquals("@page { color: blue; }", value.toString());
87112
}
@@ -94,8 +119,8 @@ public void setPseudoPage() throws Exception {
94119
CSSPageRuleImpl value = parsePageRule("@page { size: 21.0cm 29.7cm; }");
95120
assertEquals("", value.getSelectorText());
96121

97-
value = parsePageRule("@page :pseudo {color: blue}");
98-
assertEquals(":pseudo", value.getSelectorText());
122+
value = parsePageRule("@page :blank {color: blue}");
123+
assertEquals(":blank", value.getSelectorText());
99124
}
100125

101126
/**
@@ -106,7 +131,7 @@ public void getStyle() throws Exception {
106131
CSSPageRuleImpl value = parsePageRule("@page { size: 21.0cm 29.7cm; }");
107132
assertEquals("size: 21cm 29.7cm", value.getStyle().toString());
108133

109-
value = parsePageRule("@page :pseudo {color: blue}");
134+
value = parsePageRule("@page :left {color: blue}");
110135
assertEquals("color: blue", value.getStyle().toString());
111136
}
112137

src/test/java/com/gargoylesoftware/css/parser/CSS3ParserTest.java

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2122,7 +2122,7 @@ public void unexpectedEndOfMediaRule() throws Exception {
21222122
*/
21232123
@Test
21242124
public void unexpectedEndOfPageRule() throws Exception {
2125-
final String css = "@page :pageStyle { size: 21.0cm 29.7cm;";
2125+
final String css = "@page :left { size: 21.0cm 29.7cm;";
21262126

21272127
final InputSource source = new InputSource(new StringReader(css));
21282128
final CSSOMParser parser = new CSSOMParser();
@@ -2137,20 +2137,20 @@ public void unexpectedEndOfPageRule() throws Exception {
21372137
+ "(Invalid token \"<EOF>\". Was expecting one of: <S>, <IDENT>, \"}\", \";\", \"*\", <CUSTOM_PROPERTY_NAME>.)";
21382138
assertEquals(expected, errorHandler.getErrorMessage());
21392139
assertEquals("1", errorHandler.getErrorLines());
2140-
assertEquals("39", errorHandler.getErrorColumns());
2140+
assertEquals("34", errorHandler.getErrorColumns());
21412141

21422142
assertEquals(0, errorHandler.getFatalErrorCount());
21432143
assertEquals(1, errorHandler.getWarningCount());
21442144
assertEquals("Ignoring the whole rule.", errorHandler.getWarningMessage());
21452145
assertEquals("1", errorHandler.getWarningLines());
2146-
assertEquals("39", errorHandler.getWarningColumns());
2146+
assertEquals("34", errorHandler.getWarningColumns());
21472147

21482148
final CSSRuleListImpl rules = sheet.getCssRules();
21492149

21502150
assertEquals(1, rules.getLength());
21512151

21522152
final AbstractCSSRuleImpl rule = rules.getRules().get(0);
2153-
assertEquals("@page :pageStyle { size: 21cm 29.7cm; }", rule.getCssText());
2153+
assertEquals("@page :left { size: 21cm 29.7cm; }", rule.getCssText());
21542154
}
21552155

21562156
/**
@@ -3665,25 +3665,25 @@ public void backslashZeroHack() throws Exception {
36653665
*/
36663666
@Test
36673667
public void unicode() throws Exception {
3668-
unicode("@p\\41ge :pageStyle {}", "@page :pageStyle { }");
3669-
unicode("@p\\041ge :pageStyle {}", "@page :pageStyle { }");
3670-
unicode("@p\\0041ge :pageStyle {}", "@page :pageStyle { }");
3671-
unicode("@p\\00041ge :pageStyle {}", "@page :pageStyle { }");
3672-
unicode("@p\\000041ge :pageStyle {}", "@page :pageStyle { }");
3668+
unicode("@p\\41ge :right {}", "@page :right { }");
3669+
unicode("@p\\041ge :right {}", "@page :right { }");
3670+
unicode("@p\\0041ge :right {}", "@page :right { }");
3671+
unicode("@p\\00041ge :right {}", "@page :right { }");
3672+
unicode("@p\\000041ge :right {}", "@page :right { }");
36733673

36743674
// \\0000041 - fails
3675-
unicode("@p\\0000041ge :pageStyle {}", "@p\\0000041ge :pageStyle {}");
3675+
unicode("@p\\0000041ge :right {}", "@p\\0000041ge :right {}");
36763676

36773677
// terminated by whitespace
3678-
unicode("@\\0070 age :pageStyle {}", "@page :pageStyle { }");
3679-
unicode("@\\0070\tage :pageStyle {}", "@page :pageStyle { }");
3680-
unicode("@\\0070\r\nage :pageStyle {}", "@page :pageStyle { }");
3678+
unicode("@\\0070 age :right {}", "@page :right { }");
3679+
unicode("@\\0070\tage :right {}", "@page :right { }");
3680+
unicode("@\\0070\r\nage :right {}", "@page :right { }");
36813681

36823682
// terminated by lenght
3683-
unicode("@\\000070age :pageStyle {}", "@page :pageStyle { }");
3683+
unicode("@\\000070age :right {}", "@page :right { }");
36843684

36853685
// backslash ignored
3686-
unicode("@\\page :pageStyle {}", "@page :pageStyle { }");
3686+
unicode("@\\page :right {}", "@page :right { }");
36873687
}
36883688

36893689
/**
@@ -3693,7 +3693,7 @@ public void unicode() throws Exception {
36933693
public void unicodeEscaping() throws Exception {
36943694
unicode("@media paper\\7b { }", "@media paper{ {\n}");
36953695
unicode(".class\\7b { color: blue }", "*.class{ { color: blue; }");
3696-
unicode("@page :pseu\\64o { color: blue }", "@page :pseudo { color: blue; }");
3696+
unicode("@page :bl\\61nk { color: blue }", "@page :blank { color: blue; }");
36973697
unicode("h1:first-l\\69ne { color: blue }", "h1:first-line { color: blue; }");
36983698
unicode(".cls { color: blu\\65 }", "*.cls { color: blue; }");
36993699
}

src/test/java/com/gargoylesoftware/css/parser/CSSOMParserTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -432,21 +432,21 @@ private String getCssTextFromDeclaration(final AbstractCSSParser p, final String
432432
*/
433433
@Test
434434
public void parsePageDeclaration() throws Exception {
435-
final Reader r = new StringReader("@page :pageStyle { size: 21.0cm 29.7cm; }");
435+
final Reader r = new StringReader("@page :blank { size: 21.0cm 29.7cm; }");
436436
final InputSource is = new InputSource(r);
437437
final CSSStyleSheetImpl ss = new CSSOMParser().parseStyleSheet(is, null);
438438

439-
assertEquals("@page :pageStyle { size: 21cm 29.7cm; }", ss.toString().trim());
439+
assertEquals("@page :blank { size: 21cm 29.7cm; }", ss.toString().trim());
440440

441441
final CSSRuleListImpl rules = ss.getCssRules();
442442
assertEquals(1, rules.getLength());
443443

444444
final AbstractCSSRuleImpl rule = rules.getRules().get(0);
445445

446-
assertEquals("@page :pageStyle { size: 21cm 29.7cm; }", rule.getCssText());
446+
assertEquals("@page :blank { size: 21cm 29.7cm; }", rule.getCssText());
447447

448448
final CSSPageRuleImpl pageRule = (CSSPageRuleImpl) rule;
449-
assertEquals(":pageStyle", pageRule.getSelectorText());
449+
assertEquals(":blank", pageRule.getSelectorText());
450450
assertEquals("size: 21cm 29.7cm", pageRule.getStyle().getCssText());
451451
}
452452

0 commit comments

Comments
 (0)