htmldoc 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.txt CHANGED
@@ -1,3 +1,27 @@
1
+ 2007-03-07 ronaldo <ronaldo@reflectivesurface.com>
2
+
3
+ * Changed the instance variable result to a hash of information
4
+ about the generation, including bytes and pages generated, and the
5
+ raw result of the program's execution
6
+
7
+ * Added an errors instance variable to register all the errors
8
+ generated in the course of the program's execution
9
+
10
+ * Refactored generate
11
+
12
+ * Changed generate so it now raises an exception if the program
13
+ path cannot be found
14
+
15
+ * Improved the tests
16
+
17
+ * Improved the documentation
18
+
19
+ 2007-03-06 ronaldo <ronaldo@reflectivesurface.com>
20
+
21
+ * Fixed spelling and grammatical error in README.txt
22
+
23
+ * Fixed a couple of naming issues in Rakefile
24
+
1
25
  2007-03-05 ronaldo <ronaldo@reflectivesurface.com>
2
26
 
3
27
  * Initial release
data/History.txt CHANGED
@@ -1,2 +1,8 @@
1
+ 0.2.0
2
+ * Improved the way results are reported
3
+ * Added information about errors generated in the course of execution
4
+ * Refactored a couple of internal methods
5
+ * Improved the tests and documentation
6
+
1
7
  0.1.0
2
8
  * Initial release
data/README.txt CHANGED
@@ -5,11 +5,11 @@ that converts HTML input files into formatted HTML, PDF or PostScript
5
5
  output.
6
6
 
7
7
  Home:: http://rubyforge.org/projects/pdf-htmldoc/
8
- HTMLDOC Home: http://www.htmldoc.org/
8
+ HTMLDOC Home:: http://www.htmldoc.org/
9
9
  Copyright:: 2007, Ronaldo M. Ferraz
10
10
 
11
11
  This is a preview release, which means it had only limited testing. As
12
- far as it's know, it will work on all platforms in which HTMLDOC is
12
+ far as I know, it will work on all platforms in which HTMLDOC is
13
13
  available. Comments, suggestions, and further tests are welcome.
14
14
 
15
15
  == LICENSE NOTES
@@ -59,7 +59,7 @@ A similar approach can be used for inline generation:
59
59
  p << "/var/doc/file2.html"
60
60
 
61
61
  p << @report.to_html
62
- p << "Some other text that will be incorporated to the report"
62
+ p << "Some other text that will be incorporated in the report"
63
63
 
64
64
  p.footer ".1."
65
65
 
@@ -73,10 +73,46 @@ your system.
73
73
 
74
74
  require "htmldoc"
75
75
 
76
- PDF::HTMLDoc.program_path = "\"C:\Program Files\HTMLDOC\ghtmldoc.exe\""
76
+ PDF::HTMLDoc.program_path = "\"C:\\Program Files\\HTMLDOC\\ghtmldoc.exe\""
77
77
 
78
78
  See the notes below for usage considerations.
79
79
 
