diff --git a/src/__tests__/namespaces.mjs b/src/__tests__/namespaces.mjs index 46e66b6..50cdde1 100644 --- a/src/__tests__/namespaces.mjs +++ b/src/__tests__/namespaces.mjs @@ -77,6 +77,21 @@ test("ns alias for namespace", "f\\oo|h1.foo", (t, tree) => { t.deepEqual(tag.ns, "bar"); }); +test("empty namespace after a comment is not a prefix", "/* c */|b", (t, tree) => { + t.deepEqual(tree.nodes[0].nodes[1].namespace, true); + t.deepEqual(tree.nodes[0].nodes[1].value, "b"); +}); + +test("empty namespace after a comma is not a prefix", ".a,|b", (t, tree) => { + t.deepEqual(tree.nodes[1].nodes[0].namespace, true); + t.deepEqual(tree.nodes[1].nodes[0].value, "b"); +}); + +test("empty namespace after a combinator is not a prefix", ".a > |b", (t, tree) => { + t.deepEqual(tree.nodes[0].nodes[2].namespace, true); + t.deepEqual(tree.nodes[0].nodes[2].value, "b"); +}); + throws("lone pipe symbol", "|"); throws("lone pipe symbol with leading spaces", " |"); throws("lone pipe symbol with trailing spaces", "| "); diff --git a/src/parser.js b/src/parser.js index 3b00836..efc1789 100644 --- a/src/parser.js +++ b/src/parser.js @@ -696,7 +696,17 @@ export default class Parser { } namespace() { - const before = (this.prevToken && this.content(this.prevToken)) || true; + const prev = this.prevToken; + // Only treat the previous token as a namespace prefix when it can actually + // be one (a type/word or the universal `*`). A comment, comma, combinator + // or whitespace before `|` means an empty namespace, not a prefix. + const before = + prev && + (prev[TOKEN.TYPE] === tokens.word || + prev[TOKEN.TYPE] === tokens.asterisk || + prev[TOKEN.TYPE] === tokens.ampersand) + ? this.content(prev) + : true; if (this.nextToken[TOKEN.TYPE] === tokens.word) { this.position++; return this.word(before);