summaryrefslogtreecommitdiff
path: root/Hutch
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-07-15 19:29:57 -0500
committerChristian Cleberg <[email protected]>2026-07-15 19:29:57 -0500
commitc5247f7021090358e8db70daa9ed09521e9f206a (patch)
tree78ae404d3a7f81a2a3d6148b745c891330aec40e /Hutch
parent07b269c82f4d45af44ab7097e4a7cd5953c2af94 (diff)
downloadhutch-c5247f7021090358e8db70daa9ed09521e9f206a.tar.gz
hutch-c5247f7021090358e8db70daa9ed09521e9f206a.tar.bz2
hutch-c5247f7021090358e8db70daa9ed09521e9f206a.zip
fix: render code span contents literally
processInline protected allowlisted HTML tags before it handled code spans, so a `<b>` written inside backticks was carried through as a live tag and applied formatting instead of rendering as text. Every other inline pass ran against code span contents for the same reason, so `**x**` in backticks was emitted as bold. Protect code spans first with their contents escaped, which takes them out of reach of the tag, emphasis, and link passes.
Diffstat (limited to 'Hutch')
-rw-r--r--Hutch/Views/Repositories/ReadmeView.swift20
1 files changed, 13 insertions, 7 deletions
diff --git a/Hutch/Views/Repositories/ReadmeView.swift b/Hutch/Views/Repositories/ReadmeView.swift
index 720dff0..69d105b 100644
--- a/Hutch/Views/Repositories/ReadmeView.swift
+++ b/Hutch/Views/Repositories/ReadmeView.swift
@@ -371,8 +371,21 @@ nonisolated func processInline(
) -> String {
var protectedFragments: [String: String] = [:]
+
+ // Code spans render their contents literally, so they have to be taken out of
+ // the text before any later pass can treat those contents as markup — the tag
+ // pass below would otherwise promote an allowlisted `<b>` into a live tag.
var result = protectMatches(
in: text,
+ pattern: #"`([^`]+)`"#,
+ protectedFragments: &protectedFragments
+ ) { match, nsText in
+ let code = nsText.substring(with: match.range(at: 1))
+ return "<code>\(escapeHTML(code))</code>"
+ }
+
+ result = protectMatches(
+ in: result,
pattern: #"</?[A-Za-z][^>]*?>"#,
protectedFragments: &protectedFragments
) { match, nsText in
@@ -438,13 +451,6 @@ nonisolated func processInline(
with: "<em>$1</em>",
options: .regularExpression
)
- // Inline code: `text`
- result = result.replacingOccurrences(
- of: #"`([^`]+)`"#,
- with: "<code>$1</code>",
- options: .regularExpression
- )
-
for (token, fragment) in protectedFragments {
result = result.replacingOccurrences(of: token, with: fragment)
}