Skip to content

Commit 631ffe8

Browse files
committed
(it was defined but not parsed and checked), recast :lang() as expecting a value. Note that we might move to a complete CssExpression parsing and not only one value if needed in the future.
1 parent 2ac365d commit 631ffe8

File tree

7 files changed

+151
-20
lines changed

7 files changed

+151
-20
lines changed

org/w3c/css/parser/CssSelectors.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.w3c.css.util.Messages;
2626
import org.w3c.css.util.Util;
2727
import org.w3c.css.util.Warnings;
28+
import org.w3c.css.values.CssExpression;
2829

2930
import java.util.ArrayList;
3031

@@ -271,6 +272,22 @@ public void setPseudoFun(ApplContext ac, String pseudo, ArrayList<CssSelectors>
271272
}
272273
}
273274

275+
public void setPseudoFun(ApplContext ac, String pseudo, CssExpression expression)
276+
throws InvalidParamException {
277+
278+
CssVersion version = ac.getCssVersion();
279+
String[] ps = PseudoFactory.getPseudoFunction(version);
280+
if (ps != null) {
281+
for (String s : ps) {
282+
if (pseudo.equals(s)) {
283+
addPseudoFunction(PseudoFactory.newPseudoFunction(pseudo, expression, ac));
284+
return;
285+
}
286+
}
287+
throw new InvalidParamException("pseudo", ":" + pseudo, ac);
288+
}
289+
}
290+
274291

