Refactor: 1167 _esc() → UI.escape() in 36 Dateien, SW by-v1113

Bündel 1 aus dem Duplikat-Audit: existierende zentrale Helper nutzen
statt lokale Duplikate.

Pure Migration ohne neuen Code:
- 1167 _esc()-Aufrufe in 36 Page-Modulen migriert auf UI.escape()
- 24 lokale _esc/_escape-Definitionen entfernt
- lost.js hatte _escape() (Variante) — 17 Aufrufe ebenfalls migriert
- jobs.js + breeder.js: tote Alias-Wrapper entfernt

UI.escape() existierte schon — wurde nur überall lokal nochmal
implementiert. Funktional identisch (gleiche 4-replace-chain für
& < > ").

Tests 19/19 grün. Frontend-LOC um ~120 Zeilen reduziert.

Hinweis: _emptyState (7 Stellen) und _icon (8 Stellen) wurden NICHT
migriert — sie haben abweichende Signaturen von UI.emptyState({...})
bzw. UI.icon(name). Eigener Sprint nötig.
This commit is contained in:
rene 2026-05-27 10:15:33 +02:00
parent e7939ce98e
commit c517c9281d
42 changed files with 1115 additions and 1341 deletions

View file

@ -46,7 +46,7 @@ window.Page_breeder_editor = (() => {
background:var(--c-surface-2);overflow:hidden;flex-shrink:0;
display:flex;align-items:center;justify-content:center">
${p.logo_url
? `<img src="${_esc(p.logo_url)}" style="width:100%;height:100%;object-fit:cover">`
? `<img src="${UI.escape(p.logo_url)}" style="width:100%;height:100%;object-fit:cover">`
: `<svg class="ph-icon" style="width:32px;height:32px;opacity:.3"><use href="/icons/phosphor.svg#image"></use></svg>`}
</div>
<div>
@ -70,45 +70,45 @@ window.Page_breeder_editor = (() => {
<div class="form-group">
<label class="form-label">Zwingername *</label>
<input class="form-control" name="zwingername" type="text" required
value="${_esc(p.zwingername || '')}">
value="${UI.escape(p.zwingername || '')}">
</div>
<div class="form-group">
<label class="form-label">Rasse(n)</label>
<input class="form-control" name="rasse_text" type="text"
value="${_esc(p.rasse_text || '')}">
value="${UI.escape(p.rasse_text || '')}">
</div>
</div>
<div class="form-group">
<label class="form-label">Slogan <span style="font-weight:400;color:var(--c-text-muted)">(max. 80 Zeichen)</span></label>
<input class="form-control" name="tagline" type="text" maxlength="80"
placeholder="z. B. Liebevolle Aufzucht seit 2010 · VDH-anerkannt"
value="${_esc(p.tagline || '')}">
value="${UI.escape(p.tagline || '')}">
</div>
<div class="form-group">
<label class="form-label">Über uns / Zwingerbeschreibung</label>
<textarea class="form-control" name="beschreibung" rows="4" maxlength="800"
placeholder="Wer seid ihr, was ist euch bei der Zucht wichtig?">${_esc(p.beschreibung || '')}</textarea>
placeholder="Wer seid ihr, was ist euch bei der Zucht wichtig?">${UI.escape(p.beschreibung || '')}</textarea>
</div>
<div class="grid-2">
<div class="form-group">
<label class="form-label">Stadt</label>
<input class="form-control" name="stadt" type="text" value="${_esc(p.stadt || '')}">
<input class="form-control" name="stadt" type="text" value="${UI.escape(p.stadt || '')}">
</div>
<div class="form-group">
<label class="form-label">Verein</label>
<input class="form-control" name="verein" type="text" value="${_esc(p.verein || '')}">
<input class="form-control" name="verein" type="text" value="${UI.escape(p.verein || '')}">
</div>
</div>
<div class="grid-2">
<div class="form-group">
<label class="form-label">Website</label>
<input class="form-control" name="website" type="url"
placeholder="https://" value="${_esc(p.website || '')}">
placeholder="https://" value="${UI.escape(p.website || '')}">
</div>
<div class="form-group">
<label class="form-label">Instagram</label>
<input class="form-control" name="instagram" type="text"
placeholder="@zwingername" value="${_esc(p.instagram || '')}">
placeholder="@zwingername" value="${UI.escape(p.instagram || '')}">
</div>
</div>
<button type="submit" class="btn btn-secondary btn-sm" style="align-self:flex-start">
@ -161,10 +161,10 @@ window.Page_breeder_editor = (() => {
return `
<div style="position:relative;aspect-ratio:1;border-radius:var(--radius-md);overflow:hidden;background:var(--c-surface-2)">
${isVid
? `<video src="${_esc(ph.url)}" style="width:100%;height:100%;object-fit:cover" muted playsinline loop
? `<video src="${UI.escape(ph.url)}" style="width:100%;height:100%;object-fit:cover" muted playsinline loop
onmouseenter="this.play()" onmouseleave="this.pause()"></video>
<div style="position:absolute;bottom:4px;left:4px;background:rgba(0,0,0,.55);border-radius:4px;padding:1px 5px;font-size:10px;color:#fff"> Video</div>`
: `<img src="${_esc(ph.thumbnail_url || ph.url)}" style="width:100%;height:100%;object-fit:cover">`}
: `<img src="${UI.escape(ph.thumbnail_url || ph.url)}" style="width:100%;height:100%;object-fit:cover">`}
${ph.is_primary ? `<div style="position:absolute;top:4px;left:4px;background:rgba(196,132,58,.9);border-radius:3px;padding:1px 5px;font-size:9px;color:#fff;font-weight:700">LOGO</div>` : ''}
<button class="be-photo-del" data-id="${ph.id}"
style="position:absolute;top:4px;right:4px;background:rgba(0,0,0,.6);
@ -190,14 +190,14 @@ window.Page_breeder_editor = (() => {
<div style="border:1px solid var(--c-border);border-radius:var(--radius-md);padding:var(--space-3)">
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--space-2)">
<div>
<div style="font-weight:700;font-size:var(--text-sm)">${_esc(label)}</div>
<div style="font-weight:700;font-size:var(--text-sm)">${UI.escape(label)}</div>
<div class="text-xs-muted">${info}</div>
</div>
<label class="btn btn-secondary btn-sm" style="cursor:pointer">
<svg class="ph-icon" style="width:14px;height:14px"><use href="/icons/phosphor.svg#upload-simple"></use></svg>
Upload
<input type="file" class="be-litter-input" data-litter-id="${l.id}"
data-label="${_esc(label)}" accept="image/*,video/*" class="hidden">
data-label="${UI.escape(label)}" accept="image/*,video/*" class="hidden">
</label>
</div>
</div>`;
@ -312,10 +312,6 @@ window.Page_breeder_editor = (() => {
});
}
function _esc(s) {
return String(s ?? '').replace(/[&<>"']/g, c =>
({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
}
return { init, refresh, onDogChange };