Skip to content

Commit

Permalink
feat: add a helper method to get equivalent selectors
Browse files Browse the repository at this point in the history
  • Loading branch information
leonfeng committed Nov 21, 2023
1 parent eed7597 commit 6eff68c
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 0 deletions.
31 changes: 31 additions & 0 deletions lib/__tests__/css-helper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,37 @@ describe('css-help', () => {
);
});
});
describe('selectorsFromSelector', () => {
it('should return an empty array', () => {
setupDocument();
expect(t.selectorsFromSelector('.void')).toEqual([]);
});
it('should return an array with 9 members', () => {
setupDocument();
expect(t.selectorsFromSelector('a')).toEqual([
'a',
'label > a',
'label a',
'form > label > a',
'form label a',
'body > form > label > a',
'body form label a',
'html > body > form > label > a',
'html body form label a',
]);
});

function setupDocument() {
const form = doc.createElement('form');
form.innerHTML = `
<label>
<input type="checkbox" /> I accept the <a href="#">terms and conditions</a>
</label>
<input type="submit" value="Submit" />
`;
doc.body.appendChild(form);
}
});
afterEach(() => {
document.body.innerHTML = '';
document.head.innerHTML = '';
Expand Down
33 changes: 33 additions & 0 deletions lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,4 +212,37 @@ export class CSSHelp {
): CSSRule[] {
return Array.from(styleSheet?.cssRules || []);
}
// takes a CSS selector, returns all equivelant selectors from the current document
// or an empty array if there are no matches
selectorsFromSelector(selector: string): string[] {
const elements = this.doc.querySelectorAll(selector);
const allSelectors = Array.from(elements).map((element: Element) => {
let directPath = [];
let indirectPath = [];
let allPaths = [];

while (element.parentNode) {
let tag = element.tagName.toLowerCase();
let siblings = Array.from(element.parentNode.children);

if (siblings.filter(e => e.tagName === element.tagName).length > 1) {
let allSiblings = Array.from(element.parentNode.childNodes);
let index = allSiblings.indexOf(element);
tag += `:nth-child(${index + 1})`;
}

directPath.unshift(tag);
indirectPath.unshift(tag);
allPaths.push([directPath.join(' > '), indirectPath.join(' ')]);

// traverse up the DOM tree
element = element.parentNode as Element;
}

return allPaths.flat();
}).flat();

// remove duplicates
return [...new Set(allSelectors)];
}
}

0 comments on commit 6eff68c

Please sign in to comment.