aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-09-27 19:13:03 -0700
committerAdam Soltys <[email protected]>2026-09-27 19:13:03 -0700
commit5f5e92e05672c8a985c98a9d062b4a122a714912 (patch)
treeeb56187dc98861cb14ec01a24c4b2150f590f5dc
parent55cb118f25ddd69ffe9cc4bd44a36b1e689ee19e (diff)
downloadcoinosv3-5f5e92e05672c8a985c98a9d062b4a122a714912.tar.gz
coinosv3-5f5e92e05672c8a985c98a9d062b4a122a714912.zip
Link previews: the common named entities decode too (an &ndash; 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.js8
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.