From ef3447b5a6367c8c7a42a302d526d697d7221cf5 Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Tue, 17 Dec 2024 23:41:24 +0100 Subject: [PATCH] fix: descendant selector --- cli/js/40_lint_selector.js | 23 ++++++++++++-------- cli/js/40_lint_selector_parser_test.ts | 30 ++++++++++++++++++++------ cli/js/40_lint_selector_test.ts | 14 ++++++++++++ 3 files changed, 51 insertions(+), 16 deletions(-) diff --git a/cli/js/40_lint_selector.js b/cli/js/40_lint_selector.js index e44529b29d..97940bd2f4 100644 --- a/cli/js/40_lint_selector.js +++ b/cli/js/40_lint_selector.js @@ -447,16 +447,15 @@ export function parseSelector(input, toElem, toAttr) { }); lex.next(); - // Descendant selector - if (lex.token === Token.Space) { - lex.next(); + continue; + } else if (lex.token === Token.Space) { + lex.next(); - if (lex.token === Token.Word) { - current.push({ - type: RELATION_NODE, - op: BinOp.Space, - }); - } + if (lex.token === Token.Word) { + current.push({ + type: RELATION_NODE, + op: BinOp.Space, + }); } continue; @@ -632,8 +631,14 @@ export function parseSelector(input, toElem, toAttr) { throw new Error(`Multiple selector arguments not supported here`); } + lex.next(); + if (lex.token === Token.Space) { + lex.next(); + } + popSelector(result, stack); stack.push([]); + continue; } else if (lex.token === Token.BraceClose) { throwOnComma = false; popSelector(result, stack); diff --git a/cli/js/40_lint_selector_parser_test.ts b/cli/js/40_lint_selector_parser_test.ts index 56efd0c9f3..baead4a6fd 100644 --- a/cli/js/40_lint_selector_parser_test.ts +++ b/cli/js/40_lint_selector_parser_test.ts @@ -435,7 +435,7 @@ Deno.test("Parser - Pseudo nth-child", () => { { type: PSEUDO_NTH_CHILD, of: null, - backwards: false, + op: null, step: 0, stepOffset: 1, repeat: false, @@ -445,7 +445,7 @@ Deno.test("Parser - Pseudo nth-child", () => { { type: PSEUDO_NTH_CHILD, of: null, - backwards: false, + op: null, step: 2, stepOffset: 0, repeat: true, @@ -455,8 +455,8 @@ Deno.test("Parser - Pseudo nth-child", () => { { type: PSEUDO_NTH_CHILD, of: null, - backwards: true, - step: 2, + op: null, + step: -2, stepOffset: 0, repeat: true, }, @@ -465,7 +465,7 @@ Deno.test("Parser - Pseudo nth-child", () => { { type: PSEUDO_NTH_CHILD, of: null, - backwards: false, + op: "+", step: 2, stepOffset: 1, repeat: true, @@ -479,7 +479,7 @@ Deno.test("Parser - Pseudo nth-child", () => { { type: ELEM_NODE, elem: 1, wildcard: false }, { type: ATTR_EXISTS_NODE, prop: [4] }, ], - backwards: false, + op: "+", step: 2, stepOffset: 1, repeat: true, @@ -489,7 +489,6 @@ Deno.test("Parser - Pseudo nth-child", () => { // Invalid selectors expect(() => testParse(":nth-child(2n + 1 of Foo[attr], Bar)")) .toThrow(); - expect(() => testParse(":nth-child(2n - 1)")).toThrow(); expect(() => testParse(":nth-child(2n - 1 foo)")).toThrow(); }); @@ -574,3 +573,20 @@ Deno.test("Parser - Pseudo not", () => { }, ]]); }); + +Deno.test("Parser - mixed", () => { + expect(testParse("Foo[foo=true] Bar")).toEqual([[ + { + type: ELEM_NODE, + elem: 1, + wildcard: false, + }, + { type: ATTR_BIN_NODE, op: BinOp.Equal, prop: [1], value: true }, + { type: RELATION_NODE, op: BinOp.Space }, + { + type: ELEM_NODE, + elem: 2, + wildcard: false, + }, + ]]); +}); diff --git a/cli/js/40_lint_selector_test.ts b/cli/js/40_lint_selector_test.ts index 976ddee3fa..1b4520c846 100644 --- a/cli/js/40_lint_selector_test.ts +++ b/cli/js/40_lint_selector_test.ts @@ -480,3 +480,17 @@ Deno.test("splitSelectors", () => { "foobar", ]); }); + +Deno.test("mixed", () => { + const ast: TestNode = { + type: "Foo", + attr: true, + children: [ + { type: "Foo", msg: "a" }, + { type: "Foo", msg: "b" }, + { type: "Foo", msg: "c" }, + { type: "Foo", msg: "d" }, + ], + }; + expect(testSelector(ast, "Foo[attr=true] Foo")).toEqual(ast.children![0]); +});