html-renderer 0.0.4 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ef89dd4c00345deca8c54a7ac62823dd8a506a0f941186cdd6d82ebd51ae7d47
4
- data.tar.gz: 4a2fd1e8b670ff87fd63b7e94a7e50af7bd66e73f94bb48b197b9f8374b8d196
3
+ metadata.gz: 663966745c8218ad48bbe7d05b18a2c3b28e744de5f29e1749206e636957c2e6
4
+ data.tar.gz: fde2480e07086d500cf4cd47fe15b3f5093d704bac2a0eca6fee2e1a47ddb77b
5
5
  SHA512:
6
- metadata.gz: b0dd0122febdc3018b1d2d1f38cd6fc19c23e2495989b6b8ccca1f5e7cf096d159a38aa85fdb600f48767d75827ce6f025282a9b0a206e74aa93c60e5c02bedc
7
- data.tar.gz: 8164fb8d54a3f2895bb288d32eb9e03716ff8bd3a40b68382385c499cae363c1d0ff685f77abeac96a83c0b313edfd9c9c3b013173d878ac46b155b28b84466c
6
+ metadata.gz: f260e527a4ea41de4c6d2a9bbef83054925c53a5d9243824fbb94f452a44ebd4a65df7df488299f38c36244a64e44654f3c64b8b2718f2461bcc45e5e3fa446e
7
+ data.tar.gz: e70eea4c85614825128afebd9d1cf77d9ac39d9676cc45103ee3e2bae0054f4ed261009848cda2c930a1296569225b21c2af8766fa609999c4ccd92ed2676061
data/.gemspec CHANGED
@@ -13,10 +13,9 @@ Gem::Specification.new do |s|
13
13
  s.authors = ["epitron"]
14
14
 
15
15
  s.files = `git ls`.lines.map(&:strip)
16
- s.executables = ['html2ansi']
17
16
  s.extra_rdoc_files = ["README.md", "LICENSE"]
18
-
19
- s.add_dependency "oga", "~> 2"
17
+
18
+ s.add_dependency "oga", ">= 2.0"
20
19
  s.add_dependency "terminal-table", "~> 1.8"
21
- # s.add_development "ansi", "~> 1"
20
+ s.add_dependency "term-ansicolor", "~> 1.7"
22
21
  end
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ /pkg/
data/README.md CHANGED
@@ -2,11 +2,29 @@
2
2
 
3
3
  ## Overview
4
4
 
5
- Allows you to subclass `HTMLRenderer::Base`, add some methods, and then parse HTML to generate custom output.
5
+ An extensible HTML renderer.
6
6
 
