grover 1.2.6 → 1.2.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 52cfb87c3efabd49ef2e83562f918ca7c8f5e0d51721ae52ca35ad9281b2b378
4
- data.tar.gz: 6ecadfce0b7efb45a693df41f0065a0136ed315555b65c0580ace664b4f380c1
3
+ metadata.gz: 7db2892eede2403ccadf9ba0f08437a0baa981891cfa15b352a9a93540fa210e
4
+ data.tar.gz: 7d1e39781fb526c53f3445545ee810d275cea55c1216b08b1b3f8135027c0d58
5
5
  SHA512:
6
- metadata.gz: f41aa2df2e2580e1102830315b0845a00cbe4184d2aee839e1161e11fcc22fa794209293ca50c5bb7c543404b79ae71251b7fb3131ae0e1350e8aa72374f0d77
7
- data.tar.gz: e7df3f9cca33bf7dd1f18010dbfd01f85f8ac616601f337372ff968e5178a6f54a9429717dcd9a93bb01bcea79446d481374522112b373b96a06b731d243625c
6
+ metadata.gz: d54d14998ffe44d160b5b4586dc7a41a09f80a63a362b0745916052fc06d126b273c358992fc4a5273e6d7c2c668d18120cad4392409905de56ffa54e0850648
7
+ data.tar.gz: 58c59d86aceb48f4968bcc1c0ad6bd44b8e7602450e24304da1d61249b6e529ae9614e6c9d15c1fdad1e49f8575cd6a6c282a634af24000532573a68e03f8ca1
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Grover
4
+ #
5
+ # DevToolsParser helper class for simplifying the debug output
6
+ #
7
+ class DevToolsParser
8
+ class << self
9
+ def parse(raw_devtools_output) # rubocop:disable Metrics/MethodLength
10
+ lines = raw_devtools_output.strip.split("\n")
11
+ simplified_output = []
12
+
13
+ while lines.any?
14
+ if starts_with_array_pattern? lines
15
+ simplified_output.push extract_array_pattern!(lines)
16
+ elsif starts_with_hash_pattern? lines
17
+ simplified_output.push extract_hash_pattern!(lines)
18
+ else
19
+ simplified_output.push lines.shift
20
+ end
21
+ end
22
+
23
+ simplified_output
24
+ end
25
+
26
+ private
27
+
28
+ def starts_with_array_pattern?(lines)
29
+ lines.length >= 3 && lines[0].end_with?(' [') && lines[1].start_with?(" '") && lines[2] == ']'
30
+ end
31
+
32
+ def extract_array_pattern!(lines)
33
+ "#{lines.shift}#{lines.shift[1..]} #{lines.shift}"
34
+ end
35
+
36
+ def starts_with_hash_pattern?(lines)
37
+ return false unless lines.length >= 3 && lines[0].end_with?(' {')
38
+
39
+ last_hash_line = lines[1..].index { |line| !line.match?(/\A .*,\z/) }
40
+ return false if last_hash_line.nil?
41
+
42
+ lines[last_hash_line + 1].match?(/\A .*[^,]\z/) && lines[last_hash_line + 2] == '}'
43
+ end
44
+
45
+ def extract_hash_pattern!(lines)
46
+ result = lines.shift
47
+ result += lines.shift[1..] while lines[0] != '}'
48
+ result + " #{lines.shift}"
49
+ end
50
+ end
51
+ end
52
+ end
data/lib/grover/errors.rb CHANGED
@@ -6,11 +6,18 @@ class Grover
6
6
  #
7
7
  # Heavily based on the Schmooze library https://github.com/Shopify/schmooze
8
8
  #
9
- Error = Class.new(StandardError)
10
- DependencyError = Class.new(Error)
9
+ class Error < StandardError
10
+ end
11
+
12
+ class DependencyError < Error
13
+ end
14
+
11
15
  module JavaScript # rubocop:disable Style/Documentation
12
- Error = Class.new(::Grover::Error)
13
- UnknownError = Class.new(Error)
16
+ class Error < ::Grover::Error
17
+ end
18
+
19
+ class UnknownError < Error
20
+ end
14
21
 
15
22
  ErrorWithDetails = Class.new(Error) do
16
23
  def initialize(name, error_details)
@@ -20,12 +27,17 @@ class Grover
20
27
 
21
28
  attr_reader :error_details
22
29
  end
23
- RequestFailedError = Class.new(ErrorWithDetails)
24
- PageRenderError = Class.new(ErrorWithDetails)
30
+ class RequestFailedError < ErrorWithDetails
31
+ end
32
+
33
+ class PageRenderError < ErrorWithDetails
34
+ end
25
35
 
