From b8e69dda548715388c300d20ea9a4f0bbf60fd9e Mon Sep 17 00:00:00 2001 From: Sergey Kryzhanovsky Date: Sat, 24 Nov 2012 01:17:19 +0200 Subject: [PATCH] =?UTF-8?q?:not(X)=20support=20=E2=80=94=20https://github.?= =?UTF-8?q?com/css/csso/issues/111?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 ++ lib/gonzales.cssp.node.js | 29 +++++++++++++++++-- src/cssp.ast.shared.js | 29 +++++++++++++++++-- .../data/test_attrselector/attrselector.5.css | 1 + .../data/test_attrselector/attrselector.5.l | 1 + .../data/test_attrselector/attrselector.5.p | 1 + .../test_simpleselector/simpleselector.11.p | 3 +- .../test_simpleselector/simpleselector.12.p | 5 ++-- .../test_simpleselector/simpleselector.13.p | 7 +++-- .../data/test_stylesheet/issue111.test1.css | 1 + .../data/test_stylesheet/issue111.test1.l | 1 + .../data/test_stylesheet/issue111.test1.p | 16 ++++++++++ web/gonzales.cssp.web.js | 29 +++++++++++++++++-- 13 files changed, 113 insertions(+), 12 deletions(-) create mode 100644 test/cssp/data/test_attrselector/attrselector.5.css create mode 100644 test/cssp/data/test_attrselector/attrselector.5.l create mode 100644 test/cssp/data/test_attrselector/attrselector.5.p create mode 100644 test/cssp/data/test_stylesheet/issue111.test1.css create mode 100644 test/cssp/data/test_stylesheet/issue111.test1.l create mode 100644 test/cssp/data/test_stylesheet/issue111.test1.p diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f94abe..0f251a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ Gomzales changelog ------------------------- - Typo fix (global variable leak): https://github.com/css/csso/pull/110 +- Attribute selectors extended by `|`. +- `not(..)` pseudo-class special support: https://github.com/css/csso/issues/111 28.10.2012, Version 1.0.5 ------------------------- diff --git a/lib/gonzales.cssp.node.js b/lib/gonzales.cssp.node.js index f66bf31..4673094 100644 --- a/lib/gonzales.cssp.node.js +++ b/lib/gonzales.cssp.node.js @@ -554,6 +554,7 @@ function getCSSPAST(_tokens, rule, _needInfo) { //attrselector = (seq('=') | seq('~=') | seq('^=') | seq('$=') | seq('*=') | seq('|=')):x -> [#attrselector, x] function checkAttrselector(_i) { if (tokens[_i].type === TokenType.EqualsSign) return 1; + if (tokens[_i].type === TokenType.VerticalLine && (!tokens[_i + 1] || tokens[_i + 1].type !== TokenType.EqualsSign)) return 1; if (!tokens[_i + 1] || tokens[_i + 1].type !== TokenType.EqualsSign) return fail(tokens[_i]); @@ -1205,7 +1206,9 @@ function getCSSPAST(_tokens, rule, _needInfo) { pos++; - var body = getFunctionBody(); + var body = ident[needInfo? 2 : 1] !== 'not'? + getFunctionBody() : + getNotFunctionBody(); // ok, here we have CSS3 initial draft: http://dev.w3.org/csswg/selectors3/#negation return needInfo? [{ ln: tokens[startPos].ln }, CSSPNodeType.FunktionType, ident, body] : @@ -1220,11 +1223,33 @@ function getCSSPAST(_tokens, rule, _needInfo) { while (tokens[pos].type !== TokenType.RightParenthesis) { if (checkTset(pos)) { x = getTset(); - if ((needInfo && typeof x[1] === 'string') || typeof x[0] === 'string') body.push(x); else body = body.concat(x); } else if (checkClazz(pos)) { body.push(getClazz()); + } else { + throwError(); + } + } + + pos++; + + return (needInfo? + [{ ln: tokens[startPos].ln }, CSSPNodeType.FunctionBodyType] : + [CSSPNodeType.FunctionBodyType] + ).concat(body); + } + + function getNotFunctionBody() { + var startPos = pos, + body = [], + x; + + while (tokens[pos].type !== TokenType.RightParenthesis) { + if (checkSimpleselector(pos)) { + body.push(getSimpleSelector()); + } else { + throwError(); } } diff --git a/src/cssp.ast.shared.js b/src/cssp.ast.shared.js index 5b0eb1b..0e33e84 100644 --- a/src/cssp.ast.shared.js +++ b/src/cssp.ast.shared.js @@ -282,6 +282,7 @@ function getCSSPAST(_tokens, rule, _needInfo) { //attrselector = (seq('=') | seq('~=') | seq('^=') | seq('$=') | seq('*=') | seq('|=')):x -> [#attrselector, x] function checkAttrselector(_i) { if (tokens[_i].type === TokenType.EqualsSign) return 1; + if (tokens[_i].type === TokenType.VerticalLine && (!tokens[_i + 1] || tokens[_i + 1].type !== TokenType.EqualsSign)) return 1; if (!tokens[_i + 1] || tokens[_i + 1].type !== TokenType.EqualsSign) return fail(tokens[_i]); @@ -933,7 +934,9 @@ function getCSSPAST(_tokens, rule, _needInfo) { pos++; - var body = getFunctionBody(); + var body = ident[needInfo? 2 : 1] !== 'not'? + getFunctionBody() : + getNotFunctionBody(); // ok, here we have CSS3 initial draft: http://dev.w3.org/csswg/selectors3/#negation return needInfo? [{ ln: tokens[startPos].ln }, CSSPNodeType.FunktionType, ident, body] : @@ -948,11 +951,33 @@ function getCSSPAST(_tokens, rule, _needInfo) { while (tokens[pos].type !== TokenType.RightParenthesis) { if (checkTset(pos)) { x = getTset(); - if ((needInfo && typeof x[1] === 'string') || typeof x[0] === 'string') body.push(x); else body = body.concat(x); } else if (checkClazz(pos)) { body.push(getClazz()); + } else { + throwError(); + } + } + + pos++; + + return (needInfo? + [{ ln: tokens[startPos].ln }, CSSPNodeType.FunctionBodyType] : + [CSSPNodeType.FunctionBodyType] + ).concat(body); + } + + function getNotFunctionBody() { + var startPos = pos, + body = [], + x; + + while (tokens[pos].type !== TokenType.RightParenthesis) { + if (checkSimpleselector(pos)) { + body.push(getSimpleSelector()); + } else { + throwError(); } } diff --git a/test/cssp/data/test_attrselector/attrselector.5.css b/test/cssp/data/test_attrselector/attrselector.5.css new file mode 100644 index 0000000..948cf94 --- /dev/null +++ b/test/cssp/data/test_attrselector/attrselector.5.css @@ -0,0 +1 @@ +| diff --git a/test/cssp/data/test_attrselector/attrselector.5.l b/test/cssp/data/test_attrselector/attrselector.5.l new file mode 100644 index 0000000..948cf94 --- /dev/null +++ b/test/cssp/data/test_attrselector/attrselector.5.l @@ -0,0 +1 @@ +| diff --git a/test/cssp/data/test_attrselector/attrselector.5.p b/test/cssp/data/test_attrselector/attrselector.5.p new file mode 100644 index 0000000..41762f1 --- /dev/null +++ b/test/cssp/data/test_attrselector/attrselector.5.p @@ -0,0 +1 @@ +['attrselector', '|'] diff --git a/test/cssp/data/test_simpleselector/simpleselector.11.p b/test/cssp/data/test_simpleselector/simpleselector.11.p index 0e456f1..4ac95bc 100644 --- a/test/cssp/data/test_simpleselector/simpleselector.11.p +++ b/test/cssp/data/test_simpleselector/simpleselector.11.p @@ -6,4 +6,5 @@ ['funktion', ['ident', 'not'], ['functionBody', - ['ident', '*']]]]] \ No newline at end of file + ['simpleselector', + ['ident', '*']]]]]] \ No newline at end of file diff --git a/test/cssp/data/test_simpleselector/simpleselector.12.p b/test/cssp/data/test_simpleselector/simpleselector.12.p index 35c72a2..92033ed 100644 --- a/test/cssp/data/test_simpleselector/simpleselector.12.p +++ b/test/cssp/data/test_simpleselector/simpleselector.12.p @@ -4,5 +4,6 @@ ['funktion', ['ident', 'not'], ['functionBody', - ['braces', '[', ']', - ['ident', 'ABC']]]]]] \ No newline at end of file + ['simpleselector', + ['attrib', + ['ident', 'ABC']]]]]]] \ No newline at end of file diff --git a/test/cssp/data/test_simpleselector/simpleselector.13.p b/test/cssp/data/test_simpleselector/simpleselector.13.p index 44fd833..c8f0294 100644 --- a/test/cssp/data/test_simpleselector/simpleselector.13.p +++ b/test/cssp/data/test_simpleselector/simpleselector.13.p @@ -3,6 +3,7 @@ ['funktion', ['ident', 'not'], ['functionBody', - ['ident', 'el'], - ['clazz', - ['ident', 'class-postfix']]]]]] \ No newline at end of file + ['simpleselector', + ['ident', 'el'], + ['clazz', + ['ident', 'class-postfix']]]]]]] \ No newline at end of file diff --git a/test/cssp/data/test_stylesheet/issue111.test1.css b/test/cssp/data/test_stylesheet/issue111.test1.css new file mode 100644 index 0000000..2f2befa --- /dev/null +++ b/test/cssp/data/test_stylesheet/issue111.test1.css @@ -0,0 +1 @@ +body:not([x|x]) {} \ No newline at end of file diff --git a/test/cssp/data/test_stylesheet/issue111.test1.l b/test/cssp/data/test_stylesheet/issue111.test1.l new file mode 100644 index 0000000..50fe29e --- /dev/null +++ b/test/cssp/data/test_stylesheet/issue111.test1.l @@ -0,0 +1 @@ +body:not([x|x]) {} diff --git a/test/cssp/data/test_stylesheet/issue111.test1.p b/test/cssp/data/test_stylesheet/issue111.test1.p new file mode 100644 index 0000000..7dfb41b --- /dev/null +++ b/test/cssp/data/test_stylesheet/issue111.test1.p @@ -0,0 +1,16 @@ +['stylesheet', + ['ruleset', + ['selector', + ['simpleselector', + ['ident', 'body'], + ['pseudoc', + ['funktion', + ['ident', 'not'], + ['functionBody', + ['simpleselector', + ['attrib', + ['ident', 'x'], + ['attrselector', '|'], + ['ident', 'x']]]]]], + ['s', ' ']]], + ['block']]] \ No newline at end of file diff --git a/web/gonzales.cssp.web.js b/web/gonzales.cssp.web.js index 1d47ded..587d77a 100644 --- a/web/gonzales.cssp.web.js +++ b/web/gonzales.cssp.web.js @@ -554,6 +554,7 @@ function getCSSPAST(_tokens, rule, _needInfo) { //attrselector = (seq('=') | seq('~=') | seq('^=') | seq('$=') | seq('*=') | seq('|=')):x -> [#attrselector, x] function checkAttrselector(_i) { if (tokens[_i].type === TokenType.EqualsSign) return 1; + if (tokens[_i].type === TokenType.VerticalLine && (!tokens[_i + 1] || tokens[_i + 1].type !== TokenType.EqualsSign)) return 1; if (!tokens[_i + 1] || tokens[_i + 1].type !== TokenType.EqualsSign) return fail(tokens[_i]); @@ -1205,7 +1206,9 @@ function getCSSPAST(_tokens, rule, _needInfo) { pos++; - var body = getFunctionBody(); + var body = ident[needInfo? 2 : 1] !== 'not'? + getFunctionBody() : + getNotFunctionBody(); // ok, here we have CSS3 initial draft: http://dev.w3.org/csswg/selectors3/#negation return needInfo? [{ ln: tokens[startPos].ln }, CSSPNodeType.FunktionType, ident, body] : @@ -1220,11 +1223,33 @@ function getCSSPAST(_tokens, rule, _needInfo) { while (tokens[pos].type !== TokenType.RightParenthesis) { if (checkTset(pos)) { x = getTset(); - if ((needInfo && typeof x[1] === 'string') || typeof x[0] === 'string') body.push(x); else body = body.concat(x); } else if (checkClazz(pos)) { body.push(getClazz()); + } else { + throwError(); + } + } + + pos++; + + return (needInfo? + [{ ln: tokens[startPos].ln }, CSSPNodeType.FunctionBodyType] : + [CSSPNodeType.FunctionBodyType] + ).concat(body); + } + + function getNotFunctionBody() { + var startPos = pos, + body = [], + x; + + while (tokens[pos].type !== TokenType.RightParenthesis) { + if (checkSimpleselector(pos)) { + body.push(getSimpleSelector()); + } else { + throwError(); } }