grover 0.2.2 → 0.3.0
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.
- checksums.yaml +4 -4
- data/lib/grover/configuration.rb +12 -0
- data/lib/grover/middleware.rb +4 -2
- data/lib/grover/utils.rb +35 -0
- data/lib/grover/version.rb +1 -1
- data/lib/grover.rb +61 -9
- metadata +45 -3
- data/lib/grover/processor.rb +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0f700a9f110114c8de7c64f68ada3c60b183e002
|
4
|
+
data.tar.gz: 10038b11d2dc0e3a7deb9c8be59c17ce9fe75f5a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '08d9ea6100709712c0ac3a3adaf6c00c80ae45fca0fe38176d808e4f4c89efe8b900128d750056ca9b4a7db73dae1f099cec4d5f97851501459728480d181ab4'
|
7
|
+
data.tar.gz: df95c29b666dd3eb53bbb5c23acfd328f3750cdd2931dd08a9432805ec4089a9f13f17303b7f3a1cffe7655179f1ea97fb16d270f51287736692dc38fc085227
|
data/lib/grover/middleware.rb
CHANGED
@@ -29,12 +29,14 @@ class Grover
|
|
29
29
|
|
30
30
|
private
|
31
31
|
|
32
|
+
PDF_REGEX = /\.pdf$/i
|
33
|
+
|
32
34
|
def rendering_pdf?
|
33
35
|
@render_pdf
|
34
36
|
end
|
35
37
|
|
36
38
|
def render_as_pdf?
|
37
|
-
|
39
|
+
!@request.path.match(PDF_REGEX).nil?
|
38
40
|
end
|
39
41
|
|
40
42
|
def html_content?(headers)
|
@@ -61,7 +63,7 @@ class Grover
|
|
61
63
|
def configure_env_for_pdf_request(env)
|
62
64
|
@render_pdf = true
|
63
65
|
|
64
|
-
path = @request.path.sub(
|
66
|
+
path = @request.path.sub(PDF_REGEX, '')
|
65
67
|
path = path.sub(@request.script_name, '')
|
66
68
|
|
67
69
|
%w[PATH_INFO REQUEST_URI].each { |e| env[e] = path }
|
data/lib/grover/utils.rb
CHANGED
@@ -3,11 +3,46 @@ class Grover
|
|
3
3
|
# Utility class for Grover helper methods
|
4
4
|
#
|
5
5
|
class Utils
|
6
|
+
ACRONYMS = {
|
7
|
+
'css' => 'CSS'
|
8
|
+
}.freeze
|
9
|
+
private_constant :ACRONYMS
|
10
|
+
|
11
|
+
#
|
12
|
+
# Removes leading/trailing whitespaces and squishes inner whitespace with a single space
|
13
|
+
#
|
14
|
+
# N.B. whitespace includes all 'blank' characters as well as newlines/carriage returns etc.
|
15
|
+
#
|
6
16
|
def self.squish(string)
|
7
17
|
string.
|
8
18
|
gsub(/\A[[:space:]]+/, '').
|
9
19
|
gsub(/[[:space:]]+\z/, '').
|
10
20
|
gsub(/[[:space:]]+/, ' ')
|
11
21
|
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# Recursively normalizes hash objects with camelized string keys
|
25
|
+
#
|
26
|
+
def self.normalize_object(object)
|
27
|
+
if object.is_a? Hash
|
28
|
+
object.each_with_object({}) do |(k, v), acc|
|
29
|
+
acc[normalize_key(k)] = normalize_object(v)
|
30
|
+
end
|
31
|
+
else
|
32
|
+
object
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# Normalizes hash keys into camelized strings, including up-casing known acronyms
|
38
|
+
#
|
39
|
+
# Regex sourced from ActiveSupport camelize
|
40
|
+
#
|
41
|
+
def self.normalize_key(key)
|
42
|
+
key.to_s.downcase.gsub(%r{(?:_|(/))([a-z\d]*)}) do
|
43
|
+
"#{Regexp.last_match(1)}#{ACRONYMS[Regexp.last_match(2)] || Regexp.last_match(2).capitalize}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
private_class_method :normalize_key
|
12
47
|
end
|
13
48
|
end
|
data/lib/grover/version.rb
CHANGED
data/lib/grover.rb
CHANGED
@@ -1,14 +1,48 @@
|
|
1
1
|
require 'grover/version'
|
2
2
|
|
3
3
|
require 'grover/utils'
|
4
|
-
require 'grover/processor'
|
5
4
|
require 'grover/html_preprocessor'
|
6
5
|
require 'grover/middleware'
|
6
|
+
require 'grover/configuration'
|
7
|
+
|
8
|
+
require 'schmooze'
|
7
9
|
|
8
10
|
#
|
9
11
|
# Grover interface for converting HTML to PDF
|
10
12
|
#
|
11
13
|
class Grover
|
14
|
+
#
|
15
|
+
# Processor helper class for calling out to Puppeteer NodeJS library
|
16
|
+
#
|
17
|
+
class Processor < Schmooze::Base
|
18
|
+
dependencies puppeteer: 'puppeteer'
|
19
|
+
|
20
|
+
def self.launch_params
|
21
|
+
ENV['CI'] == 'true' ? "{args: ['--no-sandbox', '--disable-setuid-sandbox']}" : ''
|
22
|
+
end
|
23
|
+
|
24
|
+
method :convert_pdf, Utils.squish(<<-FUNCTION)
|
25
|
+
async (url, options) => {
|
26
|
+
let browser;
|
27
|
+
try {
|
28
|
+
browser = await puppeteer.launch(#{launch_params});
|
29
|
+
const page = await browser.newPage();
|
30
|
+
if (url.match(/^http/i)) {
|
31
|
+
await page.goto(url, { waitUntil: 'networkidle2' });
|
32
|
+
} else {
|
33
|
+
await page.goto(`data:text/html,${url}`, { waitUntil: 'networkidle0' });
|
34
|
+
}
|
35
|
+
return await page.pdf(options);
|
36
|
+
} finally {
|
37
|
+
if (browser) {
|
38
|
+
await browser.close();
|
39
|
+
}
|
40
|
+
}
|
41
|
+
}
|
42
|
+
FUNCTION
|
43
|
+
end
|
44
|
+
private_constant :Processor
|
45
|
+
|
12
46
|
#
|
13
47
|
# @param [String] url URL of the page to convert
|
14
48
|
# @param [Hash] options Optional parameters to pass to PDF processor
|
@@ -16,32 +50,44 @@ class Grover
|
|
16
50
|
#
|
17
51
|
def initialize(url, options = {})
|
18
52
|
@url = url
|
19
|
-
@
|
20
|
-
@
|
53
|
+
@options = Grover.configuration.options.merge options
|
54
|
+
@root_path = @options.delete :root_path
|
21
55
|
end
|
22
56
|
|
23
57
|
#
|
24
58
|
# Request URL with provided options and create PDF
|
25
59
|
#
|
26
60
|
# @param [String] path Optional path to write the PDF to
|
27
|
-
# @return [
|
61
|
+
# @return [String] The resulting PDF data
|
28
62
|
#
|
29
63
|
def to_pdf(path = nil)
|
30
|
-
|
31
|
-
options[:path] = path if path
|
32
|
-
result = processor.convert_pdf @url, options
|
64
|
+
result = processor.convert_pdf @url, normalized_options(path)
|
33
65
|
result['data'].pack('c*')
|
34
66
|
end
|
35
67
|
|
68
|
+
#
|
69
|
+
# Instance inspection
|
70
|
+
#
|
36
71
|
def inspect
|
37
72
|
format(
|
38
73
|
'#<%<class_name>s:0x%<object_id>p @url="%<url>s">',
|
39
74
|
class_name: self.class.name,
|
40
75
|
object_id: object_id,
|
41
|
-
url: url
|
76
|
+
url: @url
|
42
77
|
)
|
43
78
|
end
|
44
79
|
|
80
|
+
#
|
81
|
+
# Configuration for the conversion
|
82
|
+
#
|
83
|
+
def self.configuration
|
84
|
+
@configuration ||= Configuration.new
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.configure
|
88
|
+
yield(configuration)
|
89
|
+
end
|
90
|
+
|
45
91
|
private
|
46
92
|
|
47
93
|
def root_path
|
@@ -49,6 +95,12 @@ class Grover
|
|
49
95
|
end
|
50
96
|
|
51
97
|
def processor
|
52
|
-
|
98
|
+
Processor.new(root_path)
|
99
|
+
end
|
100
|
+
|
101
|
+
def normalized_options(path)
|
102
|
+
options = Utils.normalize_object @options
|
103
|
+
options['path'] = path if path
|
104
|
+
options
|
53
105
|
end
|
54
106
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: grover
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Bromwich
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-08-
|
11
|
+
date: 2018-08-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: schmooze
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '5.2'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '5.2'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: bundler
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,6 +52,20 @@ dependencies:
|
|
38
52
|
- - "~>"
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '1.3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rack-test
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.1'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.1'
|
41
69
|
- !ruby/object:Gem::Dependency
|
42
70
|
name: rake
|
43
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +108,20 @@ dependencies:
|
|
80
108
|
- - "~>"
|
81
109
|
- !ruby/object:Gem::Version
|
82
110
|
version: '0.53'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rubocop-rspec
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '1.28'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '1.28'
|
83
125
|
- !ruby/object:Gem::Dependency
|
84
126
|
name: simplecov
|
85
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -102,9 +144,9 @@ extensions: []
|
|
102
144
|
extra_rdoc_files: []
|
103
145
|
files:
|
104
146
|
- lib/grover.rb
|
147
|
+
- lib/grover/configuration.rb
|
105
148
|
- lib/grover/html_preprocessor.rb
|
106
149
|
- lib/grover/middleware.rb
|
107
|
-
- lib/grover/processor.rb
|
108
150
|
- lib/grover/utils.rb
|
109
151
|
- lib/grover/version.rb
|
110
152
|
homepage: http://github.com/Studiosity/grover
|
data/lib/grover/processor.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
require 'schmooze'
|
2
|
-
|
3
|
-
class Grover
|
4
|
-
#
|
5
|
-
# Processor helper class for calling out to Puppeteer NodeJS library
|
6
|
-
#
|
7
|
-
class Processor < Schmooze::Base
|
8
|
-
dependencies puppeteer: 'puppeteer'
|
9
|
-
|
10
|
-
def self.launch_params
|
11
|
-
ENV['CI'] == 'true' ? "{args: ['--no-sandbox', '--disable-setuid-sandbox']}" : ''
|
12
|
-
end
|
13
|
-
private_class_method :launch_params
|
14
|
-
|
15
|
-
method :convert_pdf, Utils.squish(<<-FUNCTION)
|
16
|
-
async (url, options) => {
|
17
|
-
let browser;
|
18
|
-
try {
|
19
|
-
browser = await puppeteer.launch(#{launch_params});
|
20
|
-
const page = await browser.newPage();
|
21
|
-
if (url.match(/^http/i)) {
|
22
|
-
await page.goto(url, { waitUntil: 'networkidle2' });
|
23
|
-
} else {
|
24
|
-
await page.goto(`data:text/html,${url}`, { waitUntil: 'networkidle0' });
|
25
|
-
}
|
26
|
-
return await page.pdf(options);
|
27
|
-
} finally {
|
28
|
-
if (browser) {
|
29
|
-
await browser.close();
|
30
|
-
}
|
31
|
-
}
|
32
|
-
}
|
33
|
-
FUNCTION
|
34
|
-
end
|
35
|
-
end
|