tilt-pdf 0.1.2 → 0.9.0

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
  SHA1:
3
- metadata.gz: 904b13930a088f4c72611eccdfe740a85a98471c
4
- data.tar.gz: 44ebea0f15cf06dc5a01a6bd1116d249d71f0b44
3
+ metadata.gz: 247b71fd7cda93fc8cdceb16c353970f65e797b1
4
+ data.tar.gz: a807223ca174825f593c1f4054ea5acee03595bd
5
5
  SHA512:
6
- metadata.gz: 970fb92052f681cb25da3c9cc4e496ed6f0ed8f7c087e416803d519ba3cc65e048ba722161f7f36830b3f6b5b081389cab1bd1aac72e7701c57d1fd86ffabbf9
7
- data.tar.gz: b7486a64fe8b15e6298d402fc26731b99b1d27c4d0cf80e28bca80939aa7d8da51fec8851ebc496a2c26fd5f6bf3bb08b11594476ab5e1043aaf213b6632f330
6
+ metadata.gz: afcd08e875fe00d859c62de97dcc73ebb2ca84d9f9d884a8d11ad0237f6961b490f0d7eedaa6f8fe1d3aaef5801e1241c50e67af52108f830d7460a783197abb
7
+ data.tar.gz: 68ae18b4493492f9e79b5aee73aab29c2b8f3d48859d75f95e9aa86a1848f45548b161a3200506b998b49aeaded6388ee7f109cadbb532cee7d63ab8ee52b129
data/Gemfile.lock CHANGED
@@ -11,8 +11,13 @@ GEM
11
11
  celluloid (0.15.2)
12
12
  timers (~> 1.1.0)
13
13
  coderay (1.0.9)
14
+ coffee-script (2.2.0)
15
+ coffee-script-source
16
+ execjs
17
+ coffee-script-source (1.7.0)
14
18
  commonjs (0.2.7)
15
19
  diff-lcs (1.2.4)
20
+ execjs (2.0.2)
16
21
  ffi (1.9.0)
17
22
  formatador (0.2.4)
18
23
  guard (2.1.1)
@@ -67,6 +72,7 @@ PLATFORMS
67
72
  ruby
68
73
 
69
74
  DEPENDENCIES
75
+ coffee-script
70
76
  guard-rspec
71
77
  less
72
78
  pry
data/README.mdown CHANGED
@@ -1,20 +1,36 @@
1
1
  # Tilt::PDF
2
2
 
3
- Integrates PDF generation into a Tilt flow
3
+ Integrates PDF generation into a Tilt flow for maxxed out ease of use.
4
+
5
+ Contrary to other solutions, all files will be rendered locally without relying
6
+ on a web server. It follows that even if used in a web server, no concurrent
7
+ requests are being made to render assets.
4
8
 
5
9
  ## Dependencies
6
10
 
7
- This gem depends on PDFKit, which in turn requires `wkhtmltopdf`. It is recommended to use the statically compiled version of the latter, as it is built against a patched QT that supports more features.
11
+ This gem depends on PDFKit, which in turn requires `wkhtmltopdf`. It is
12
+ recommended to use the statically compiled version of the latter, as it is
13
+ built against a patched QT that supports more features.
8
14
 
9
15
  ## Usage as a Tilt template
10
16
 
11
- Add `tilt-pdf` to your Gemfile. Also add any template engine you may optionally want, such as `less` or `slim`.
17
+ Add `tilt-pdf` to your Gemfile. Also add any template engine you may optionally
18
+ want, such as `less` or `slim`.
12
19
 
13
20
  A `foo` template is currently threefold:
14
21
 
