diff options
| author | Adam Soltys <[email protected]> | 2026-09-27 19:13:03 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-09-27 19:13:03 -0700 |
| commit | 5f5e92e05672c8a985c98a9d062b4a122a714912 (patch) | |
| tree | eb56187dc98861cb14ec01a24c4b2150f590f5dc | |
| parent | 55cb118f25ddd69ffe9cc4bd44a36b1e689ee19e (diff) | |
| download | coinosv3-5f5e92e05672c8a985c98a9d062b4a122a714912.tar.gz coinosv3-5f5e92e05672c8a985c98a9d062b4a122a714912.zip | |
Link previews: the common named entities decode too (an – showed raw in a card).
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
| -rw-r--r-- | names/preview.js | 8 |
1 files changed, 5 insertions, 3 deletions
diff --git a/names/preview.js b/names/preview.js index 25051d9..b9af975 100644 --- a/names/preview.js +++ b/names/preview.js @@ -45,10 +45,12 @@ async function publicUrl(str) { return u; } +const ENTITIES = { amp: '&', quot: '"', apos: "'", lt: '<', gt: '>', nbsp: ' ', ndash: '–', mdash: '—', hellip: '…', + lsquo: '‘', rsquo: '’', ldquo: '“', rdquo: '”', laquo: '«', raquo: '»', copy: '©', reg: '®', trade: '™', middot: '·', bull: '•', euro: '€', pound: '£' }; const decodeEntities = (s) => String(s || '') - .replace(/&#x([0-9a-f]+);/gi, (_, h) => String.fromCodePoint(parseInt(h, 16))) - .replace(/&#(\d+);/g, (_, d) => String.fromCodePoint(Number(d))) - .replace(/&(amp|quot|apos|lt|gt|nbsp);/g, (_, e) => ({ amp: '&', quot: '"', apos: "'", lt: '<', gt: '>', nbsp: ' ' })[e]); + .replace(/&#x([0-9a-f]+);/gi, (_, h) => { try { return String.fromCodePoint(parseInt(h, 16)); } catch { return ''; } }) + .replace(/&#(\d+);/g, (_, d) => { try { return String.fromCodePoint(Number(d)); } catch { return ''; } }) + .replace(/&([a-z]+);/gi, (m, e) => ENTITIES[e.toLowerCase()] ?? m); const tidy = (s, max) => decodeEntities(s).replace(/\s+/g, ' ').trim().slice(0, max); // Every <meta> in the head, whichever way its attributes are ordered. |
