This is an automated email from the ASF dual-hosted git repository. gcruz pushed a commit to branch db/fix_markdown_cleaning in repository https://gitbox.apache.org/repos/asf/allura.git
The following commit(s) were added to refs/heads/db/fix_markdown_cleaning by this push: new f704c6fd6 more classes included into the whitelist and test updates f704c6fd6 is described below commit f704c6fd6cb59fb841b52ced3a1fb39ec5de7a5c Author: Guillermo Cruz <guillermo.c...@slashdotmedia.com> AuthorDate: Thu Aug 21 08:09:27 2025 -0600 more classes included into the whitelist and test updates --- Allura/allura/lib/app_globals.py | 3 +-- Allura/allura/lib/utils.py | 16 +++++++++------- Allura/allura/public/nf/js/allura-base.js | 5 ++--- Allura/allura/tests/test_globals.py | 10 +++++----- Allura/allura/tests/test_helpers.py | 2 +- ForgeTracker/forgetracker/tests/functional/test_root.py | 2 +- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Allura/allura/lib/app_globals.py b/Allura/allura/lib/app_globals.py index 4b504b53b..cfc46b8e1 100644 --- a/Allura/allura/lib/app_globals.py +++ b/Allura/allura/lib/app_globals.py @@ -82,9 +82,8 @@ def make_markdown_instance(self, **forge_ext_kwargs): # when multiple threads are using the same instance # TestCachedMarkdown re-uses the same instance previously, and had a bug that AddCustomClass wasn't running - def toc_slugify_with_prefix(value, separator): - return 'h:' + toc.slugify(value, separator) + return 'h-' + toc.slugify(value, separator) return markdown.Markdown( extensions=['markdown.extensions.fenced_code', 'markdown.extensions.codehilite', diff --git a/Allura/allura/lib/utils.py b/Allura/allura/lib/utils.py index 7955d3891..75ead7cd3 100644 --- a/Allura/allura/lib/utils.py +++ b/Allura/allura/lib/utils.py @@ -48,7 +48,7 @@ from tg import redirect, app_globals as g from tg.decorators import before_validate from tg.controllers.util import etag_cache -from paste.deploy.converters import asbool, asint +from paste.deploy.converters import asbool, asint, aslist from markupsafe import Markup from webob import exc from pygments.formatters import HtmlFormatter @@ -564,16 +564,18 @@ def __init__(self, *args, **kwargs): self.valid_class_values = { 'markdown_content', # our wrapper class # standard extensions: - 'codehilite', 'footnote', 'checklist', 'toc', 'footnote-ref', 'footnote-backref', - 'alink', # ForgeLinkPattern - 'user-mention', # UserMentionExtension + 'codehilite', 'footnote', 'checklist', 'toc', 'footnote-ref', 'footnote-backref', 'codehilitetable', + 'user-mention', 'macro_projects_total', 'proj_icon', 'list', 'card', 'feature', 'box', 'notch', 'desc', + 'strikethrough', + 'alink', 'notfound', # ForgeLinkPattern # our macros: 'neighborhood_feed_entry', 'md-users-list', 'md-users-list-more', # codehilite classes: - 'hll', 'c', 'k', 'o', 'cm', 'cp', 'c1', 'cs', 'gd', 'ge', 'gr', 'gh', 'gi', 'go', 'gp', 'gs', 'gu', 'gt', 'kc', 'kd', 'kn', 'kp', 'kr', 'kt', 'm', 's', 'na', 'nb', 'nc', 'no', 'nd', 'ni', 'ne', 'nf', 'nl', 'nn', 'nt', 'nv', 'ow', 'w', 'mf', 'mh', 'mi', 'mo', 'sb', 'sc', 'sd', 's2', 'se', 'sh', 'si', 'sx', 'sr', 's1', 'ss', 'bp', 'vc', 'vg', 'vi', 'il', 'code_block', 'lineno', + 'p', 'n', 'hll', 'c', 'k', 'o', 'cm', 'cp', 'c1', 'cs', 'gd', 'ge', 'gr', 'gh', 'gi', 'go', 'gp', 'gs', 'gu', 'gt', 'kc', 'kd', 'kn', 'kp', 'kr', 'kt', 'm', 's', 'na', 'nb', 'nc', 'no', 'nd', 'ni', 'ne', 'nf', 'nl', 'nn', 'nt', 'nv', 'ow', 'w', 'mf', 'mh', 'mi', 'mo', 'sb', 'sc', 'sd', 's2', 'se', 'sh', 'si', 'sx', 'sr', 's1', 'ss', 'bp', 'vc', 'vg', 'vi', 'il', 'code_block', 'lineno', } + self.valid_partial_class_prefixes = tuple(aslist(tg.config.get('markdown_valid_partial_class_prefixes', None))) self.valid_id_prefixes = { - 'h:', # see toc_slugify_with_prefix + 'h-', # see toc_slugify_with_prefix 'fn:', 'fnref:', # from footnotes extension } self._prev_token_was_ok_iframe = False @@ -605,7 +607,7 @@ def sanitize_token(self, token): classes = token.get('data', {}).get((None, 'class'), '') if classes: classes = classes.split() - cleaned_classes = [c for c in classes if c in self.valid_class_values] + cleaned_classes = [c for c in classes if c in self.valid_class_values or c.startswith(self.valid_partial_class_prefixes)] if cleaned_classes != classes: log.info(f'Removed invalid classes: {classes} => {cleaned_classes}') token['data'][(None, 'class')] = ' '.join(cleaned_classes) diff --git a/Allura/allura/public/nf/js/allura-base.js b/Allura/allura/public/nf/js/allura-base.js index 7a8b15cdd..c6db0ce0a 100644 --- a/Allura/allura/public/nf/js/allura-base.js +++ b/Allura/allura/public/nf/js/allura-base.js @@ -239,14 +239,13 @@ $(function(){ e.preventDefault(); }); - // backwards compatibility for old anchors. If there's an intended target, but not an active one, try again with TOC prefix if (window.location.hash && !document.querySelector(':target')) { - var new_hash = window.location.hash.replace('#', '#h:'); + var new_hash = window.location.hash.replace('#', '#h-'); if (document.querySelector(new_hash)) { window.location.hash = new_hash; } else { - new_hash = window.location.hash.replace('#h:', '#user-content-'); + new_hash = window.location.hash.replace('#h-', '#user-content-'); if (document.querySelector(new_hash)) { window.location.hash = new_hash; } diff --git a/Allura/allura/tests/test_globals.py b/Allura/allura/tests/test_globals.py index 2ae86f4c0..76f8e2ecf 100644 --- a/Allura/allura/tests/test_globals.py +++ b/Allura/allura/tests/test_globals.py @@ -387,8 +387,8 @@ def test_markdown_toc(self): ## Header 2""")) assert dedent('''\ <ul> - <li><a href="#header-1">Header 1</a><ul> - <li><a href="#header-2">Header 2</a></li> + <li><a href="#h-header-1">Header 1</a><ul> + <li><a href="#h-header-2">Header 2</a></li> </ul> </li> </ul>''') in r @@ -447,11 +447,11 @@ def test_markdown_basics(self): with h.push_context('test', 'wiki', neighborhood='Projects'): text = g.markdown.convert('# Foo!\n[Home]') assert (text == - '<div class="markdown_content"><h1 id="h:foo">Foo!</h1>\n' + '<div class="markdown_content"><h1 id="h-foo">Foo!</h1>\n' '<p><a class="alink" href="/p/test/wiki/Home/">[Home]</a></p></div>') text = g.markdown.convert('# Foo!\n[Rooted]') assert (text == - '<div class="markdown_content"><h1 id="h:foo">Foo!</h1>\n' + '<div class="markdown_content"><h1 id="h-foo">Foo!</h1>\n' '<p><span>[Rooted]</span></p></div>') assert ( @@ -476,7 +476,7 @@ def test_markdown_basics(self): for i in range(10): print i ''')) == dedent('''\ - <div class="markdown_content"><h1 id="h:header">Header</h1> + <div class="markdown_content"><h1 id="h-header">Header</h1> <p>Some text in a regular paragraph</p> <div class="codehilite"><pre><span></span><code><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span> <span class="nb">print</span> <span class="n">i</span> diff --git a/Allura/allura/tests/test_helpers.py b/Allura/allura/tests/test_helpers.py index 1efa0a781..752477303 100644 --- a/Allura/allura/tests/test_helpers.py +++ b/Allura/allura/tests/test_helpers.py @@ -273,7 +273,7 @@ def test_render_any_markup_plain(): def test_render_any_markup_formatting(): assert (str(h.render_any_markup('README.md', '### foo\n' ' <script>alert(1)</script>bar')) == - '<div class="markdown_content"><h3 id="h:foo">foo</h3>\n' + '<div class="markdown_content"><h3 id="h-foo">foo</h3>\n' '<div class="codehilite"><pre><span></span><code><span class="nt">' '<script></span>alert(1)<span class="nt">' '</script></span>bar\n</code></pre></div>\n</div>') diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py index 6661b7ac2..4a3a4d46e 100644 --- a/ForgeTracker/forgetracker/tests/functional/test_root.py +++ b/ForgeTracker/forgetracker/tests/functional/test_root.py @@ -803,7 +803,7 @@ def test_cached_convert(self): # Make sure the cache has been saved. t = tm.Ticket.query.find({'_id': ticket._id}).first() - assert '<h1 id="test-markdown-cached_convert">Test markdown cached_convert</h1>' in t.description_cache.html + assert '<h1 id="h-test-markdown-cached_convert">Test markdown cached_convert</h1>' in t.description_cache.html def test_ticket_diffs(self): self.new_ticket(summary='difftest', description='1\n2\n3\n')