Skip to content

Commit 17634e6

Browse files
authored
feat: [#1642] Adds support for child combinator to :has pseudo selector (#1660)
1 parent d5d94a4 commit 17634e6

File tree

3 files changed

+25
-5
lines changed

3 files changed

+25
-5
lines changed

packages/happy-dom/src/query-selector/SelectorItem.ts

+10
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,16 @@ export default class SelectorItem {
340340
priorityWeightForHas = match.priorityWeight;
341341
}
342342
}
343+
} else if (pseudo.arguments[0] === '>') {
344+
for (const selectorItem of pseudo.selectorItems) {
345+
for (const child of element[PropertySymbol.elementArray]) {
346+
const match = selectorItem.match(child);
347+
if (match && priorityWeightForHas < match.priorityWeight) {
348+
priorityWeightForHas = match.priorityWeight;
349+
break;
350+
}
351+
}
352+
}
343353
} else {
344354
for (const selectorItem of pseudo.selectorItems) {
345355
const match = this.matchChildOfElement(selectorItem, element);

packages/happy-dom/src/query-selector/SelectorParser.ts

+11-4
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,10 @@ export default class SelectorParser {
277277
): ISelectorPseudo {
278278
const lowerName = name.toLowerCase();
279279

280+
if (args) {
281+
args = args.trim();
282+
}
283+
280284
if (!args) {
281285
return { name: lowerName, arguments: null, selectorItems: null, nthFunction: null };
282286
}
@@ -328,10 +332,13 @@ export default class SelectorParser {
328332

329333
// The ":has()" pseudo selector doesn't allow for it to be nested inside another ":has()" pseudo selector, as it can lead to cyclic querying.
330334
if (!args.includes(':has(')) {
331-
for (const group of this.getSelectorGroups(
332-
args[0] === '+' ? args.replace('+', '') : args,
333-
options
334-
)) {
335+
let newArgs = args;
336+
if (args[0] === '+') {
337+
newArgs = args.replace('+', '');
338+
} else if (args[0] === '>') {
339+
newArgs = args.replace('>', '');
340+
}
341+
for (const group of this.getSelectorGroups(newArgs, options)) {
335342
hasSelectorItems.push(group[0]);
336343
}
337344
}

packages/happy-dom/test/query-selector/QuerySelector.test.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -1205,9 +1205,12 @@ describe('QuerySelector', () => {
12051205
expect(Array.from(container.querySelectorAll('span:has(+video)'))).toEqual([
12061206
container.children[1]
12071207
]);
1208-
expect(Array.from(container.querySelectorAll('h1:has(+h2)'))).toEqual([
1208+
expect(Array.from(container.querySelectorAll('h1:has( +h2)'))).toEqual([
12091209
container.children[3]
12101210
]);
1211+
expect(Array.from(container.querySelectorAll('span:has(> video)'))).toEqual([
1212+
container.children[0]
1213+
]);
12111214
});
12121215
});
12131216

0 commit comments

Comments
 (0)