| 1 |
// DOM primitives ported from static/mnw.js. |
| 2 |
|
| 3 |
/** |
| 4 |
* Escape all five HTML-special characters. Safe for both element-content and |
| 5 |
* attribute interpolation. Ported from mnw.js:19 (the Run 20 single escaper); |
| 6 |
* the one canonical escaper — feature code must not ship its own. |
| 7 |
*/ |
| 8 |
export function escapeHtml(s: unknown): string { |
| 9 |
return String(s) |
| 10 |
.replace(/&/g, '&') |
| 11 |
.replace(/</g, '<') |
| 12 |
.replace(/>/g, '>') |
| 13 |
.replace(/"/g, '"') |
| 14 |
.replace(/'/g, '''); |
| 15 |
} |
| 16 |
|
| 17 |
/** Attribute-context alias — identical five-char escape (escapeHtml is already |
| 18 |
* attribute-safe); named separately so call sites read intentfully. */ |
| 19 |
export const escapeAttr = escapeHtml; |
| 20 |
|
| 21 |
/** Resolve `data-target` (space-separated element ids) to the elements that |
| 22 |
* currently exist. Ported from mnw.js:725. */ |
| 23 |
export function targets(el: Element): HTMLElement[] { |
| 24 |
const raw = el.getAttribute('data-target'); |
| 25 |
if (!raw) return []; |
| 26 |
return raw |
| 27 |
.split(/\s+/) |
| 28 |
.filter(Boolean) |
| 29 |
.map((id) => document.getElementById(id)) |
| 30 |
.filter((e): e is HTMLElement => e !== null); |
| 31 |
} |
| 32 |
|
| 33 |
/** `document.getElementById` guarded against null/empty ids. */ |
| 34 |
export function byId(id: string | null | undefined): HTMLElement | null { |
| 35 |
return id ? document.getElementById(id) : null; |
| 36 |
} |
| 37 |
|