HS: element → HTML via outerHTML (+1 test)

Adds an `outerHTML` getter to the mock `El` class. Builds `<tag attrs>inner</tag>`
by merging `.id` / `.className` (set as direct properties via host-set!) with
the `.attributes` bag, and falling back to `innerText` / `textContent` when
there are no children or innerHTML.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-23 21:28:47 +00:00
parent 94b47a4b2b
commit e195b5bd72

View File

@@ -99,6 +99,31 @@ class El {
if (!('_origDefault' in this)) { this.defaultValue = this.textContent; this._origDefault = true; } if (!('_origDefault' in this)) { this.defaultValue = this.textContent; this._origDefault = true; }
} }
} }
get outerHTML() {
const tag = this.tagName.toLowerCase();
// Merge .id / .className (set directly) into attribute output.
const attrOrder = [];
const attrMap = {};
if (this.id) { attrMap['id'] = this.id; attrOrder.push('id'); }
if (this.className) { attrMap['class'] = this.className; attrOrder.push('class'); }
for (const k of Object.keys(this.attributes)) {
if (!(k in attrMap)) { attrMap[k] = this.attributes[k]; attrOrder.push(k); }
else attrMap[k] = this.attributes[k]; // prefer explicit attr value when set
}
const attrs = attrOrder.map(k => ` ${k}="${String(attrMap[k]).replace(/"/g, '&quot;')}"`).join('');
if (VOID_TAGS.has(tag)) return `<${tag}${attrs}>`;
let inner = '';
if (this.children && this.children.length) {
inner = this.children.map(c => c.outerHTML || c.textContent || '').join('');
} else if (this.innerHTML) {
inner = this.innerHTML;
} else if (this.innerText !== undefined && this.innerText !== '') {
inner = this.innerText;
} else if (this.textContent) {
inner = this.textContent;
}
return `<${tag}${attrs}>${inner}</${tag}>`;
}
get firstElementChild() { return this.children[0]||null; } get firstElementChild() { return this.children[0]||null; }
get lastElementChild() { return this.children[this.children.length-1]||null; } get lastElementChild() { return this.children[this.children.length-1]||null; }
get nextElementSibling() { if(!this.parentElement)return null; const i=this.parentElement.children.indexOf(this); return this.parentElement.children[i+1]||null; } get nextElementSibling() { if(!this.parentElement)return null; const i=this.parentElement.children.indexOf(this); return this.parentElement.children[i+1]||null; }