puppet_pdf 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +191 -7
- data/Gemfile.lock +13 -17
- data/README.md +36 -7
- data/javascript/pdf_creator.js +89 -0
- data/lib/puppet_pdf.rb +4 -4
- data/lib/puppet_pdf/helpers/controller.rb +40 -0
- data/lib/puppet_pdf/helpers/view.rb +39 -0
- data/lib/puppet_pdf/pdf_creator.rb +22 -7
- data/lib/puppet_pdf/railtie.rb +8 -0
- data/lib/puppet_pdf/version.rb +1 -1
- data/lib/utils/yarn_wrapper.rb +4 -2
- data/package.json +1 -2
- data/puppet_pdf.gemspec +4 -5
- metadata +32 -18
- data/javascript/pdf_from_html.js +0 -52
- data/javascript/pdf_from_url.js +0 -50
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 931e17a61d7981d219cf583c45dd464599a0f86e56edf87c3dad6c21bf2a4b65
|
4
|
+
data.tar.gz: d87e8e519952e5e197918f4884696ccf4856346c8d9e5b3d4d275dd41c4c4931
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 440037c96df342cf09b6be6084ffd330bcb79843b8a2ecfc1193a7fb1741872b29bdaa9e6bc2b5bfc9a56d5a3d6f648787102a7ddbf846215b1f83117f36ee0a
|
7
|
+
data.tar.gz: 629f58890f6d32abcb6e99d008d9cd57117e85a22c6637dc37cf8104e884257808c7f392ddc1e23bf0c0d88d566a0ef8a321908f809e9f7ff0e7e569b161fd81
|
data/.gitignore
CHANGED
@@ -1,13 +1,197 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
# Created by https://www.gitignore.io/api/vim,node,ruby,macos
|
2
|
+
# Edit at https://www.gitignore.io/?templates=vim,node,ruby,macos
|
3
|
+
|
4
|
+
### macOS ###
|
5
|
+
# General
|
6
|
+
.DS_Store
|
7
|
+
.AppleDouble
|
8
|
+
.LSOverride
|
9
|
+
|
10
|
+
# Icon must end with two \r
|
11
|
+
Icon
|
12
|
+
|
13
|
+
# Thumbnails
|
14
|
+
._*
|
15
|
+
|
16
|
+
# Files that might appear in the root of a volume
|
17
|
+
.DocumentRevisions-V100
|
18
|
+
.fseventsd
|
19
|
+
.Spotlight-V100
|
20
|
+
.TemporaryItems
|
21
|
+
.Trashes
|
22
|
+
.VolumeIcon.icns
|
23
|
+
.com.apple.timemachine.donotpresent
|
24
|
+
|
25
|
+
# Directories potentially created on remote AFP share
|
26
|
+
.AppleDB
|
27
|
+
.AppleDesktop
|
28
|
+
Network Trash Folder
|
29
|
+
Temporary Items
|
30
|
+
.apdisk
|
31
|
+
|
32
|
+
### Node ###
|
33
|
+
# Logs
|
34
|
+
logs
|
35
|
+
*.log
|
36
|
+
npm-debug.log*
|
37
|
+
yarn-debug.log*
|
38
|
+
yarn-error.log*
|
39
|
+
lerna-debug.log*
|
40
|
+
|
41
|
+
# Diagnostic reports (https://nodejs.org/api/report.html)
|
42
|
+
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
43
|
+
|
44
|
+
# Runtime data
|
45
|
+
pids
|
46
|
+
*.pid
|
47
|
+
*.seed
|
48
|
+
*.pid.lock
|
49
|
+
|
50
|
+
# Directory for instrumented libs generated by jscoverage/JSCover
|
51
|
+
lib-cov
|
52
|
+
|
53
|
+
# Coverage directory used by tools like istanbul
|
54
|
+
coverage
|
55
|
+
*.lcov
|
56
|
+
|
57
|
+
# nyc test coverage
|
58
|
+
.nyc_output
|
59
|
+
|
60
|
+
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
61
|
+
.grunt
|
62
|
+
|
63
|
+
# Bower dependency directory (https://bower.io/)
|
64
|
+
bower_components
|
65
|
+
|
66
|
+
# node-waf configuration
|
67
|
+
.lock-wscript
|
68
|
+
|
69
|
+
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
70
|
+
build/Release
|
71
|
+
|
72
|
+
# Dependency directories
|
73
|
+
node_modules/
|
74
|
+
jspm_packages/
|
75
|
+
|
76
|
+
# TypeScript v1 declaration files
|
77
|
+
typings/
|
78
|
+
|
79
|
+
# TypeScript cache
|
80
|
+
*.tsbuildinfo
|
81
|
+
|
82
|
+
# Optional npm cache directory
|
83
|
+
.npm
|
84
|
+
|
85
|
+
# Optional eslint cache
|
86
|
+
.eslintcache
|
87
|
+
|
88
|
+
# Optional REPL history
|
89
|
+
.node_repl_history
|
90
|
+
|
91
|
+
# Output of 'npm pack'
|
92
|
+
*.tgz
|
93
|
+
|
94
|
+
# Yarn Integrity file
|
95
|
+
.yarn-integrity
|
96
|
+
|
97
|
+
# dotenv environment variables file
|
98
|
+
.env
|
99
|
+
.env.test
|
100
|
+
|
101
|
+
# parcel-bundler cache (https://parceljs.org/)
|
102
|
+
.cache
|
103
|
+
|
104
|
+
# next.js build output
|
105
|
+
.next
|
106
|
+
|
107
|
+
# nuxt.js build output
|
108
|
+
.nuxt
|
109
|
+
|
110
|
+
# vuepress build output
|
111
|
+
.vuepress/dist
|
112
|
+
|
113
|
+
# Serverless directories
|
114
|
+
.serverless/
|
115
|
+
|
116
|
+
# FuseBox cache
|
117
|
+
.fusebox/
|
118
|
+
|
119
|
+
# DynamoDB Local files
|
120
|
+
.dynamodb/
|
121
|
+
|
122
|
+
### Ruby ###
|
123
|
+
*.gem
|
124
|
+
*.rbc
|
125
|
+
/.config
|
4
126
|
/coverage/
|
5
|
-
/
|
127
|
+
/InstalledFiles
|
6
128
|
/pkg/
|
7
129
|
/spec/reports/
|
130
|
+
/spec/examples.txt
|
131
|
+
/test/tmp/
|
132
|
+
/test/version_tmp/
|
8
133
|
/tmp/
|
9
134
|
|
10
|
-
#
|
11
|
-
.
|
135
|
+
# Used by dotenv library to load environment variables.
|
136
|
+
# .env
|
137
|
+
|
138
|
+
# Ignore Byebug command history file.
|
139
|
+
.byebug_history
|
140
|
+
|
141
|
+
## Specific to RubyMotion:
|
142
|
+
.dat*
|
143
|
+
.repl_history
|
144
|
+
build/
|
145
|
+
*.bridgesupport
|
146
|
+
build-iPhoneOS/
|
147
|
+
build-iPhoneSimulator/
|
12
148
|
|
13
|
-
|
149
|
+
## Specific to RubyMotion (use of CocoaPods):
|
150
|
+
#
|
151
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
152
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
153
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
154
|
+
# vendor/Pods/
|
155
|
+
|
156
|
+
## Documentation cache and generated files:
|
157
|
+
/.yardoc/
|
158
|
+
/_yardoc/
|
159
|
+
/doc/
|
160
|
+
/rdoc/
|
161
|
+
|
162
|
+
## Environment normalization:
|
163
|
+
/.bundle/
|
164
|
+
/vendor/bundle
|
165
|
+
/lib/bundler/man/
|
166
|
+
|
167
|
+
# for a library or gem, you might want to ignore these files since the code is
|
168
|
+
# intended to run in multiple environments; otherwise, check them in:
|
169
|
+
# Gemfile.lock
|
170
|
+
# .ruby-version
|
171
|
+
# .ruby-gemset
|
172
|
+
|
173
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
174
|
+
.rvmrc
|
175
|
+
|
176
|
+
### Vim ###
|
177
|
+
# Swap
|
178
|
+
[._]*.s[a-v][a-z]
|
179
|
+
[._]*.sw[a-p]
|
180
|
+
[._]s[a-rt-v][a-z]
|
181
|
+
[._]ss[a-gi-z]
|
182
|
+
[._]sw[a-p]
|
183
|
+
|
184
|
+
# Session
|
185
|
+
Session.vim
|
186
|
+
Sessionx.vim
|
187
|
+
|
188
|
+
# Temporary
|
189
|
+
.netrwhist
|
190
|
+
*~
|
191
|
+
# Auto-generated tag files
|
192
|
+
tags
|
193
|
+
# Persistent undo
|
194
|
+
[._]*.un~
|
195
|
+
|
196
|
+
# End of https://www.gitignore.io/api/vim,node,ruby,macos# rspec failure tracking
|
197
|
+
.rspec_status
|
data/Gemfile.lock
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
puppet_pdf (0.
|
5
|
-
activerecord
|
6
|
-
railties
|
4
|
+
puppet_pdf (0.2.0)
|
5
|
+
activerecord (~> 5.0, >= 5.0.0.1)
|
6
|
+
railties (~> 5.2, >= 5.2.3)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
@@ -42,7 +42,7 @@ GEM
|
|
42
42
|
erubi (1.8.0)
|
43
43
|
i18n (1.6.0)
|
44
44
|
concurrent-ruby (~> 1.0)
|
45
|
-
jaro_winkler (1.5.
|
45
|
+
jaro_winkler (1.5.3)
|
46
46
|
loofah (2.2.3)
|
47
47
|
crass (~> 1.0.2)
|
48
48
|
nokogiri (>= 1.5.9)
|
@@ -51,14 +51,12 @@ GEM
|
|
51
51
|
minitest (5.11.3)
|
52
52
|
nokogiri (1.10.3)
|
53
53
|
mini_portile2 (~> 2.4.0)
|
54
|
-
parallel (1.
|
55
|
-
parser (2.6.
|
54
|
+
parallel (1.17.0)
|
55
|
+
parser (2.6.3.0)
|
56
56
|
ast (~> 2.4.0)
|
57
|
-
powerpack (0.1.2)
|
58
57
|
pry (0.12.2)
|
59
58
|
coderay (~> 1.1.0)
|
60
59
|
method_source (~> 0.9.0)
|
61
|
-
psych (3.1.0)
|
62
60
|
rack (2.0.7)
|
63
61
|
rack-test (1.1.0)
|
64
62
|
rack (>= 1.0, < 3)
|
@@ -88,32 +86,30 @@ GEM
|
|
88
86
|
diff-lcs (>= 1.2.0, < 2.0)
|
89
87
|
rspec-support (~> 3.8.0)
|
90
88
|
rspec-support (3.8.0)
|
91
|
-
rubocop (0.
|
89
|
+
rubocop (0.72.0)
|
92
90
|
jaro_winkler (~> 1.5.1)
|
93
91
|
parallel (~> 1.10)
|
94
|
-
parser (>= 2.
|
95
|
-
powerpack (~> 0.1)
|
96
|
-
psych (>= 3.1.0)
|
92
|
+
parser (>= 2.6)
|
97
93
|
rainbow (>= 2.2.2, < 4.0)
|
98
94
|
ruby-progressbar (~> 1.7)
|
99
|
-
unicode-display_width (
|
100
|
-
ruby-progressbar (1.10.
|
95
|
+
unicode-display_width (>= 1.4.0, < 1.7)
|
96
|
+
ruby-progressbar (1.10.1)
|
101
97
|
thor (0.20.3)
|
102
98
|
thread_safe (0.3.6)
|
103
99
|
tzinfo (1.2.5)
|
104
100
|
thread_safe (~> 0.1)
|
105
|
-
unicode-display_width (1.
|
101
|
+
unicode-display_width (1.6.0)
|
106
102
|
|
107
103
|
PLATFORMS
|
108
104
|
ruby
|
109
105
|
|
110
106
|
DEPENDENCIES
|
111
107
|
bundler (~> 1.16)
|
112
|
-
pry
|
108
|
+
pry (~> 0.12.2)
|
113
109
|
puppet_pdf!
|
114
110
|
rake (~> 10.0)
|
115
111
|
rspec (~> 3.0)
|
116
|
-
rubocop
|
112
|
+
rubocop (~> 0.72.0)
|
117
113
|
|
118
114
|
BUNDLED WITH
|
119
115
|
1.17.3
|
data/README.md
CHANGED
@@ -26,24 +26,53 @@ Run this task to install some dependencies:
|
|
26
26
|
|
27
27
|
## Usage
|
28
28
|
|
29
|
-
|
29
|
+
### Render in a controller
|
30
30
|
|
31
31
|
```ruby
|
32
|
-
|
32
|
+
class TasksController < ApplicationController
|
33
|
+
def pdf
|
34
|
+
render_pdf
|
35
|
+
end
|
36
|
+
end
|
33
37
|
```
|
34
38
|
|
35
|
-
to
|
39
|
+
You can pass some options to `render_pdf` like template, layout and the output filename. The available options are:
|
36
40
|
|
37
41
|
```ruby
|
38
|
-
|
42
|
+
{
|
43
|
+
template: String, # The template to be rendered. Default: 'controller_path/action_name'
|
44
|
+
layout: String, # Default: 'application'
|
45
|
+
filename: String, # Default: 'action_name.pdf'
|
46
|
+
header: String, # The header of the pdf. Default: '<header></header>'
|
47
|
+
footer: String, # The header of the pdf. Default: '<footer></footer>'
|
48
|
+
margins: Hash, # The margins of the pdf. Default: { top: 36, right: 36, bottom: 45, left: 36 }
|
49
|
+
loading_delay: Integer, # Time to load the page javascript in ms. Default: 1000
|
50
|
+
output_path: String # The output path of the pdf. Default: generated by Tempfile
|
51
|
+
}
|
39
52
|
```
|
40
53
|
|
41
|
-
to generate a pdf from an html.
|
42
54
|
|
55
|
+
### View Helpers
|
56
|
+
In you views you need to replace `stylesheet_link_tag` with `puppet_stylesheet_link_tag`, and `javascript_include_tag` with `puppet_javascript_script_tag`
|
43
57
|
|
44
|
-
|
58
|
+
```html
|
59
|
+
<!DOCTYPE html>
|
60
|
+
<html>
|
61
|
+
<head>
|
62
|
+
<title>PuppetPdfExample</title>
|
63
|
+
<%= csrf_meta_tags %>
|
64
|
+
<%= csp_meta_tag %>
|
65
|
+
|
66
|
+
<%= puppet_stylesheet_link_tag('application.css') %>
|
67
|
+
<%= puppet_javascript_script_tag('application.js') %>
|
68
|
+
</head>
|
69
|
+
|
70
|
+
<body>
|
71
|
+
<%= yield %>
|
72
|
+
</body>
|
73
|
+
</html>
|
74
|
+
```
|
45
75
|
|
46
|
-
And a pdf of the given url will be generated, and the path to this file is going to be returned.
|
47
76
|
|
48
77
|
## Contributing
|
49
78
|
|
@@ -0,0 +1,89 @@
|
|
1
|
+
'use strict'
|
2
|
+
|
3
|
+
const puppeteer = require('puppeteer')
|
4
|
+
const fs = require('fs')
|
5
|
+
const path = require('path')
|
6
|
+
|
7
|
+
var log = fs.createWriteStream(path.resolve(__dirname, '/tmp/puppet_pdf.log'), { 'flags': 'a' })
|
8
|
+
process.stdout.write = process.stderr.write = log.write.bind(log)
|
9
|
+
|
10
|
+
const defaultOptions = {
|
11
|
+
header: "<header></header>",
|
12
|
+
footer: "<footer></footer>",
|
13
|
+
loadingDelay: 1000,
|
14
|
+
margin: { top: 36, right: 36, bottom: 45, left: 36 }
|
15
|
+
}
|
16
|
+
|
17
|
+
/**
|
18
|
+
*
|
19
|
+
* argv[2] source The source of the pdf content.
|
20
|
+
* argv[3] options A JSON with the pdf creation options.
|
21
|
+
* The available options are:
|
22
|
+
* - outputPath
|
23
|
+
* - header
|
24
|
+
* - footer
|
25
|
+
* - loadingDelay
|
26
|
+
* - margin: { :top, :right, :bottom, :left }
|
27
|
+
*
|
28
|
+
*/
|
29
|
+
async function createPdf() {
|
30
|
+
const source = process.argv[2]
|
31
|
+
const options = JSON.parse(process.argv[3])
|
32
|
+
|
33
|
+
if(Object.is(options.outputPath, undefined)) throw 'You must provide the outputPath option'
|
34
|
+
|
35
|
+
let browser
|
36
|
+
try {
|
37
|
+
const browser = await getBrowser()
|
38
|
+
const page = await getPageWithContent(browser, source)
|
39
|
+
|
40
|
+
await page.waitFor(getOption('loadingDelay', options))
|
41
|
+
await page.pdf({
|
42
|
+
path: options.outputPath,
|
43
|
+
format: 'A4',
|
44
|
+
margin: getOption('margin', options),
|
45
|
+
displayHeaderFooter: true,
|
46
|
+
headerTemplate: getOption('header', options),
|
47
|
+
footerTemplate: getOption('footer', options),
|
48
|
+
})
|
49
|
+
} catch (err) {
|
50
|
+
const formatedMessage = `\n ${err.message} at: ${getCurrentTimeFormated()}`
|
51
|
+
log.write(formatedMessage)
|
52
|
+
} finally {
|
53
|
+
if (browser) browser.close()
|
54
|
+
|
55
|
+
process.exit()
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
async function getPageWithContent(browser, source) {
|
60
|
+
const page = await browser.newPage()
|
61
|
+
const pageOptions = { timeout: 900000, waitUntil: 'networkidle0' }
|
62
|
+
|
63
|
+
const contents = fs.readFileSync(source, 'utf8')
|
64
|
+
await page.setContent(contents, pageOptions)
|
65
|
+
|
66
|
+
return page
|
67
|
+
}
|
68
|
+
|
69
|
+
async function getBrowser() {
|
70
|
+
return puppeteer.launch({
|
71
|
+
headless: true,
|
72
|
+
pipe: true,
|
73
|
+
args: ['--disable-gpu', '--full-memory-crash-report', '--unlimited-storage',
|
74
|
+
'--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage'],
|
75
|
+
})
|
76
|
+
}
|
77
|
+
|
78
|
+
function getOption(key, options) {
|
79
|
+
return Object.is(options[key], undefined) ? defaultOptions[key] : options[key]
|
80
|
+
}
|
81
|
+
|
82
|
+
function getCurrentTimeFormated() {
|
83
|
+
const date = new Date()
|
84
|
+
const dateFormatted = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`
|
85
|
+
|
86
|
+
return `${dateFormatted}, ${date.toLocaleTimeString('en')}`
|
87
|
+
}
|
88
|
+
|
89
|
+
createPdf()
|
data/lib/puppet_pdf.rb
CHANGED
@@ -4,14 +4,14 @@ require 'puppet_pdf/railtie' if defined?(Rails)
|
|
4
4
|
|
5
5
|
module PuppetPdf
|
6
6
|
def self.pdf_from_url(url, options = {})
|
7
|
-
pdf_creator(:
|
7
|
+
pdf_creator(:url, url, options).call
|
8
8
|
end
|
9
9
|
|
10
10
|
def self.pdf_from_html(html, options = {})
|
11
|
-
pdf_creator(:
|
11
|
+
pdf_creator(:html, html, options).call
|
12
12
|
end
|
13
13
|
|
14
|
-
private_class_method def self.pdf_creator(
|
15
|
-
::PuppetPdf::PdfCreator.new(
|
14
|
+
private_class_method def self.pdf_creator(source_type, source, options)
|
15
|
+
::PuppetPdf::PdfCreator.new(source_type, source, options)
|
16
16
|
end
|
17
17
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module PuppetPdf
|
2
|
+
module Helpers
|
3
|
+
module Controller
|
4
|
+
def render_pdf(args = {})
|
5
|
+
html = render_to_string(render_params(args))
|
6
|
+
|
7
|
+
html_path = create_file_and_get_path(html)
|
8
|
+
options = args.slice(:header, :footer, :margins, :loading_delay)
|
9
|
+
file_path = ::PuppetPdf::PdfCreator.new(html_path, options).call
|
10
|
+
|
11
|
+
send_file(file_path,
|
12
|
+
filename: args.fetch(:filename, "#{action_name}.pdf"),
|
13
|
+
disposition: :inline)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def render_params(params)
|
19
|
+
{
|
20
|
+
template: params.fetch(:template, default_template),
|
21
|
+
layout: params.fetch(:layout, 'application'),
|
22
|
+
locals: params.fetch(:locals, {})
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def default_template
|
27
|
+
File.join(controller_path, action_name)
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_file_and_get_path(content)
|
31
|
+
file = Tempfile.new(Time.now.to_i.to_s)
|
32
|
+
file_path = file.path
|
33
|
+
file.write(content)
|
34
|
+
file.close
|
35
|
+
|
36
|
+
file_path
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'active_support/core_ext/string/output_safety'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
module PuppetPdf
|
5
|
+
module Helpers
|
6
|
+
module View
|
7
|
+
def puppet_stylesheet_link_tag(asset)
|
8
|
+
asset_tag = <<~TAG
|
9
|
+
<style type='text/css'>
|
10
|
+
#{asset_content(asset)}
|
11
|
+
</style>
|
12
|
+
TAG
|
13
|
+
|
14
|
+
asset_tag
|
15
|
+
.force_encoding('utf-8')
|
16
|
+
.html_safe
|
17
|
+
end
|
18
|
+
|
19
|
+
def puppet_javascript_script_tag(asset)
|
20
|
+
asset_tag = <<~TAG
|
21
|
+
<script type='application/javascript'>
|
22
|
+
#{asset_content(asset)}
|
23
|
+
</script>
|
24
|
+
TAG
|
25
|
+
|
26
|
+
asset_tag
|
27
|
+
.force_encoding('utf-8')
|
28
|
+
.html_safe
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def asset_content(asset)
|
34
|
+
url = asset_url(asset)
|
35
|
+
OpenURI.open_uri(url, &:read)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -1,26 +1,41 @@
|
|
1
1
|
require 'tempfile'
|
2
2
|
require 'utils/yarn_wrapper'
|
3
|
+
require 'json'
|
3
4
|
|
4
5
|
module PuppetPdf
|
5
6
|
class PdfCreator
|
6
7
|
include ::Utils::YarnWrapper
|
7
8
|
|
8
|
-
|
9
|
+
attr_reader :source, :options
|
10
|
+
|
11
|
+
def initialize(source, options = {})
|
9
12
|
validate_yarn_installation
|
10
13
|
|
11
|
-
@
|
12
|
-
@
|
13
|
-
|
14
|
+
@source = source
|
15
|
+
@options = options.tap do |opt|
|
16
|
+
opt[:output_path] = opt.fetch(:output_path, default_output_path)
|
17
|
+
end
|
14
18
|
end
|
15
19
|
|
16
20
|
def call
|
17
|
-
run_yarn(
|
18
|
-
output_path
|
21
|
+
run_yarn(:create_pdf, source, options_json)
|
22
|
+
options[:output_path]
|
19
23
|
end
|
20
24
|
|
21
25
|
private
|
22
26
|
|
23
|
-
|
27
|
+
def options_json
|
28
|
+
options
|
29
|
+
.each_with_object({}) { |(key, val), opts| opts[camelize(key)] = val }
|
30
|
+
.to_json
|
31
|
+
end
|
32
|
+
|
33
|
+
def camelize(string)
|
34
|
+
string_arr = string.to_s.split('_')
|
35
|
+
head, *tail = string_arr
|
36
|
+
|
37
|
+
head.downcase + tail.map(&:capitalize).join
|
38
|
+
end
|
24
39
|
|
25
40
|
def default_output_path
|
26
41
|
file = Tempfile.new(["puppet_pdf_#{Time.now.to_i}", '.pdf'])
|
data/lib/puppet_pdf/railtie.rb
CHANGED
@@ -1,7 +1,15 @@
|
|
1
|
+
require 'puppet_pdf/helpers/controller'
|
2
|
+
require 'puppet_pdf/helpers/view'
|
3
|
+
|
1
4
|
module PuppetPdf
|
2
5
|
class Railtie < Rails::Railtie
|
3
6
|
rake_tasks do
|
4
7
|
load 'tasks/install_dependencies.rake'
|
5
8
|
end
|
9
|
+
|
10
|
+
initializer 'puppet_pdf.register_helpers' do |_|
|
11
|
+
ActionController::Base.send :prepend, PuppetPdf::Helpers::Controller
|
12
|
+
ActionView::Base.send :include, PuppetPdf::Helpers::View
|
13
|
+
end
|
6
14
|
end
|
7
15
|
end
|
data/lib/puppet_pdf/version.rb
CHANGED
data/lib/utils/yarn_wrapper.rb
CHANGED
@@ -10,8 +10,6 @@ module Utils
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def validate_yarn_installation
|
13
|
-
which_yarn_output = `which yarn`
|
14
|
-
|
15
13
|
raise 'Yarn not installed!' if which_yarn_output.empty?
|
16
14
|
end
|
17
15
|
|
@@ -22,6 +20,10 @@ module Utils
|
|
22
20
|
Shellwords.escape(Gem.loaded_specs['puppet_pdf'].full_gem_path)
|
23
21
|
end
|
24
22
|
|
23
|
+
def which_yarn_output
|
24
|
+
`which yarn`
|
25
|
+
end
|
26
|
+
|
25
27
|
def prepare_args(args)
|
26
28
|
args.map { |arg| Shellwords.escape(arg) }.join(' ')
|
27
29
|
end
|
data/package.json
CHANGED
data/puppet_pdf.gemspec
CHANGED
@@ -9,7 +9,6 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.email = ['fernandesanderson14@gmail.com']
|
10
10
|
|
11
11
|
spec.summary = 'Simple PDF generator based on Google Puppeteer'
|
12
|
-
spec.description = 'Simple PDF generator based on Google Puppeteer'
|
13
12
|
spec.homepage = 'https://github.com/andersonfernandes/puppet_pdf'
|
14
13
|
spec.license = 'MIT'
|
15
14
|
|
@@ -21,11 +20,11 @@ Gem::Specification.new do |spec|
|
|
21
20
|
spec.require_paths = ['lib']
|
22
21
|
|
23
22
|
spec.add_development_dependency 'bundler', '~> 1.16'
|
24
|
-
spec.add_development_dependency 'pry'
|
23
|
+
spec.add_development_dependency 'pry', '~> 0.12.2'
|
25
24
|
spec.add_development_dependency 'rake', '~> 10.0'
|
26
25
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
27
|
-
spec.add_development_dependency 'rubocop'
|
26
|
+
spec.add_development_dependency 'rubocop', '~> 0.72.0'
|
28
27
|
|
29
|
-
spec.add_dependency 'activerecord'
|
30
|
-
spec.add_dependency 'railties'
|
28
|
+
spec.add_dependency 'activerecord', '~> 5.0', '>= 5.0.0.1'
|
29
|
+
spec.add_dependency 'railties', '~> 5.2', '>= 5.2.3'
|
31
30
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puppet_pdf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anderson Fernandes
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-07-
|
11
|
+
date: 2019-07-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -28,16 +28,16 @@ dependencies:
|
|
28
28
|
name: pry
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 0.12.2
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 0.12.2
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -70,45 +70,57 @@ dependencies:
|
|
70
70
|
name: rubocop
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
75
|
+
version: 0.72.0
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - "
|
80
|
+
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
82
|
+
version: 0.72.0
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: activerecord
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '5.0'
|
87
90
|
- - ">="
|
88
91
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
92
|
+
version: 5.0.0.1
|
90
93
|
type: :runtime
|
91
94
|
prerelease: false
|
92
95
|
version_requirements: !ruby/object:Gem::Requirement
|
93
96
|
requirements:
|
97
|
+
- - "~>"
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '5.0'
|
94
100
|
- - ">="
|
95
101
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
102
|
+
version: 5.0.0.1
|
97
103
|
- !ruby/object:Gem::Dependency
|
98
104
|
name: railties
|
99
105
|
requirement: !ruby/object:Gem::Requirement
|
100
106
|
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '5.2'
|
101
110
|
- - ">="
|
102
111
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
112
|
+
version: 5.2.3
|
104
113
|
type: :runtime
|
105
114
|
prerelease: false
|
106
115
|
version_requirements: !ruby/object:Gem::Requirement
|
107
116
|
requirements:
|
117
|
+
- - "~>"
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '5.2'
|
108
120
|
- - ">="
|
109
121
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
111
|
-
description:
|
122
|
+
version: 5.2.3
|
123
|
+
description:
|
112
124
|
email:
|
113
125
|
- fernandesanderson14@gmail.com
|
114
126
|
executables: []
|
@@ -127,9 +139,10 @@ files:
|
|
127
139
|
- Rakefile
|
128
140
|
- bin/console
|
129
141
|
- bin/setup
|
130
|
-
- javascript/
|
131
|
-
- javascript/pdf_from_url.js
|
142
|
+
- javascript/pdf_creator.js
|
132
143
|
- lib/puppet_pdf.rb
|
144
|
+
- lib/puppet_pdf/helpers/controller.rb
|
145
|
+
- lib/puppet_pdf/helpers/view.rb
|
133
146
|
- lib/puppet_pdf/pdf_creator.rb
|
134
147
|
- lib/puppet_pdf/railtie.rb
|
135
148
|
- lib/puppet_pdf/version.rb
|
@@ -157,7 +170,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
157
170
|
- !ruby/object:Gem::Version
|
158
171
|
version: '0'
|
159
172
|
requirements: []
|
160
|
-
|
173
|
+
rubyforge_project:
|
174
|
+
rubygems_version: 2.7.7
|
161
175
|
signing_key:
|
162
176
|
specification_version: 4
|
163
177
|
summary: Simple PDF generator based on Google Puppeteer
|
data/javascript/pdf_from_html.js
DELETED
@@ -1,52 +0,0 @@
|
|
1
|
-
'use strict';
|
2
|
-
|
3
|
-
const puppeteer = require('puppeteer');
|
4
|
-
const fs = require('fs')
|
5
|
-
const path = require('path')
|
6
|
-
|
7
|
-
function getCurrentTimeFormated() {
|
8
|
-
const date = new Date();
|
9
|
-
const dateFormatted = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`
|
10
|
-
|
11
|
-
return `${dateFormatted}, ${date.toLocaleTimeString('en')}`
|
12
|
-
}
|
13
|
-
|
14
|
-
var access = fs.createWriteStream(path.resolve(__dirname, '/tmp/puppeteer.log'), { 'flags': 'a' });
|
15
|
-
// Redirect stdout/stderr to puppeteer.log file
|
16
|
-
process.stdout.write = process.stderr.write = access.write.bind(access);
|
17
|
-
|
18
|
-
const pdf_from_html = async () => {
|
19
|
-
let browser;
|
20
|
-
try {
|
21
|
-
const browser = await puppeteer.launch({
|
22
|
-
headless: true,
|
23
|
-
pipe: true,
|
24
|
-
args: ['--disable-gpu', '--full-memory-crash-report', '--unlimited-storage',
|
25
|
-
'--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage'],
|
26
|
-
});
|
27
|
-
const page = await browser.newPage();
|
28
|
-
|
29
|
-
var contents = fs.readFileSync(process.argv[2], 'utf8');
|
30
|
-
await page.setContent(contents, { timeout: 900000, waitUntil: 'networkidle0' });
|
31
|
-
await page.waitFor(1000);
|
32
|
-
await page.pdf({
|
33
|
-
path: process.argv[3],
|
34
|
-
format: 'A4',
|
35
|
-
margin: { top: 36, right: 36, bottom: 45, left: 36 },
|
36
|
-
displayHeaderFooter: true,
|
37
|
-
headerTemplate: "<div></div>",
|
38
|
-
footerTemplate: "<div></div>"
|
39
|
-
});
|
40
|
-
} catch (err) {
|
41
|
-
const formatedMessage = `\n ${err.message} at: ${getCurrentTimeFormated()}`;
|
42
|
-
access.write(formatedMessage)
|
43
|
-
} finally {
|
44
|
-
if (browser) {
|
45
|
-
browser.close();
|
46
|
-
}
|
47
|
-
process.exit();
|
48
|
-
}
|
49
|
-
};
|
50
|
-
|
51
|
-
pdf_from_html();
|
52
|
-
|
data/javascript/pdf_from_url.js
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
'use strict';
|
2
|
-
|
3
|
-
const puppeteer = require('puppeteer');
|
4
|
-
const fs = require('fs')
|
5
|
-
const path = require('path')
|
6
|
-
|
7
|
-
function getCurrentTimeFormated() {
|
8
|
-
const date = new Date();
|
9
|
-
const dateFormatted = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`
|
10
|
-
|
11
|
-
return `${dateFormatted}, ${date.toLocaleTimeString('en')}`
|
12
|
-
}
|
13
|
-
|
14
|
-
var access = fs.createWriteStream(path.resolve(__dirname, '/tmp/puppeteer.log'), { 'flags': 'a' });
|
15
|
-
// Redirect stdout/stderr to puppeteer.log file
|
16
|
-
process.stdout.write = process.stderr.write = access.write.bind(access);
|
17
|
-
|
18
|
-
const pdf_from_url = async () => {
|
19
|
-
let browser;
|
20
|
-
try {
|
21
|
-
const browser = await puppeteer.launch({
|
22
|
-
headless: true,
|
23
|
-
pipe: true,
|
24
|
-
args: ['--disable-gpu', '--full-memory-crash-report', '--unlimited-storage',
|
25
|
-
'--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage'],
|
26
|
-
});
|
27
|
-
const page = await browser.newPage();
|
28
|
-
await page.goto(process.argv[2], { timeout: 90000, waitUntil: 'networkidle0' });
|
29
|
-
await page.waitFor(1000);
|
30
|
-
await page.pdf({
|
31
|
-
path: process.argv[3],
|
32
|
-
format: 'A4',
|
33
|
-
margin: { top: 36, right: 36, bottom: 45, left: 36 },
|
34
|
-
displayHeaderFooter: true,
|
35
|
-
headerTemplate: "<div></div>",
|
36
|
-
footerTemplate: "<div></div>"
|
37
|
-
});
|
38
|
-
} catch (err) {
|
39
|
-
const formatedMessage = `\n ${err.message} at: ${getCurrentTimeFormated()}`;
|
40
|
-
access.write(formatedMessage)
|
41
|
-
} finally {
|
42
|
-
if (browser) {
|
43
|
-
browser.close();
|
44
|
-
}
|
45
|
-
process.exit();
|
46
|
-
}
|
47
|
-
};
|
48
|
-
|
49
|
-
pdf_from_url();
|
50
|
-
|