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
This commit is contained in:
Marius Balteanu
2025-11-10 08:23:01 +00:00
parent a25321e1e7
commit 2cd1e05fe8
2 changed files with 22 additions and 22 deletions

View File

@@ -31,22 +31,22 @@ module Redmine
}.freeze }.freeze
class AlertsIconsScrubber < Loofah::Scrubber class AlertsIconsScrubber < Loofah::Scrubber
def scrub(doc) def scrub(node)
doc.search("p.markdown-alert-title").each do |node| if node.name == 'p' && node['class'] == 'markdown-alert-title'
parent_node = node.parent parent_node = node.parent
parent_class_attr = parent_node['class'] # e.g., "markdown-alert markdown-alert-note" 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") # Extract the specific alert type (e.g., "note", "tip", "warning")
# from the parent div's classes. # from the parent div's classes.
match_data = parent_class_attr.match(/markdown-alert-(\w+)/) 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] alert_type = match_data[1]
# Get the corresponding icon name from our map. # Get the corresponding icon name from our map.
icon_name = ALERT_TYPE_TO_ICON_NAME[alert_type] 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 # Translate the alert title only if it matches a known alert type
# (i.e., the title has not been overridden) # (i.e., the title has not been overridden)
@@ -61,7 +61,6 @@ module Redmine
node.children.first.replace(icon_html) node.children.first.replace(icon_html)
end end
end end
doc
end end
end end
end end

View File

@@ -24,26 +24,27 @@ module Redmine
# blocks as generated by commonmarker # blocks as generated by commonmarker
class SyntaxHighlightScrubber < Loofah::Scrubber class SyntaxHighlightScrubber < Loofah::Scrubber
def scrub(node) def scrub(node)
if node.matches?("pre > code") # Equivalent to the CSS selector "pre > code". Implemented for performance
return unless lang = node["class"].presence return unless node.name == 'code' && node.parent.name == 'pre'
return unless lang =~ /\Alanguage-(\S+)\z/
lang = $1 return unless lang = node["class"].presence
text = node.inner_text return unless lang =~ /\Alanguage-(\S+)\z/
# original language for extension development lang = $1
node["data-language"] = lang unless node["data-language"] text = node.inner_text
if Redmine::SyntaxHighlighting.language_supported?(lang) # original language for extension development
html = Redmine::SyntaxHighlighting.highlight_by_language(text, lang) node["data-language"] = lang unless node["data-language"]
return if html.nil?
node.inner_html = html if Redmine::SyntaxHighlighting.language_supported?(lang)
node["class"] = "#{lang} syntaxhl" html = Redmine::SyntaxHighlighting.highlight_by_language(text, lang)
else return if html.nil?
# unsupported language, remove the class attribute
node.remove_attribute("class") node.inner_html = html
end node["class"] = "#{lang} syntaxhl"
else
# unsupported language, remove the class attribute
node.remove_attribute("class")
end end
end end
end end