From 815d812297e5d359fc5dca0805daf94c49e8e541 Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Tue, 3 Jun 2025 23:10:07 +0100 Subject: [PATCH] Re-enable Bleach linkify to add rel=nofollow --- app/markdown/__init__.py | 1 - app/markdown/cleaner.py | 17 ++++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/app/markdown/__init__.py b/app/markdown/__init__.py index 9e4257f9..b693aaa2 100644 --- a/app/markdown/__init__.py +++ b/app/markdown/__init__.py @@ -53,7 +53,6 @@ def render_code(self, tokens: Sequence[Token], idx, options, env): return f"
{escapeHtml(token.content)}
" - gfm_like.make() md = MarkdownIt("gfm-like", {"highlight": highlight_code}) md.add_render_rule("fence", render_code) diff --git a/app/markdown/cleaner.py b/app/markdown/cleaner.py index b7281394..013845cc 100644 --- a/app/markdown/cleaner.py +++ b/app/markdown/cleaner.py @@ -14,7 +14,9 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +from functools import partial from bleach import Cleaner +from bleach.linkifier import LinkifyFilter, DEFAULT_CALLBACKS # Based on @@ -38,6 +40,7 @@ ALLOWED_TAGS = { "div", "span", "del", "s", "details", "summary", + "sup", } ALLOWED_CSS = [ @@ -70,9 +73,21 @@ ALLOWED_ATTRIBUTES = { ALLOWED_PROTOCOLS = {"http", "https", "mailto"} +def linker_callback(attrs, new=False): + if new: + text = attrs.get("_text") + if not (text.startswith("http://") or text.startswith("https://")): + return None + + return attrs + + def clean_html(html: str): cleaner = Cleaner( tags=ALLOWED_TAGS, attributes=ALLOWED_ATTRIBUTES, - protocols=ALLOWED_PROTOCOLS) + protocols=ALLOWED_PROTOCOLS, + filters=[partial(LinkifyFilter, + callbacks=[linker_callback] + DEFAULT_CALLBACKS, + skip_tags={"pre", "code"})]) return cleaner.clean(html)