mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-17 00:26:41 +03:00
fix: hydrate attribute-bound each values and guard style directives
Addresses two cursor review findings:
- {#each} bodies whose bound values appear in attributes (href={link.href},
src={item.img}) now record attr slots; the browser hydrates them from the
rendered attribute so component previews no longer mount with empty links.
Single-expression attributes hydrate exactly; mixed values stay unhydrated
as before. A new slot classifier also refuses shapes that would crash a
shallow hydration item (deep paths, method calls, bare item renders) and
routes them to source-preview mode instead.
- Style directives now run the mixed loop/outer identifier check before the
free-identifier param check, so style:width={base + r.pct} falls back
instead of minting a broken param.
Tests: attr-slot analysis units, crashy/lossy fallback units, an attribute-
bound anchor in the stateful SvelteKit fixture asserted through accept, and
a mountedDomProbe e2e hook that reads the hydrated href off the mounted
variant DOM (verified to fail when hydration is disabled).
AI-assisted (Claude Code).
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Code
parent
6997e4bdb5
commit
39f233ac24
@@ -5446,6 +5446,16 @@
|
||||
const texts = collectVisibleTexts(itemEl).filter((t) => !statics.has(t));
|
||||
const item = {};
|
||||
slots.forEach((slot, i) => { item[slot.key] = texts[i] != null ? texts[i] : ''; });
|
||||
// Attribute-bound values (href={link.href}) hydrate from the
|
||||
// rendered attribute on the live item element or a descendant.
|
||||
for (const slot of entry.item.attrSlots || []) {
|
||||
if (item[slot.key] != null || !slot.tag) continue;
|
||||
const sel = slot.tag + (slot.classes || []).map((c) => '.' + cssEscapeIdent(c)).join('');
|
||||
let el = null;
|
||||
try { el = itemEl.matches(sel) ? itemEl : itemEl.querySelector(sel); } catch { el = null; }
|
||||
const value = el ? el.getAttribute(slot.attr) : null;
|
||||
if (value != null) item[slot.key] = value;
|
||||
}
|
||||
// Keyed each: the key field is never rendered, so hydrate it with a
|
||||
// unique per-index value or Svelte throws each_key_duplicate.
|
||||
if (entry.item.keyField && item[entry.item.keyField] == null) {
|
||||
|
||||
Reference in New Issue
Block a user