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 +4 -4
- data/Gemfile.lock +6 -0
- data/README.mdown +68 -8
- data/bin/rpdf +12 -0
- data/lib/tilt/pdf.rb +160 -19
- data/lib/tilt/pdf/version.rb +1 -1
- data/tilt-pdf.gemspec +1 -0
- metadata +19 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 247b71fd7cda93fc8cdceb16c353970f65e797b1
|
4
|
+
data.tar.gz: a807223ca174825f593c1f4054ea5acee03595bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
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
|
16
|
-
|
17
|
-
|
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
|
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
|
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
|
-
|
14
|
-
|
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
|
-
|
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
|
-
|
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
|
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.
|
52
|
-
|
53
|
-
|
54
|
-
|
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
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
data/lib/tilt/pdf/version.rb
CHANGED
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.
|
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:
|
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
|