0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-05 19:38:04 +08:00
discourse/app/views/topics
Régis Hanol 75a57f129c
FIX: Prevent double-escaping of HTML entities in titles and meta descriptions (#41261)
Previously, content that was already HTML-escaped — topic `fancy_title`s
on the 404/oops pages, GitHub onebox labels, and topic/group/category
`<meta>` descriptions — got escaped a second time, so readers (and
crawlers) saw literal entities like `&rsquo;` and `&amp;` instead of `'`
and `&`.

This change escapes every value exactly once, by converting it to plain
text before it reaches the renderer instead of flagging anything
`html_safe`:

- `Emoji.codes_to_img` escapes its text segments with `html_escape_once`
so the already-escaped `fancy_title` and sanitized GitHub labels aren't
escaped again. All of its callers render into element content, and the
attribute escaping inside `emoji_img_tag` is untouched.
- the new `ExcerptParser.to_plain_text` converts a stored excerpt
(escaped text, the `&hellip;` truncation marker, and the hashtag
placeholder markup the parser keeps) back to plain text, exposed as
`Topic#plain_text_excerpt`. It's a tag-strip plus a memoized
`htmlentities` decode — pure Ruby, a few microseconds per excerpt, no
Nokogiri in the hot path.
- `Category#plain_text_description` caches the pre-escape plain text
that `description_text` previously discarded, and the category meta
descriptions use it directly. This also fixes the double-escaped
`og:description`/`twitter:description` on category pages, where
`gsub_emoji_to_unicode` silently drops the `html_safe` flag of
`description_text`.
- the new `Group#bio_summary` mirrors `UserProfile#bio_summary`: a
plain-text excerpt of the bio with links and images stripped and
hashtags rendered as plain `#slug`.

Marking the stored values `html_safe` would have worked for the column
data — every writer of `topics.excerpt` escapes — but `topic.excerpt`
can be swapped in-memory with a localized excerpt that isn't guaranteed
to be escaped, so treating everything as unsafe plain text is both
simpler and safer.
2026-07-02 20:26:35 +02:00
..
plain.html.erb FIX: add og:image:type to OpenGraph tags (#37854) 2026-02-17 16:05:00 +01:00
show.html.erb FIX: Prevent double-escaping of HTML entities in titles and meta descriptions (#41261) 2026-07-02 20:26:35 +02:00
show.rss.erb