80
+ == COMMON OPTIONS
81
+
82
+ Here are a few of the common options that can be used to control
83
+ HTMLDOC's output (assuming that <tt>pdf</tt> is a valid instance of
84
+ PDF::HTMLDoc):
85
+
86
+ To change the orientation to portrait mode, use:
87
+ pdf.set_option :portrait, true
88
+
89
+ To change the orientation to landscape mode, use:
90
+ pdf.set_option :landscape, true
91
+
92
+ To set the margins use:
93
+ pdf.set_option :top, "15"
94
+ pdf.set_option :right, "3cm"
95
+ pdf.set_option :left, "0.25in"
96
+ pdf.set_option :bottom, "20mm"
97
+
98
+ To disable the automatic table of contents, use:
99
+ pdf.set_option :toc, false
100
+
101
+ To control the header and footer, use:
102
+ pdf.header "lcr"
103
+ pdf.footer "lcr"
104
+
105
+ In the code above, "lcr" is a thee-character string representing the
106
+ left, center, and right fields of the header or footer. A ".1."
107
+ string, for example, indicates that the left and right fields should
108
+ be blank, and that the center field should contain the current page
109
+ number in decimal format. You can find more information about the
110
+ possible options in the HTMLDOC
111
+ documentation[http://www.htmldoc.org/htmldoc.html#footer].
112
+
113
+ More information about other options can be found in the HTMLDOC
114
+ command-line reference[http://www.htmldoc.org/htmldoc.html#CMDREF].
115
+
80
116
  == NOTES
81
117
 
82
118
  * PDF::HTMLDoc is both a Rails plugin and a gem, which means it can be
@@ -84,13 +120,21 @@ See the notes below for usage considerations.
84
120
  further dependencies.
85
121
 
86
122
  * Under Windows, it's better to point the program path for the HTMLDOC
87
- executable to the GUI vesion. It will avoid a DOS command window from
88
- popping-up in your application,
89
-
90
- * Keep in mind that HTMLDOC is not fast over large documents. If you
91
- need to generate very large documents, you be better off spawning an
92
- additional thread if your are in a traditional application or
93
- farming off the generation for a background deamon that will
94
- communicate with your application using some RPC
123
+ executable to the GUI version. It will prevent a DOS command window
124
+ from popping-up in your application,
125
+
126
+ * Keep in mind that HTMLDOC is not very fast over large documents. If
127
+ you need to generate very large documents, you'll be better off
128
+ spawning an additional thread if you are developing a traditional
129
+ application or farming off the generation for a background deamon
130
+ that will communicate with your application using some RPC
95
131
  mechanism. BackgrounDRb[http://backgroundrb.rubyforge.org] is a good
96
132
  choice for that.
133
+
134
+ * HTMLDOC doesn't support CSS files in its current stable version
135
+ (1.8.27). The development version (1.9) does support CSS, but in a
136
+ limited way.
137
+
138
+ * HTMLDOC doesn't support UTF-8. Since PDF::HTMLDOC makes no attempt
139
+ to convert any input passed to it, it's the caller's responsibility
140
+ to provide any necessary conversions.
data/Rakefile CHANGED
@@ -19,7 +19,7 @@ GEM_NAME = "htmldoc"
19
19
  RUBYFORGE_PROJECT = "htmldoc"
20
20
  HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
21
21
 
22
- NAME = "htmldoc"
22
+ NAME = "HTMLDOC"
23
23
  REV = File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
24
24
  VERS = ENV['VERSION'] || (PDF::HTMLDOC::VERSION::STRING + (REV ? ".#{REV}" : ""))
25
25
  CLEAN.include ['**/.*.sw?', '*.gem', '.config']
data/lib/htmldoc.rb CHANGED
@@ -44,9 +44,21 @@ module PDF
44
44
  # <code>"C:\Program Files\HTMLDOC\HTMLDOC.exe"</code>.
45
45
  @@program_path = "htmldoc"
46
46
 
47
- # The last result from the generation of the output file(s).
47
+ # The last result from the generation of the output file(s). It's
48
+ # a hash comprising three pairs:
49
+ # <tt>bytes</tt>:: The number of bytes generated in the last request or <tt>nil</tt>
50
+ # <tt>pages</tt>:: The number of pages generated in the last request or <tt>nil</tt>
51
+ # <tt>output</tt>:: The raw output of the command
48
52
  attr_reader :result
49
53
 
54
+ # The last error messages generate by the command. It's a hash
55
+ # where they key represents the error number, and the value
56
+ # represents the error message. If the error number is zero,
57
+ # HTMLDOC was called with invalid parameters. Errors can happen
58
+ # even if generation succeeds, for example, if an image can't be
59
+ # found in the course of the generation.
60
+ attr_reader :errors
61
+
50
62
  # Creates a blank HTMLDOC wrapper, using <tt>format</tt> to
51
63
  # indicate whether the output will be HTML, PDF or PS. The format
52
64
  # defaults to PDF, and can change using one of the module
@@ -56,13 +68,13 @@ module PDF
56
68
  @options = {}
57
69
  @pages = []
58
70
  @tempfiles = []
59
- @result = ""
71
+ reset
60
72
  end
61
73
 
62
74
  # Creates a blank HTMLDOC wrapper and passes it to a block. When
63
75
  # the block finishes running, the <tt>generate</tt> method is
64
- # automatically called. The result of generate is then passed back
65
- # to the application.
76
+ # automatically called. The result of <tt>generate</tt> is then
77
+ # passed back to the application.
66
78
  def self.create(format = PDF, &block)
67
79
  pdf = HTMLDoc.new(format)
68
80
  if block_given?
@@ -131,16 +143,16 @@ module PDF
131
143
  # or file is provided, the method will return <tt>true</tt> or
132
144
  # <tt>false</tt> to indicate completion. If no output directory or
133
145
  # file is provided, it will return a string representing the
134
- # entire output.
146
+ # entire output. Generate will raise a PDF::HTMLDocException if
147
+ # the program path can't be found.
135
148
  def generate
136
149
  tempfile = nil
137
150
  unless @options[:outdir] || @options[:outfile]
138
151
  tempfile = Tempfile.new("htmldoc.temp")
139
152
  @options[:outfile] = tempfile.path
140
153
  end
141
- command = @@program_path + " " + get_command_options + " " + get_command_pages + " 2>&1"
142
- @result = IO.popen(command) { |s| s.read }
143
- if (/BYTES/ =~ @result)
154
+ execute
155
+ if @result[:bytes]
144
156
  if tempfile
145
157
  File.open(tempfile.path, "rb") { |f| f.read }
146
158
  else
@@ -150,12 +162,46 @@ module PDF
150
162
  false
151
163
  end
152
164
  ensure
153
- tempfile.close if tempfile
165
+ if tempfile
166
+ tempfile.close
167
+ @options[:outfile] = nil
168
+ end
154
169
  @tempfiles.each { |t| t.close }
155
170
  end
156
171
 
157
172
  private
158
173
 
174
+ def execute
175
+ # Reset internal variables
176
+ reset
177
+ # Execute
178
+ command = @@program_path + " " + get_command_options + " " + get_command_pages + " 2>&1"
179
+ result = IO.popen(command) { |s| s.read }
180
+ # Check whether the program really was executed
181
+ if $?.exitstatus == 127
182
+ raise HTMLDocException.new("Invalid program path: #{@@program_path}")
183
+ else
184
+ @result[:output] = result
185
+ result.split("\n").each do |line|
186
+ case line
187
+ when /^BYTES: (\d+)/
188
+ @result[:bytes] = $1.to_i
189
+ when /^PAGES: (\d+)/
190
+ @result[:pages] = $1.to_i
191
+ when /^ERROR: (.*)$/
192
+ @errors[0] = $1.strip
193
+ when /^ERR(\d+): (.*)$/
194
+ @errors[$1.to_i] = $2.strip
195
+ end
196
+ end
197
+ end
198
+ end
199
+
200
+ def reset
201
+ @result = { :bytes => nil, :pages => nil, :output => nil }
202
+ @errors = { }
203
+ end
204
+
159
205
  def get_command_pages
160
206
  pages = @pages.collect do |page|
161
207
  case page[:type]
@@ -5,7 +5,7 @@ module PDF
5
5
  module VERSION #:nodoc:
6
6
 
7
7
  MAJOR = 0
8
- MINOR = 1
8
+ MINOR = 2
9
9
  TINY = 0
10
10
 
11
11
  STRING = [MAJOR, MINOR, TINY].join(".")
@@ -23,65 +23,101 @@ class GenerationTest < Test::Unit::TestCase
23
23
  basic_test(PDF::PDF)
24
24
  end
25
25
 
26
+ def test_generation_results
27
+ pdf = PDF::HTMLDoc.new
28
+ pdf.set_option :webpage, true
29
+ pdf.set_option :toc, false
30
+ pdf << "<h1>Random title</h1>"
31
+ assert_kind_of String, pdf.generate
32
+ assert_not_nil pdf.result[:bytes]
33
+ assert_not_nil pdf.result[:pages]
34
+ assert_equal 0, pdf.errors.size
35
+ assert_equal 1, pdf.result[:pages]
36
+ end
37
+
38
+ def test_invalid_program_path
39
+ PDF::HTMLDoc.program_path = @program_path + "-non-existing-path"
40
+ assert_raise(PDF::HTMLDocException) { PDF::HTMLDoc.new.generate }
41
+ ensure
42
+ PDF::HTMLDoc.program_path = @program_path
43
+ end
44
+
45
+ def test_generation_errors
46
+ # This test can fail if the collapsing wavefront of the Internet
47
+ # somehow becomes random.
48
+ # Test invalid input
49
+ pdf = PDF::HTMLDoc.new
50
+ pdf.set_option :outfile, "test.pdf"
51
+ pdf << "http://#{simple_uid(".com")}:12345/#{simple_uid(".html")}"
52
+ pdf.generate
53
+ assert_not_equal 0, pdf.errors.size
54
+ assert_nil pdf.result[:bytes]
55
+ assert_nil pdf.result[:pages]
56
+ # Test an invalid option
57
+ pdf = PDF::HTMLDoc.new
58
+ pdf.set_option :outfile, "test.pdf"
59
+ pdf << "http://#{simple_uid(".com")}:12345/#{simple_uid(".html")} --non-existing-option"
60
+ pdf.generate
61
+ assert_not_equal 0, pdf.errors.size
62
+ assert_nil pdf.result[:bytes]
63
+ assert_nil pdf.result[:pages]
64
+ end
65
+
26
66
  private
27
67
 
28
68
  def basic_test(format)
69
+ # Temporary files
29
70
  path1, path2 = (1..2).collect { |i| Dir.tmpdir + "/#{i}.#{format}" }
71
+ # Create a temporary file for the duration of the test
30
72
  Tempfile.open("htmldoc.test") do |tempfile|
73
+ # Load the temporary file with some test datas
31
74
  page = "<h1>Page 1</h1><p>Test.</p><h1>Page 2</h1><p>Test.</p>"
32
75
  tempfile.binmode
33
76
  tempfile.write(page)
34
77
  tempfile.flush
35
- begin
36
- pdf = PDF::HTMLDoc.new(format)
37
- pdf.set_option :outfile, path1
38
- pdf.add_page tempfile.path
39
- assert_equal true, pdf.generate
40
- assert_equal pdf.result, execute_htmldoc(path2, tempfile.path, "--format #{format}")
41
- ensure
42
- File.delete(path1)
43
- File.delete(path2)
44
- end
45
- begin
46
- pdf = PDF::HTMLDoc.new(format)
47
- pdf.set_option :outfile, path1
48
- pdf.set_option :webpage, true
49
- pdf.add_page tempfile.path
50
- assert_equal true, pdf.generate
51
- assert_equal pdf.result, execute_htmldoc(path2, tempfile.path, "--webpage --format #{format}")
52
- ensure
53
- File.delete(path1)
54
- File.delete(path2)
55
- end
56
- begin
57
- pdf = PDF::HTMLDoc.new(format)
58
- pdf.set_option :outfile, path1
59
- pdf.set_option :bodycolor, :black
60
- pdf.add_page tempfile.path
61
- assert_equal true, pdf.generate
62
- assert_equal pdf.result, execute_htmldoc(path2, tempfile.path, "--bodycolor black --format #{format}")
63
- ensure
64
- File.delete(path1)
65
- File.delete(path2)
66
- end
67
- begin
68
- pdf = PDF::HTMLDoc.new(format)
69
- pdf.add_page page
70
- pdf.generate
71
- assert_equal pdf.result, execute_htmldoc(path2, tempfile.path, "--format #{format}")
72
- ensure
73
- File.delete(path2)
74
- end
75
- begin
76
- result = PDF::HTMLDoc.create(format) do |p|
77
- p.set_option :outfile, path1
78
- p.set_option :bodycolor, :black
79
- p.add_page tempfile.path
80
- end
81
- assert_equal true, result
82
- ensure
83
- File.delete(path1)
78
+ # Simple format test
79
+ pdf = PDF::HTMLDoc.new(format)
80
+ pdf.set_option :outfile, path1
81
+ pdf.add_page tempfile.path
82
+ assert_equal true, pdf.generate
83
+ assert_equal pdf.result[:output], execute_htmldoc(path2, tempfile.path, "--format #{format}")
84
+ # Delete temporary files
85
+ File.delete(path1) if File.exists?(path1)
86
+ File.delete(path2) if File.exists?(path2)
87
+ # Simple webpag format test
88
+ pdf = PDF::HTMLDoc.new(format)
89
+ pdf.set_option :outfile, path1
90
+ pdf.set_option :webpage, true
91
+ pdf.add_page tempfile.path
92
+ assert_equal true, pdf.generate
93
+ assert_equal pdf.result[:output], execute_htmldoc(path2, tempfile.path, "--webpage --format #{format}")
94
+ # Delete temporary files
95
+ File.delete(path1) if File.exists?(path1)
96
+ File.delete(path2) if File.exists?(path2)
97
+ # Simple options test
98
+ pdf = PDF::HTMLDoc.new(format)
99
+ pdf.set_option :outfile, path1
100
+ pdf.set_option :bodycolor, :black
101
+ pdf.add_page tempfile.path
102
+ assert_equal true, pdf.generate
103
+ assert_equal pdf.result[:output], execute_htmldoc(path2, tempfile.path, "--bodycolor black --format #{format}")
104
+ # Delete temporary files
105
+ File.delete(path1) if File.exists?(path1)
106
+ File.delete(path2) if File.exists?(path2)
107
+ # Free text generate test
108
+ pdf = PDF::HTMLDoc.new(format)
109
+ pdf.add_page page
110
+ pdf.generate
111
+ assert_equal pdf.result[:output], execute_htmldoc(path2, tempfile.path, "--format #{format}")
112
+ # Delete temporary files
113
+ File.delete(path2) if File.exists?(path2)
114
+ # Inline generation test
115
+ result = PDF::HTMLDoc.create(format) do |p|
116
+ p.set_option :outfile, path1
117
+ p.set_option :bodycolor, :black
118
+ p.add_page tempfile.path
84
119
  end
120
+ assert_equal true, result
85
121
  end
86
122
  end
87
123
 
@@ -89,4 +125,11 @@ class GenerationTest < Test::Unit::TestCase
89
125
  IO.popen("#{@program_path} #{options} -f #{output} #{input} 2>&1") { |s| s.read }
90
126
  end
91
127
 
128
+ def simple_uid(extension)
129
+ chars = ('A'..'Z').to_a + ('0'..'9').to_a
130
+ (1..100).inject("") { |r, i| r + chars[rand(chars.length)] }
131
+ end
132
+
92
133
  end
134
+
135
+ # LocalWords: HTMLDOC
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
3
3
  specification_version: 1
4
4
  name: htmldoc
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.0
7
- date: 2007-03-05 00:00:00 -03:00
6
+ version: 0.2.0
7
+ date: 2007-03-07 00:00:00 -03:00
8
8
  summary: A wrapper around HTMLDOC, a PDF generation utility
9
9
  require_paths:
10
10
  - lib