diff options
| author | Christian Cleberg <[email protected]> | 2026-07-15 19:29:57 -0500 |
|---|---|---|
| committer | Christian Cleberg <[email protected]> | 2026-07-15 19:29:57 -0500 |
| commit | c5247f7021090358e8db70daa9ed09521e9f206a (patch) | |
| tree | 78ae404d3a7f81a2a3d6148b745c891330aec40e /Hutch | |
| parent | 07b269c82f4d45af44ab7097e4a7cd5953c2af94 (diff) | |
| download | hutch-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.swift | 20 |
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) } |
