This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git

commit bb66149d532c4bbbc55c20dc7e7aa63360a3045f
Author: Dave Brondsema <[email protected]>
AuthorDate: Wed May 6 17:18:23 2026 -0400

    [#8603] use Markup in SxsOutputGenerator
---
 Allura/allura/lib/diff.py        | 28 ++++++++++++++--------------
 Allura/allura/tests/test_diff.py | 16 +++++++++++++++-
 2 files changed, 29 insertions(+), 15 deletions(-)

diff --git a/Allura/allura/lib/diff.py b/Allura/allura/lib/diff.py
index 3199b28e2..e75cb0f82 100644
--- a/Allura/allura/lib/diff.py
+++ b/Allura/allura/lib/diff.py
@@ -46,7 +46,7 @@ def is_single_chg(chg_parts: ElementsHolder) -> bool:
 class SxsOutputGenerator(sxsdiff.BaseGenerator):
     # based on sxsdiff.generators.github.GitHubStyledGenerator
 
-    table_tmpl_start = '''
+    table_tmpl_start = Markup('''
 <table class="side-by-side-diff">
   <thead>
     <th class="lineno"></th>
@@ -54,9 +54,9 @@ class SxsOutputGenerator(sxsdiff.BaseGenerator):
     <th class="lineno"></th>
     <th>%s</th>
   </thead>
-'''.strip()
+''').strip()
 
-    table_tmpl_end = '</table>'
+    table_tmpl_end = Markup('</table>')
 
     def __init__(self, adesc: str, bdesc: str):
         self.adesc = adesc
@@ -66,9 +66,9 @@ def _spit(self, content):
         self.out += content + '\n'
 
     def run(self, diff_result: Iterable[LineChange | None]):
-        self.out = ''
+        self.out = Markup('')
         super().run(diff_result)
-        return Markup(self.out)  # noqa: S704 "safe" because we use 
html.escape in a few key places below
+        return self.out
 
     def visit_row(self, line_change: LineChange | None):
         if line_change is None:
@@ -86,9 +86,9 @@ def visit_row(self, line_change: LineChange | None):
 
     @contextlib.contextmanager
     def wrap_row(self, line_change):
-        self._spit('<tr>')
+        self._spit(Markup('<tr>'))
         yield
-        self._spit('</tr>')
+        self._spit(Markup('</tr>'))
 
     @contextlib.contextmanager
     def wrap_result(self, sxs_result):
@@ -108,7 +108,7 @@ def _spit_unchanged_side(self, lineno, holder):
         context = {
             'mode': 'context',
             'lineno': lineno,
-            'code': html.escape(str(holder)),
+            'code': str(holder),
         }
         self._spit_side_from_context(context)
 
@@ -119,7 +119,7 @@ def _spit_changed_side(self, mode, lineno, holder):
 
         bits = []
         for elem in holder.elements:
-            piece = html.escape(str(elem))
+            piece = str(elem)
             if elem.is_changed and not is_single_chg(holder):
                 if elem.flag == diff_match_patch.DIFF_INSERT:
                     clss = 'diff-add'
@@ -127,10 +127,10 @@ def _spit_changed_side(self, mode, lineno, holder):
                     clss = 'diff-rem'
                 else:
                     clss = ''
-                bits.append(f'<span class="{clss}">{piece}</span>')
+                bits.append(Markup('<span 
class="{clss}">{piece}</span>').format(clss=clss, piece=piece))
             else:
                 bits.append(piece)
-        code = ''.join(bits)
+        code = Markup('').join(bits)
 
         context = {
             'mode': mode,
@@ -140,10 +140,10 @@ def _spit_changed_side(self, mode, lineno, holder):
         self._spit_side_from_context(context)
 
     def _spit_side_from_context(self, context):
-        self._spit(f'  <td class="lineno">{context["lineno"]}</td>')
+        self._spit(Markup('  <td 
class="lineno">{lineno}</td>').format(lineno=context["lineno"]))
         mode = context['mode']
-        clss = (' class="%s"' % mode) if mode not in ['context', ''] else ''
-        self._spit(f'  <td{clss}><pre>{context["code"]}</pre></td>')
+        clss = Markup(' class="%s"') % mode if mode not in ['context', ''] 
else ''
+        self._spit(Markup('  
<td{clss}><pre>{code}</pre></td>').format(clss=clss, code=context["code"]))
 
 
 def sxsdiff_cleanup_trailing(input_lines: Iterable[LineChange]) -> 
Iterable[LineChange]:
diff --git a/Allura/allura/tests/test_diff.py b/Allura/allura/tests/test_diff.py
index 0d528af68..b22f2e809 100644
--- a/Allura/allura/tests/test_diff.py
+++ b/Allura/allura/tests/test_diff.py
@@ -58,7 +58,7 @@ def test_make_table(self):
   <td class="lineno"></td>
   <td><pre></pre></td>
   <td class="lineno">4</td>
-  <td class="diff-add"><pre>    new&lt;script&gt;&amp;&quot;</pre></td>
+  <td class="diff-add"><pre>    new&lt;script&gt;&amp;&#34;</pre></td>
 </tr>
 </table>
 '''.strip()
@@ -124,3 +124,17 @@ def test_unicode_make_table(self):
         b = ['измененная строка']
         html = HtmlSideBySideDiff().make_table(a, b, 'file a', 'file b')
         assert 'строка' in html
+
+    def test_make_table_with_html_tags(self):
+        a = ['foo<b>bar</b>']
+        b = ['<em>as</em>df']
+        html = HtmlSideBySideDiff().make_table(a, b, 'file <a>', 'file <b>')
+        assert 'foo&lt;b&gt;bar&lt;/b&gt;' in html
+        assert 'foo<b>bar</b>' not in html
+        assert '&lt;em&gt;as&lt;/em&gt;df' in html
+        assert '<em>as</em>df' not in html
+        assert 'file &lt;a&gt;' in html
+        assert 'file <a>' not in html
+        assert 'file &lt;b&gt;' in html
+        assert 'file <b>' not in html
+

Reply via email to