15
- - `foo.rpdf`: this file is a YAML file containing options pertaining to the PDF generation process, such as page size, orientation and metadata. Options are apssed as is to PDFKit, and subsequently to `wkhtmltopdf`.
16
- - `foo.html`: this document can be written in any template language you need (such as ERB or Slim), and the Tilt template resolution system via extension chaining will apply. Tilt will pass the render block to be yielded to this document.
17
- - `foo.css`: this stylesheet can be written in any template language you need (such as Sass or Less), and the Tilt template resolution system via extension chaining will apply. Tilt will *not* pass the block to be yielded to this template.
22
+ - `foo.rpdf`: this file is a YAML file containing options pertaining to the PDF
23
+ generation process, such as page size, orientation, metadata, support files,
24
+ headers and footers. Some options are passed as is to PDFKit, and
25
+ subsequently to `wkhtmltopdf`.
26
+ - `foo.html`: this document can be written in any template language you need
27
+ (such as ERB or Slim), and the Tilt template resolution system via extension
28
+ chaining will apply. Tilt will pass the render block to be yielded to this
29
+ document.
30
+ - `foo.css`: this stylesheet can be written in any template language you need
31
+ (such as Sass or Less), and the Tilt template resolution system via extension
32
+ chaining will apply. Tilt will *not* pass the block to be yielded to this
33
+ template.
18
34
 
19
35
  The three files must currently be stored in the *same* directory.
20
36
 
@@ -26,12 +42,56 @@ require 'tilt-pdf'
26
42
  pdf = Tilt.new('foo.rpdf').render()
27
43
  ```
28
44
 
45
+ ## The rpdf file
46
+
47
+ This file contains options. If empty, it is made to 'just work' as
48
+ summplemental files will be looked up according to its basename.
49
+
50
+ - `main`: document body, overriding the default derived from the basename.
51
+ - `footer` and `header`: html that will get used for (surprise!) header and
52
+ footers.
53
+ - `stylesheets`: list of stylesheets to include (used for all html, incl.
54
+ headers/footers). Defaults to one file from the basename.
55
+ - `javascripts`: list of javascripts to include (used for all html, incl.
56
+ headers/footers). Defaults to one file from the basename.
57
+ - `pdfkit`: While a few PDFKit options are made available at the toplevel for
58
+ convenience, this key passes all options as-is to PDFKit.
59
+
60
+ Example:
61
+
62
+ ```
63
+ title: Foorever young
64
+ page-size: A4
65
+ orientation: landscape
66
+ grayscale: true
67
+ margin-left: 0
68
+ margin-right: 0
69
+ margin-top: 0
70
+ margin-bottom: 0
71
+ pdfkit:
72
+ print-media-type: true
73
+ main: foorever_young.html.slim
74
+ stylesheets:
75
+ - novel.css.less
76
+ - common.css
77
+ javascripts:
78
+ - page_numbering.js.coffee
79
+ footer: footer.html.slim
80
+ ```
81
+
82
+ Filenames can be relative or absolute. When relative, they will be evaluated
83
+ as based from the rpdf file.
84
+
29
85
  ## Rails and ActionView integration
30
86
 
31
- Require `tilt/pdf/rails` if you want to set up and register `tilt-pdf` as an ActionView template handler. You can do it in an initializer, or straight from the Gemfile:
87
+ Require `tilt/pdf/rails` if you want to set up and register `tilt-pdf` as an
88
+ ActionView template handler. You can do it in an initializer, or straight from
89
+ the Gemfile:
32
90
 
33
91
  ```ruby
34
92
  gem 'tilt-pdf', require: 'tilt/pdf/rails'
