Skip to content

Commit

Permalink
capricorn86#661@trivial: Improves the Regexp to include any escaped c…
Browse files Browse the repository at this point in the history
…haracter.
  • Loading branch information
capricorn86 committed Dec 3, 2022
1 parent fc21d75 commit 9cd047f
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 11 deletions.
16 changes: 5 additions & 11 deletions packages/happy-dom/src/query-selector/SelectorItem.ts
Expand Up @@ -7,9 +7,9 @@ const ATTRIBUTE_REGEXP =
const ATTRIBUTE_NAME_REGEXP = /[^a-zA-Z0-9-_$]/;
const PSUEDO_REGEXP =
/(?<!\\):([a-zA-Z-]+)\(([0-9n+-]+|odd|even)\)|(?<!\\):not\(([^)]+)\)|(?<!\\):([a-zA-Z-]+)/g;
const CLASS_REGEXP = /\.(([a-zA-Z0-9-_$]|\\:)+)/g;
const CLASS_REGEXP = /\.(([a-zA-Z0-9-_$]|\\.)+)/g;
const TAG_NAME_REGEXP = /^[a-zA-Z0-9-]+/;
const ID_REGEXP = /#[A-Za-z][-A-Za-z0-9_]*/g;
const ID_REGEXP = /(?<!\\)#[A-Za-z][-A-Za-z0-9_]*/g;
const CSS_ESCAPE_REGEXP = /(?<!\\):/g;
const CSS_ESCAPE_CHAR_REGEXP = /\\/g;

Expand All @@ -34,9 +34,10 @@ export default class SelectorItem {
*/
constructor(selector: string) {
const baseSelector = selector.replace(new RegExp(PSUEDO_REGEXP, 'g'), '');
const idMatch = !this.isAll && selector.includes('#') ? baseSelector.match(ID_REGEXP) : null;

this.isAll = baseSelector === '*';
this.isID = !this.isAll ? selector.indexOf('#') !== -1 : false;
this.isID = !!idMatch;
this.isAttribute = !this.isAll && baseSelector.includes('[');
// If baseSelector !== selector then some psuedo selector was replaced above
this.isPseudo = !this.isAll && baseSelector !== selector;
Expand All @@ -45,14 +46,7 @@ export default class SelectorItem {
this.tagName = this.tagName ? this.tagName[0].toUpperCase() : null;
this.isTagName = this.tagName !== null;
this.selector = selector;
this.id = null;

if (!this.isAll && this.isID) {
const idMatches = baseSelector.match(ID_REGEXP);
if (idMatches) {
this.id = idMatches[0].replace('#', '');
}
}
this.id = idMatch ? idMatch[0].replace('#', '') : null;
}

/**
Expand Down
51 changes: 51 additions & 0 deletions packages/happy-dom/test/query-selector/QuerySelector.test.ts
Expand Up @@ -51,6 +51,57 @@ describe('QuerySelector', () => {
expect(elements[3]).toBe(container.children[0].children[1].children[1]);
});

it('Returns all elements with class name "before:after".', () => {
const container = document.createElement('div');
const element1 = document.createElement('div');
const element2 = document.createElement('div');
element1.className = 'before:after';
element2.className = 'before:after';
container.appendChild(element1);
container.appendChild(element2);

const invalidSelectorElements = container.querySelectorAll('.before:');
const validSelectorElements = container.querySelectorAll('.before\\:after');
expect(invalidSelectorElements.length).toBe(0);
expect(validSelectorElements.length).toBe(2);
expect(validSelectorElements[0]).toBe(element1);
expect(validSelectorElements[1]).toBe(element2);
});

it('Returns all elements with class name "before#after".', () => {
const container = document.createElement('div');
const element1 = document.createElement('div');
const element2 = document.createElement('div');
element1.className = 'before#after';
element2.className = 'before#after';
container.appendChild(element1);
container.appendChild(element2);

const invalidSelectorElements = container.querySelectorAll('.before#after');
const validSelectorElements = container.querySelectorAll('.before\\#after');
expect(invalidSelectorElements.length).toBe(0);
expect(validSelectorElements.length).toBe(2);
expect(validSelectorElements[0]).toBe(element1);
expect(validSelectorElements[1]).toBe(element2);
});

it('Returns all elements with class name "before&after".', () => {
const container = document.createElement('div');
const element1 = document.createElement('div');
const element2 = document.createElement('div');
element1.className = 'before&after';
element2.className = 'before&after';
container.appendChild(element1);
container.appendChild(element2);

const invalidSelectorElements = container.querySelectorAll('.before&after');
const validSelectorElements = container.querySelectorAll('.before\\&after');
expect(invalidSelectorElements.length).toBe(0);
expect(validSelectorElements.length).toBe(2);
expect(validSelectorElements[0]).toBe(element1);
expect(validSelectorElements[1]).toBe(element2);
});

it('Returns all elements with class name "class1 class2".', () => {
const container = document.createElement('div');
container.innerHTML = QuerySelectorHTML;
Expand Down

0 comments on commit 9cd047f

Please sign in to comment.