275292
public void addType(TypeSelector type) throws InvalidParamException {
276293
super.addType(type);

org/w3c/css/parser/analyzer/CssParser.jj

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2675,6 +2675,7 @@ CssExpression param = null;
26752675
ArrayList<CssSelectors> selector_list = null;
26762676
CssSelectors sel = null;
26772677
String error_str = null;
2678+
CssExpression exp = new CssExpression();
26782679
}
26792680
{
26802681
<COLON> ( ( n=ident()
@@ -2688,11 +2689,9 @@ String error_str = null;
26882689
getBeginColumn(), getEndLine(), getEndColumn(), e));
26892690
}
26902691
} )
2691-
// FXIXME rewrite to make :lang( use a special case
2692-
| ( ( n=<FUNCTIONLANG> ( <S> )* ( language=ident() | language=<STRING> ) ( <S> )* ) {
2692+
| ( ( ( n=<FUNCTIONDIR> | n=<FUNCTIONLANG> ) ( <S> )* term(exp) ) {
26932693
try {
2694-
s.setPseudoFun(ac, convertStringIndex(n.image, 0, n.image.length() -1, false).toLowerCase(),
2695-
convertIdent(language.image));
2694+
s.setPseudoFun(ac, convertStringIndex(n.image, 0, n.image.length() -1, false).toLowerCase(), exp);
26962695
} catch(InvalidParamException e) {
26972696
removeThisRule();
26982697
ac.getFrame()

org/w3c/css/selectors/PseudoFactory.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package org.w3c.css.selectors;
66

77
import org.w3c.css.parser.CssSelectors;
8+
import org.w3c.css.selectors.pseudofunctions.PseudoFunctionDir;
89
import org.w3c.css.selectors.pseudofunctions.PseudoFunctionHas;
910
import org.w3c.css.selectors.pseudofunctions.PseudoFunctionHost;
1011
import org.w3c.css.selectors.pseudofunctions.PseudoFunctionHostContext;
@@ -21,6 +22,7 @@
2122
import org.w3c.css.util.CssProfile;
2223
import org.w3c.css.util.CssVersion;
2324
import org.w3c.css.util.InvalidParamException;
25+
import org.w3c.css.values.CssExpression;
2426

2527
import java.util.ArrayList;
2628

@@ -215,9 +217,6 @@ public static PseudoFunctionSelector newPseudoFunction(String name,
215217
throw new InvalidParamException("pseudo",
216218
"null pseudofunction", ac);
217219
}
218-
if (name.equals("lang")) {
219-
return new PseudoFunctionLang(name, value, ac);
220-
}
221220
if (name.equals("not")) {
222221
return new PseudoFunctionNot(name, value);
223222
}
@@ -278,4 +277,22 @@ public static PseudoFunctionSelector newPseudoFunction(String name,
278277
throw new InvalidParamException("pseudo",
279278
":" + name, ac);
280279
}
280+
281+
public static PseudoFunctionSelector newPseudoFunction(String name,
282+
CssExpression exp,
283+
ApplContext ac)
284+
throws InvalidParamException {
285+
if (name == null) {
286+
throw new InvalidParamException("pseudo",
287+
"null pseudofunction", ac);
288+
}
289+
if (name.equals("dir")) {
290+
return new PseudoFunctionDir(name, exp, ac);
291+
}
292+
if (name.equals("lang")) {
293+
return new PseudoFunctionLang(name, exp, ac);
294+
}
295+
throw new InvalidParamException("pseudo",
296+
":" + name, ac);
297+
}
281298
}

org/w3c/css/selectors/PseudoFunctionSelector.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,16 @@ public String toString() {
9797
}
9898
return representation;
9999
}
100+
101+
public String functionName() {
102+
StringBuilder sb = new StringBuilder();
103+
if (isElement) {
104+
sb.append(':');
105+
}
106+
sb.append(':');
107+
sb.append(name);
108+
sb.append('(');
109+
sb.append(')');
110+
return sb.toString();
111+
}
100112
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
//
2+
// Author: Yves Lafon <ylafon@w3.org>
3+
//
4+
// (c) COPYRIGHT MIT, ERCIM, Keio, Beihang, 2021.
5+
// Please first read the full copyright statement in file COPYRIGHT.html
6+
package org.w3c.css.selectors.pseudofunctions;
7+
8+
import org.w3c.css.selectors.PseudoFunctionSelector;
9+
import org.w3c.css.util.ApplContext;
10+
import org.w3c.css.util.InvalidParamException;
11+
import org.w3c.css.values.CssExpression;
12+
import org.w3c.css.values.CssIdent;
13+
import org.w3c.css.values.CssTypes;
14+
import org.w3c.css.values.CssValue;
15+
16+
/**
17+
* PseudoFunctionDir
18+
*/
19+
public class PseudoFunctionDir extends PseudoFunctionSelector {
20+
21+
public static final CssIdent[] allowed_values;
22+
23+
static {
24+
String[] _allowed_values = {"ltr", "rtl"};
25+
allowed_values = new CssIdent[_allowed_values.length];
26+
int i = 0;
27+
for (String s : _allowed_values) {
28+
allowed_values[i++] = CssIdent.getIdent(s);
29+
}
30+
}
31+
32+
public static CssIdent getAllowedValues(CssIdent ident) {
33+
for (CssIdent id : allowed_values) {
34+
if (id.equals(ident)) {
35+
return id;
36+
}
37+
}
38+
return null;
39+
}
40+
41+
42+
public PseudoFunctionDir(String name, CssExpression exp, ApplContext ac)
43+
throws InvalidParamException {
44+
setName(name);
45+
setParam(parseDir(ac, exp, functionName()));
46+
}
47+
48+
/**
49+
* verify a language tag per BCP47
50+
*
51+
* @param ac the ApplContext
52+
* @param exp the CssExpression
53+
* @param caller the property/selector/context calling for verification
54+
* @throws InvalidParamException if invalid
55+
*/
56+
public static final CssValue parseDir(ApplContext ac, CssExpression exp, String caller)
57+
throws InvalidParamException {
58+
if (exp.getCount() != 1) {
59+
throw new InvalidParamException("unrecognize", caller, ac);
60+
}
61+
CssValue val = exp.getValue();
62+
if ((val.getType() != CssTypes.CSS_IDENT) || (getAllowedValues(val.getIdent()) == null)) {
63+
throw new InvalidParamException("value", val.toString(), caller, ac);
64+
}
65+
exp.next();
66+
return val;
67+
}
68+
69+
}

org/w3c/css/selectors/pseudofunctions/PseudoFunctionIs.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import java.util.ArrayList;
1212

1313
/**
14-
* PseudoFunctionNot
14+
* PseudoFunctionIs
1515
*/
1616
public class PseudoFunctionIs extends PseudoFunctionSelector {
1717

org/w3c/css/selectors/pseudofunctions/PseudoFunctionLang.java

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
import org.w3c.css.selectors.PseudoFunctionSelector;
88
import org.w3c.css.util.ApplContext;
99
import org.w3c.css.util.InvalidParamException;
10+
import org.w3c.css.values.CssExpression;
11+
import org.w3c.css.values.CssTypes;
12+
import org.w3c.css.values.CssValue;
1013

1114
import java.util.IllformedLocaleException;
1215
import java.util.Locale;
@@ -18,37 +21,51 @@
1821
*/
1922
public class PseudoFunctionLang extends PseudoFunctionSelector {
2023

21-
public PseudoFunctionLang(String name, String lang, ApplContext ac)
24+
public PseudoFunctionLang(String name, CssExpression exp, ApplContext ac)
2225
throws InvalidParamException {
2326
setName(name);
24-
parseLang(ac, lang, name);
25-
setParam(lang);
27+
setParam(parseLang(ac, exp, functionName()));
2628
}
2729

2830
/**
2931
* verify a language tag per BCP47
3032
*
3133
* @param ac the ApplContext
32-
* @param lang the language tag
34+
* @param exp the CssExpression containing the value
3335
* @param caller the property/selector/context calling for verification
3436
* @throws InvalidParamException if invalid
3537
*/
36-
public static final void parseLang(ApplContext ac, String lang, String caller)
38+
public static final CssValue parseLang(ApplContext ac, CssExpression exp, String caller)
3739
throws InvalidParamException {
40+
String lang;
41+
if (exp.getCount() != 1) {
42+
throw new InvalidParamException("unrecognize", caller, ac);
43+
}
44+
CssValue val = exp.getValue();
45+
switch (val.getType()) {
46+
case CssTypes.CSS_IDENT:
47+
lang = val.getIdent().toString();
48+
break;
49+
case CssTypes.CSS_STRING:
50+
lang = val.getString().toString();
51+
if (lang.charAt(0) == '"' || lang.charAt(0) == '\'') {
52+
lang = lang.substring(1, lang.lastIndexOf(lang.charAt(0)));
53+
}
54+
break;
55+
default:
56+
throw new InvalidParamException("value", val.toString(), caller, ac);
57+
}
58+
3859
try {
3960
// FIXME validate ranges and not only TAGS.
4061
if (lang.contains("*")) {
41-
return;
42-
}
43-
String lang_tag = lang;
44-
if (lang.charAt(0) == '"' || lang.charAt(0) == '\'') {
45-
// trim the string
46-
lang_tag = lang.substring(1, lang.lastIndexOf(lang.charAt(0)));
62+
return val;
4763
}
4864
// use Locale builder parsing to check BCP 47 values
4965
Builder builder = new Builder();
50-
builder.setLanguageTag(lang_tag);
66+
builder.setLanguageTag(lang);
5167
Locale l = builder.build();
68+
return val;
5269
} catch (IllformedLocaleException ex) {
5370
throw new InvalidParamException("value", lang, caller, ac);
5471
}

0 commit comments

Comments
 (0)