35
93
  ```
36
94
 
37
- Put your three template files *together* in the relevant `app/views/foo` view directory. Work is in progress to enable better integration with Rails file layout.
95
+ Put your three template files *together* in the relevant `app/views/foo` view
96
+ directory, or use absolute paths using application/engine root. Work is in
97
+ progress to enable better integration with Rails file layout.
data/bin/rpdf ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.push File.expand_path(File.join(__FILE__, '../..'))
4
+
5
+ require 'tilt-pdf'
6
+ require 'slim'
7
+
8
+ rpdf = ARGV.shift or fail('usage: rpdf filename')
9
+ pdf = Tilt.new(rpdf).render
10
+ File.open(File.basename(rpdf, '.rpdf') + '.pdf', 'wb') do |f|
11
+ f.write(pdf)
12
+ end
data/lib/tilt/pdf.rb CHANGED
@@ -2,6 +2,8 @@ require 'pdfkit'
2
2
  require 'tilt'
3
3
  require 'tilt/template'
4
4
  require 'yaml'
5
+ require 'tempfile'
6
+ require 'pry'
5
7
 
6
8
  module Tilt
7
9
  class PDFTemplate < Template
@@ -10,13 +12,24 @@ module Tilt
10
12
  def prepare; end
11
13
 
12
14
  def evaluate(scope, locals, &block)
13
- html_file = find_html
14
- html = render_html(html_file, scope, locals, &block)
15
+ files = aux_files
16
+ files << main_html_file
17
+ render_to_tmp(*files, scope, locals, block) do |tmp|
18
+ opts = pdfkit_options
19
+
20
+ if header
21
+ htmp = tmp.select { |_, f, _| f == header }.first[2]
22
+ opts.merge!('header-html' => htmp) if header
23
+ end
24
+
25
+ if footer
26
+ ftmp = tmp.select { |_, f, _| f == footer }.first[2]
27
+ opts.merge!('footer-html' => ftmp) if footer
28
+ end
29
+
30
+ main = tmp.select { |_, f, _| f == main_html_file }.first[2]
31
+ kit = PDFKit.new(File.read(main), opts)
15
32
 
16
- css_files = find_css
17
- render_css(*css_files) do |*css|
18
- kit = PDFKit.new(html, pdfkit_options)
19
- css.each { |f| kit.stylesheets << f }
20
33
  @output = kit.to_pdf
21
34
  end
22
35
 
@@ -25,12 +38,83 @@ module Tilt
25
38
 
26
39
  private
27
40
 
41
+ def absolutize(path)
42
+ Pathname.new(path).absolute? ? path : File.join(dirname, path)
43
+ end
44
+
45
+ def config
46
+ @config = (YAML.load(data) || {})
47
+ end
48
+
49
+ def aux_files
50
+ files = []
51
+ files.concat css_files
52
+ files.concat js_files
53
+ files << header if header
54
+ files << footer if footer
55
+
56
+ files
57
+ end
58
+
59
+ def header
60
+ if (f = config['header'])
61
+ absolutize(f)
62
+ end
63
+ end
64
+
65
+ def footer
66
+ if (f = config['footer'])
67
+ absolutize(f)
68
+ end
69
+ end
70
+
71
+ def main_html_file
72
+ main_html_from_config || find_html
73
+ end
74
+
75
+ def main_html_from_config
76
+ if (f = config['main'])
77
+ absolutize(f)
78
+ end
79
+ end
80
+
81
+ def css_files
82
+ css_from_config || find_css
83
+ end
84
+
85
+ def css_from_config
86
+ return unless config.key?('stylesheets')
87
+
88
+ config.fetch('stylesheets', []).map { |f| absolutize(f) }
89
+ end
90
+
91
+ def js_files
92
+ js_from_config || find_js
93
+ end
94
+
95
+ def js_from_config
96
+ return unless config.key?('javascripts')
97
+
98
+ config.fetch('javascripts', []).map { |f| absolutize(f) }
99
+ end
100
+
28
101
  def pdfkit_options
29
- YAML.load(data) || {}
102
+ toplevel_options = %w[title
103
+ orientation
104
+ grayscale
105
+ page-size
106
+ margin-left
107
+ margin-right
108
+ margin-top
109
+ margin-bottom]
110
+
111
+ options = config.select { |k, _| toplevel_options.include?(k) }
112
+
113
+ options.merge config.fetch('pdfkit', {})
30
114
  end
31
115
 
32
116
  def dirname
33
- eval_file.gsub(/#{basename}$/, '').chomp('/')
117
+ File.dirname(eval_file)
34
118
  end
35
119
 
36
120
  def find_html
@@ -41,26 +125,83 @@ module Tilt
41
125
  Dir.glob(File.join(dirname, name + '.css*'))
42
126
  end
43
127
 
128
+ def find_js
129
+ Dir.glob(File.join(dirname, name + '.js*'))
130
+ end
131
+
44
132
  def render_html(file, scope, locals, &block)
45
133
  Tilt.new(file).render(scope, locals, &block)
46
134
  end
47
135
 
48
- def render_css(*files)
136
+ def inject_css!(document, stylesheet)
137
+ append_to_head!(document, "<style>#{stylesheet}</style>")
138
+ end
139
+
140
+ def inject_js!(document, script)
141
+ append_to_head!(document, "<script>#{script}</script>")
142
+ end
143
+
144
+ def append_to_head!(document, tag)
145
+ if document.match(/<\/head>/)
146
+ document.gsub!(/(<\/head>)/) { |s| tag + s }
147
+ else
148
+ document.insert(0, tag)
149
+ end
150
+ end
151
+
152
+ def render_to_tmp(*files, scope, locals, block)
49
153
  tmps = []
154
+ no_tilt = %w[html css js]
50
155
 
51
- files.each do |file|
52
- case file
53
- when /.*\.css$/
54
- yield file
156
+ result = files.map do |file|
157
+ ext = File.extname(file).sub(/^\./, '')
158
+ if no_tilt.include?(ext)
159
+ mime = case ext
160
+ when 'js', 'javascript' then 'application/javascript'
161
+ else "text/#{ext}"
162
+ end
163
+ rendered = File.read(file)
55
164
  else
56
- tmp = Tempfile.new(File.basename(file))
57
- tmps << tmp
58
- css = Tilt.new(file).render
59
- tmp.write(css)
60
- tmp.close
61
- yield tmp.path
165
+ template = Tilt.new(file)
166
+ mime = template.class.default_mime_type
167
+ ext = mime.split('/').last
168
+ rendered = template.render(scope, locals, &block)
169
+ end
170
+
171
+ [ext, mime, file, rendered]
172
+ end
173
+
174
+ result.sort! do |a, b|
175
+ a[1] <=> b[1] # css < html
176
+ end
177
+
178
+ styles = result.select { |_, mime, _, _| mime == 'text/css' }
179
+ scripts = result.select { |_, mime, _, _| mime == 'application/javascript' }
180
+ result.map! do |ext, mime, file, rendered|
181
+ if mime == 'text/html'
182
+ styles.each do |_, _, _, style|
183
+ inject_css!(rendered, style)
184
+ end
185
+ scripts.each do |_, _, _, script|
186
+ inject_js!(rendered, script)
187
+ end
62
188
  end
189
+
190
+ [ext, mime, file, rendered]
63
191
  end
192
+
193
+ result.map! do |ext, mime, file, rendered|
194
+ tmp = Tempfile.new([File.basename(file), '.' + ext])
195
+ tmps << tmp
196
+ tmp.write(rendered)
197
+ tmp.close
198
+
199
+ path = tmp.path
200
+
201
+ [mime, file, path]
202
+ end
203
+
204
+ yield result
64
205
  ensure
65
206
  tmps.each { |tmp| tmp.close! }
66
207
  end
@@ -1,5 +1,5 @@
1
1
  module Tilt
2
2
  module PDF
3
- VERSION = '0.1.2'
3
+ VERSION = '0.9.0'
4
4
  end
5
5
  end
data/tilt-pdf.gemspec CHANGED
@@ -22,6 +22,7 @@ Gem::Specification.new do |s|
22
22
 
23
23
  s.add_development_dependency 'therubyracer'
24
24
  s.add_development_dependency 'less'
25
+ s.add_development_dependency 'coffee-script'
25
26
  s.add_development_dependency 'slim'
26
27
  s.add_development_dependency 'rspec', '~> 2.14'
27
28
  s.add_development_dependency 'rake'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tilt-pdf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Loic Nageleisen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-14 00:00:00.000000000 Z
11
+ date: 2014-02-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tilt
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - '>='
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: coffee-script
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: slim
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -139,7 +153,8 @@ dependencies:
139
153
  description: Integrates PDF generation into a Tilt flow
140
154
  email:
141
155
  - loic.nageleisen@gmail.com
142
- executables: []
156
+ executables:
157
+ - rpdf
143
158
  extensions: []
144
159
  extra_rdoc_files: []
145
160
  files:
@@ -149,6 +164,7 @@ files:
149
164
  - Gemfile.lock
150
165
  - LICENSE
151
166
  - README.mdown
167
+ - bin/rpdf
152
168
  - lib/tilt-pdf.rb
153
169
  - lib/tilt/pdf.rb
154
170
  - lib/tilt/pdf/rails.rb