"Which kinds of elements does this subtree use?" is a handy audit — for a linter, a sanitizer allowlist check, or just understanding a chunk of markup. The answer is the distinct set of tag names, and you usually want them in the order they first appear (document order), lowercased so <DIV> and <div> count as one. It's a classic "traverse + dedupe while preserving order" problem, applied to the DOM.
Implement getDomTags(root). Return the distinct lowercase tag names in the subtree (including the root), in first-appearance document order. A null root yields [].
function getDomTags(root) {
// returns string[] of distinct lowercase tags, in document order
}
// <div><p></p><span></span><p></p></div>
getDomTags(div); // ['div', 'p', 'span'] (second <p> is a duplicate)
// <section><ARTICLE></ARTICLE></section>
getDomTags(section); // ['section', 'article'] (lowercased)
querySelectorAll('*') already returns).element.tagName is uppercase for HTML; normalize with .toLowerCase().Set for membership plus an array for order, keeping each tag's first position.