// A plain-text excerpt of a post body, for the town crier and the news gump. // // **Vendored from core's `utils/sanitizeHtml.js`, deliberately, and it is worth // being precise about what was and was not copied.** Core's file exports three // things: `cleanBody` (the actual HTML sanitiser, backed by a dependency and a // tag allowlist), `OPTIONS`, and this. Only this one came, because only this one // is a pure function over a string with no security surface — it strips tags to // get at the text, it does not decide what tags are safe to render. // // Copying the sanitiser would have been the wrong call for exactly the reason // this comment exists: a second copy of a security control diverges from the // first the moment either is fixed, and the divergence is silent. A module that // needs to sanitise HTML for rendering should ask core for it. This one does // not — its output goes into a game window and a chat message as text. /** * Flatten HTML to a single line of text, truncated with an ellipsis. * * @param {string|null} html * @param {number} max characters, including the ellipsis * @returns {string|null} null when there is nothing left after stripping */ function deriveExcerpt(html, max = 280) { if (html == null) return null const text = String(html) .replace(/<[^>]+>/g, ' ') .replace(/\s+/g, ' ') .trim() if (!text) return null return text.length > max ? `${text.slice(0, max - 3)}...` : text } module.exports = { deriveExcerpt }