Commit 30e75036 authored by David Sveningsson's avatar David Sveningsson
Browse files

fix(dom): `querySelector` handles escaped characters

parent 516ca065
......@@ -118,6 +118,30 @@ describe("Selector", () => {
]);
});
it("should match id with escaped colon", () => {
expect.assertions(1);
const parser = new Parser(Config.empty().resolve());
const doc = parser.parseHtml(`<div id="foo:"></div>`).root;
const selector = new Selector("#foo\\:");
expect(fetch(selector.match(doc))).toEqual([expect.objectContaining({ tagName: "div" })]);
});
it("should match id with escaped space", () => {
expect.assertions(1);
const parser = new Parser(Config.empty().resolve());
const doc = parser.parseHtml(`<div id="foo "></div>`).root;
const selector = new Selector("#foo\\ ");
expect(fetch(selector.match(doc))).toEqual([expect.objectContaining({ tagName: "div" })]);
});
it("should match id with escaped bracket", () => {
expect.assertions(1);
const parser = new Parser(Config.empty().resolve());
const doc = parser.parseHtml(`<div id="foo[bar]"></div>`).root;
const selector = new Selector("#foo\\[bar\\]");
expect(fetch(selector.match(doc))).toEqual([expect.objectContaining({ tagName: "div" })]);
});
it("should match having attribute ([wilma])", () => {
expect.assertions(1);
const selector = new Selector("[wilma]");
......
......@@ -3,6 +3,15 @@ import { Combinator, parseCombinator } from "./combinator";
import { HtmlElement } from "./htmlelement";
import { factory as pseudoClassFunction } from "./pseudoclass";
/**
* Homage to PHP: unescapes slashes.
*
* E.g. "foo\:bar" becomes "foo:bar"
*/
function stripslashes(value: string): string {
return value.replace(/\\(.)/g, "$1");
}
class Matcher {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public match(node: HtmlElement): boolean {
......@@ -29,7 +38,7 @@ class IdMatcher extends Matcher {
public constructor(id: string) {
super();
this.id = id;
this.id = stripslashes(id);
}
public match(node: HtmlElement): boolean {
......@@ -98,7 +107,7 @@ export class Pattern {
this.selector = pattern;
this.combinator = parseCombinator(match.shift());
this.tagName = match.shift() || "*";
const p = match[0] ? match[0].split(/(?=[.#[:])/) : [];
const p = match[0] ? match[0].split(/(?=(?<!\\)[.#[:])/) : [];
this.pattern = p.map((cur: string) => this.createMatcher(cur));
}
......@@ -167,7 +176,7 @@ export class Selector {
* easier parsing */
selector = selector.replace(/([+~>]) /g, "$1");
const pattern = selector.split(/ +/);
const pattern = selector.split(/(?:(?<!\\) )+/);
return pattern.map((part: string) => new Pattern(part));
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment