From 90efeab7ea65e0c48a6ae87c3f453bcaa83a9ecc Mon Sep 17 00:00:00 2001 From: root Date: Wed, 28 Jan 2026 18:56:04 +0000 Subject: [PATCH] Fix linkify double-escaping URLs with protocols MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- app/RSpade/Core/Js/functions.js | 25 ++++++++++++++++++------- app/RSpade/helpers.php | 30 +++++++++++++++++++++--------- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/app/RSpade/Core/Js/functions.js b/app/RSpade/Core/Js/functions.js index bce7a5a35..2c03fbd72 100755 --- a/app/RSpade/Core/Js/functions.js +++ b/app/RSpade/Core/Js/functions.js @@ -532,13 +532,24 @@ function _linkify_content(content, new_window) { return '' + url + '' + trailing; }); - // Then, replace domain-like text (but not if already inside an href) - content = content.replace(domain_pattern, (match) => { - // Clean trailing punctuation - const domain = match.replace(/[.,;:!?)'\"]+$/, ''); - const trailing = match.slice(domain.length); - return '' + domain + '' + trailing; - }); + // Then, replace domain-like text only in segments NOT inside tags + // (the URL replacement above may have created tags) + const link_pattern = /(]*>.*?<\/a>)/gi; + const segments = content.split(link_pattern); + + content = segments.map(segment => { + // Skip segments that are already links + if (/^ { + // Clean trailing punctuation + const domain = match.replace(/[.,;:!?)'\"]+$/, ''); + const trailing = match.slice(domain.length); + return '' + domain + '' + trailing; + }); + }).join(''); return content; } diff --git a/app/RSpade/helpers.php b/app/RSpade/helpers.php index 8a699e9c3..d7be19572 100644 --- a/app/RSpade/helpers.php +++ b/app/RSpade/helpers.php @@ -1659,14 +1659,26 @@ function _linkify_content(string $content, bool $new_window): string return '' . $url . ''; }, $content); - // Then, replace domain-like text (but not if already inside an href) - $content = preg_replace_callback($domain_pattern, function ($matches) use ($target) { - $domain = $matches[1]; - // Clean trailing punctuation - $domain = rtrim($domain, '.,;:!?)\'\"'); - // Don't linkify if it looks like it's already in an href attribute - return '' . $domain . ''; - }, $content); + // Then, replace domain-like text only in segments NOT inside tags + // (the URL replacement above may have created tags) + $link_pattern = '/(]*>.*?<\/a>)/is'; + $segments = preg_split($link_pattern, $content, -1, PREG_SPLIT_DELIM_CAPTURE); - return $content; + $result = ''; + foreach ($segments as $segment) { + // Skip segments that are already links + if (preg_match('/^' . $domain . ''; + }, $segment); + } + } + + return $result; }