Merge pull request #396 from getmaxun/better-selector
feat: better selection
This commit is contained in:
@@ -1654,6 +1654,31 @@ export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (element.parentElement) {
|
||||||
|
// Look for identical siblings
|
||||||
|
const siblings = Array.from(element.parentElement.children);
|
||||||
|
const identicalSiblings = siblings.filter(sibling => {
|
||||||
|
if (sibling === element) return false;
|
||||||
|
|
||||||
|
let siblingSelector = sibling.tagName.toLowerCase();
|
||||||
|
const siblingClassName = typeof sibling.className === 'string' ? sibling.className : '';
|
||||||
|
if (siblingClassName) {
|
||||||
|
const siblingClasses = siblingClassName.split(/\s+/).filter(Boolean);
|
||||||
|
const validSiblingClasses = siblingClasses.filter(cls => !cls.startsWith('!') && !cls.includes(':'));
|
||||||
|
if (validSiblingClasses.length > 0) {
|
||||||
|
siblingSelector += '.' + validSiblingClasses.map(cls => CSS.escape(cls)).join('.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return siblingSelector === selector;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (identicalSiblings.length > 0) {
|
||||||
|
const position = siblings.indexOf(element) + 1;
|
||||||
|
selector += `:nth-child(${position})`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return selector;
|
return selector;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1894,6 +1919,31 @@ export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (element.parentElement) {
|
||||||
|
// Look for identical siblings
|
||||||
|
const siblings = Array.from(element.parentElement.children);
|
||||||
|
const identicalSiblings = siblings.filter(sibling => {
|
||||||
|
if (sibling === element) return false;
|
||||||
|
|
||||||
|
let siblingSelector = sibling.tagName.toLowerCase();
|
||||||
|
const siblingClassName = typeof sibling.className === 'string' ? sibling.className : '';
|
||||||
|
if (siblingClassName) {
|
||||||
|
const siblingClasses = siblingClassName.split(/\s+/).filter(Boolean);
|
||||||
|
const validSiblingClasses = siblingClasses.filter(cls => !cls.startsWith('!') && !cls.includes(':'));
|
||||||
|
if (validSiblingClasses.length > 0) {
|
||||||
|
siblingSelector += '.' + validSiblingClasses.map(cls => CSS.escape(cls)).join('.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return siblingSelector === selector;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (identicalSiblings.length > 0) {
|
||||||
|
const position = siblings.indexOf(element) + 1;
|
||||||
|
selector += `:nth-child(${position})`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return selector;
|
return selector;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2025,6 +2075,31 @@ export const getChildSelectors = async (page: Page, parentSelector: string): Pro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (element.parentElement) {
|
||||||
|
// Look for identical siblings
|
||||||
|
const siblings = Array.from(element.parentElement.children);
|
||||||
|
const identicalSiblings = siblings.filter(sibling => {
|
||||||
|
if (sibling === element) return false;
|
||||||
|
|
||||||
|
let siblingSelector = sibling.tagName.toLowerCase();
|
||||||
|
const siblingClassName = typeof sibling.className === 'string' ? sibling.className : '';
|
||||||
|
if (siblingClassName) {
|
||||||
|
const siblingClasses = siblingClassName.split(/\s+/).filter(Boolean);
|
||||||
|
const validSiblingClasses = siblingClasses.filter(cls => !cls.startsWith('!') && !cls.includes(':'));
|
||||||
|
if (validSiblingClasses.length > 0) {
|
||||||
|
siblingSelector += '.' + validSiblingClasses.map(cls => CSS.escape(cls)).join('.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return siblingSelector === selector;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (identicalSiblings.length > 0) {
|
||||||
|
const position = siblings.indexOf(element) + 1;
|
||||||
|
selector += `:nth-child(${position})`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return selector;
|
return selector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -263,7 +263,12 @@ export const BrowserWindow = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (getList === true && !listSelector) {
|
if (getList === true && !listSelector) {
|
||||||
setListSelector(highlighterData.selector);
|
let cleanedSelector = highlighterData.selector;
|
||||||
|
if (cleanedSelector.includes('nth-child')) {
|
||||||
|
cleanedSelector = cleanedSelector.replace(/:nth-child\(\d+\)/g, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
setListSelector(cleanedSelector);
|
||||||
notify(`info`, t('browser_window.attribute_modal.notifications.list_select_success'));
|
notify(`info`, t('browser_window.attribute_modal.notifications.list_select_success'));
|
||||||
setCurrentListId(Date.now());
|
setCurrentListId(Date.now());
|
||||||
setFields({});
|
setFields({});
|
||||||
@@ -275,13 +280,25 @@ export const BrowserWindow = () => {
|
|||||||
// Add fields to the list
|
// Add fields to the list
|
||||||
if (options.length === 1) {
|
if (options.length === 1) {
|
||||||
const attribute = options[0].value;
|
const attribute = options[0].value;
|
||||||
|
let currentSelector = highlighterData.selector;
|
||||||
|
|
||||||
|
if (currentSelector.includes('>')) {
|
||||||
|
const [firstPart, ...restParts] = currentSelector.split('>').map(p => p.trim());
|
||||||
|
const listSelectorRightPart = listSelector.split('>').pop()?.trim().replace(/:nth-child\(\d+\)/g, '');
|
||||||
|
|
||||||
|
if (firstPart.includes('nth-child') &&
|
||||||
|
firstPart.replace(/:nth-child\(\d+\)/g, '') === listSelectorRightPart) {
|
||||||
|
currentSelector = `${firstPart.replace(/:nth-child\(\d+\)/g, '')} > ${restParts.join(' > ')}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const newField: TextStep = {
|
const newField: TextStep = {
|
||||||
id: Date.now(),
|
id: Date.now(),
|
||||||
type: 'text',
|
type: 'text',
|
||||||
label: `Label ${Object.keys(fields).length + 1}`,
|
label: `Label ${Object.keys(fields).length + 1}`,
|
||||||
data: data,
|
data: data,
|
||||||
selectorObj: {
|
selectorObj: {
|
||||||
selector: highlighterData.selector,
|
selector: currentSelector,
|
||||||
tag: highlighterData.elementInfo?.tagName,
|
tag: highlighterData.elementInfo?.tagName,
|
||||||
shadow: highlighterData.elementInfo?.isShadowRoot,
|
shadow: highlighterData.elementInfo?.isShadowRoot,
|
||||||
attribute
|
attribute
|
||||||
|
|||||||
Reference in New Issue
Block a user