Skip to content

Commit

Permalink
feat: [#1642] Adds support for child combinator to :has pseudo select…
Browse files Browse the repository at this point in the history
…or (#1660)
  • Loading branch information
capricorn86 authored Jan 1, 2025
1 parent d5d94a4 commit 17634e6
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 5 deletions.
10 changes: 10 additions & 0 deletions packages/happy-dom/src/query-selector/SelectorItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,16 @@ export default class SelectorItem {
priorityWeightForHas = match.priorityWeight;
}
}
} else if (pseudo.arguments[0] === '>') {
for (const selectorItem of pseudo.selectorItems) {
for (const child of element[PropertySymbol.elementArray]) {
const match = selectorItem.match(child);
if (match && priorityWeightForHas < match.priorityWeight) {
priorityWeightForHas = match.priorityWeight;
break;
}
}
}
} else {
for (const selectorItem of pseudo.selectorItems) {
const match = this.matchChildOfElement(selectorItem, element);
Expand Down
15 changes: 11 additions & 4 deletions packages/happy-dom/src/query-selector/SelectorParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,10 @@ export default class SelectorParser {
): ISelectorPseudo {
const lowerName = name.toLowerCase();

if (args) {
args = args.trim();
}

if (!args) {
return { name: lowerName, arguments: null, selectorItems: null, nthFunction: null };
}
Expand Down Expand Up @@ -328,10 +332,13 @@ export default class SelectorParser {

// The ":has()" pseudo selector doesn't allow for it to be nested inside another ":has()" pseudo selector, as it can lead to cyclic querying.
if (!args.includes(':has(')) {
for (const group of this.getSelectorGroups(
args[0] === '+' ? args.replace('+', '') : args,
options
)) {
let newArgs = args;
if (args[0] === '+') {
newArgs = args.replace('+', '');
} else if (args[0] === '>') {
newArgs = args.replace('>', '');
}
for (const group of this.getSelectorGroups(newArgs, options)) {
hasSelectorItems.push(group[0]);
}
}
Expand Down
5 changes: 4 additions & 1 deletion packages/happy-dom/test/query-selector/QuerySelector.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1205,9 +1205,12 @@ describe('QuerySelector', () => {
expect(Array.from(container.querySelectorAll('span:has(+video)'))).toEqual([
container.children[1]
]);
expect(Array.from(container.querySelectorAll('h1:has(+h2)'))).toEqual([
expect(Array.from(container.querySelectorAll('h1:has( +h2)'))).toEqual([
container.children[3]
]);
expect(Array.from(container.querySelectorAll('span:has(> video)'))).toEqual([
container.children[0]
]);
});
});

Expand Down

0 comments on commit 17634e6

Please sign in to comment.