artex 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ v2.1.0
2
+
3
+ Forked from RTeX 2.1.0.
@@ -0,0 +1,25 @@
1
+ CHANGELOG
2
+ Manifest
3
+ README.rdoc
4
+ Rakefile
5
+ artex.gemspec
6
+ init.rb
7
+ lib/artex.rb
8
+ lib/artex/document.rb
9
+ lib/artex/escaping.rb
10
+ lib/artex/framework/merb.rb
11
+ lib/artex/framework/rails.rb
12
+ lib/artex/pdf.rb
13
+ lib/artex/tempdir.rb
14
+ lib/artex/version.rb
15
+ rails/init.rb
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
@@ -0,0 +1,46 @@
1
+ = ArTeX: TeX/PDF Generation for Ruby
2
+
3
+ Project homepage (FAQ, manual, documentation, contact info): http://github.com/avarteq/artex
4
+
5
+ Source repository at: http://github.com/avarteq/artex
6
+
7
+ == Dependencies
8
+
9
+ * pdflatex executable, available in modern teTeX distributions
10
+ * Requires Ruby
11
+
12
+ == Motivation
13
+ This gem has been forked from the rtex gem (http://github.com/bruce/rtex).
14
+ RTeX can be used either as stand alone executable or as a rails plugin.
15
+ Using it as rails plugin means to create PDF files using the rails rendering engine.
16
+ This will bring you in trouble if you don't want to generate your PDF files within controllers.
17
+ In contrast to that ArTeX has no dependencies on ActionPack and thus can also be used in models.
18
+
19
+ We'll keep on updating the gem and we'll try to provide some examples in the future.
20
+ Besides of that the code will be iteratively cut down, rewritten and enhanced.
21
+
22
+
23
+ == License
24
+
25
+ (The MIT License)
26
+
27
+ Copyright (c) 2006-2010 Bruce Williams, Wiebe Cazemier, Julian Fischer
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.
@@ -0,0 +1,22 @@
1
+ require 'rubygems'
2
+ require 'echoe'
3
+
4
+ require File.dirname(__FILE__) << "/lib/artex/version"
5
+
6
+ Echoe.new 'artex' do |p|
7
+ p.version = ArTeX::Version::STRING
8
+ p.author = ['Bruce Williams', 'Wiebe Cazemier', 'Julian Fischer']
9
+ p.email = 'artex@avarteq.de'
10
+ p.project = 'artex'
11
+ p.summary = "LaTeX preprocessor for PDF generation; Rails plugin"
12
+ p.url = "http://github.com/avarteq/artex"
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
@@ -0,0 +1,37 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{artex}
5
+ s.version = "2.1.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Bruce Williams, Wiebe Cazemier, Julian Fischer"]
9
+ s.date = %q{2010-04-19}
10
+ s.description = %q{LaTeX preprocessor for PDF generation; Rails plugin}
11
+ s.email = %q{artex@avarteq.de}
12
+ s.extra_rdoc_files = ["CHANGELOG", "README.rdoc", "lib/artex.rb", "lib/artex/document.rb", "lib/artex/escaping.rb", "lib/artex/framework/merb.rb", "lib/artex/framework/rails.rb", "lib/artex/pdf.rb", "lib/artex/tempdir.rb", "lib/artex/version.rb"]
13
+ s.files = ["CHANGELOG", "Manifest", "README.rdoc", "Rakefile", "artex.gemspec", "init.rb", "lib/artex.rb", "lib/artex/document.rb", "lib/artex/escaping.rb", "lib/artex/framework/merb.rb", "lib/artex/framework/rails.rb", "lib/artex/pdf.rb", "lib/artex/tempdir.rb", "lib/artex/version.rb", "rails/init.rb", "test/document_test.rb", "test/filter_test.rb", "test/fixtures/first.tex", "test/fixtures/first.tex.erb", "test/fixtures/fragment.tex.erb", "test/fixtures/text.textile", "test/tempdir_test.rb", "test/test_helper.rb", "vendor/instiki/LICENSE", "vendor/instiki/redcloth_for_tex.rb"]
14
+ s.homepage = %q{http://github.com/avarteq/artex}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Artex", "--main", "README.rdoc"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{artex}
18
+ s.rubygems_version = %q{1.3.5}
19
+ s.summary = %q{LaTeX preprocessor for PDF generation; Rails plugin}
20
+ s.test_files = ["test/document_test.rb", "test/filter_test.rb", "test/tempdir_test.rb", "test/test_helper.rb"]
21
+
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.specification_version = 3
25
+
26
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
27
+ s.add_development_dependency(%q<Shoulda>, [">= 0"])
28
+ s.add_development_dependency(%q<echoe>, [">= 0"])
29
+ else
30
+ s.add_dependency(%q<Shoulda>, [">= 0"])
31
+ s.add_dependency(%q<echoe>, [">= 0"])
32
+ end
33
+ else
34
+ s.add_dependency(%q<Shoulda>, [">= 0"])
35
+ s.add_dependency(%q<echoe>, [">= 0"])
36
+ end
37
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.dirname(__FILE__) << "/rails/init"
@@ -0,0 +1,31 @@
1
+ $:.unshift(File.dirname(__FILE__) << '/artex')
2
+
3
+ require 'document'
4
+ require 'version'
5
+ require 'pdf'
6
+
7
+ module ArTeX
8
+
9
+ def self.filters #:nodoc:
10
+ @filters ||= {}
11
+ end
12
+
13
+ def self.basic_layout #:nodoc:
14
+ "\\documentclass[12pt]{article}\n\\begin{document}\n<%= yield %>\n\\end{document}"
15
+ end
16
+
17
+ # Define a processing filter
18
+ # call-seq:
19
+ # filter(:name) { |text_to_transform| ... } # => result
20
+ def self.filter(name, &block)
21
+ filters[name.to_s] = block
22
+ end
23
+
24
+ filter :textile do |source|
25
+ require File.dirname(__FILE__) << '/../vendor/instiki/redcloth_for_tex'
26
+ RedClothForTex.new(source).to_tex
27
+ end
28
+
29
+ end
30
+
31
+
@@ -0,0 +1,175 @@
1
+ require 'erb'
2
+ require 'ostruct'
3
+ require 'tmpdir'
4
+
5
+ require 'escaping'
6
+ require 'tempdir'
7
+
8
+ module ArTeX
9
+
10
+ class Document
11
+
12
+ extend Escaping
13
+
14
+ class FilterError < ::StandardError; end
15
+ class GenerationError < ::StandardError; end
16
+ class ExecutableNotFoundError < ::StandardError; end
17
+
18
+ # Default options
19
+ # [+:preprocess+] Are we preprocessing? Default is +false+
20
+ # [+:preprocessor+] Executable to use during preprocessing (generating TOCs, etc). Default is +latex+
21
+ # [+:shell_redirect+] Option redirection for shell output (eg, +"> /dev/null 2>&1"+ ). Default is +nil+.
22
+ # [+:tmpdir+] Location of temporary directory (default: +Dir.tmpdir+)
23
+ def self.options
24
+ @options ||= {
25
+ :preprocessor => 'latex',
26
+ :preprocess => false,
27
+ :processor => 'pdflatex',
28
+ #
29
+ :shell_redirect => nil,
30
+ # Temporary Directory
31
+ :tempdir => Dir.tmpdir
32
+ }
33
+ end
34
+
35
+ def initialize(content, options={})
36
+ @options = self.class.options.merge(options)
37
+ if @options[:processed]
38
+ @source = content
39
+ else
40
+ @erb = ERB.new(content)
41
+ end
42
+ end
43
+
44
+ # Get the source for the entire
45
+ def source(binding=nil) #:nodoc:
46
+ @source ||= wrap_in_layout do
47
+ filter @erb.result(binding)
48
+ end
49
+ end
50
+
51
+ # Process through defined filter
52
+ def filter(text) #:nodoc:
53
+ return text unless @options[:filter]
54
+ if (process = ArTeX.filters[@options[:filter]])
55
+ process[text]
56
+ else
57
+ raise FilterError, "No `#{@options[:filter]}' filter"
58
+ end
59
+ end
60
+
61
+ # Wrap content in optional layout
62
+ def wrap_in_layout #:nodoc:
63
+ if @options[:layout]
64
+ ERB.new(@options[:layout]).result(binding)
65
+ else
66
+ yield
67
+ end
68
+ end
69
+
70
+ # Generate PDF from
71
+ # call-seq:
72
+ # to_pdf # => PDF in a String
73
+ # to_pdf { |filename| ... }
74
+ def to_pdf(binding=nil, &file_handler)
75
+ process_pdf_from(source(binding), &file_handler)
76
+ end
77
+
78
+ def processor #:nodoc:
79
+ @processor ||= check_path_for @options[:processor]
80
+ end
81
+
82
+ def preprocessor #:nodoc:
83
+ @preprocessor ||= check_path_for @options[:preprocessor]
84
+ end
85
+
86
+ def system_path #:nodoc:
87
+ ENV['PATH']
88
+ end
89
+
90
+ #######
91
+ private
92
+ #######
93
+
94
+ # Verify existence of executable in search path
95
+ def check_path_for(command)
96
+ unless FileTest.executable?(command) || system_path.split(":").any?{ |path| FileTest.executable?(File.join(path, command))}
97
+ raise ExecutableNotFoundError, command
98
+ end
99
+ command
100
+ end
101
+
102
+ # Basic processing
103
+ def process_pdf_from(input, &file_handler)
104
+ Tempdir.open(@options[:tempdir]) do |tempdir|
105
+ prepare input
106
+ if generating?
107
+ preprocess! if preprocessing?
108
+ process!
109
+ verify!
110
+ end
111
+ if file_handler
112
+ yield full_path_in(tempdir.path)
113
+ else
114
+ result_as_string
115
+ end
116
+ end
117
+ end
118
+
119
+ def process!
120
+ unless `#{processor} --interaction=nonstopmode '#{source_file}' #{@options[:shell_redirect]}`
121
+ raise GenerationError, "Could not generate PDF using #{processor}"
122
+ end
123
+ end
124
+
125
+ def preprocess!
126
+ unless `#{preprocessor} --interaction=nonstopmode '#{source_file}' #{@options[:shell_redirect]}`
127
+ raise GenerationError, "Could not preprocess using #{preprocessor}"
128
+ end
129
+ end
130
+
131
+ def preprocessing?
132
+ @options[:preprocess]
133
+ end
134
+
135
+ def source_file
136
+ @source_file ||= file(:tex)
137
+ end
138
+
139
+ def log_file
140
+ @log_file ||= file(:log)
141
+ end
142
+
143
+ def result_file
144
+ @result_file ||= file(@options[:tex] ? :tex : :pdf)
145
+ end
146
+
147
+ def file(extension)
148
+ "document.#{extension}"
149
+ end
150
+
151
+ def generating?
152
+ !@options[:tex]
153
+ end
154
+
155
+ def verify!
156
+ unless File.exists?(result_file)
157
+ raise GenerationError, "Could not find result PDF #{result_file} after generation.\nCheck #{File.expand_path(log_file)}"
158
+ end
159
+ end
160
+
161
+ def prepare(input)
162
+ File.open(source_file, 'wb') { |f| f.puts input }
163
+ end
164
+
165
+ def result_as_string
166
+ File.open(result_file, 'rb') { |f| f.read }
167
+ end
168
+
169
+ def full_path_in(directory)
170
+ File.expand_path(File.join(directory, result_file))
171
+ end
172
+
173
+ end
174
+
175
+ end
@@ -0,0 +1,28 @@
1
+ module ArTeX
2
+
3
+ module Escaping
4
+
5
+ # Escape text using +replacements+
6
+ def escape(text)
7
+ replacements.inject(text.to_s) do |corpus, (pattern, replacement)|
8
+ corpus.gsub(pattern, replacement)
9
+ end
10
+ end
11
+
12
+ # List of replacements
13
+ def replacements
14
+ @replacements ||= [
15
+ [/([{}])/, '\\\\\1'],
16
+ [/\\/, '\textbackslash{}'],
17
+ [/\^/, '\textasciicircum{}'],
18
+ [/~/, '\textasciitilde{}'],
19
+ [/\|/, '\textbar{}'],
20
+ [/\</, '\textless{}'],
21
+ [/\>/, '\textgreater{}'],
22
+ [/([_$&%#])/, '\\\\\1']
23
+ ]
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,13 @@
1
+ module ArTeX
2
+
3
+ module Framework #:nodoc:
4
+
5
+ module Merb #:nodoc:
6
+
7
+ # TODO
8
+
9
+ end
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,28 @@
1
+ require 'tempfile'
2
+
3
+ module ArTeX
4
+ module Framework #:nodoc:
5
+ module Rails #:nodoc:
6
+
7
+ def self.setup
8
+ ArTeX::Document.options[:tempdir] = File.expand_path(File.join(RAILS_ROOT, 'tmp'))
9
+ end
10
+
11
+ module HelperMethods
12
+ # Similar to h()
13
+ def latex_escape(*args)
14
+ # Since Rails' I18n implementation aliases l() to localize(), LaTeX
15
+ # escaping should only be done if ArTeX is doing the rendering.
16
+ # Otherwise, control should be be passed to localize().
17
+ if Thread.current[:_rendering_rtex]
18
+ ArTeX::Document.escape(*args)
19
+ else
20
+ localize(*args)
21
+ end
22
+ end
23
+ alias :l :latex_escape
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,81 @@
1
+ #TODO Translate comments.
2
+ module ArTeX
3
+ class PDF
4
+
5
+ # Wir bilden das Verhalten von render :partial nach.
6
+ # So wird die Abhängigkeit zu ActionView aufgelöst.
7
+ # Dabei gehen sicherlich Möglichkeiten verloren, die hier aber auch nicht benötigt werden.
8
+ # Ziel ist die Verlagerung der PDF-Generierung aus dem Controller in Klassen bzw. Models,
9
+ # so dass dies auch im Hintergrund erfolgen kann.
10
+ #
11
+ # === Beispiele
12
+ # render :partial => "layouts/brandings/#{@bill.branding.template_name}"
13
+ # render :partial => 'bills/form/billing_position/_billing_position.pdf.rtex', :collection => @bill.billing_positions
14
+ def render(options = {})
15
+ content = ""
16
+
17
+ # Relativer Pfad zum Template
18
+ # z.B. 'bills/form/billing_position/_billing_position.pdf.rtex'
19
+ template_name = get_template_name_from_partial_name(options[:partial])
20
+
21
+ if is_collection?(options) then
22
+ content = render_collection(options[:collection], binding, template_name)
23
+ else
24
+ content = render_to_latex(binding, template_name)
25
+ end
26
+ return content
27
+ end
28
+
29
+ def is_collection?(options)
30
+ options[:collection] && options[:collection].is_a?(Array)
31
+ end
32
+
33
+ def render_collection(collection, binding, template_name)
34
+ content = ""
35
+
36
+ #TODO refactor
37
+ collection.each do |billing_position|
38
+ @billing_position = billing_position
39
+ latex = render_to_latex(binding, template_name)
40
+ content += latex
41
+ end
42
+ return content
43
+ end
44
+
45
+ # 'bills/form/billing_position/_billing_position.pdf.rtex' -> 'bills/form/billing_position/_billing_position.pdf.rtex'
46
+ def get_template_name_from_partial_name(partial_name)
47
+ parts = partial_name.split(/\//)
48
+
49
+ # "_" vor das letzte Element setzen.
50
+ parts[-1] = "_" + parts.last
51
+ template_name = parts.join("/")
52
+ template_name
53
+ end
54
+
55
+ def render_to_latex(binding, path)
56
+ template_path = get_template_path(path)
57
+ template = File.read(template_path)
58
+
59
+ latex_code = ERB.new(template).result(binding)
60
+ return latex_code
61
+ end
62
+
63
+ # Nimmt Latex und schreibt ein PDF. Gibt den Pfad zum PDF zurück.
64
+ def latex_to_pdf(latex_content)
65
+ pdf_file = ""
66
+ ::ArTeX::Document.new(latex_content, {:process => true} ).to_pdf do |filename|
67
+ pdf_file = Tempfile.new('artex-pdf')
68
+ FileUtils.mv filename, pdf_file.path
69
+ end
70
+ return pdf_file.path
71
+ end
72
+
73
+ def get_template_path(path)
74
+ raise "unimplemented"
75
+ end
76
+
77
+ def l(*args)
78
+ return ArTeX::Document.escape(*args)
79
+ end
80
+ end
81
+ end