awhyte-rtex 2.1.2

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.
data/CHANGELOG ADDED
@@ -0,0 +1,48 @@
1
+ v2.1.0
2
+
3
+ Merge in rails-2.2.2 branch, modify to make sure Prawn isn't trampled and
4
+ 2.3.0 is supported.
5
+ Simplify tagging of templates for later processing (+ ensure it works
6
+ with compiled templates).
7
+ Update README_RAILS
8
+
9
+ v2.0.5
10
+
11
+ Fix issue with Echoe being ultra-sensitive on RubyGems versions (v2.0.4
12
+ was RubyGems 1.2 only, and 1.3 just came out)
13
+
14
+ v2.0.4
15
+
16
+ Support for TeX escaping (via l()) calling to_s on the argument.
17
+ This should handle nils.
18
+
19
+ v2.0.3
20
+
21
+ Rails 2.0 compat:
22
+ Fix issue with init.rb not requiring rails/init.rb
23
+
24
+ v1.99.0 2008-04-20
25
+
26
+ Released RTeX v1.99.0 as a Rubygem, with a standalone executable for PDF generation
27
+ and support for plugin installation from the executable.
28
+
29
+ This release requires Rails >= 2.0.1
30
+
31
+ Thanks to:
32
+ * Jonas Bähr for a patch with additional LaTeX escaping
33
+ * Fouad Mardini for a TemplateHandler patch
34
+
35
+ v1.0.0+
36
+
37
+ Added quite a few *long* overdue fixes & enhancements sent in by various people.
38
+
39
+ * Added latex escaping 'l' method (Thanks, Benjamin Quorning)
40
+ * Added support for @options_for_rtex hash for configuration:
41
+ * Added :tempdir option, and changed default temporary directory
42
+ (Thanks, Francesco Levorato)
43
+ * Added :preprocess option to support running through latex before pdflatex
44
+ (Thanks Charles Lesburg, Benjamin Quorning)
45
+ * Moved old @filename setting to :filename option in this hash
46
+
47
+ If you're using the same settings for @options_for_rtex often, you might want to
48
+ put your assignment in a before_filter (perhaps overriding :filename, etc in your actions).
data/Manifest ADDED
@@ -0,0 +1,25 @@
1
+ bin/rtex
2
+ CHANGELOG
3
+ init.rb
4
+ lib/rtex/document.rb
5
+ lib/rtex/escaping.rb
6
+ lib/rtex/framework/merb.rb
7
+ lib/rtex/framework/rails.rb
8
+ lib/rtex/tempdir.rb
9
+ lib/rtex/version.rb
10
+ lib/rtex.rb
11
+ Manifest
12
+ rails/init.rb
13
+ Rakefile
14
+ README.rdoc
15
+ README_RAILS.rdoc
16
+ test/document_test.rb
17
+ test/filter_test.rb
18
+ test/fixtures/first.tex
19
+ test/fixtures/first.tex.erb
20
+ test/fixtures/fragment.tex.erb
21
+ test/fixtures/text.textile
22
+ test/tempdir_test.rb
23
+ test/test_helper.rb
24
+ vendor/instiki/LICENSE
25
+ vendor/instiki/redcloth_for_tex.rb
data/README.rdoc ADDED
@@ -0,0 +1,46 @@
1
+ = RTeX: TeX/PDF Generation for Ruby
2
+
3
+ Project homepage (FAQ, manual, documentation, contact info): http://rtex.rubyforge.org
4
+
5
+ Source repository at: http://github.com/bruce/rtex
6
+
7
+ == Dependencies
8
+
9
+ * pdflatex executable, available in modern teTeX distributions
10
+ * Requires Rails >= 2.0.1 if used as a plugin.
11
+
12
+ == Usage
13
+
14
+ For use as a standalone executable, see `rtex --help'
15
+
16
+ For use as a Rails plugin, see README_RAILS.rdoc
17
+
18
+ == More Information
19
+
20
+ Additional help may be available at the project homepage,
21
+ http://rtex.rubyforge.org
22
+
23
+ == License
24
+
25
+ (The MIT License)
26
+
27
+ Copyright (c) 2006-2008 Bruce Williams, Wiebe Cazemier
28
+
29
+ Permission is hereby granted, free of charge, to any person obtaining
30
+ a copy of this software and associated documentation files (the
31
+ 'Software'), to deal in the Software without restriction, including
32
+ without limitation the rights to use, copy, modify, merge, publish,
33
+ distribute, sublicense, and/or sell copies of the Software, and to
34
+ permit persons to whom the Software is furnished to do so, subject to
35
+ the following conditions:
36
+
37
+ The above copyright notice and this permission notice shall be
38
+ included in all copies or substantial portions of the Software.
39
+
40
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
41
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
42
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
43
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
44
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
45
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
46
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README_RAILS.rdoc ADDED
@@ -0,0 +1,58 @@
1
+ = RTeX for Rails
2
+
3
+ == Installation
4
+
5
+ sudo gem install rtex
6
+
7
+ Rails 2.0.X, 2.1+ in vendor/plugins (not recommended):
8
+ rtex --install /path/to/rails/app
9
+
10
+ Or, as a Rails 2.1+ gem dependency, just add the following
11
+ to your config/environment.rb:
12
+ config.gem 'rtex'
13
+
14
+ == Dependencies
15
+
16
+ * Rails >= 2.0.1
17
+
18
+ == Usage
19
+
20
+ Create files pdf.rtex extensions (eg, index.pdf.rtex) using standard LaTeX markup.
21
+
22
+ * Layouts are supported, eg: application.pdf.rtex
23
+ * Partials are supported, eg: _item.pdf.rtex
24
+
25
+ === Example
26
+
27
+ With the following:
28
+
29
+ # In config/initializers/mime_types.rb (or environment.rb in older Rails)
30
+ Mime::Type.register "application/pdf", :pdf
31
+
32
+ # app/controllers/items_controller.rb
33
+ def index
34
+ @items = Item.find(:all)
35
+ respond_to do |format|
36
+ format.html # We support the normal HTML view as well
37
+ format.pdf
38
+ end
39
+ end
40
+
41
+ # app/views/items/index.pdf.rtex
42
+ \section*{Items}
43
+ \begin{itemize}
44
+ <%= render :partial => @items %>
45
+ \end{itemize}
46
+
47
+ # app/views/items/_item.pdf.rtex
48
+ \item <%=l item.name %> \\
49
+
50
+ # app/layouts/application.pdf.rtex
51
+ \documentclass[12pt]{article}
52
+ \begin{document}
53
+ <%= yield %>
54
+ \end{document}
55
+
56
+ If you hit /items.pdf, you end up with a nice PDF listing of items.
57
+
58
+ Obviously a simplistic example.
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'rubygems'
2
+ require 'echoe'
3
+
4
+ require File.dirname(__FILE__) << "/lib/rtex/version"
5
+
6
+ Echoe.new 'rtex' do |p|
7
+ p.version = RTeX::Version::STRING
8
+ p.author = ['Bruce Williams', 'Wiebe Cazemier']
9
+ p.email = 'bruce@codefluency.com'
10
+ p.project = 'rtex'
11
+ p.summary = "LaTeX preprocessor for PDF generation; Rails plugin"
12
+ p.url = "http://rtex.rubyforge.org"
13
+ p.include_rakefile = true
14
+ p.development_dependencies = %w(Shoulda echoe)
15
+ p.rcov_options = '--exclude gems --exclude version.rb --sort coverage --text-summary --html -o coverage'
16
+ p.ignore_pattern = /^(pkg|doc|site)|\.svn|CVS|\.bzr|\.DS|\.git/
17
+ p.rubygems_version = nil
18
+ end
19
+
20
+ task :coverage do
21
+ system "open coverage/index.html" if PLATFORM['darwin']
22
+ end
data/bin/rtex ADDED
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'fileutils'
5
+
6
+ require File.dirname(__FILE__) << '/../lib/rtex'
7
+
8
+ options = {}
9
+
10
+ opts = OptionParser.new do |opts|
11
+
12
+ opts.banner = [
13
+ "RTeX v#{RTeX::Version::STRING} (c) 2006-2007 Bruce Williams, Wiebe Cazemier",
14
+ "Usage: rtex [OPTION...] FILE...\n\n"
15
+ ].join("\n")
16
+
17
+ opts.on('-l LAYOUT', '--layout LAYOUT', 'Path to layout file (use <%= yield %>)') do |layout|
18
+ if File.exists?(layout)
19
+ options[:layout] = File.read(layout)
20
+ else
21
+ STDERR.puts "Layout file not found: #{layout}"
22
+ exit 1
23
+ end
24
+ end
25
+
26
+ opts.on('-o OUTFILE', '--output OUTFILE', "Output to file (defaults to STDOUT)") do |path|
27
+ options[:outfile] = path
28
+ end
29
+
30
+ filters = RTeX.filters.keys.map { |k| k.to_s }.sort.join(', ')
31
+ opts.on('-f FILTER', '--filter FILTER', "Filter input (supported: #{filters})", "(Wraps in a basic `article' document; use --layout to customize)") do |filter|
32
+ options[:filter] = filter
33
+ end
34
+
35
+ opts.on('--no-pdf', "Don't generate PDF (just output TeX)") do
36
+ options[:tex] = true
37
+ end
38
+
39
+ opts.on('-i PATH', '--install PATH', "Install as plugin into Rails app at PATH") do |path|
40
+ unless Dir[plugins = File.join(path, 'vendor/plugins')].any?
41
+ STDERR.puts "Could not find application at #{path}"
42
+ exit 1
43
+ end
44
+ plugin_path = File.join(plugins, 'rtex')
45
+ FileUtils.cp_r(File.dirname(__FILE__) << '/..', plugin_path)
46
+ %w(Rakefile Manifest.txt bin tasks).each do |prune|
47
+ FileUtils.rm_rf(File.join(plugin_path, prune)) rescue nil
48
+ end
49
+ STDERR.puts "Installed at #{plugin_path}"
50
+ exit
51
+ end
52
+
53
+ opts.on('-p PROCESSOR', '--processor PROCESSOR', "Specify the LaTeX processor (default: #{RTeX::Document.options[:processor]})") do |processor|
54
+ options[:processor] = processor
55
+ end
56
+
57
+ opts.on('-h', '--help', "Show this message\n")
58
+ opts.separator "With no FILEs, or when FILE is -, read from standard input."
59
+
60
+ opts.on_tail do
61
+ STDERR.puts opts
62
+ exit
63
+ end
64
+ end
65
+ opts.parse!(ARGV)
66
+
67
+ if options[:filter] && !options[:layout]
68
+ STDERR.puts "Warning: Using default `article' layout (see --help on '--layout')"
69
+ options[:layout] = RTeX.basic_layout
70
+ end
71
+
72
+ RTeX::Document.create(ARGF.read, options) do |document|
73
+ document.to_pdf do |filename|
74
+ begin
75
+ location = File.expand_path options[:outfile]
76
+ FileUtils.move filename, location
77
+ rescue
78
+ STDOUT.print File.read(filename)
79
+ end
80
+ end
81
+ end
82
+
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.dirname(__FILE__) << "/rails/init"
data/lib/rtex.rb ADDED
@@ -0,0 +1,37 @@
1
+ $:.unshift(File.dirname(__FILE__) << '/rtex')
2
+
3
+ require 'document'
4
+ require 'version'
5
+
6
+ module RTeX
7
+
8
+ # Load code to initialize RTeX for framework
9
+ def self.framework(name)
10
+ require File.dirname(__FILE__) << "/rtex/framework/#{name}"
11
+ framework = ::RTeX::Framework.const_get(name.to_s.capitalize)
12
+ framework.setup
13
+ end
14
+
15
+ def self.filters #:nodoc:
16
+ @filters ||= {}
17
+ end
18
+
19
+ def self.basic_layout #:nodoc:
20
+ "\\documentclass[12pt]{article}\n\\begin{document}\n<%= yield %>\n\\end{document}"
21
+ end
22
+
23
+ # Define a processing filter
24
+ # call-seq:
25
+ # filter(:name) { |text_to_transform| ... } # => result
26
+ def self.filter(name, &block)
27
+ filters[name.to_s] = block
28
+ end
29
+
30
+ filter :textile do |source|
31
+ require File.dirname(__FILE__) << '/../vendor/instiki/redcloth_for_tex'
32
+ RedClothForTex.new(source).to_tex
33
+ end
34
+
35
+ end
36
+
37
+
@@ -0,0 +1,245 @@
1
+ require 'erb'
2
+ require 'escaping'
3
+ require 'tempdir'
4
+
5
+ module RTeX
6
+ class Document
7
+ extend Escaping
8
+
9
+ class FilterError < ::StandardError; end
10
+ class GenerationError < ::StandardError; end
11
+ class ExecutableNotFoundError < ::StandardError; end
12
+
13
+ # Create a new +RTeX::Document+. A temporary directory will be created
14
+ # for the lifetime of the document, and then destroyed at the end of the block.
15
+ #
16
+ # RTeX::Document.create(source, :processor => "xelatex") do |document|
17
+ # puts "working in #{document.tempdir}"
18
+ #
19
+ # document.to_pdf do |filename|
20
+ # # process PDF file
21
+ # # ...
22
+ # end
23
+ # end
24
+ #
25
+ # Options passed to +#create+ are the same as those for +#new+.
26
+ #
27
+ # To specify which temporary directory should be created for processing the
28
+ # document, set +:tempdir+.
29
+ #
30
+ def self.create(content, options={})
31
+ Tempdir.open(options[:tempdir]) do |dir|
32
+ doc = Document.new(content, options.merge(:tempdir => dir))
33
+ yield doc
34
+ end
35
+ end
36
+
37
+ # Create a new +RTeX::Document+ in either the current directory (default)
38
+ # or a specified, pre-existing directory.
39
+ #
40
+ # The +content+ parameter should contain the document source.
41
+ #
42
+ # The +options+ hash may contain:
43
+ # [+:processor+] Executable with which to output the document
44
+ # (default: 'pdflatex')
45
+ # [+:preprocessor+] Executable to use during preprocessing (particularly
46
+ # for longer documents containing a table-of-contents or
47
+ # bibliography section (default: 'latex')
48
+ # [+:preprocess+] Either a boolean specifying whether to preprocess the
49
+ # input file(s), or an integer for the number of times to
50
+ # preprocess (default: false / 0)
51
+ # [+:tmpdir+] Location of temporary directory (default: +Dir.getwd+)
52
+ # [+:shell_redirect+] Option redirection for shell output,
53
+ # e.g. +"> /dev/null 2>&1"+ (default: +nil+).
54
+ #
55
+ def initialize(content, options={})
56
+ @options = self.class.options.merge(options)
57
+ if @options[:processed]
58
+ @source = content
59
+ else
60
+ @erb = ERB.new(content)
61
+ end
62
+ end
63
+
64
+ # Get the compiled source for the entire document
65
+ def source(binding=nil) #:nodoc:
66
+ @source ||= wrap_in_layout do
67
+ filter @erb.result(binding)
68
+ end
69
+ end
70
+
71
+ # Process through defined filter
72
+ def filter(text) #:nodoc:
73
+ return text unless @options[:filter]
74
+ if (process = RTeX.filters[@options[:filter]])
75
+ process[text]
76
+ else
77
+ raise FilterError, "No `#{@options[:filter]}' filter"
78
+ end
79
+ end
80
+
81
+ # Wrap content in optional layout
82
+ def wrap_in_layout #:nodoc:
83
+ if @options[:layout]
84
+ ERB.new(@options[:layout]).result(binding)
85
+ else
86
+ yield
87
+ end
88
+ end
89
+
90
+ # Generate PDF output:
91
+ #
92
+ # to_pdf # => PDF in a String
93
+ # to_pdf { |filename| ... }
94
+ #
95
+ def to_pdf(binding=nil, &file_handler)
96
+ process_pdf_from(source(binding), &file_handler)
97
+ end
98
+
99
+ def processor #:nodoc:
100
+ @processor ||= check_path_for @options[:processor]
101
+ end
102
+
103
+ def preprocessor #:nodoc:
104
+ @preprocessor ||= check_path_for @options[:preprocessor]
105
+ end
106
+
107
+ def system_path #:nodoc:
108
+ ENV['PATH']
109
+ end
110
+
111
+ def self.options #:nodoc:
112
+ @options ||= {
113
+ :preprocessor => 'latex',
114
+ :preprocess => false,
115
+ :processor => 'pdflatex',
116
+ :shell_redirect => nil,
117
+ :tex_inputs => nil,
118
+ :tempdir => Dir.getwd # Current directory unless otherwise set
119
+ }
120
+ end
121
+
122
+ private
123
+
124
+ # Verify existence of executable in search path
125
+ def check_path_for(command)
126
+ unless FileTest.executable?(command) || system_path.split(":").any?{ |path| FileTest.executable?(File.join(path, command))}
127
+ raise ExecutableNotFoundError, command
128
+ end
129
+ command
130
+ end
131
+
132
+ # Basic processing
133
+ #
134
+ # The general call sequence is:
135
+ # #to_pdf (from user) => #source (ruby compile) => #process_pdf_from => #prepare => #preprocess! => #process! => #verify! => return as string or output filename
136
+ #
137
+ def process_pdf_from(input, &file_handler)
138
+ prepare input
139
+ if generating?
140
+ preprocess_count.times { preprocess! }
141
+ process!
142
+ verify!
143
+ end
144
+ if file_handler
145
+ yield result_file
146
+ else
147
+ result_as_string
148
+ end
149
+ end
150
+
151
+ # Save the Ruby-compiled document source to a file
152
+ # It is then ready for LaTeX to compile it into a PDF
153
+ #
154
+ def prepare(input)
155
+ File.open(source_file, 'wb') { |f| f.puts input }
156
+ end
157
+
158
+ # Run LaTeX pre-processing step on the source file
159
+ def preprocess!
160
+ unless `#{environment_vars}#{preprocessor} --output-directory=#{tempdir} --interaction=nonstopmode '#{File.basename(source_file)}' #{@options[:shell_redirect]}`
161
+ raise GenerationError, "Could not preprocess using #{preprocessor}"
162
+ end
163
+ end
164
+
165
+ # Run LaTeX output generation step on the source file
166
+ def process!
167
+ unless `#{environment_vars}#{tex_inputs} #{processor} --output-directory=#{tempdir} --interaction=nonstopmode '#{File.basename(source_file)}' #{@options[:shell_redirect]}`
168
+ raise GenerationError, "Could not generate PDF using #{processor}"
169
+ end
170
+ end
171
+
172
+ # Check the output file has been generated correctly
173
+ def verify!
174
+ unless File.exists?(result_file)
175
+ raise GenerationError, "Could not find result PDF #{result_file} after generation.\nCheck #{log_file}"
176
+ end
177
+ end
178
+
179
+ # Load the output file and return its contents
180
+ def result_as_string
181
+ File.open(result_file, 'rb') { |f| f.read }
182
+ end
183
+
184
+ # Should we pre-process?
185
+ def preprocessing?
186
+ preprocess_count > 0
187
+ end
188
+
189
+ def preprocess_count
190
+ case @options[:preprocess]
191
+ when Numeric
192
+ @options[:preprocess].to_i
193
+ when true
194
+ 1
195
+ else
196
+ 0
197
+ end
198
+ end
199
+
200
+ # Compile list of extra directories to search for LaTeX packages, using
201
+ # the file or array of files held in the :tex_inputs option.
202
+ #
203
+ def tex_inputs
204
+ if inputs = @options[:tex_inputs]
205
+ inputs = [inputs].flatten.select { |i| File.exists? i }
206
+ "TEXINPUTS='#{inputs.join(':')}:'"
207
+ else
208
+ nil
209
+ end
210
+ end
211
+
212
+ # Produce a list of environment variables to prefix the process and
213
+ # preprocess commands.
214
+ #
215
+ def environment_vars
216
+ list = [tex_inputs].compact
217
+ list.empty? ? "" : list.join(" ") + " "
218
+ end
219
+
220
+ def source_file
221
+ @source_file ||= file(:tex)
222
+ end
223
+
224
+ def log_file
225
+ @log_file ||= file(:log)
226
+ end
227
+
228
+ def result_file
229
+ @result_file ||= file(@options[:tex] ? :tex : :pdf)
230
+ end
231
+
232
+ def tempdir
233
+ @options[:tempdir]
234
+ end
235
+
236
+ def file(extension)
237
+ File.join(tempdir.to_s, "document.#{extension}")
238
+ end
239
+
240
+ def generating?
241
+ !@options[:tex]
242
+ end
243
+
244
+ end
245
+ end