Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package rubygem-loofah for openSUSE:Factory 
checked in at 2026-11-06 19:47:30
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rubygem-loofah (Old)
 and      /work/SRC/openSUSE:Factory/.rubygem-loofah.new.3759290 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "rubygem-loofah"

Fri Nov  6 19:47:30 2026 rev:30 rq:1395478 version:2.25.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/rubygem-loofah/rubygem-loofah.changes    
2026-09-10 11:51:11.464086746 +0200
+++ 
/work/SRC/openSUSE:Factory/.rubygem-loofah.new.3759290/rubygem-loofah.changes   
    2026-11-06 19:53:35.755176654 +0100
@@ -1,0 +2,77 @@
+Wed Nov  4 10:29:15 UTC 2026 - Marcus Rueckert <[email protected]>
+
+- update to 2.25.3
+  - Security
+    - Ensure `Loofah::HTML5::Scrub.allowed_uri?` rejects schemes
+      split by a numeric character reference without a semicolon
+      that ends at a character `allowed_uri?` strips (e.g.
+      `javascript&#x3a alert(1)`) or at another character reference
+      (e.g. `javascript&#x3a&#x61;lert(1)`). Character references
+      are now decoded before anything is stripped, as browsers do.
+      See GHSA-p9wj-w8xq-vjx6. @flavorjones
+    - Ensure `Loofah::HTML5::Scrub.allowed_uri?` recognizes the
+      named character reference `&sol;`, which `CGI.unescapeHTML`
+      does not decode and browsers read as `/`, and rejects `data:`
+      URIs that disguise a disallowed mediatype with it (e.g.
+      `data:text&sol;html,<script>alert(1)</script>`). Previously
+      that mediatype was treated as malformed and fell back to the
+      allowed `text/plain`. Only v2.25.2 is affected. See
+      GHSA-jcff-cj73-4w4f. @flavorjones
+    - Ensure `Loofah::HTML5::Scrub.scrub_css` does not decode CSS
+      escapes in identifiers. Previously, escaped parentheses (e.g.
+      `url\28 http://example.com/\29`) came out as a live `url()`,
+      which could make the viewer's browser fetch an
+      attacker-chosen URL. See GHSA-m3x9-938q-5767. @flavorjones
+    - Ensure that `href` and `xlink:href` on SVG `textPath` and
+      `mpath` elements are restricted to local (same-document)
+      references. Previously `SVG_ALLOW_LOCAL_HREF` spelled
+      `textPath` in lowercase, which never matched the name the
+      HTML5 parser assigns inside `<svg>`, and omitted `mpath`
+      entirely. See GHSA-345x-3rq2-jfrm. @flavorjones
+    - Fix quadratic-time scrubbing of the `href` and `xlink:href`
+      attributes of SVG elements. Only Ruby 3.1 and earlier are
+      affected, because Ruby 3.2 introduced linear-time regexp
+      matching. See GHSA-mf2j-8f84-cc9q. @flavorjones
+    - Ensure HTML5 scrubber output does not turn into new markup
+      when a browser parses it again. The fix is in Nokogiri
+      v1.19.5, which escapes `<` and `>` in attribute values as the
+      HTML standard requires, so Loofah now requires Nokogiri >=
+      1.19.5. See GHSA-h6v6-rg66-fqj4 @flavorjones @hackvertor
+  - Dependencies
+    - Loofah now requires Ruby >= 3.2, the minimum that Nokogiri
+      v1.19.x supports. We don't like dropping Ruby versions in a
+      patch release, and we're sorry for the inconvenience, but
+      it's the only way to make sure everyone gets the security fix
+      in GHSA-h6v6-rg66-fqj4
+  - Added
+    - `Loofah::HTML5::Scrub.prefixed_attribute_name` and
+      `Loofah::HTML5::Scrub.scrub_attribute_value` expose the
+      html5lib attribute name and value rules, so downstream
+      consumers can apply them instead of carrying their own copy.
+      @flavorjones
+  - Fixed
+    - Fix `:double_breakpoint`, which left document fragments
+      unchanged despite its documented example. The scrubber now
+      changes only paragraphs inside the scrubbed node, and its run
+      time on a document grows linearly, not quadratically, with
+      the paragraph count. #309 @OskarEichler
+    - Fix `:whitewash`, which passed CDATA sections through
+      unchanged. Markup inside a CDATA section in
+      `Loofah.xml_fragment` or `Loofah.xml_document` survived
+      scrubbing and became live elements if the output was later
+      parsed as HTML. The scrubber now escapes CDATA content, as
+      `:strip`, `:prune` and `:escape` already do. On JRuby, every
+      sanitizer now emits escaped CDATA content as a CDATA section,
+      as on CRuby, instead of a text node that double-escaped it.
+      #313 @flavorjones (reported by @MegaManSec)
+    - Fix `:double_breakpoint`, which raised `NoMethodError` on a
+      paragraph that ends with a `<br>` after a double break. #314
+      @flavorjones (reported by @MegaManSec)
+    - Fix `Loofah::HTML5::Scrub.allowed_uri?`, which raised
+      `Encoding::CompatibilityError` on a string in an encoding
+      other than UTF-8 and `ArgumentError` on invalid UTF-8. It now
+      transcodes the input to UTF-8 and returns `false` when the
+      input has an invalid byte sequence or no UTF-8
+      representation. #315 @flavorjones
+
+-------------------------------------------------------------------

