Skip to content

Commit 4b65e77

Browse files
committed
selector edge cases fix
1 parent 3e105c7 commit 4b65e77

File tree

1 file changed

+37
-7
lines changed

1 file changed

+37
-7
lines changed

lib/core/utils/dq-element.js

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,25 @@ import cache from '../base/cache';
66

77
const CACHE_KEY = 'DqElm.RunOptions';
88

9+
/**
10+
* Escapes a string for use in CSS selectors
11+
* @param {String} str - The string to escape
12+
* @returns {String} The escaped string
13+
*/
14+
function escapeCSSSelector(str) {
15+
// Use the CSS.escape method if available
16+
if (window.CSS && window.CSS.escape) {
17+
return window.CSS.escape(str);
18+
}
19+
// Simple fallback for browsers that don't support CSS.escape
20+
return str
21+
.replace(/[!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g, '\\$&')
22+
.replace(/^\d/, '\\3$& ');
23+
}
24+
925
function getFullPathSelector(elm) {
10-
if (elm.nodeName === 'BODY') {
11-
return 'BODY';
26+
if (elm.nodeName === 'HTML' || elm.nodeName === 'BODY') {
27+
return elm.nodeName.toLowerCase();
1228
}
1329

1430
if (cache.get('getFullPathSelector') === undefined) {
@@ -28,15 +44,29 @@ function getFullPathSelector(elm) {
2844
names.unshift(sourceCache.get(elm));
2945
break;
3046
} else if (elm.id) {
31-
names.unshift('#' + elm.getAttribute('id'));
32-
break;
47+
// Check if the ID is unique in the document before using it
48+
const escapedId = escapeCSSSelector(elm.getAttribute('id'));
49+
const elementsWithSameId = document.querySelectorAll(`#${escapedId}`);
50+
if (elementsWithSameId.length === 1) {
51+
// ID is unique, safe to use
52+
names.unshift('#' + escapedId);
53+
break;
54+
} else {
55+
// ID is not unique, fallback to position-based selector
56+
let c = 1;
57+
let e = elm;
58+
for (; e.previousElementSibling; e = e.previousElementSibling, c++) {
59+
// Increment counter for each previous sibling
60+
}
61+
names.unshift(`${elm.nodeName.toLowerCase()}:nth-child(${c})`);
62+
}
3363
} else {
34-
let c = 1,
35-
e = elm;
64+
let c = 1;
65+
let e = elm;
3666
for (; e.previousElementSibling; e = e.previousElementSibling, c++) {
3767
// Increment counter for each previous sibling
3868
}
39-
names.unshift(elm.nodeName + ':nth-child(' + c + ')');
69+
names.unshift(`${elm.nodeName.toLowerCase()}:nth-child(${c})`);
4070
}
4171
elm = elm.parentElement;
4272
}

0 commit comments

Comments
 (0)