From 2cd1e05fe88b579bf66844127db52e3b6eb8b758 Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Mon, 10 Nov 2025 08:23:01 +0000 Subject: [PATCH] Fixes significant performance degradation introduced in r24094 by removing the CSS selectors from scrubbers (#43446). Patch by Takashi Kato (user:tohosaku). git-svn-id: https://svn.redmine.org/redmine/trunk@24139 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../common_mark/alerts_icons_scrubber.rb | 11 +++---- .../common_mark/syntax_highlight_scrubber.rb | 33 ++++++++++--------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/lib/redmine/wiki_formatting/common_mark/alerts_icons_scrubber.rb b/lib/redmine/wiki_formatting/common_mark/alerts_icons_scrubber.rb index 7e36be00d..0ae0b86b3 100644 --- a/lib/redmine/wiki_formatting/common_mark/alerts_icons_scrubber.rb +++ b/lib/redmine/wiki_formatting/common_mark/alerts_icons_scrubber.rb @@ -31,22 +31,22 @@ module Redmine }.freeze class AlertsIconsScrubber < Loofah::Scrubber - def scrub(doc) - doc.search("p.markdown-alert-title").each do |node| + def scrub(node) + if node.name == 'p' && node['class'] == 'markdown-alert-title' parent_node = node.parent parent_class_attr = parent_node['class'] # e.g., "markdown-alert markdown-alert-note" - next unless parent_class_attr + return unless parent_class_attr # Extract the specific alert type (e.g., "note", "tip", "warning") # from the parent div's classes. match_data = parent_class_attr.match(/markdown-alert-(\w+)/) - next unless match_data && match_data[1] # Ensure a type is found + return unless match_data && match_data[1] # Ensure a type is found alert_type = match_data[1] # Get the corresponding icon name from our map. icon_name = ALERT_TYPE_TO_ICON_NAME[alert_type] - next unless icon_name # Skip if no specific icon is defined for this alert type + return unless icon_name # Skip if no specific icon is defined for this alert type # Translate the alert title only if it matches a known alert type # (i.e., the title has not been overridden) @@ -61,7 +61,6 @@ module Redmine node.children.first.replace(icon_html) end end - doc end end end diff --git a/lib/redmine/wiki_formatting/common_mark/syntax_highlight_scrubber.rb b/lib/redmine/wiki_formatting/common_mark/syntax_highlight_scrubber.rb index 8b907b82c..5d9dfb380 100644 --- a/lib/redmine/wiki_formatting/common_mark/syntax_highlight_scrubber.rb +++ b/lib/redmine/wiki_formatting/common_mark/syntax_highlight_scrubber.rb @@ -24,26 +24,27 @@ module Redmine # blocks as generated by commonmarker class SyntaxHighlightScrubber < Loofah::Scrubber def scrub(node) - if node.matches?("pre > code") - return unless lang = node["class"].presence - return unless lang =~ /\Alanguage-(\S+)\z/ + # Equivalent to the CSS selector "pre > code". Implemented for performance + return unless node.name == 'code' && node.parent.name == 'pre' - lang = $1 - text = node.inner_text + return unless lang = node["class"].presence + return unless lang =~ /\Alanguage-(\S+)\z/ - # original language for extension development - node["data-language"] = lang unless node["data-language"] + lang = $1 + text = node.inner_text - if Redmine::SyntaxHighlighting.language_supported?(lang) - html = Redmine::SyntaxHighlighting.highlight_by_language(text, lang) - return if html.nil? + # original language for extension development + node["data-language"] = lang unless node["data-language"] - node.inner_html = html - node["class"] = "#{lang} syntaxhl" - else - # unsupported language, remove the class attribute - node.remove_attribute("class") - end + if Redmine::SyntaxHighlighting.language_supported?(lang) + html = Redmine::SyntaxHighlighting.highlight_by_language(text, lang) + return if html.nil? + + node.inner_html = html + node["class"] = "#{lang} syntaxhl" + else + # unsupported language, remove the class attribute + node.remove_attribute("class") end end end