7
- (Uses a similar API to the [RedCarpet](https://github.com/vmg/redcarpet) gem.)
7
+ Comes with two built-in renderers:
8
+ * `HTMLRenderer::ANSI` (outputs colored text to the termnial)
9
+ * `HTMLRenderer::Text` (outputs plain text)
8
10
 
9
- ## Examples
11
+ ## Usage
10
12
 
11
- * [HTML to Plain Text Renderer](https://github.com/epitron/html-renderer/blob/master/examples/plain_text_renderer.rb)
12
- * [HTML to ANSI Renderer](https://github.com/epitron/html-renderer/blob/master/examples/ansi_renderer.rb)
13
+ Render to ANSI:
14
+ ```
15
+ ansi_text = HTMLRenderer::ANSI.render("<b>hello html</b>")
16
+ ansi_text = HTMLRenderer::ANSI.render(open("file.html"))
17
+ ```
18
+
19
+ Render to plain text:
20
+ ```
21
+ plain_text = HTMLRenderer::Text.render(open("file.html"))
22
+ ```
23
+
24
+ ## Extending it
25
+
26
+ The API design uses the same philosophy as [RedCarpet](https://github.com/vmg/redcarpet).
27
+
28
+ To create a new renderer, subclass `HTMLRenderer::Base`, then add a method to handle each type of element. Whatever the method returns is output by the renderer.
29
+
30
+ Example renderer: [HTMLRenderer::ANSI](https://github.com/epitron/html-renderer/blob/master/lib/html-renderer/ansi.rb)
data/Rakefile CHANGED
@@ -1,14 +1,13 @@
1
- pkgname = "html-renderer"
2
- gem_version = File.read("VERSION").strip
1
+ gem = eval(File.read '.gemspec')
3
2
 
4
- gemfile = "#{pkgname}-#{gem_version}.gem"
3
+ gemfile = "#{gem.name}-#{gem.version}.gem"
5
4
 
6
5
  task :build do
7
6
  system "gem build .gemspec"
8
7
  system "mkdir pkg/" unless File.directory? "pkg"
9
8
  system "mv #{gemfile} pkg/"
10
9
  end
11
-
10
+
12
11
  task :release => :build do
13
12
  system "gem push pkg/#{gemfile}"
14
13
  end
@@ -18,3 +17,9 @@ task :gem => :build
18
17
  task :install => :build do
19
18
  system "gem install pkg/#{gemfile}"
20
19
  end
20
+
21
+ task :test do
22
+ Dir.chdir "test"
23
+ $: << "../lib"
24
+ load "test.rb"
25
+ end
data/TODO.md ADDED
@@ -0,0 +1,14 @@
1
+ # TODO list
2
+
3
+ ## Base class
4
+
5
+ ! add HTMLRenderer.reflow_paragraph
6
+ * #render takes options (and passes them to subclasses)
7
+ * :debug option (hide parse errors unless 'true')
8
+
9
+ ## ANSI renderer
10
+
11
+ * use HTMLRenderer.reflow_paragraph
12
+ * :wrap option (with optional terminal width)
13
+ * Better table renderer (with line-drawing)
14
+ * Follow `<table>` style attributes when drawing tables (eg: borders)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.4
1
+ 0.1.4
@@ -1,16 +1,24 @@
1
1
  require 'html-renderer'
2
2
  require 'ansi/mixin'
3
3
  require 'terminal-table'
4
- require 'coderay'
5
4
 
6
- class String
7
- include ANSI::Mixin
5
+ ###########################################################################
8
6
 
9
- def grey; self.black.bold; end
7
+ module ANSI::Mixin
8
+ def grey; ANSI::Code.bold { ANSI::Code.black { to_s } }; end
10
9
  end
11
10
 
11
+ module HTMLRenderer::ANSIStrings
12
+ refine String do
13
+ include ANSI::Mixin
14
+ end
15
+ end
16
+
17
+ ###########################################################################
18
+
19
+ class HTMLRenderer::ANSI < HTMLRenderer::Base
12
20
 
13
- class ANSIRenderer < HTMLRenderer::Base
21
+ using HTMLRenderer::ANSIStrings
14
22
 
15
23
  private
16
24
 
@@ -32,6 +40,9 @@ private
32
40
  s&.downcase&.scan(/\w+/)&.join
33
41
  end
34
42
 
43
+ def subscript(s)
44
+ "[#{s}]"
45
+ end
35
46
 
36
47
  public
37
48
 
@@ -78,13 +89,7 @@ public
78
89
  end
79
90
 
80
91
  def block_code(code, language)
81
- language ||= :ruby
82
-
83
- language = language[1..-1] if language[0] == "." # strip leading "."
84
- language = :cpp if language == "C++"
85
-
86
- require 'coderay'
87
- "#{indent CodeRay.scan(code, language).term, 4}\n"
92
+ code.bold.cyan + "\n"
88
93
  end
89
94
 
90
95
  def block_quote(text)
@@ -174,7 +179,8 @@ public
174
179
 
175
180
  end
176
181
 
182
+ ###########################################################################
177
183
 
178
184
  if __FILE__ == $0
179
- puts ANSIRenderer.render(open(ARGV.first || "test.html"))
185
+ puts HTMLRenderer::ANSI.render(open(ARGV.first || "test.html"))
180
186
  end
@@ -1,30 +1,25 @@
1
1
  ######################################################################################
2
2
  require 'oga'
3
3
  ######################################################################################
4
- #
5
- # TODOs:
6
- # - Streaming output (yield every paragraph/div/header)
7
- # - Embed into 'c' tool (for rendering raw HTML blocks)
8
- #
9
- ######################################################################################
10
-
11
- class String
12
4
 
13
- def tighten
14
- gsub(/\s+/, ' ').strip
15
- end
5
+ module HTMLRenderer
16
6
 
17
- def blank?; !!self[/[^\s]/]; end
7
+ module STDLIBRefinements
8
+ refine String do
9
+ def tighten
10
+ gsub(/\s+/, ' ').strip
11
+ end
18
12
 
19
- end
13
+ def blank?; !!self[/[^\s]/]; end
14
+ end
20
15
 
21
- class NilClass
22
- def blank?; true; end
23
- end
16
+ refine NilClass do
17
+ def blank?; true; end
18
+ end
19
+ end
24
20
 
25
- ######################################################################################
21
+ using STDLIBRefinements
26
22
 
27
- module HTMLRenderer
28
23
 
29
24
  class State
30
25
  attr_accessor :list_order
@@ -65,14 +60,16 @@ private
65
60
  content.blank? ? normal_text(content) : nil
66
61
 
67
62
  when Oga::XML::Element
68
- case node.name
63
+ case node.name.downcase
69
64
  when "a"
70
65
  url = node["href"]
71
66
  title = node["title"]
72
67
  name = node["name"]
73
68
  content = render_children(node, state)
74
69
 
75
- if name and not url
70
+ if title.blank? and url.blank? and name.blank?
71
+ content
72
+ elsif name and not url
76
73
  anchor(name, title, content)
77
74
  else
78
75
  link(url, title, content)
@@ -151,23 +148,25 @@ private
151
148
  table(header, rows)
152
149
 
153
150
  when "html", "body", "nav", "span", "form", "label", "input", "button", "section", "fieldset",
154
- "menu", "article", "header", "time", "aside", "footer", "nobr", "wbr",
151
+ "pre", "menu", "article", "header", "time", "aside", "footer", "nobr", "wbr",
155
152
  "table", "tr", "td", "th", "tt", "thead", "tbody", "noscript", "select",
156
153
  "address", "center", "small"
157
154
  render_children(node, state)
158
155
 
159
156
  when "head", "script", "link", "style"
160
- # skip it
161
-
157
+ #
158
+ # don't render anything
159
+ #
162
160
  else
163
161
  # raise "Unrecognized HTML tag: #{node.name} -> #{node.inspect}"
164
- $stderr.puts "Unrecognized HTML tag: #{node.name} -> #{node.inspect}"
162
+ $stderr.puts "Unrecognized HTML tag: #{node.name} -> #{node.inspect}" if $VERBOSE
165
163
  render_children(node, state)
166
164
  end
167
165
 
168
- when Oga::XML::Comment
169
- # skip it
170
-
166
+ when Oga::XML::Comment, Oga::XML::Cdata, Oga::XML::ProcessingInstruction
167
+ #
168
+ # i'm not sure why you'd care about these, but here's a place to, if you do
169
+ #
171
170
  else
172
171
  raise "Unhandled Oga node type: #{node.class}"
173
172
  end
@@ -0,0 +1,9 @@
1
+ require 'html-renderer'
2
+
3
+ class HTMLRenderer::DebugRenderer < HTMLRenderer::Base
4
+
5
+ def method_missing(meth, *args)
6
+ "#{meth}(#{args})"
7
+ end
8
+
9
+ end
@@ -102,4 +102,4 @@ html = File.read(file)
102
102
  r = HTMLParser.new(html)
103
103
  r.each_tag{|t| p t}
104
104
 
105
- # puts r.as_tree
105
+ # puts r.as_tree
@@ -1,9 +1,10 @@
1
1
  require 'html-renderer'
2
2
 
3
3
  #
4
- # Everything-stripping renderer.
4
+ # Strips out everything but the plain text.
5
5
  #
6
- class PlainTextRenderer < HTMLRenderer::Base
6
+ class HTMLRenderer::Text < HTMLRenderer::Base
7
+
7
8
  # Methods where the first argument is the text content
8
9
  [
9
10
  # block-level calls
@@ -65,8 +66,3 @@ class PlainTextRenderer < HTMLRenderer::Base
65
66
  content + "\t"
66
67
  end
67
68
  end
68
-
69
-
70
- if __FILE__ == $0
71
- puts PlainTextRenderer.render(open("test.html"))
72
- end
data/lib/html-renderer.rb CHANGED
@@ -1 +1,6 @@
1
1
  require 'html-renderer/base'
2
+
3
+ module HTMLRenderer
4
+ autoload :ANSI, 'html-renderer/ansi'
5
+ autoload :Text, 'html-renderer/text'
6
+ end
File without changes
data/test/test.rb ADDED
@@ -0,0 +1,15 @@
1
+ require 'html-renderer'
2
+ require 'html-renderer/debug'
3
+
4
+ [
5
+ HTMLRenderer::ANSI,
6
+ HTMLRenderer::Text,
7
+ HTMLRenderer::DebugRenderer,
8
+ ].each do |renderer|
9
+ puts
10
+ puts "=== #{renderer} =============================="
11
+ puts
12
+ puts renderer.render(open("test.html"))
13
+ puts
14
+ puts
15
+ end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: html-renderer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - epitron
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-05 00:00:00.000000000 Z
11
+ date: 2021-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oga
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '2'
19
+ version: '2.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '2'
26
+ version: '2.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: terminal-table
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,35 +38,50 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: term-ansicolor
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.7'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.7'
41
55
  description: Easily implement an HTML renderer by creating a subclass and adding some
42
56
  methods, similar to RedCarpet. (Examples are included for rendering HTML to ANSI
43
57
  and plain text.)
44
58
  email: chris@ill-logic.com
45
- executables:
46
- - html2ansi
59
+ executables: []
47
60
  extensions: []
48
61
  extra_rdoc_files:
49
62
  - README.md
50
63
  - LICENSE
51
64
  files:
52
65
  - ".gemspec"
66
+ - ".gitignore"
53
67
  - LICENSE
54
68
  - README.md
55
69
  - Rakefile
70
+ - TODO.md
56
71
  - VERSION
57
- - bin/html2ansi
58
- - examples/ansi_renderer.rb
59
- - examples/debug_renderer.rb
60
- - examples/plain_text_renderer.rb
61
- - examples/test.html
62
72
  - lib/html-renderer.rb
73
+ - lib/html-renderer/ansi.rb
63
74
  - lib/html-renderer/base.rb
75
+ - lib/html-renderer/debug.rb
64
76
  - lib/html-renderer/html_parser.rb
77
+ - lib/html-renderer/text.rb
78
+ - test/test.html
79
+ - test/test.rb
65
80
  homepage: http://github.com/epitron/html-renderer/
66
81
  licenses:
67
82
  - WTFPL
68
83
  metadata: {}
69
- post_install_message:
84
+ post_install_message:
70
85
  rdoc_options: []
71
86
  require_paths:
72
87
  - lib
@@ -81,9 +96,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
81
96
  - !ruby/object:Gem::Version
82
97
  version: '0'
83
98
  requirements: []
84
- rubyforge_project:
85
- rubygems_version: 2.7.7
86
- signing_key:
99
+ rubygems_version: 3.2.21
100
+ signing_key:
87
101
  specification_version: 4
88
102
  summary: HTML Renderer
89
103
  test_files: []
data/bin/html2ansi DELETED
@@ -1,248 +0,0 @@
1
- #!/usr/bin/env ruby
2
- #######################################################################################
3
- require 'html-renderer'
4
- require 'terminal-table'
5
- require 'term/ansicolor'
6
- require 'coderay'
7
- #######################################################################################
8
-
9
- class String
10
- # include ANSI::Mixin
11
- include Term::ANSIColor
12
-
13
- def grey; self.black.bold; end
14
- end
15
-
16
- #######################################################################################
17
-
18
- def lesspipe(*args)
19
- if args.any? and args.last.is_a?(Hash)
20
- options = args.pop
21
- else
22
- options = {}
23
- end
24
-
25
- output = args.first if args.any?
26
-
27
- params = []
28
- params << "-R" unless options[:color] == false
29
- params << "-S" unless options[:wrap] == true
30
- params << "-F" unless options[:always] == true
31
- if options[:tail] == true
32
- params << "+\\>"
33
- $stderr.puts "Seeking to end of stream..."
34
- end
35
- params << "-X"
36
-
37
- IO.popen("less #{params * ' '}", "w") do |less|
38
- if output
39
- less.puts output
40
- else
41
- yield less
42
- end
43
- end
44
- rescue Errno::EPIPE, Interrupt
45
- # less just quit -- eat the exception.
46
- end
47
-
48
- #######################################################################################
49
-
50
- class ANSIRenderer < HTMLRenderer::Base
51
-
52
- private
53
-
54
- def indented?(text)
55
- indent_sizes = text.lines.map{ |line| if line =~ /^(\s+)/ then $1 else '' end }.map(&:size)
56
- indent_sizes.all? {|dent| dent > 0 }
57
- end
58
-
59
- def unwrap(text)
60
- return text unless indented? text
61
- text.lines.to_a.map(&:strip).join ' '
62
- end
63
-
64
- def indent(text,amount=2)
65
- text.lines.map{|line| " "*amount + line }.join
66
- end
67
-
68
- def smash(s)
69
- s&.downcase&.scan(/\w+/)&.join
70
- end
71
-
72
- def subscript(s)
73
- "[#{s}]"
74
- end
75
-
76
- public
77
-
78
- def normal_text(text)
79
- text
80
- end
81
-
82
- def underline(content)
83
- content.magenta.bold
84
- end
85
-
86
- def superscript(content)
87
- "^(#{content})"
88
- end
89
-
90
- def link(link, title, content)
91
- unless content&.[] /^Back /
92
- str = ""
93
- # str += "<15>#{content}</15>" if content
94
- str += content.white.bold if content
95
- if smash(link) != smash(content)
96
- # str += " <8>(</8><11>#{link}</11><8>)</8>"
97
- str += " #{"(".grey}#{link&.cyan&.bold}#{")".grey}"
98
- end
99
-
100
- str
101
- end
102
- end
103
-
104
- def anchor(name, title=nil, content=nil)
105
- result = "Anchor: ##{name}"
106
- result << " (#{title})" if title
107
- result << "\n"
108
- result << "#{content}\n" if content
109
- result
110
- end
111
-
112
- def image(link, title, content)
113
- link(link, nil, title)
114
- end
115
-
116
- def italic(text)
117
- text.yellow.bold
118
- end
119
-
120
- def block_code(code, language)
121
- language ||= :ruby
122
-
123
- language = language[1..-1] if language[0] == "." # strip leading "."
124
- language = :cpp if language == "C++"
125
-
126
- require 'coderay'
127
- "#{indent CodeRay.scan(code, language).term, 4}\n"
128
- end
129
-
130
- def block_quote(text)
131
- indent paragraph(text)
132
- end
133
-
134
- def codespan(code)
135
- code.cyan
136
- end
137
-
138
- def header(title, level, anchor=nil)
139
- bar = ("-"*(title.size+4)).grey
140
-
141
- title = case level
142
- when 1 then title.bold.yellow
143
- when 2 then title.bold.cyan
144
- when 3 then title.bold.blue
145
- else title.magenta
146
- end
147
-
148
- "#{bar}\n #{title}\n#{bar}\n\n"
149
- end
150
-
151
- def double_emphasis(text)
152
- text.bold.green
153
- end
154
-
155
- def emphasis(text)
156
- text.green
157
- end
158
-
159
- def linebreak
160
- "\n"
161
- end
162
-
163
- def paragraph(text)
164
- div(text) + "\n"
165
- end
166
-
167
- def div(text)
168
- "#{indented?(text) ? text : unwrap(text)}\n"
169
- end
170
-
171
- def list(content, list_type)
172
- case list_type
173
- when :ordered
174
- @counter = 0
175
- "#{content}\n"
176
- when :unordered
177
- "#{content}\n"
178
- end
179
- end
180
-
181
- def list_item(content, list_type)
182
- case list_type
183
- when :ordered
184
- @counter ||= 0
185
- @counter += 1
186
- # " <8>#{@counter}.</8> #{content.strip}\n".colorize
187
- " #{@counter.to_s.grey}. #{content.strip}\n"
188
- when :unordered
189
- # " <8>*</8> #{content.strip}\n".colorize
190
- " #{"*".grey} #{content.strip}\n"
191
- end
192
- end
193
-
194
- def definition_list(defs)
195
- defs.each do |dt, dd|
196
- puts "<15>#{dt}<7>:".colorize
197
- puts " #{dd}"
198
- puts
199
- end
200
- end
201
-
202
- def table(header, rows)
203
- if header
204
- table = Terminal::Table.new(headings: header, rows: rows)
205
- else
206
- table = Terminal::Table.new(rows: rows)
207
- end
208
- "#{table}\n\n"
209
- end
210
-
211
- def separator
212
- "_____________________________\n\n"
213
- end
214
-
215
- end
216
-
217
- #######################################################################################
218
-
219
- def render(stream, paged=false)
220
- output = ANSIRenderer.render(stream)
221
- if paged
222
- lesspipe { |less| less.puts output }
223
- else
224
- puts output
225
- end
226
- end
227
-
228
- #######################################################################################
229
-
230
- opts, args = ARGV.partition { |arg| arg[/^--?\w/] }
231
-
232
- if opts.include?("-h") or opts.include?("--help")
233
- puts "usage:"
234
- puts " html2ansi [options] <file.html>"
235
- puts " or"
236
- puts " curl http://host/path.html | html2ansi [options]"
237
- puts
238
- puts "options:"
239
- puts " -p Paged (redirect output to less)"
240
- puts
241
- else
242
- paged = opts.include?("-p") or opts.include?("--paged")
243
- if args.empty?
244
- render($stdin, paged)
245
- else
246
- args.each { |arg| render(open(arg), paged) }
247
- end
248
- end
@@ -1,14 +0,0 @@
1
- require 'html-renderer'
2
-
3
- class DebugRenderer < HTMLRenderer::Base
4
-
5
- def method_missing(meth, *args)
6
- "#{meth}(#{args})"
7
- end
8
-
9
- end
10
-
11
-
12
- if __FILE__ == $0
13
- puts DebugRenderer.render(open("test.html"))
14
- end