Old:
----
  loofah-2.25.2.gem

New:
----
  loofah-2.25.3.gem

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ rubygem-loofah.spec ++++++
--- /var/tmp/diff_new_pack.UGssin/_old  2026-11-06 19:53:38.483290882 +0100
+++ /var/tmp/diff_new_pack.UGssin/_new  2026-11-06 19:53:38.488291091 +0100
@@ -24,11 +24,11 @@
 #
 
 Name:           rubygem-loofah
-Version:        2.25.2
+Version:        2.25.3
 Release:        0
 %define mod_name loofah
 %define mod_full_name %{mod_name}-%{version}
-BuildRequires:  %{ruby >= 2.5.0}
+BuildRequires:  %{ruby >= 3.2.0}
 BuildRequires:  %{rubygem gem2rpm}
 BuildRequires:  ruby-macros >= 5
 URL:            https://github.com/flavorjones/loofah

++++++ loofah-2.25.2.gem -> loofah-2.25.3.gem ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CHANGELOG.md new/CHANGELOG.md
--- old/CHANGELOG.md    1980-01-02 01:00:00.000000000 +0100
+++ new/CHANGELOG.md    1980-01-02 01:00:00.000000000 +0100
@@ -1,5 +1,32 @@
 # Changelog
 
+## 2.25.3 / 2026-11-01
+
+### Security
+
+* Ensure `Loofah::HTML5::Scrub.allowed_uri?` rejects schemes split by a 
numeric character reference without a semicolon that ends at a character 
`allowed_uri?` strips (e.g. `javascript&#x3a alert(1)`) or at another character 
reference (e.g. `javascript&#x3a&#x61;lert(1)`). Character references are now 
decoded before anything is stripped, as browsers do. See 
[GHSA-p9wj-w8xq-vjx6](https://github.com/flavorjones/loofah/security/advisories/GHSA-p9wj-w8xq-vjx6).
 @flavorjones
+* Ensure `Loofah::HTML5::Scrub.allowed_uri?` recognizes the named character 
reference `&sol;`, which `CGI.unescapeHTML` does not decode and browsers read 
as `/`, and rejects `data:` URIs that disguise a disallowed mediatype with it 
(e.g. `data:text&sol;html,<script>alert(1)</script>`). Previously that 
mediatype was treated as malformed and fell back to the allowed `text/plain`. 
Only v2.25.2 is affected. See 
[GHSA-jcff-cj73-4w4f](https://github.com/flavorjones/loofah/security/advisories/GHSA-jcff-cj73-4w4f).
 @flavorjones
+* Ensure `Loofah::HTML5::Scrub.scrub_css` does not decode CSS escapes in 
identifiers. Previously, escaped parentheses (e.g. `url\28 
http://example.com/\29`) came out as a live `url()`, which could make the 
viewer's browser fetch an attacker-chosen URL. See 
[GHSA-m3x9-938q-5767](https://github.com/flavorjones/loofah/security/advisories/GHSA-m3x9-938q-5767).
 @flavorjones
+* Ensure that `href` and `xlink:href` on SVG `textPath` and `mpath` elements 
are restricted to local (same-document) references. Previously 
`SVG_ALLOW_LOCAL_HREF` spelled `textPath` in lowercase, which never matched the 
name the HTML5 parser assigns inside `<svg>`, and omitted `mpath` entirely. See 
[GHSA-345x-3rq2-jfrm](https://github.com/flavorjones/loofah/security/advisories/GHSA-345x-3rq2-jfrm).
 @flavorjones
+* Fix quadratic-time scrubbing of the `href` and `xlink:href` attributes of 
SVG elements. Only Ruby 3.1 and earlier are affected, because Ruby 3.2 
introduced linear-time regexp matching. See 
[GHSA-mf2j-8f84-cc9q](https://github.com/flavorjones/loofah/security/advisories/GHSA-mf2j-8f84-cc9q).
 @flavorjones
+* Ensure HTML5 scrubber output does not turn into new markup when a browser 
parses it again. The fix is in Nokogiri v1.19.5, which escapes `<` and `>` in 
attribute values as the HTML standard requires, so Loofah now requires Nokogiri 
>= 1.19.5. See 
[GHSA-h6v6-rg66-fqj4](https://github.com/flavorjones/loofah/security/advisories/GHSA-h6v6-rg66-fqj4).
 @flavorjones @hackvertor
+
+### Dependencies
+
+* Loofah now requires Ruby >= 3.2, the minimum that Nokogiri v1.19.x supports. 
We don't like dropping Ruby versions in a patch release, and we're sorry for 
the inconvenience, but it's the only way to make sure everyone gets the 
security fix in 
[GHSA-h6v6-rg66-fqj4](https://github.com/flavorjones/loofah/security/advisories/GHSA-h6v6-rg66-fqj4).
+
+### Added
+
+* `Loofah::HTML5::Scrub.prefixed_attribute_name` and 
`Loofah::HTML5::Scrub.scrub_attribute_value` expose the html5lib attribute name 
and value rules, so downstream consumers can apply them instead of carrying 
their own copy. @flavorjones
+
+### Fixed
+
+* Fix `:double_breakpoint`, which left document fragments unchanged despite 
its documented example. The scrubber now changes only paragraphs inside the 
scrubbed node, and its run time on a document grows linearly, not 
quadratically, with the paragraph count. #309 @OskarEichler
+* Fix `:whitewash`, which passed CDATA sections through unchanged. Markup 
inside a CDATA section in `Loofah.xml_fragment` or `Loofah.xml_document` 
survived scrubbing and became live elements if the output was later parsed as 
HTML. The scrubber now escapes CDATA content, as `:strip`, `:prune` and 
`:escape` already do. On JRuby, every sanitizer now emits escaped CDATA content 
as a CDATA section, as on CRuby, instead of a text node that double-escaped it. 
#313 @flavorjones (reported by @MegaManSec)
+* Fix `:double_breakpoint`, which raised `NoMethodError` on a paragraph that 
ends with a `<br>` after a double break. #314 @flavorjones (reported by 
@MegaManSec)
+* Fix `Loofah::HTML5::Scrub.allowed_uri?`, which raised 
`Encoding::CompatibilityError` on a string in an encoding other than UTF-8 and 
`ArgumentError` on invalid UTF-8. It now transcodes the input to UTF-8 and 
returns `false` when the input has an invalid byte sequence or no UTF-8 
representation. #315 @flavorjones
+
+
 ## 2.25.2 / 2026-07-15
 
 ### Security
Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/loofah/html5/safelist.rb 
new/lib/loofah/html5/safelist.rb
--- old/lib/loofah/html5/safelist.rb    1980-01-02 01:00:00.000000000 +0100
+++ new/lib/loofah/html5/safelist.rb    1980-01-02 01:00:00.000000000 +0100
@@ -623,7 +623,8 @@
         "pattern",
         "radialGradient",
         "set",
-        "textpath",
+        "mpath",
+        "textPath",
         "tref",
         "use",
       ])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/loofah/html5/scrub.rb 
new/lib/loofah/html5/scrub.rb
--- old/lib/loofah/html5/scrub.rb       1980-01-02 01:00:00.000000000 +0100
+++ new/lib/loofah/html5/scrub.rb       1980-01-02 01:00:00.000000000 +0100
@@ -13,6 +13,7 @@
       CSS_IMPORTANT = "!important"
       CSS_WHITESPACE = " "
       CSS_PROPERTY_STRING_WITHOUT_EMBEDDED_QUOTES = /\A(["'])?[^"']+\1\z/
+      CSS_URLISH_NODES = [:url, :bad_url, :bad_string]
       DATA_ATTRIBUTE_NAME = /\Adata-[\w-]+\z/
 
       # Decimal (`&#58`) or hexadecimal (`&#x3a`) form, with or without the 
trailing semicolon that
@@ -52,6 +53,15 @@
       # URIs. CGI.unescapeHTML does not decode these, so they are handled 
explicitly.
       WHITESPACE_CHARACTER_REFERENCES = /&(Tab|NewLine);/
 
+      # HTML5 named character references for the delimiters that decide how a 
URI parses:
+      # ":" ends the scheme, and "/" separates the type and subtype of a data: 
mediatype.
+      # CGI.unescapeHTML does not decode these either. Together with
+      # WHITESPACE_CHARACTER_REFERENCES these are every named character 
reference that
+      # decodes to U+0009, U+000A, U+002F, or U+003A, so no other named 
reference can
+      # change how a URI parses.
+      DELIMITER_CHARACTER_REFERENCES = { "&colon;" => ":", "&sol;" => "/" 
}.freeze
+      DELIMITER_CHARACTER_REFERENCE = 
Regexp.union(DELIMITER_CHARACTER_REFERENCES.keys)
+
       class << self
         def allowed_element?(element_name)
           
::Loofah::HTML5::SafeList::ALLOWED_ELEMENTS_WITH_LIBXML2.include?(element_name)
@@ -60,11 +70,7 @@
         #  alternative implementation of the html5lib attribute scrubbing 
algorithm
         def scrub_attributes(node)
           node.attribute_nodes.each do |attr_node|
-            attr_name = if attr_node.namespace
-              "#{attr_node.namespace.prefix}:#{attr_node.node_name}"
-            else
-              attr_node.node_name
-            end
+            attr_name = prefixed_attribute_name(attr_node)
 
             if DATA_ATTRIBUTE_NAME.match?(attr_name)
               next
@@ -75,20 +81,7 @@
               next
             end
 
-            if SafeList::ATTR_VAL_IS_URI.include?(attr_name)
-              next if scrub_uri_attribute(attr_node)
-            end
-
-            if SafeList::SVG_ATTR_VAL_ALLOWS_REF.include?(attr_name)
-              scrub_attribute_that_allows_local_ref(attr_node)
-            end
-
-            next unless SafeList::SVG_ALLOW_LOCAL_HREF.include?(node.name) &&
-              SafeList::SVG_HREF_ATTRIBUTES.include?(attr_name) &&
-              attr_node.value =~ /^\s*[^#\s].*/m
-
-            attr_node.remove
-            next
+            scrub_attribute_value(node, attr_node, attr_name)
           end
 
           scrub_css_attribute(node)
@@ -102,28 +95,58 @@
           force_correct_attribute_escaping!(node)
         end
 
+        #  The name an attribute is matched by in the safelists, qualified by 
its namespace prefix.
+        def prefixed_attribute_name(attr_node)
+          if attr_node.namespace
+            "#{attr_node.namespace.prefix}:#{attr_node.node_name}"
+          else
+            attr_node.node_name
+          end
+        end
+
+        #  Apply the html5lib value rules to an attribute that is already 
permitted by name.
+        #  Returns true when `scrub_uri_attribute` removed the attribute, in 
which case the caller
+        #  should stop scrubbing it.
+        def scrub_attribute_value(node, attr_node, attr_name = 
prefixed_attribute_name(attr_node))
+          if SafeList::ATTR_VAL_IS_URI.include?(attr_name)
+            return true if scrub_uri_attribute(attr_node)
+          end
+
+          if SafeList::SVG_ATTR_VAL_ALLOWS_REF.include?(attr_name)
+            scrub_attribute_that_allows_local_ref(attr_node)
+          end
+
+          # The whitespace run is `[^\S\n]*` rather than `\s*` so that it 
cannot cross a line
+          # boundary. With `\s*` the engine rescanned the entire run from 
every line start,
+          # which is quadratic in the length of an all-whitespace value.
+          if SafeList::SVG_ALLOW_LOCAL_HREF.include?(node.name) &&
+              SafeList::SVG_HREF_ATTRIBUTES.include?(attr_name) &&
+              attr_node.value =~ /^[^\S\n]*[^#\s]/
+            attr_node.remove
+          end
+
+          false
+        end
+
         def scrub_css_attribute(node)
           style = node.attributes["style"]
           style.value = scrub_css(style.value) if style
         end
 
         def scrub_css(style)
-          url_flags = [:url, :bad_url]
           style_tree = Crass.parse_properties(style)
           sanitized_tree = []
 
           style_tree.each do |node|
             next unless node[:node] == :property
-            next if node[:children].any? do |child|
-              url_flags.include?(child[:node])
-            end
+            next if node[:children].any? { |child| 
CSS_URLISH_NODES.include?(child[:node]) }
 
             name = node[:name].downcase
             next unless SafeList::ALLOWED_CSS_PROPERTIES.include?(name) ||
               SafeList::ALLOWED_SVG_PROPERTIES.include?(name) ||
               
SafeList::SHORTHAND_CSS_PROPERTIES.include?(name.split("-").first)
 
-            value = node[:children].map do |child|
+            value = node[:children].filter_map do |child|
               case child[:node]
               when :whitespace
                 CSS_WHITESPACE
@@ -140,30 +163,55 @@
                 if 
!SafeList::SHORTHAND_CSS_PROPERTIES.include?(name.split("-").first) ||
                     SafeList::ALLOWED_CSS_KEYWORDS.include?(keyword) ||
                     (keyword =~ CSS_KEYWORDISH)
-                  keyword
+                  child[:raw]
                 end
               else
                 child[:raw]
               end
-            end.compact.join.strip
+            end.join.strip
 
             next if value.empty?
 
             value << CSS_WHITESPACE << CSS_IMPORTANT if node[:important]
+            # Dropping tokens can join the survivors into new ones 
(`url/(a)*/(b)` becomes `url/*/`),
+            # so the rebuilt string may tokenize differently from the original 
and stringify
+            # differently again. Keep a property only if its rebuilt string 
survives a parse and
+            # stringify unchanged, so the tokens checked are exactly the 
tokens a browser will see.
             propstring = format("%s:%s", name, value)
             sanitized_node = Crass.parse_properties(propstring).first
+            next unless Crass::Parser.stringify(sanitized_node) == propstring
+            next if css_property_unsafe?(sanitized_node)
+
             sanitized_tree << sanitized_node << CRASS_SEMICOLON
           end
 
           Crass::Parser.stringify(sanitized_tree)
         end
 
+        # Dropping a token joins its neighbours, which can build a token that 
was not in the input:
+        # dropping the string from `url\28 "x"linear-gradient(red)` leaves one 
function token. So the
+        # rebuilt property is checked for functions and strings, which the 
input check never sees.
+        def css_property_unsafe?(node)
+          node[:children].any? do |child|
+            case child[:node]
+            when *CSS_URLISH_NODES
+              true
+            when :string
+              !CSS_PROPERTY_STRING_WITHOUT_EMBEDDED_QUOTES.match?(child[:raw])
+            when :function
+              
!SafeList::ALLOWED_CSS_FUNCTIONS.include?(child[:name].downcase(:ascii))
+            else
+              false
+            end
+          end
+        end
+
         def scrub_attribute_that_allows_local_ref(attr_node)
           return unless attr_node.value
 
           nodes = Crass::Parser.new(attr_node.value).parse_component_values
 
-          values = nodes.map do |node|
+          values = nodes.filter_map do |node|
             case node[:node]
             when :url
               if node[:value].start_with?("#")
@@ -172,7 +220,7 @@
             when :hash, :ident, :string
               node[:raw]
             end
-          end.compact
+          end
 
           attr_node.value = values.join(" ")
         end
@@ -180,16 +228,27 @@
         # Returns true if the given URI string is safe, false otherwise. This 
method can be used to
         # validate URI attribute values without requiring a Nokogiri DOM node.
         def allowed_uri?(uri_string)
+          # The character-reference regexps are UTF-8, so the input has to be 
transcoded before it can
+          # be matched against them. String#encode is a no-op on a string 
already tagged UTF-8, so an
+          # invalid byte sequence has to be rejected separately.
+          return false unless uri_string.valid_encoding?
+
+          begin
+            uri_string = uri_string.encode(Encoding::UTF_8)
+          rescue EncodingError
+            return false
+          end
+
+          # Decode character references before stripping anything, as a 
browser does: an HTML parser
+          # decodes the attribute value, then the URL parser strips characters 
from the result. A
+          # semicolon-less numeric reference ends at the first character that 
cannot extend it, so
+          # stripping that character first would let the reference run on into 
the following text.
           # CGI.unescapeHTML decodes numeric references only when they carry a 
trailing semicolon, so
-          # also decode the semicolon-less ones, which browsers still decode 
and execute. Normalizing
-          # more aggressively than a browser only rejects more, which is safe. 
Control characters are
-          # stripped both before and after decoding, since decoding can 
produce them. That strip must
-          # precede WHITESPACE_CHARACTER_REFERENCES: removing a control 
character can reveal a named
-          # whitespace reference.
-          uri_string = 
decode_numeric_character_references(CGI.unescapeHTML(uri_string.gsub(CONTROL_CHARACTERS,
 "")))
+          # the semicolon-less ones are decoded separately.
+          uri_string = 
CGI.unescapeHTML(decode_numeric_character_references(uri_string))
           uri_string.gsub!(CONTROL_CHARACTERS, "")
           uri_string.gsub!(WHITESPACE_CHARACTER_REFERENCES, "")
-          uri_string.gsub!("&colon;", ":")
+          uri_string.gsub!(DELIMITER_CHARACTER_REFERENCE, 
DELIMITER_CHARACTER_REFERENCES)
           uri_string.downcase!
           if URI_PROTOCOL_REGEX.match?(uri_string)
             protocol = uri_string.split(SafeList::PROTOCOL_SEPARATOR)[0]
@@ -265,10 +324,10 @@
 
         def cdata_escape(node)
           escaped_text = escape_tags(node.text)
-          if Nokogiri.jruby?
-            node.document.create_text_node(escaped_text)
-          else
+          if node.cdata?
             node.document.create_cdata(escaped_text)
+          else
+            node.document.create_text_node(escaped_text)
           end
         end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/loofah/scrubbers.rb new/lib/loofah/scrubbers.rb
--- old/lib/loofah/scrubbers.rb 1980-01-02 01:00:00.000000000 +0100
+++ new/lib/loofah/scrubbers.rb 1980-01-02 01:00:00.000000000 +0100
@@ -201,7 +201,11 @@
             return CONTINUE if node.namespaces.empty?
           end
         when Nokogiri::XML::Node::TEXT_NODE, 
Nokogiri::XML::Node::CDATA_SECTION_NODE
-          return CONTINUE
+          if HTML5::Scrub.cdata_needs_escaping?(node)
+            node.before(HTML5::Scrub.cdata_escape(node))
+          else
+            return CONTINUE
+          end
         end
         node.remove
         STOP
@@ -361,37 +365,34 @@
     #
     class DoubleBreakpoint < Scrubber
       def initialize # rubocop:disable Lint/MissingSuper
-        @direction = :top_down
+        # a top-down walk would empty a paragraph before reaching a paragraph 
nested in it
+        @direction = :bottom_up
       end
 
       def scrub(node)
         return CONTINUE unless (node.type == 
Nokogiri::XML::Node::ELEMENT_NODE) && (node.name == "p")
+        return CONTINUE unless node.at_xpath("./br[following-sibling::br]")
 
-        paragraph_with_break_point_nodes = 
node.xpath("//p[br[following-sibling::br]]")
-
-        paragraph_with_break_point_nodes.each do |paragraph_node|
-          new_paragraph = paragraph_node.add_previous_sibling("<p>").first
+        new_paragraph = node.add_previous_sibling("<p>").first
 
-          paragraph_node.children.each do |child|
-            remove_blank_text_nodes(child)
-          end
+        node.children.each do |child|
+          remove_blank_text_nodes(child)
+        end
 
-          paragraph_node.children.each do |child|
-            # already unlinked
-            next if child.parent.nil?
-
-            if child.name == "br" && child.next_sibling.name == "br"
-              new_paragraph = paragraph_node.add_previous_sibling("<p>").first
-              child.next_sibling.unlink
-              child.unlink
-            else
-              child.parent = new_paragraph
-            end
+        node.children.each do |child|
+          # already unlinked
+          next if child.parent.nil?
+
+          if child.name == "br" && child.next_sibling&.name == "br"
+            new_paragraph = node.add_previous_sibling("<p>").first
+            child.next_sibling.unlink
+            child.unlink
+          else
+            child.parent = new_paragraph
           end
-
-          paragraph_node.unlink
         end
 
+        node.unlink
         CONTINUE
       end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/loofah/version.rb new/lib/loofah/version.rb
--- old/lib/loofah/version.rb   1980-01-02 01:00:00.000000000 +0100
+++ new/lib/loofah/version.rb   1980-01-02 01:00:00.000000000 +0100
@@ -2,5 +2,5 @@
 
 module Loofah
   # The version of Loofah you are using
-  VERSION = "2.25.2"
+  VERSION = "2.25.3"
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/loofah.rb new/lib/loofah.rb
--- old/lib/loofah.rb   1980-01-02 01:00:00.000000000 +0100
+++ new/lib/loofah.rb   1980-01-02 01:00:00.000000000 +0100
@@ -5,13 +5,7 @@
 module Loofah
   class << self
     def html5_support?
-      # Note that Loofah can only support HTML5 in Nokogiri >= 1.14.0 because 
it requires the
-      # subclassing fix from 
https://github.com/sparklemotion/nokogiri/pull/2534
-      return @html5_support if defined? @html5_support
-
-      @html5_support =
-        Gem::Version.new(Nokogiri::VERSION) > Gem::Version.new("1.14.0") &&
-        Nokogiri.uses_gumbo?
+      Nokogiri.uses_gumbo?
     end
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/metadata new/metadata
--- old/metadata        1980-01-02 01:00:00.000000000 +0100
+++ new/metadata        1980-01-02 01:00:00.000000000 +0100
@@ -1,7 +1,7 @@
 --- !ruby/object:Gem::Specification
 name: loofah
 version: !ruby/object:Gem::Version
-  version: 2.25.2
+  version: 2.25.3
 platform: ruby
 authors:
 - Mike Dalessio
@@ -30,14 +30,14 @@
     requirements:
     - - ">="
       - !ruby/object:Gem::Version
-        version: 1.12.0
+        version: 1.19.5
   type: :runtime
   prerelease: false
   version_requirements: !ruby/object:Gem::Requirement
     requirements:
     - - ">="
       - !ruby/object:Gem::Version
-        version: 1.12.0
+        version: 1.19.5
 description: |
   Loofah is a general library for manipulating and transforming HTML/XML 
documents and fragments,
   built on top of Nokogiri.
@@ -89,14 +89,14 @@
   requirements:
   - - ">="
     - !ruby/object:Gem::Version
-      version: 2.5.0
+      version: 3.2.0
 required_rubygems_version: !ruby/object:Gem::Requirement
   requirements:
   - - ">="
     - !ruby/object:Gem::Version
       version: '0'
 requirements: []
-rubygems_version: 4.0.10
+rubygems_version: 4.0.20
 specification_version: 4
 summary: Loofah is a general library for manipulating and transforming 
HTML/XML documents
   and fragments, built on top of Nokogiri.

Reply via email to