26
36
  def self.const_missing(name)
27
37
  const_set name, Class.new(Error)
28
38
  end
29
39
  end
30
- UnsafeConfigurationError = Class.new(Error)
40
+
41
+ class UnsafeConfigurationError < Error
42
+ end
31
43
  end
@@ -26,6 +26,8 @@ class Grover
26
26
  cleanup_process if stdin
27
27
  end
28
28
 
29
+ attr_reader :debug_output
30
+
29
31
  private
30
32
 
31
33
  attr_reader :app_root, :stdin, :stdout, :stderr, :wait_thr
@@ -83,6 +85,8 @@ class Grover
83
85
  input = stdout.gets
84
86
  raise Errno::EPIPE, "Can't read from worker" if input.nil?
85
87
 
88
+ capture_debug_output if node_debug_enabled?
89
+
86
90
  status, message, error_class, errors = JSON.parse(input)
87
91
 
88
92
  if status == 'ok'
@@ -98,6 +102,18 @@ class Grover
98
102
  raise Grover::Error, "Worker process failed:\n#{stderr.read}"
99
103
  end
100
104
 
105
+ def capture_debug_output
106
+ error_output = ''
107
+ begin
108
+ loop { error_output += stderr.read_nonblock(4096).force_encoding('UTF-8') }
109
+ rescue IO::WaitReadable
110
+ nil
111
+ end
112
+ @debug_output = Grover::DevToolsParser.parse(error_output)
113
+ end
114
+
115
+ def node_debug_enabled? = Grover.configuration.node_env_vars.keys.include?('DEBUG')
116
+
101
117
  def cleanup_process
102
118
  stdin.close
103
119
  stdout.close
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Grover
4
- VERSION = '1.2.6'
4
+ VERSION = '1.2.7'
5
5
  end
data/lib/grover.rb CHANGED
@@ -10,6 +10,7 @@ require 'grover/html_preprocessor'
10
10
  require 'grover/middleware'
11
11
  require 'grover/configuration'
12
12
  require 'grover/options_builder'
13
+ require 'grover/dev_tools_parser'
13
14
  require 'grover/processor'
14
15
 
15
16
  require 'nokogiri'
@@ -48,6 +49,7 @@ class Grover
48
49
  # @return [String] The resulting PDF data
49
50
  #
50
51
  def to_pdf(path = nil)
52
+ @processor = nil # Flush out the processor from any previous use
51
53
  processor.convert :pdf, @uri, normalized_options(path: path)
52
54
  end
53
55
 
@@ -57,6 +59,7 @@ class Grover
57
59
  # @return [String] The resulting HTML string
58
60
  #
59
61
  def to_html
62
+ @processor = nil # Flush out the processor from any previous use
60
63
  processor.convert :content, @uri, normalized_options(path: nil)
61
64
  end
62
65
 
@@ -68,6 +71,7 @@ class Grover
68
71
  # @return [String] The resulting image data
69
72
  #
70
73
  def screenshot(path: nil, format: nil)
74
+ @processor = nil # Flush out the processor from any previous use
71
75
  options = normalized_options(path: path)
72
76
  options['type'] = format if %w[png jpeg].include? format
73
77
  processor.convert :screenshot, @uri, options
@@ -111,6 +115,15 @@ class Grover
111
115
  back_cover_path.is_a?(::String) && back_cover_path.start_with?('/')
112
116
  end
113
117
 
118
+ #
119
+ # Returns the debug output from the conversion process.
120
+ #
121
+ # @return [Array<String>, nil] An array of DevTools log output, or `nil` if DEBUG env var is not enabled
122
+ #
123
+ def debug_output
124
+ processor.debug_output
125
+ end
126
+
114
127
  #
115
128
  # Instance inspection
116
129
  #
@@ -141,7 +154,7 @@ class Grover
141
154
  end
142
155
 
143
156
  def processor
144
- Processor.new(root_path)
157
+ @processor ||= Processor.new(root_path)
145
158
  end
146
159
 
147
160
  def normalized_options(path:)
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: 1.2.6
4
+ version: 1.2.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Bromwich
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-01-14 00:00:00.000000000 Z
11
+ date: 2026-02-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -36,6 +36,7 @@ files:
36
36
  - lib/active_support_ext/object/duplicable.rb
37
37
  - lib/grover.rb
38
38
  - lib/grover/configuration.rb
39
+ - lib/grover/dev_tools_parser.rb
39
40
  - lib/grover/errors.rb
40
41
  - lib/grover/html_preprocessor.rb
41
42
  - lib/grover/js/processor.cjs