html2text 0.4.0 → 0.5.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -2
- data/README.md +1 -1
- data/lib/html2text/version.rb +1 -1
- data/lib/html2text.rb +29 -39
- metadata +4 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1a1e6fcee8973815b391ca28bd156a878e36594e0bfbece01f7ff8c67f6cad6f
|
|
4
|
+
data.tar.gz: f515c6edb112deeae87f59b717aa4a2aed5d37b4b42db151fc49359f2b98d0b9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3972abc5f287146a5f43969fe3a37b83333559618b198ccc6ca3b105178c7cb37a03c9b44317428c8323c9b86e7e7a22a78276d9ddb7cccaab1819105e469a18
|
|
7
|
+
data.tar.gz: dcc2f39ebc4d772b47762cacb5de22ab16f386fbc4952c7fcf72ae66938fffcacad1fad7062714fdebc21a6b74c802224d02b796c099d2a00d1b3d13729f5d6d
|
data/CHANGELOG.md
CHANGED
|
@@ -4,9 +4,19 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
-
## [Unreleased]
|
|
7
|
+
## [Unreleased](https://github.com/soundasleep/html2text_ruby/compare/v0.5.0...master)
|
|
8
8
|
|
|
9
|
-
## [0.4.0
|
|
9
|
+
## [0.5.0](https://github.com/soundasleep/html2text_ruby/compare/v0.4.0...v0.5.0) - 2026-07-08
|
|
10
|
+
### Added
|
|
11
|
+
- Add a `wrap_links:` option to `Html2Text.convert` and `Html2Text.new` (default `true`); when `false`, hyperlinks render as `text: href` instead of markdown-style `[text](href)`. Only affects `<a href>` links — images and named anchors keep their `[bracketed]` format ([#40](https://github.com/soundasleep/html2text_ruby/pull/40))
|
|
12
|
+
- Specs covering subclass overrides of `prefix_whitespace`, `suffix_whitespace`, `iterate_over`, `wrap_link` and `image_text`, plus unit specs for `fix_newlines` and `replace_entities` ([#41](https://github.com/soundasleep/html2text_ruby/pull/41))
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- Require Ruby 3.3+, since all earlier Rubies are EOL; CI now tests Ruby 3.3, 3.4 and 4.0 ([#42](https://github.com/soundasleep/html2text_ruby/pull/42))
|
|
16
|
+
- Reduce object allocations in `iterate_over` for ~1.6x faster conversion of large documents ([#41](https://github.com/soundasleep/html2text_ruby/pull/41))
|
|
17
|
+
- Update development dependencies (rubocop 1.88, nokogiri 1.19 in the lockfile), removing the transitive `rexml` dependency ([#42](https://github.com/soundasleep/html2text_ruby/pull/42))
|
|
18
|
+
|
|
19
|
+
## [0.4.0](https://github.com/soundasleep/html2text_ruby/compare/0.3.1...v0.4.0) - 2024-06-08
|
|
10
20
|
### Added
|
|
11
21
|
- Switch from Travis to Github Actions for Build and Test
|
|
12
22
|
- Add rubocop for linting and cleanup existing violations ([#36](https://github.com/soundasleep/html2text_ruby/pull/36))
|
data/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
html2text  [](https://
|
|
1
|
+
html2text  [](https://badge.fury.io/rb/html2text)
|
|
2
2
|
---
|
|
3
3
|
|
|
4
4
|
`html2text` is a very simple gem that uses DOM methods to convert HTML into a format similar to what would be
|
data/lib/html2text/version.rb
CHANGED
data/lib/html2text.rb
CHANGED
|
@@ -5,11 +5,12 @@ require 'nokogiri'
|
|
|
5
5
|
class Html2Text
|
|
6
6
|
attr_reader :doc
|
|
7
7
|
|
|
8
|
-
def initialize(doc)
|
|
8
|
+
def initialize(doc, wrap_links: true)
|
|
9
9
|
@doc = doc
|
|
10
|
+
@wrap_links = wrap_links
|
|
10
11
|
end
|
|
11
12
|
|
|
12
|
-
def self.convert(html)
|
|
13
|
+
def self.convert(html, wrap_links: true)
|
|
13
14
|
html = html.to_s
|
|
14
15
|
|
|
15
16
|
if office_document?(html)
|
|
@@ -27,7 +28,7 @@ class Html2Text
|
|
|
27
28
|
html = fix_newlines(replace_entities(html))
|
|
28
29
|
doc = Nokogiri::HTML(html)
|
|
29
30
|
|
|
30
|
-
new(doc).convert
|
|
31
|
+
new(doc, wrap_links: wrap_links).convert
|
|
31
32
|
end
|
|
32
33
|
|
|
33
34
|
def self.fix_newlines(text)
|
|
@@ -50,6 +51,7 @@ class Html2Text
|
|
|
50
51
|
end
|
|
51
52
|
|
|
52
53
|
DO_NOT_TOUCH_WHITESPACE = '<do-not-touch-whitespace>'
|
|
54
|
+
IGNORED_TAGS = Set.new(%w[style head title meta script]).freeze
|
|
53
55
|
|
|
54
56
|
def remove_leading_and_trailing_whitespace(text)
|
|
55
57
|
# ignore any <pre> blocks, which we don't want to interact with
|
|
@@ -74,14 +76,14 @@ class Html2Text
|
|
|
74
76
|
private
|
|
75
77
|
|
|
76
78
|
def remove_unnecessary_empty_lines(text)
|
|
77
|
-
text.gsub(/\n
|
|
79
|
+
text.gsub(/\n{3,}/, "\n\n")
|
|
78
80
|
end
|
|
79
81
|
|
|
80
82
|
def trimmed_whitespace(text)
|
|
81
83
|
# Replace whitespace characters with a space (equivalent to \s)
|
|
82
84
|
# and force any text encoding into UTF-8
|
|
83
85
|
if text.valid_encoding?
|
|
84
|
-
text.gsub(/[\t\n\f\r ]
|
|
86
|
+
text.gsub(/[\t\n\f\r ]+/, ' ')
|
|
85
87
|
else
|
|
86
88
|
text.force_encoding('WINDOWS-1252')
|
|
87
89
|
trimmed_whitespace(text.encode('UTF-16be', invalid: :replace, replace: '?').encode('UTF-8'))
|
|
@@ -89,45 +91,36 @@ class Html2Text
|
|
|
89
91
|
end
|
|
90
92
|
|
|
91
93
|
def iterate_over(node)
|
|
92
|
-
return "\n" if node.name.downcase == 'br' && next_node_is_text?(node)
|
|
93
|
-
|
|
94
94
|
return trimmed_whitespace(node.text) if node.text?
|
|
95
95
|
|
|
96
|
-
|
|
96
|
+
name = node.name&.downcase
|
|
97
97
|
|
|
98
|
-
return
|
|
98
|
+
return '' if name.nil? || IGNORED_TAGS.include?(name)
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
return "\n" if name == 'br' && next_node_is_text?(node)
|
|
101
101
|
|
|
102
|
-
|
|
103
|
-
output += node.children.map do |child|
|
|
104
|
-
iterate_over(child) unless child.name.nil?
|
|
105
|
-
end
|
|
106
|
-
output << suffix_whitespace(node)
|
|
102
|
+
return "\n#{DO_NOT_TOUCH_WHITESPACE}#{node.text}#{DO_NOT_TOUCH_WHITESPACE}" if name == 'pre'
|
|
107
103
|
|
|
108
|
-
|
|
104
|
+
return image_text(node) if name == 'img'
|
|
109
105
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
output = image_text(node)
|
|
115
|
-
end
|
|
106
|
+
output = +''
|
|
107
|
+
output << (prefix_whitespace(node) || '')
|
|
108
|
+
node.children.each do |child|
|
|
109
|
+
output << iterate_over(child)
|
|
116
110
|
end
|
|
111
|
+
output << (suffix_whitespace(node) || '')
|
|
112
|
+
|
|
113
|
+
output = wrap_link(node, output) if name == 'a'
|
|
117
114
|
|
|
118
115
|
output
|
|
119
116
|
end
|
|
120
117
|
|
|
121
|
-
# rubocop:disable Lint/DuplicateBranch
|
|
122
118
|
def prefix_whitespace(node)
|
|
123
119
|
case node.name.downcase
|
|
124
120
|
when 'hr'
|
|
125
121
|
"\n---------------------------------------------------------------\n"
|
|
126
122
|
|
|
127
|
-
when 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ol', 'ul'
|
|
128
|
-
"\n\n"
|
|
129
|
-
|
|
130
|
-
when 'p'
|
|
123
|
+
when 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ol', 'ul', 'p'
|
|
131
124
|
"\n\n"
|
|
132
125
|
|
|
133
126
|
when 'tr'
|
|
@@ -147,20 +140,15 @@ class Html2Text
|
|
|
147
140
|
'- '
|
|
148
141
|
end
|
|
149
142
|
end
|
|
150
|
-
# rubocop:enable Lint/DuplicateBranch
|
|
151
143
|
|
|
152
|
-
# rubocop:disable Lint/DuplicateBranch
|
|
153
144
|
def suffix_whitespace(node)
|
|
154
145
|
case node.name.downcase
|
|
155
|
-
when 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'
|
|
156
|
-
# add another line
|
|
157
|
-
"\n\n"
|
|
158
|
-
|
|
159
|
-
when 'p'
|
|
146
|
+
when 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p'
|
|
160
147
|
"\n\n"
|
|
161
148
|
|
|
162
149
|
when 'br'
|
|
163
|
-
|
|
150
|
+
next_name = next_node_name(node)
|
|
151
|
+
"\n" if !next_name.nil? && next_name != 'div'
|
|
164
152
|
|
|
165
153
|
when 'li'
|
|
166
154
|
"\n"
|
|
@@ -168,14 +156,14 @@ class Html2Text
|
|
|
168
156
|
when 'div'
|
|
169
157
|
if next_node_is_text?(node)
|
|
170
158
|
"\n"
|
|
171
|
-
|
|
172
|
-
|
|
159
|
+
else
|
|
160
|
+
next_name = next_node_name(node)
|
|
161
|
+
"\n" if !next_name.nil? && next_name != 'div'
|
|
173
162
|
end
|
|
174
163
|
end
|
|
175
164
|
end
|
|
176
|
-
# rubocop:enable Lint/DuplicateBranch
|
|
177
165
|
|
|
178
|
-
# links are returned in [text](link) format
|
|
166
|
+
# links are returned in [text](link) format, or "text: link" with wrap_links: false
|
|
179
167
|
def wrap_link(node, output)
|
|
180
168
|
href = node.attribute('href')
|
|
181
169
|
name = node.attribute('name')
|
|
@@ -202,6 +190,8 @@ class Html2Text
|
|
|
202
190
|
href != "http://#{output}" && href != "https://#{output}"
|
|
203
191
|
output = if output.empty?
|
|
204
192
|
href
|
|
193
|
+
elsif !@wrap_links
|
|
194
|
+
"#{output}: #{href}"
|
|
205
195
|
else
|
|
206
196
|
"[#{output}](#{href})"
|
|
207
197
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: html2text
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jevon Wright
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: nokogiri
|
|
@@ -159,7 +158,6 @@ licenses:
|
|
|
159
158
|
- MIT
|
|
160
159
|
metadata:
|
|
161
160
|
rubygems_mfa_required: 'true'
|
|
162
|
-
post_install_message:
|
|
163
161
|
rdoc_options: []
|
|
164
162
|
require_paths:
|
|
165
163
|
- lib
|
|
@@ -167,15 +165,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
167
165
|
requirements:
|
|
168
166
|
- - ">="
|
|
169
167
|
- !ruby/object:Gem::Version
|
|
170
|
-
version: '3.
|
|
168
|
+
version: '3.3'
|
|
171
169
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
172
170
|
requirements:
|
|
173
171
|
- - ">="
|
|
174
172
|
- !ruby/object:Gem::Version
|
|
175
173
|
version: '0'
|
|
176
174
|
requirements: []
|
|
177
|
-
rubygems_version:
|
|
178
|
-
signing_key:
|
|
175
|
+
rubygems_version: 4.0.10
|
|
179
176
|
specification_version: 4
|
|
180
177
|
summary: Convert HTML into plain text.
|
|
181
178
|
test_files: []
|