loofah 2.6.0 → 2.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,23 +7,26 @@ module Loofah
7
7
  module Scrub
8
8
  CONTROL_CHARACTERS = /[`\u0000-\u0020\u007f\u0080-\u0101]/
9
9
  CSS_KEYWORDISH = /\A(#[0-9a-fA-F]+|rgb\(\d+%?,\d*%?,?\d*%?\)?|-?\d{0,3}\.?\d{0,10}(ch|cm|r?em|ex|in|lh|mm|pc|pt|px|Q|vmax|vmin|vw|vh|%|,|\))?)\z/
10
- CRASS_SEMICOLON = { :node => :semicolon, :raw => ";" }
10
+ CRASS_SEMICOLON = { node: :semicolon, raw: ";" }
11
+ CSS_IMPORTANT = '!important'
12
+ CSS_PROPERTY_STRING_WITHOUT_EMBEDDED_QUOTES = /\A(["'])?[^"']+\1\z/
13
+ DATA_ATTRIBUTE_NAME = /\Adata-[\w-]+\z/
11
14
 
12
15
  class << self
13
16
  def allowed_element?(element_name)
14
- ::Loofah::HTML5::SafeList::ALLOWED_ELEMENTS_WITH_LIBXML2.include? element_name
17
+ ::Loofah::HTML5::SafeList::ALLOWED_ELEMENTS_WITH_LIBXML2.include?(element_name)
15
18
  end
16
19
 
17
20
  # alternative implementation of the html5lib attribute scrubbing algorithm
18
21
  def scrub_attributes(node)
19
22
  node.attribute_nodes.each do |attr_node|
20
23
  attr_name = if attr_node.namespace
21
- "#{attr_node.namespace.prefix}:#{attr_node.node_name}"
22
- else
23
- attr_node.node_name
24
- end
24
+ "#{attr_node.namespace.prefix}:#{attr_node.node_name}"
25
+ else
26
+ attr_node.node_name
27
+ end
25
28
 
26
- if attr_name =~ /\Adata-[\w-]+\z/
29
+ if attr_name =~ DATA_ATTRIBUTE_NAME
27
30
  next
28
31
  end
29
32
 
@@ -33,37 +36,28 @@ module Loofah
33
36
  end
34
37
 
35
38
  if SafeList::ATTR_VAL_IS_URI.include?(attr_name)
36
- # this block lifted nearly verbatim from HTML5 sanitization
37
- val_unescaped = CGI.unescapeHTML(attr_node.value).gsub(CONTROL_CHARACTERS, "").downcase
38
- if val_unescaped =~ /^[a-z0-9][-+.a-z0-9]*:/ && !SafeList::ALLOWED_PROTOCOLS.include?(val_unescaped.split(SafeList::PROTOCOL_SEPARATOR)[0])
39
- attr_node.remove
40
- next
41
- elsif val_unescaped.split(SafeList::PROTOCOL_SEPARATOR)[0] == "data"
42
- # permit only allowed data mediatypes
43
- mediatype = val_unescaped.split(SafeList::PROTOCOL_SEPARATOR)[1]
44
- mediatype, _ = mediatype.split(";")[0..1] if mediatype
45
- if mediatype && !SafeList::ALLOWED_URI_DATA_MEDIATYPES.include?(mediatype)
46
- attr_node.remove
47
- next
48
- end
49
- end
39
+ next if scrub_uri_attribute(attr_node)
50
40
  end
41
+
51
42
  if SafeList::SVG_ATTR_VAL_ALLOWS_REF.include?(attr_name)
52
- attr_node.value = attr_node.value.gsub(/url\s*\(\s*[^#\s][^)]+?\)/m, " ") if attr_node.value
43
+ scrub_attribute_that_allows_local_ref(attr_node)
53
44
  end
45
+
54
46
  if SafeList::SVG_ALLOW_LOCAL_HREF.include?(node.name) && attr_name == "xlink:href" && attr_node.value =~ /^\s*[^#\s].*/m
55
47
  attr_node.remove
56
48
  next
57
49
  end
58
50
  end
59
51
 
60
- scrub_css_attribute node
52
+ scrub_css_attribute(node)
61
53
 
62
54
  node.attribute_nodes.each do |attr_node|
63
- node.remove_attribute(attr_node.name) if attr_node.value !~ /[^[:space:]]/
55
+ if attr_node.value !~ /[^[:space:]]/ && attr_node.name !~ DATA_ATTRIBUTE_NAME
56
+ node.remove_attribute(attr_node.name)
57
+ end
64
58
  end
65
59
 
66
- force_correct_attribute_escaping! node
60
+ force_correct_attribute_escaping!(node)
67
61
  end
68
62
 
69
63
  def scrub_css_attribute(node)
@@ -72,32 +66,95 @@ module Loofah
72
66
  end
73
67
 
74
68
  def scrub_css(style)
75
- style_tree = Crass.parse_properties style
69
+ style_tree = Crass.parse_properties(style)
76
70
  sanitized_tree = []
77
71
 
78
72
  style_tree.each do |node|
79
73
  next unless node[:node] == :property
80
74
  next if node[:children].any? do |child|
81
- [:url, :bad_url].include?(child[:node]) || (child[:node] == :function && !SafeList::ALLOWED_CSS_FUNCTIONS.include?(child[:name].downcase))
75
+ [:url, :bad_url].include?(child[:node])
82
76
  end
77
+
83
78
  name = node[:name].downcase
84
- if SafeList::ALLOWED_CSS_PROPERTIES.include?(name) || SafeList::ALLOWED_SVG_PROPERTIES.include?(name)
85
- sanitized_tree << node << CRASS_SEMICOLON
86
- elsif SafeList::SHORTHAND_CSS_PROPERTIES.include?(name.split("-").first)
87
- value = node[:value].split.map do |keyword|
88
- if SafeList::ALLOWED_CSS_KEYWORDS.include?(keyword) || keyword =~ CSS_KEYWORDISH
79
+ next unless SafeList::ALLOWED_CSS_PROPERTIES.include?(name) ||
80
+ SafeList::ALLOWED_SVG_PROPERTIES.include?(name) ||
81
+ SafeList::SHORTHAND_CSS_PROPERTIES.include?(name.split("-").first)
82
+
83
+ value = node[:children].map do |child|
84
+ case child[:node]
85
+ when :whitespace
86
+ nil
87
+ when :string
88
+ if child[:raw] =~ CSS_PROPERTY_STRING_WITHOUT_EMBEDDED_QUOTES
89
+ Crass::Parser.stringify(child)
90
+ else
91
+ nil
92
+ end
93
+ when :function
94
+ if SafeList::ALLOWED_CSS_FUNCTIONS.include?(child[:name].downcase)
95
+ Crass::Parser.stringify(child)
96
+ end
97
+ when :ident
98
+ keyword = child[:value]
99
+ if !SafeList::SHORTHAND_CSS_PROPERTIES.include?(name.split("-").first) ||
100
+ SafeList::ALLOWED_CSS_KEYWORDS.include?(keyword) ||
101
+ (keyword =~ CSS_KEYWORDISH)
89
102
  keyword
90
103
  end
91
- end.compact
92
- unless value.empty?
93
- propstring = sprintf "%s:%s", name, value.join(" ")
94
- sanitized_node = Crass.parse_properties(propstring).first
95
- sanitized_tree << sanitized_node << CRASS_SEMICOLON
104
+ else
105
+ child[:raw]
96
106
  end
97
- end
107
+ end.compact
108
+
109
+ next if value.empty?
110
+ value << CSS_IMPORTANT if node[:important]
111
+ propstring = format("%s:%s", name, value.join(" "))
112
+ sanitized_node = Crass.parse_properties(propstring).first
113
+ sanitized_tree << sanitized_node << CRASS_SEMICOLON
98
114
  end
99
115
 
100
- Crass::Parser.stringify sanitized_tree
116
+ Crass::Parser.stringify(sanitized_tree)
117
+ end
118
+
119
+ def scrub_attribute_that_allows_local_ref(attr_node)
120
+ return unless attr_node.value
121
+
122
+ nodes = Crass::Parser.new(attr_node.value).parse_component_values
123
+
124
+ values = nodes.map do |node|
125
+ case node[:node]
126
+ when :url
127
+ if node[:value].start_with?("#")
128
+ node[:raw]
129
+ else
130
+ nil
131
+ end
132
+ when :hash, :ident, :string
133
+ node[:raw]
134
+ else
135
+ nil
136
+ end
137
+ end.compact
138
+
139
+ attr_node.value = values.join(" ")
140
+ end
141
+
142
+ def scrub_uri_attribute(attr_node)
143
+ # this block lifted nearly verbatim from HTML5 sanitization
144
+ val_unescaped = CGI.unescapeHTML(attr_node.value).gsub(CONTROL_CHARACTERS, "").downcase
145
+ if val_unescaped =~ /^[a-z0-9][-+.a-z0-9]*:/ && !SafeList::ALLOWED_PROTOCOLS.include?(val_unescaped.split(SafeList::PROTOCOL_SEPARATOR)[0])
146
+ attr_node.remove
147
+ return true
148
+ elsif val_unescaped.split(SafeList::PROTOCOL_SEPARATOR)[0] == "data"
149
+ # permit only allowed data mediatypes
150
+ mediatype = val_unescaped.split(SafeList::PROTOCOL_SEPARATOR)[1]
151
+ mediatype, _ = mediatype.split(";")[0..1] if mediatype
152
+ if mediatype && !SafeList::ALLOWED_URI_DATA_MEDIATYPES.include?(mediatype)
153
+ attr_node.remove
154
+ return true
155
+ end
156
+ end
157
+ false
101
158
  end
102
159
 
103
160
  #
@@ -125,6 +182,46 @@ module Loofah
125
182
  end.force_encoding(encoding)
126
183
  end
127
184
  end
185
+
186
+ def cdata_needs_escaping?(node)
187
+ # Nokogiri's HTML4 parser on JRuby doesn't flag the child of a `style` or `script` tag as cdata, but it acts that way
188
+ node.cdata? || (Nokogiri.jruby? && node.text? && (node.parent.name == "style" || node.parent.name == "script"))
189
+ end
190
+
191
+ def cdata_escape(node)
192
+ escaped_text = escape_tags(node.text)
193
+ if Nokogiri.jruby?
194
+ node.document.create_text_node(escaped_text)
195
+ else
196
+ node.document.create_cdata(escaped_text)
197
+ end
198
+ end
199
+
200
+ TABLE_FOR_ESCAPE_HTML__ = {
201
+ '<' => '&lt;',
202
+ '>' => '&gt;',
203
+ '&' => '&amp;',
204
+ }
205
+
206
+ def escape_tags(string)
207
+ # modified version of CGI.escapeHTML from ruby 3.1
208
+ enc = string.encoding
209
+ unless enc.ascii_compatible?
210
+ if enc.dummy?
211
+ origenc = enc
212
+ enc = Encoding::Converter.asciicompat_encoding(enc)
213
+ string = enc ? string.encode(enc) : string.b
214
+ end
215
+ table = Hash[TABLE_FOR_ESCAPE_HTML__.map {|pair|pair.map {|s|s.encode(enc)}}]
216
+ string = string.gsub(/#{"[<>&]".encode(enc)}/, table)
217
+ string.encode!(origenc) if origenc
218
+ string
219
+ else
220
+ string = string.b
221
+ string.gsub!(/[<>&]/, TABLE_FOR_ESCAPE_HTML__)
222
+ string.force_encoding(enc)
223
+ end
224
+ end
128
225
  end
129
226
  end
130
227
  end
@@ -93,7 +93,11 @@ module Loofah
93
93
  # frag.text(:encode_special_chars => false) # => "<script>alert('EVIL');</script>"
94
94
  #
95
95
  def text(options = {})
96
- result = serialize_root.children.inner_text rescue ""
96
+ result = if serialize_root
97
+ serialize_root.children.reject(&:comment?).map(&:inner_text).join("")
98
+ else
99
+ ""
100
+ end
97
101
  if options[:encode_special_chars] == false
98
102
  result # possibly dangerous if rendered in a browser
99
103
  else
@@ -108,11 +112,11 @@ module Loofah
108
112
  # Returns a plain-text version of the markup contained by the
109
113
  # fragment, with HTML entities encoded.
110
114
  #
111
- # This method is slower than #to_text, but is clever about
112
- # whitespace around block elements.
115
+ # This method is slower than #text, but is clever about
116
+ # whitespace around block elements and line break elements.
113
117
  #
114
- # Loofah.document("<h1>Title</h1><div>Content</div>").to_text
115
- # # => "\nTitle\n\nContent\n"
118
+ # Loofah.document("<h1>Title</h1><div>Content<br>Next line</div>").to_text
119
+ # # => "\nTitle\n\nContent\nNext line\n"
116
120
  #
117
121
  def to_text(options = {})
118
122
  Loofah.remove_extraneous_whitespace self.dup.scrub!(:newline_block_elements).text(options)
@@ -108,6 +108,10 @@ module Loofah
108
108
  return Scrubber::CONTINUE
109
109
  end
110
110
  when Nokogiri::XML::Node::TEXT_NODE, Nokogiri::XML::Node::CDATA_SECTION_NODE
111
+ if HTML5::Scrub.cdata_needs_escaping?(node)
112
+ node.before(HTML5::Scrub.cdata_escape(node))
113
+ return Scrubber::STOP
114
+ end
111
115
  return Scrubber::CONTINUE
112
116
  end
113
117
  Scrubber::STOP
@@ -100,13 +100,9 @@ module Loofah
100
100
 
101
101
  def scrub(node)
102
102
  return CONTINUE if html5lib_sanitize(node) == CONTINUE
103
- if node.children.length == 1 && node.children.first.cdata?
104
- sanitized_text = Loofah.fragment(node.children.first.to_html).scrub!(:strip).to_html
105
- node.before Nokogiri::XML::Text.new(sanitized_text, node.document)
106
- else
107
- node.before node.children
108
- end
103
+ node.before(node.children)
109
104
  node.remove
105
+ return STOP
110
106
  end
111
107
  end
112
108
 
@@ -240,8 +236,13 @@ module Loofah
240
236
  end
241
237
 
242
238
  def scrub(node)
243
- return CONTINUE unless Loofah::Elements::BLOCK_LEVEL.include?(node.name)
244
- node.add_next_sibling Nokogiri::XML::Text.new("\n#{node.content}\n", node.document)
239
+ return CONTINUE unless Loofah::Elements::LINEBREAKERS.include?(node.name)
240
+ replacement = if Loofah::Elements::INLINE_LINE_BREAK.include?(node.name)
241
+ "\n"
242
+ else
243
+ "\n#{node.content}\n"
244
+ end
245
+ node.add_next_sibling Nokogiri::XML::Text.new(replacement, node.document)
245
246
  node.remove
246
247
  end
247
248
  end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+ module Loofah
3
+ # The version of Loofah you are using
4
+ VERSION = "2.19.1"
5
+ end
data/lib/loofah.rb CHANGED
@@ -3,21 +3,22 @@ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) unless $LOAD_PATH.i
3
3
 
4
4
  require "nokogiri"
5
5
 
6
- require "loofah/metahelpers"
7
- require "loofah/elements"
6
+ require_relative "loofah/version"
7
+ require_relative "loofah/metahelpers"
8
+ require_relative "loofah/elements"
8
9
 
9
- require "loofah/html5/safelist"
10
- require "loofah/html5/libxml2_workarounds"
11
- require "loofah/html5/scrub"
10
+ require_relative "loofah/html5/safelist"
11
+ require_relative "loofah/html5/libxml2_workarounds"
12
+ require_relative "loofah/html5/scrub"
12
13
 
13
- require "loofah/scrubber"
14
- require "loofah/scrubbers"
14
+ require_relative "loofah/scrubber"
15
+ require_relative "loofah/scrubbers"
15
16
 
16
- require "loofah/instance_methods"
17
- require "loofah/xml/document"
18
- require "loofah/xml/document_fragment"
19
- require "loofah/html/document"
20
- require "loofah/html/document_fragment"
17
+ require_relative "loofah/instance_methods"
18
+ require_relative "loofah/xml/document"
19
+ require_relative "loofah/xml/document_fragment"
20
+ require_relative "loofah/html/document"
21
+ require_relative "loofah/html/document_fragment"
21
22
 
22
23
  # == Strings and IO Objects as Input
23
24
  #
@@ -28,9 +29,6 @@ require "loofah/html/document_fragment"
28
29
  # quantities of docs.
29
30
  #
30
31
  module Loofah
31
- # The version of Loofah you are using
32
- VERSION = "2.6.0"
33
-
34
32
  class << self
35
33
  # Shortcut for Loofah::HTML::Document.parse
36
34
  # This method accepts the same parameters as Nokogiri::HTML::Document.parse
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: loofah
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.0
4
+ version: 2.19.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Dalessio
@@ -9,22 +9,8 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-06-16 00:00:00.000000000 Z
12
+ date: 2022-12-12 00:00:00.000000000 Z
13
13
  dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: nokogiri
16
- requirement: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - ">="
19
- - !ruby/object:Gem::Version
20
- version: 1.5.9
21
- type: :runtime
22
- prerelease: false
23
- version_requirements: !ruby/object:Gem::Requirement
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- version: 1.5.9
28
14
  - !ruby/object:Gem::Dependency
29
15
  name: crass
30
16
  requirement: !ruby/object:Gem::Requirement
@@ -40,193 +26,123 @@ dependencies:
40
26
  - !ruby/object:Gem::Version
41
27
  version: 1.0.2
42
28
  - !ruby/object:Gem::Dependency
43
- name: rake
44
- requirement: !ruby/object:Gem::Requirement
45
- requirements:
46
- - - "~>"
47
- - !ruby/object:Gem::Version
48
- version: '12.3'
49
- type: :development
50
- prerelease: false
51
- version_requirements: !ruby/object:Gem::Requirement
52
- requirements:
53
- - - "~>"
54
- - !ruby/object:Gem::Version
55
- version: '12.3'
56
- - !ruby/object:Gem::Dependency
57
- name: minitest
29
+ name: nokogiri
58
30
  requirement: !ruby/object:Gem::Requirement
59
31
  requirements:
60
- - - "~>"
32
+ - - ">="
61
33
  - !ruby/object:Gem::Version
62
- version: '2.2'
63
- type: :development
34
+ version: 1.5.9
35
+ type: :runtime
64
36
  prerelease: false
65
37
  version_requirements: !ruby/object:Gem::Requirement
66
38
  requirements:
67
- - - "~>"
39
+ - - ">="
68
40
  - !ruby/object:Gem::Version
69
- version: '2.2'
41
+ version: 1.5.9
70
42
  - !ruby/object:Gem::Dependency
71
- name: rr
43
+ name: hoe-markdown
72
44
  requirement: !ruby/object:Gem::Requirement
73
45
  requirements:
74
46
  - - "~>"
75
47
  - !ruby/object:Gem::Version
76
- version: 1.2.0
48
+ version: '1.3'
77
49
  type: :development
78
50
  prerelease: false
79
51
  version_requirements: !ruby/object:Gem::Requirement
80
52
  requirements:
81
53
  - - "~>"
82
54
  - !ruby/object:Gem::Version
83
- version: 1.2.0
55
+ version: '1.3'
84
56
  - !ruby/object:Gem::Dependency
85
57
  name: json
86
58
  requirement: !ruby/object:Gem::Requirement
87
59
  requirements:
88
60
  - - "~>"
89
61
  - !ruby/object:Gem::Version
90
- version: 2.2.0
62
+ version: '2.2'
91
63
  type: :development
92
64
  prerelease: false
93
65
  version_requirements: !ruby/object:Gem::Requirement
94
66
  requirements:
95
67
  - - "~>"
96
68
  - !ruby/object:Gem::Version
97
- version: 2.2.0
69
+ version: '2.2'
98
70
  - !ruby/object:Gem::Dependency
99
- name: hoe-gemspec
71
+ name: minitest
100
72
  requirement: !ruby/object:Gem::Requirement
101
73
  requirements:
102
74
  - - "~>"
103
75
  - !ruby/object:Gem::Version
104
- version: '1.0'
76
+ version: '5.14'
105
77
  type: :development
106
78
  prerelease: false
107
79
  version_requirements: !ruby/object:Gem::Requirement
108
80
  requirements:
109
81
  - - "~>"
110
82
  - !ruby/object:Gem::Version
111
- version: '1.0'
83
+ version: '5.14'
112
84
  - !ruby/object:Gem::Dependency
113
- name: hoe-debugging
85
+ name: rake
114
86
  requirement: !ruby/object:Gem::Requirement
115
87
  requirements:
116
88
  - - "~>"
117
89
  - !ruby/object:Gem::Version
118
- version: '2.0'
90
+ version: '13.0'
119
91
  type: :development
120
92
  prerelease: false
121
93
  version_requirements: !ruby/object:Gem::Requirement
122
94
  requirements:
123
95
  - - "~>"
124
96
  - !ruby/object:Gem::Version
125
- version: '2.0'
97
+ version: '13.0'
126
98
  - !ruby/object:Gem::Dependency
127
- name: hoe-bundler
99
+ name: rdoc
128
100
  requirement: !ruby/object:Gem::Requirement
129
101
  requirements:
130
- - - "~>"
131
- - !ruby/object:Gem::Version
132
- version: '1.5'
133
- type: :development
134
- prerelease: false
135
- version_requirements: !ruby/object:Gem::Requirement
136
- requirements:
137
- - - "~>"
102
+ - - ">="
138
103
  - !ruby/object:Gem::Version
139
- version: '1.5'
140
- - !ruby/object:Gem::Dependency
141
- name: hoe-git
142
- requirement: !ruby/object:Gem::Requirement
143
- requirements:
144
- - - "~>"
104
+ version: '4.0'
105
+ - - "<"
145
106
  - !ruby/object:Gem::Version
146
- version: '1.6'
107
+ version: '7'
147
108
  type: :development
148
109
  prerelease: false
149
110
  version_requirements: !ruby/object:Gem::Requirement
150
111
  requirements:
151
- - - "~>"
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '4.0'
115
+ - - "<"
152
116
  - !ruby/object:Gem::Version
153
- version: '1.6'
117
+ version: '7'
154
118
  - !ruby/object:Gem::Dependency
155
- name: hoe-markdown
119
+ name: rr
156
120
  requirement: !ruby/object:Gem::Requirement
157
121
  requirements:
158
122
  - - "~>"
159
123
  - !ruby/object:Gem::Version
160
- version: '1.2'
124
+ version: 1.2.0
161
125
  type: :development
162
126
  prerelease: false
163
127
  version_requirements: !ruby/object:Gem::Requirement
164
128
  requirements:
165
129
  - - "~>"
166
130
  - !ruby/object:Gem::Version
167
- version: '1.2'
168
- - !ruby/object:Gem::Dependency
169
- name: concourse
170
- requirement: !ruby/object:Gem::Requirement
171
- requirements:
172
- - - ">="
173
- - !ruby/object:Gem::Version
174
- version: 0.26.0
175
- type: :development
176
- prerelease: false
177
- version_requirements: !ruby/object:Gem::Requirement
178
- requirements:
179
- - - ">="
180
- - !ruby/object:Gem::Version
181
- version: 0.26.0
131
+ version: 1.2.0
182
132
  - !ruby/object:Gem::Dependency
183
133
  name: rubocop
184
- requirement: !ruby/object:Gem::Requirement
185
- requirements:
186
- - - ">="
187
- - !ruby/object:Gem::Version
188
- version: 0.76.0
189
- type: :development
190
- prerelease: false
191
- version_requirements: !ruby/object:Gem::Requirement
192
- requirements:
193
- - - ">="
194
- - !ruby/object:Gem::Version
195
- version: 0.76.0
196
- - !ruby/object:Gem::Dependency
197
- name: rdoc
198
- requirement: !ruby/object:Gem::Requirement
199
- requirements:
200
- - - ">="
201
- - !ruby/object:Gem::Version
202
- version: '4.0'
203
- - - "<"
204
- - !ruby/object:Gem::Version
205
- version: '7'
206
- type: :development
207
- prerelease: false
208
- version_requirements: !ruby/object:Gem::Requirement
209
- requirements:
210
- - - ">="
211
- - !ruby/object:Gem::Version
212
- version: '4.0'
213
- - - "<"
214
- - !ruby/object:Gem::Version
215
- version: '7'
216
- - !ruby/object:Gem::Dependency
217
- name: hoe
218
134
  requirement: !ruby/object:Gem::Requirement
219
135
  requirements:
220
136
  - - "~>"
221
137
  - !ruby/object:Gem::Version
222
- version: '3.22'
138
+ version: '1.1'
223
139
  type: :development
224
140
  prerelease: false
225
141
  version_requirements: !ruby/object:Gem::Requirement
226
142
  requirements:
227
143
  - - "~>"
228
144
  - !ruby/object:Gem::Version
229
- version: '3.22'
145
+ version: '1.1'
230
146
  description: |-
231
147
  Loofah is a general library for manipulating and transforming HTML/XML documents and fragments, built on top of Nokogiri.
232
148
 
@@ -238,24 +154,12 @@ email:
238
154
  - bryan@brynary.com
239
155
  executables: []
240
156
  extensions: []
241
- extra_rdoc_files:
242
- - CHANGELOG.md
243
- - MIT-LICENSE.txt
244
- - Manifest.txt
245
- - README.md
246
- - SECURITY.md
157
+ extra_rdoc_files: []
247
158
  files:
248
159
  - CHANGELOG.md
249
- - Gemfile
250
160
  - MIT-LICENSE.txt
251
- - Manifest.txt
252
161
  - README.md
253
- - Rakefile
254
162
  - SECURITY.md
255
- - benchmark/benchmark.rb
256
- - benchmark/fragment.html
257
- - benchmark/helper.rb
258
- - benchmark/www.slashdot.com.html
259
163
  - lib/loofah.rb
260
164
  - lib/loofah/elements.rb
261
165
  - lib/loofah/helpers.rb
@@ -268,6 +172,7 @@ files:
268
172
  - lib/loofah/metahelpers.rb
269
173
  - lib/loofah/scrubber.rb
270
174
  - lib/loofah/scrubbers.rb
175
+ - lib/loofah/version.rb
271
176
  - lib/loofah/xml/document.rb
272
177
  - lib/loofah/xml/document_fragment.rb
273
178
  homepage: https://github.com/flavorjones/loofah
@@ -275,14 +180,12 @@ licenses:
275
180
  - MIT
276
181
  metadata:
277
182
  homepage_uri: https://github.com/flavorjones/loofah
183
+ source_code_uri: https://github.com/flavorjones/loofah
278
184
  bug_tracker_uri: https://github.com/flavorjones/loofah/issues
185
+ changelog_uri: https://github.com/flavorjones/loofah/blob/main/CHANGELOG.md
279
186
  documentation_uri: https://www.rubydoc.info/gems/loofah/
280
- changelog_uri: https://github.com/flavorjones/loofah/blob/master/CHANGELOG.md
281
- source_code_uri: https://github.com/flavorjones/loofah
282
187
  post_install_message:
283
- rdoc_options:
284
- - "--main"
285
- - README.md
188
+ rdoc_options: []
286
189
  require_paths:
287
190
  - lib
288
191
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -296,7 +199,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
296
199
  - !ruby/object:Gem::Version
297
200
  version: '0'
298
201
  requirements: []
299
- rubygems_version: 3.1.2
202
+ rubygems_version: 3.3.7
300
203
  signing_key:
301
204
  specification_version: 4
302
205
  summary: Loofah is a general library for manipulating and transforming HTML/XML documents