puppeteer_entity 0.1.1
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 +7 -0
- data/.rubocop.yml +13 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +9 -0
- data/LICENSE +21 -0
- data/README.md +39 -0
- data/Rakefile +12 -0
- data/docker-compose.yml +7 -0
- data/lib/puppeteer_entity/attributes/authenticate.rb +12 -0
- data/lib/puppeteer_entity/attributes/content.rb +64 -0
- data/lib/puppeteer_entity/attributes/cookie.rb +26 -0
- data/lib/puppeteer_entity/attributes/goto_options.rb +19 -0
- data/lib/puppeteer_entity/attributes/pdf.rb +106 -0
- data/lib/puppeteer_entity/attributes/query.rb +25 -0
- data/lib/puppeteer_entity/attributes/screenshot.rb +95 -0
- data/lib/puppeteer_entity/attributes/script_tag.rb +20 -0
- data/lib/puppeteer_entity/attributes/style_tag.rb +16 -0
- data/lib/puppeteer_entity/attributes/viewport.rb +22 -0
- data/lib/puppeteer_entity/attributes/wait_for_event.rb +12 -0
- data/lib/puppeteer_entity/attributes/wait_for_function.rb +16 -0
- data/lib/puppeteer_entity/attributes/wait_for_selector.rb +14 -0
- data/lib/puppeteer_entity/base.rb +60 -0
- data/lib/puppeteer_entity/content.rb +30 -0
- data/lib/puppeteer_entity/pdf.rb +37 -0
- data/lib/puppeteer_entity/screenshot.rb +43 -0
- data/lib/puppeteer_entity/types.rb +11 -0
- data/lib/puppeteer_entity/version.rb +5 -0
- data/lib/puppeteer_entity.rb +13 -0
- metadata +187 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 633fdd774eaaa00ceb3fe75f627b18f247839546a278bd8a978b2a6dc9bbc4b1
|
4
|
+
data.tar.gz: 89e521f5f856dbfba6dffc1d57de071a743b9a2708ef02a3831fef4b66dcc3e8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fb2bf515eaa92f4b89375be8aef47568c1aca6727016ba9b23c04ae0795fd19f79752c029a719743bc17f1e6d08dff58179a5d32e238de77822c1550f1da844c
|
7
|
+
data.tar.gz: ac8b09ae2c7a883aa271a0500400fbb4ea80bff89d9ebea18f11e4f565fdf869218b6e983b669f21e16cebdc31345f992af166b48408ba78b9c21658d82261eb
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Omakase Ruby styling for Rails
|
2
|
+
inherit_gem: { rubocop-rails-omakase: rubocop.yml }
|
3
|
+
# Overwrite or add rules to create your own house style
|
4
|
+
#
|
5
|
+
# # Use `[a, [b, c]]` not `[ a, [ b, c ] ]`
|
6
|
+
# Layout/SpaceInsideArrayLiteralBrackets:
|
7
|
+
# Enabled: false
|
8
|
+
|
9
|
+
Style/HashSyntax:
|
10
|
+
EnforcedShorthandSyntax: always
|
11
|
+
|
12
|
+
AllCops:
|
13
|
+
TargetRubyVersion: 3.3.5
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.3.5
|
data/CHANGELOG.md
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2024 Tomáš Celizna
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# PuppeteerEntity
|
2
|
+
|
3
|
+
[](https://github.com/tomasc/puppeteer_entity/actions/workflows/test.yml)
|
4
|
+
|
5
|
+
`PuppeteerEntity` is a Ruby gem that provides a simple and intuitive interface for interacting with Puppeteer, a headless Chrome browser. It allows you to take screenshots, capture content, and perform other actions on web pages.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
To install PuppeteerEntity, add it to your application's Gemfile and run `bundle install`:
|
10
|
+
|
11
|
+
```bash
|
12
|
+
bundle add puppeteer_entity
|
13
|
+
```
|
14
|
+
|
15
|
+
If you're not using Bundler, you can install the gem directly:
|
16
|
+
|
17
|
+
```bash
|
18
|
+
gem install puppeteer_entity
|
19
|
+
```
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
To use PuppeteerEntity, create a new instance of the `PuppeteerEntity::Screenshot` or `PuppeteerEntity::Content` class, passing the necessary arguments. Then, call the `response` method on the instance to get the HTTP response.
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
args = { url: "https://example.com" }
|
27
|
+
entity = PuppeteerEntity::Screenshot.new(args)
|
28
|
+
response = entity.response
|
29
|
+
```
|
30
|
+
|
31
|
+
## Development
|
32
|
+
|
33
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
34
|
+
|
35
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
36
|
+
|
37
|
+
## Contributing
|
38
|
+
|
39
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/puppeteer_entity.
|
data/Rakefile
ADDED
data/docker-compose.yml
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PuppeteerEntity
|
4
|
+
module Attributes
|
5
|
+
class Authenticate < Dry::Struct
|
6
|
+
transform_keys(&:to_sym)
|
7
|
+
|
8
|
+
attribute :username, Types::Coercible::String
|
9
|
+
attribute :password, Types::Coercible::String
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PuppeteerEntity
|
4
|
+
module Attributes
|
5
|
+
class Content < Dry::Struct
|
6
|
+
transform_keys(&:to_sym)
|
7
|
+
|
8
|
+
attribute? :add_script_tag, Types::Array do
|
9
|
+
attributes_from Attributes::ScriptTag
|
10
|
+
end
|
11
|
+
|
12
|
+
attribute? :add_style_tag, Types::Array do
|
13
|
+
attributes_from Attributes::StyleTag
|
14
|
+
end
|
15
|
+
|
16
|
+
attribute? :authenticate do
|
17
|
+
attributes_from Attributes::Authenticate
|
18
|
+
end
|
19
|
+
|
20
|
+
# When bestAttempt is set to true, browserless attempt to proceed when "awaited" events fail or timeout. This includes things like goto, waitForSelector, and more.
|
21
|
+
attribute? :best_attempt, Types::Bool.optional
|
22
|
+
|
23
|
+
attribute? :cookies, Types::Array do
|
24
|
+
attributes_from Attributes::Cookie
|
25
|
+
end
|
26
|
+
|
27
|
+
attribute? :emulate_media_type, Types::Coercible::String.optional
|
28
|
+
|
29
|
+
attribute? :goto_options do
|
30
|
+
attributes_from Attributes::GotoOptions
|
31
|
+
end
|
32
|
+
|
33
|
+
attribute? :html, Types::Coercible::String.optional
|
34
|
+
|
35
|
+
attribute? :reject_request_pattern, Types::Array.of(Types::String).optional
|
36
|
+
attribute? :reject_resource_types, Types::Array.of(Types::Coercible::String.enum("cspviolationreport", "document", "eventsource", "fetch", "font", "image", "manifest", "media", "other", "ping", "prefetch", "preflight", "script", "signedexchange", "stylesheet", "texttrack", "websocket", "xhr")).optional
|
37
|
+
attribute? :request_interceptors, Types::Array.optional
|
38
|
+
|
39
|
+
attribute? :set_extra_http_headers, Types::Array.optional
|
40
|
+
attribute? :set_java_script_enabled, Types::Bool.optional
|
41
|
+
|
42
|
+
attribute? :url, Types::URL.optional
|
43
|
+
attribute? :user_agent, Types::Coercible::String.optional
|
44
|
+
|
45
|
+
attribute? :viewport do
|
46
|
+
attributes_from Attributes::Viewport
|
47
|
+
end
|
48
|
+
|
49
|
+
attribute? :wait_for_event do
|
50
|
+
attributes_from Attributes::WaitForEvent
|
51
|
+
end
|
52
|
+
|
53
|
+
attribute? :wait_for_function do
|
54
|
+
attributes_from Attributes::WaitForFunction
|
55
|
+
end
|
56
|
+
|
57
|
+
attribute? :wait_for_selector do
|
58
|
+
attributes_from Attributes::WaitForSelector
|
59
|
+
end
|
60
|
+
|
61
|
+
attribute? :wait_for_timeout, Types::Coercible::Integer.optional
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PuppeteerEntity
|
4
|
+
module Attributes
|
5
|
+
class Cookie < Dry::Struct
|
6
|
+
transform_keys(&:to_sym)
|
7
|
+
attribute :name, Types::Coercible::String
|
8
|
+
attribute :value, Types::Coercible::String
|
9
|
+
# The request-URI to associate with the setting of the cookie. This value can affect the default domain, path, source port, and source scheme values of the created cookie.
|
10
|
+
attribute? :url, Types::URL.optional
|
11
|
+
attribute? :domain, Types::Coercible::String.optional
|
12
|
+
attribute? :path, Types::Coercible::String.optional
|
13
|
+
attribute? :secure, Types::Bool.optional
|
14
|
+
attribute? :http_only, Types::Bool.optional
|
15
|
+
attribute? :same_site, Types::Coercible::String.enum("Lax", "None", "Strict").optional
|
16
|
+
attribute? :expires, Types::Coercible::Integer.optional
|
17
|
+
attribute? :priority, Types::Coercible::String.enum("High", "Low", "Medium").optional
|
18
|
+
attribute? :same_party, Types::Bool.optional
|
19
|
+
attribute? :source_scheme, Types::Coercible::String.enum("NonSecure", "Secure", "Unset").optional
|
20
|
+
# Cookie source port. Valid values are {-1, [1, 65535]}, -1 indicates an unspecified port. An unspecified port value allows protocol clients to emulate legacy cookie scope for the port. This is a temporary ability and it will be removed in the future.
|
21
|
+
attribute? :source_port, Types::Coercible::Integer.optional
|
22
|
+
# Cookie partition key. The site of the top-level URL the browser was visiting at the start of the request to the endpoint that set the cookie. If not set, the cookie will be set as not partitioned.
|
23
|
+
attribute? :partition_key, Types::Coercible::String.optional
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PuppeteerEntity
|
4
|
+
module Attributes
|
5
|
+
class GotoOptions < Dry::Struct
|
6
|
+
transform_keys(&:to_sym)
|
7
|
+
|
8
|
+
# If provided, it will take preference over the referer header value set by {@link Page.setExtraHTTPHeaderspage.setExtraHTTPHeaders()}.
|
9
|
+
attribute? :referer, Types::Coercible::String.optional
|
10
|
+
# If provided, it will take preference over the referer-policy header value set by {@link Page.setExtraHTTPHeaderspage.setExtraHTTPHeaders()}.
|
11
|
+
attribute? :referrer_policy, Types::Coercible::String.optional
|
12
|
+
# Maximum wait time in milliseconds. Pass 0 to disable the timeout.
|
13
|
+
# The default value can be changed by using the {@link Page.setDefaultTimeout} or {@link Page.setDefaultNavigationTimeout} methods.
|
14
|
+
attribute? :timeout, Types::Coercible::Integer.optional
|
15
|
+
# When to consider waiting succeeds. Given an array of event strings, waiting is considered to be successful after all events have been fired.
|
16
|
+
attribute? :wait_until, Types::Array.of(Types::Coercible::String.enum("domcontentloaded", "load", "networkidle0", "networkidle2")).optional
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PuppeteerEntity
|
4
|
+
module Attributes
|
5
|
+
class Pdf < Dry::Struct
|
6
|
+
transform_keys(&:to_sym)
|
7
|
+
|
8
|
+
attribute? :add_script_tag, Types::Array do
|
9
|
+
attributes_from Attributes::ScriptTag
|
10
|
+
end
|
11
|
+
|
12
|
+
attribute? :add_style_tag, Types::Array do
|
13
|
+
attributes_from Attributes::StyleTag
|
14
|
+
end
|
15
|
+
|
16
|
+
attribute? :authenticate do
|
17
|
+
attributes_from Attributes::Authenticate
|
18
|
+
end
|
19
|
+
|
20
|
+
# When bestAttempt is set to true, browserless attempt to proceed when "awaited" events fail or timeout. This includes things like goto, waitForSelector, and more.
|
21
|
+
attribute? :best_attempt, Types::Bool.optional
|
22
|
+
|
23
|
+
attribute? :block_modals, Types::Bool.optional
|
24
|
+
|
25
|
+
attribute? :cookies, Types::Array do
|
26
|
+
attributes_from Attributes::Cookie
|
27
|
+
end
|
28
|
+
|
29
|
+
attribute? :emulate_media_type, Types::Coercible::String.optional
|
30
|
+
|
31
|
+
attribute? :goto_options do
|
32
|
+
attributes_from Attributes::GotoOptions
|
33
|
+
end
|
34
|
+
|
35
|
+
attribute? :html, Types::Coercible::String.optional
|
36
|
+
|
37
|
+
attribute? :options do
|
38
|
+
attribute? :scale, Types::Float.optional.constrained(included_in: 0.1..2.0)
|
39
|
+
attribute? :display_header_footer, Types::Bool.optional
|
40
|
+
# HTML template for the print header. Should be valid HTML with the following classes used to inject values into them:
|
41
|
+
# * "date" formatted print date
|
42
|
+
# * "title" document title
|
43
|
+
# * "url" document location
|
44
|
+
# * "pageNumber" current page number
|
45
|
+
# * "totalPages" total pages in the document
|
46
|
+
attribute? :header_template, Types::Coercible::String.optional
|
47
|
+
# HTML template for the print footer. Has the same constraints and support for special classes as {@link PDFOptionsPDFOptions.headerTemplate}.
|
48
|
+
attribute? :footer_template, Types::Coercible::String.optional
|
49
|
+
# Print background graphics.
|
50
|
+
attribute? :print_background, Types::Bool.optional
|
51
|
+
attribute? :landscape, Types::Bool.optional
|
52
|
+
# Paper ranges to print, e.g. 1-5, 8, 11-13.
|
53
|
+
attribute? :page_ranges, Types::Coercible::String.optional
|
54
|
+
attribute? :format, Types::Coercible::String.enum("A0", "A1", "A2", "A3", "A4", "A5", "A6", "LEDGER", "LEGAL", "LETTER", "Ledger", "Legal", "Letter", "TABLOID", "Tabloid", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "ledger", "legal", "letter", "tabloid").optional
|
55
|
+
# Sets the width of paper. You can pass in a number or a string with a unit.
|
56
|
+
attribute? :width, Types::Coercible::String.optional
|
57
|
+
# Sets the height of paper. You can pass in a number or a string with a unit.
|
58
|
+
attribute? :height, Types::Coercible::String.optional
|
59
|
+
# Give any CSS @page size declared in the page priority over what is declared in the width or height or format option.
|
60
|
+
attribute? :prefer_css_page_size, Types::Bool.optional
|
61
|
+
attribute? :margin do
|
62
|
+
attribute? :top, Types::Coercible::String.optional
|
63
|
+
attribute? :bottom, Types::Coercible::String.optional
|
64
|
+
attribute? :left, Types::Coercible::String.optional
|
65
|
+
attribute? :right, Types::Coercible::String.optional
|
66
|
+
end
|
67
|
+
# The path to save the file to.
|
68
|
+
attribute? :path, Types::String.optional
|
69
|
+
# Hides default white background and allows generating pdfs with transparency.
|
70
|
+
attribute? :omit_background, Types::Bool.optional
|
71
|
+
# Generate tagged (accessible) PDF.
|
72
|
+
attribute? :tagged, Types::Bool.optional
|
73
|
+
# Timeout in milliseconds. Pass 0 to disable timeout.
|
74
|
+
attribute? :timeout, Types::Coercible::Integer.optional
|
75
|
+
end
|
76
|
+
|
77
|
+
attribute? :reject_request_pattern, Types::Array.of(Types::String).optional
|
78
|
+
attribute? :reject_resource_types, Types::Array.of(Types::Coercible::String.enum("cspviolationreport", "document", "eventsource", "fetch", "font", "image", "manifest", "media", "other", "ping", "prefetch", "preflight", "script", "signedexchange", "stylesheet", "texttrack", "websocket", "xhr")).optional
|
79
|
+
attribute? :request_interceptors, Types::Array.optional
|
80
|
+
|
81
|
+
attribute? :set_extra_http_headers, Types::Array.optional
|
82
|
+
attribute? :set_java_script_enabled, Types::Bool.optional
|
83
|
+
|
84
|
+
attribute? :url, Types::URL.optional
|
85
|
+
attribute? :user_agent, Types::Coercible::String.optional
|
86
|
+
|
87
|
+
attribute? :viewport do
|
88
|
+
attributes_from Attributes::Viewport
|
89
|
+
end
|
90
|
+
|
91
|
+
attribute? :wait_for_event do
|
92
|
+
attributes_from Attributes::WaitForEvent
|
93
|
+
end
|
94
|
+
|
95
|
+
attribute? :wait_for_function do
|
96
|
+
attributes_from Attributes::WaitForFunction
|
97
|
+
end
|
98
|
+
|
99
|
+
attribute? :wait_for_selector do
|
100
|
+
attributes_from Attributes::WaitForSelector
|
101
|
+
end
|
102
|
+
|
103
|
+
attribute? :wait_for_timeout, Types::Coercible::Integer.optional
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PuppeteerEntity
|
4
|
+
module Attributes
|
5
|
+
class Query < Dry::Struct
|
6
|
+
transform_keys(&:to_sym)
|
7
|
+
|
8
|
+
# Whether or nor to load ad-blocking extensions for the session. This currently uses uBlock Origin and may cause certain sites to not load properly.
|
9
|
+
attribute? :block_ads, Types::Bool.optional
|
10
|
+
# Launch options, which can be either an object of puppeteer.launch options or playwright.launchServer options, depending on the API.
|
11
|
+
attribute? :launch do
|
12
|
+
attribute? :args, Types::Array.of(Types::String).optional
|
13
|
+
attribute? :default_viewport do
|
14
|
+
attributes_from Attributes::Viewport
|
15
|
+
end
|
16
|
+
end
|
17
|
+
# Whether or nor to record the session. The browser will run in "head-full" mode, and recording is started and closed via the embedded browserless API. Please refer to the "Recording" section in the live documentation site for more details.
|
18
|
+
attribute? :record, Types::Bool.optional
|
19
|
+
# Override the system-level timeout for this request. Accepts a value in milliseconds.
|
20
|
+
attribute? :timeout, Types::Integer.optional
|
21
|
+
# The authorization token
|
22
|
+
attribute? :token, Types::String.optional
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PuppeteerEntity
|
4
|
+
module Attributes
|
5
|
+
class Screenshot < Dry::Struct
|
6
|
+
transform_keys(&:to_sym)
|
7
|
+
|
8
|
+
attribute? :add_script_tag, Types::Array do
|
9
|
+
attributes_from Attributes::ScriptTag
|
10
|
+
end
|
11
|
+
|
12
|
+
attribute? :add_style_tag, Types::Array do
|
13
|
+
attributes_from Attributes::StyleTag
|
14
|
+
end
|
15
|
+
|
16
|
+
attribute? :authenticate do
|
17
|
+
attributes_from Attributes::Authenticate
|
18
|
+
end
|
19
|
+
|
20
|
+
# When bestAttempt is set to true, browserless attempt to proceed when "awaited" events fail or timeout. This includes things like goto, waitForSelector, and more.
|
21
|
+
attribute? :best_attempt, Types::Bool.optional
|
22
|
+
|
23
|
+
attribute? :cookies, Types::Array do
|
24
|
+
attributes_from Attributes::Cookie
|
25
|
+
end
|
26
|
+
|
27
|
+
attribute? :emulate_media_type, Types::Coercible::String.optional
|
28
|
+
|
29
|
+
attribute? :goto_options do
|
30
|
+
attributes_from Attributes::GotoOptions
|
31
|
+
end
|
32
|
+
|
33
|
+
attribute? :html, Types::Coercible::String.optional
|
34
|
+
|
35
|
+
attribute? :options do
|
36
|
+
attribute? :optimize_for_speed, Types::Bool.optional
|
37
|
+
attribute :type, Types::Coercible::String.default("png").enum("jpeg", "png", "webp")
|
38
|
+
# Quality of the image, between 0-100. Not applicable to png images.
|
39
|
+
attribute? :quality, Types::Integer.optional.constrained(included_in: 0..100)
|
40
|
+
# Capture the screenshot from the surface, rather than the view.
|
41
|
+
attribute? :from_surface, Types::Bool.optional
|
42
|
+
# When true, takes a screenshot of the full page.
|
43
|
+
attribute? :full_page, Types::Bool.optional
|
44
|
+
# Hides default white background and allows capturing screenshots with transparency.
|
45
|
+
attribute? :omit_background, Types::Bool.optional
|
46
|
+
# The file path to save the image to. The screenshot type will be inferred from file extension. If path is a relative path, then it is resolved relative to current working directory. If no path is provided, the image won't be saved to the disk.
|
47
|
+
attribute? :path, Types::String.optional
|
48
|
+
attribute? :clip do
|
49
|
+
attribute? :scale, Types::Float.optional
|
50
|
+
# the width of the element in pixels.
|
51
|
+
attribute :width, Types::Integer
|
52
|
+
# the height of the element in pixels.
|
53
|
+
attribute :height, Types::Integer
|
54
|
+
attribute :x, Types::Integer
|
55
|
+
attribute :y, Types::Integer
|
56
|
+
end
|
57
|
+
# Encoding of the image.
|
58
|
+
attribute? :encoding, Types::Coercible::String.optional.enum("base64", "binary")
|
59
|
+
# Capture the screenshot beyond the viewport.
|
60
|
+
attribute? :capture_beyond_viewport, Types::Bool.optional
|
61
|
+
end
|
62
|
+
|
63
|
+
attribute? :reject_request_pattern, Types::Array.of(Types::String).optional
|
64
|
+
attribute? :reject_resource_types, Types::Array.of(Types::Coercible::String.enum("cspviolationreport", "document", "eventsource", "fetch", "font", "image", "manifest", "media", "other", "ping", "prefetch", "preflight", "script", "signedexchange", "stylesheet", "texttrack", "websocket", "xhr")).optional
|
65
|
+
attribute? :request_interceptors, Types::Array.optional
|
66
|
+
|
67
|
+
attribute? :scroll_page, Types::Bool.optional
|
68
|
+
attribute? :selector, Types::Coercible::String.optional
|
69
|
+
|
70
|
+
attribute? :set_extra_http_headers, Types::Array.optional
|
71
|
+
attribute? :set_java_script_enabled, Types::Bool.optional
|
72
|
+
|
73
|
+
attribute? :url, Types::URL.optional
|
74
|
+
attribute? :user_agent, Types::Coercible::String.optional
|
75
|
+
|
76
|
+
attribute? :viewport do
|
77
|
+
attributes_from Attributes::Viewport
|
78
|
+
end
|
79
|
+
|
80
|
+
attribute? :wait_for_event do
|
81
|
+
attributes_from Attributes::WaitForEvent
|
82
|
+
end
|
83
|
+
|
84
|
+
attribute? :wait_for_function do
|
85
|
+
attributes_from Attributes::WaitForFunction
|
86
|
+
end
|
87
|
+
|
88
|
+
attribute? :wait_for_selector do
|
89
|
+
attributes_from Attributes::WaitForSelector
|
90
|
+
end
|
91
|
+
|
92
|
+
attribute? :wait_for_timeout, Types::Coercible::Integer.optional
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PuppeteerEntity
|
4
|
+
module Attributes
|
5
|
+
class ScriptTag < Dry::Struct
|
6
|
+
transform_keys(&:to_sym)
|
7
|
+
|
8
|
+
# URL of the script to be added.
|
9
|
+
attribute? :url, Types::URL.optional
|
10
|
+
# Path to a JavaScript file to be injected into the frame.
|
11
|
+
attribute? :path, Types::String.optional
|
12
|
+
# JavaScript to be injected into the frame.
|
13
|
+
attribute? :content, Types::String.optional
|
14
|
+
# Sets the type of the script. Use module in order to load an ES2015 module.
|
15
|
+
attribute? :type, Types::Coercible::String.optional
|
16
|
+
# Sets the id of the script.
|
17
|
+
attribute? :id, Types::Coercible::String.optional
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PuppeteerEntity
|
4
|
+
module Attributes
|
5
|
+
class StyleTag < Dry::Struct
|
6
|
+
transform_keys(&:to_sym)
|
7
|
+
|
8
|
+
# the URL of the CSS file to be added.
|
9
|
+
attribute? :url, Types::URL.optional
|
10
|
+
# The path to a CSS file to be injected into the frame.
|
11
|
+
attribute? :path, Types::String.optional
|
12
|
+
# Raw CSS content to be injected into the frame.
|
13
|
+
attribute? :content, Types::String.optional
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PuppeteerEntity
|
4
|
+
module Attributes
|
5
|
+
class Viewport < Dry::Struct
|
6
|
+
transform_keys(&:to_sym)
|
7
|
+
|
8
|
+
# The page width in CSS pixels.
|
9
|
+
attribute :width, Types::Coercible::Integer
|
10
|
+
# The page height in CSS pixels.
|
11
|
+
attribute :height, Types::Coercible::Integer
|
12
|
+
# Specify device scale factor. See {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio devicePixelRatio} for more info.
|
13
|
+
attribute? :device_scale_factor, Types::Coercible::Float.optional
|
14
|
+
# Whether the meta viewport tag is taken into account.
|
15
|
+
attribute? :is_mobile, Types::Bool.optional
|
16
|
+
# Specifies if the viewport is in landscape mode.
|
17
|
+
attribute? :is_landscape, Types::Bool.optional
|
18
|
+
# Specify if the viewport supports touch events.
|
19
|
+
attribute? :has_touch, Types::Bool.optional
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PuppeteerEntity
|
4
|
+
module Attributes
|
5
|
+
class WaitForFunction < Dry::Struct
|
6
|
+
transform_keys(&:to_sym)
|
7
|
+
|
8
|
+
# The function, or statement, to be evaluated in browser context
|
9
|
+
attribute :fn, Types::Coercible::String
|
10
|
+
# An interval at which the pageFunction is executed, defaults to raf. If polling is a number, then it is treated as an interval in milliseconds at which the function would be executed. If polling is a string, then it can be one of the following values: "raf" or "mutation"
|
11
|
+
attribute? :polling, Types::Coercible::String.optional
|
12
|
+
# Maximum time to wait for in milliseconds. Defaults to 30000 (30 seconds). Pass 0 to disable timeout.
|
13
|
+
attribute? :timeout, Types::Coercible::Integer.optional
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PuppeteerEntity
|
4
|
+
module Attributes
|
5
|
+
class WaitForSelector < Dry::Struct
|
6
|
+
transform_keys(&:to_sym)
|
7
|
+
|
8
|
+
attribute :selector, Types::Coercible::String
|
9
|
+
attribute? :hidden, Types::Bool.optional
|
10
|
+
attribute? :timeout, Types::Coercible::Integer.optional
|
11
|
+
attribute? :visible, Types::Bool.optional
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/struct"
|
4
|
+
require "http"
|
5
|
+
require "active_support/core_ext/hash"
|
6
|
+
|
7
|
+
module PuppeteerEntity
|
8
|
+
class Base < Dry::Struct
|
9
|
+
attribute? :browserless_url, Types::URL.default { ENV["BROWSERLESS_URL"] }
|
10
|
+
attribute? :retry_limit, Types::Integer.default { 3 }
|
11
|
+
|
12
|
+
attributes_from Attributes::Query
|
13
|
+
|
14
|
+
def response
|
15
|
+
url = url_with_query_params
|
16
|
+
json = as_body_json
|
17
|
+
retries = 0
|
18
|
+
begin
|
19
|
+
HTTP.headers(response_headers)
|
20
|
+
.post(url, json:)
|
21
|
+
.tap do |res|
|
22
|
+
raise RequestError.new(res.body.to_s) unless res.status.success?
|
23
|
+
rescue RequestError => e
|
24
|
+
retries = retries + 1
|
25
|
+
retries > retry_limit ? raise(e) : retry
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def response_headers
|
33
|
+
{
|
34
|
+
content_type: "application/json"
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def browserless_uri
|
39
|
+
raise NotImplementedError
|
40
|
+
end
|
41
|
+
|
42
|
+
def url_with_query_params
|
43
|
+
browserless_uri.tap do |uri|
|
44
|
+
uri.query = URI.encode_www_form(as_query_params)
|
45
|
+
end.to_s
|
46
|
+
end
|
47
|
+
|
48
|
+
def as_query_params
|
49
|
+
to_h
|
50
|
+
.slice(*Attributes::Query.attribute_names)
|
51
|
+
.reject { |_, v| v.blank? }
|
52
|
+
.deep_stringify_keys
|
53
|
+
.deep_transform_keys { |k| k.camelcase(:lower) }
|
54
|
+
end
|
55
|
+
|
56
|
+
def as_body_json
|
57
|
+
raise NotImplementedError
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PuppeteerEntity
|
4
|
+
class Content < Base
|
5
|
+
attributes_from Attributes::Content
|
6
|
+
|
7
|
+
transform_keys(&:to_sym)
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def as_body_json
|
12
|
+
to_h
|
13
|
+
.slice(*Attributes::Content.attribute_names)
|
14
|
+
.reject { |_, v| v.blank? }
|
15
|
+
.deep_stringify_keys
|
16
|
+
.deep_transform_keys do |k|
|
17
|
+
case k
|
18
|
+
when "set_extra_http_headers" then "setExtraHTTPHeaders"
|
19
|
+
else k.camelcase(:lower)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def browserless_uri
|
25
|
+
URI.parse(browserless_url).tap do |uri|
|
26
|
+
uri.path = "/content"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PuppeteerEntity
|
4
|
+
class Pdf < Base
|
5
|
+
attributes_from Attributes::Pdf
|
6
|
+
|
7
|
+
transform_keys(&:to_sym)
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def response_headers
|
12
|
+
super.merge(
|
13
|
+
accept: "application/pdf"
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
def as_body_json
|
18
|
+
to_h
|
19
|
+
.slice(*Attributes::Pdf.attribute_names)
|
20
|
+
.reject { |_, v| v.blank? }
|
21
|
+
.deep_stringify_keys
|
22
|
+
.deep_transform_keys do |k|
|
23
|
+
case k
|
24
|
+
when "set_extra_http_headers" then "setExtraHTTPHeaders"
|
25
|
+
when "prefer_css_page_size" then "preferCSSPageSize"
|
26
|
+
else k.camelcase(:lower)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def browserless_uri
|
32
|
+
URI.parse(browserless_url).tap do |uri|
|
33
|
+
uri.path = "/pdf"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PuppeteerEntity
|
4
|
+
class Screenshot < Base
|
5
|
+
attributes_from Attributes::Screenshot
|
6
|
+
|
7
|
+
MIME_TYPES = {
|
8
|
+
"png" => "image/png",
|
9
|
+
"jpeg" => "image/jpeg",
|
10
|
+
"webp" => "image/webp"
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
transform_keys(&:to_sym)
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def response_headers
|
18
|
+
type = to_h.dig(:options, :type) || "png"
|
19
|
+
super.merge(
|
20
|
+
accept: MIME_TYPES[type.downcase]
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
def as_body_json
|
25
|
+
to_h
|
26
|
+
.slice(*Attributes::Screenshot.attribute_names)
|
27
|
+
.reject { |_, v| v.blank? }
|
28
|
+
.deep_stringify_keys
|
29
|
+
.deep_transform_keys do |k|
|
30
|
+
case k
|
31
|
+
when "set_extra_http_headers" then "setExtraHTTPHeaders"
|
32
|
+
else k.camelcase(:lower)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def browserless_uri
|
38
|
+
URI.parse(browserless_url).tap do |uri|
|
39
|
+
uri.path = "/screenshot"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
metadata
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: puppeteer_entity
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tomas Celizna
|
8
|
+
- Asger Behncke Jacobsen
|
9
|
+
autorequire:
|
10
|
+
bindir: exe
|
11
|
+
cert_chain: []
|
12
|
+
date: 2024-10-17 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: dry-struct
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: http
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: zeitwerk
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: activesupport
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: minitest
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '5.0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '5.0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: faker
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: pdf-reader
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: rubocop-rails-omakase
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
type: :development
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
description: PuppeteerEntity provides a simple and intuitive interface for interacting
|
127
|
+
with Puppeteer, a headless Chrome browser.
|
128
|
+
email:
|
129
|
+
- mail@tomascelizna.com
|
130
|
+
- a@asgerbehnckejacobsen.dk
|
131
|
+
executables: []
|
132
|
+
extensions: []
|
133
|
+
extra_rdoc_files: []
|
134
|
+
files:
|
135
|
+
- ".rubocop.yml"
|
136
|
+
- ".ruby-version"
|
137
|
+
- CHANGELOG.md
|
138
|
+
- LICENSE
|
139
|
+
- README.md
|
140
|
+
- Rakefile
|
141
|
+
- docker-compose.yml
|
142
|
+
- lib/puppeteer_entity.rb
|
143
|
+
- lib/puppeteer_entity/attributes/authenticate.rb
|
144
|
+
- lib/puppeteer_entity/attributes/content.rb
|
145
|
+
- lib/puppeteer_entity/attributes/cookie.rb
|
146
|
+
- lib/puppeteer_entity/attributes/goto_options.rb
|
147
|
+
- lib/puppeteer_entity/attributes/pdf.rb
|
148
|
+
- lib/puppeteer_entity/attributes/query.rb
|
149
|
+
- lib/puppeteer_entity/attributes/screenshot.rb
|
150
|
+
- lib/puppeteer_entity/attributes/script_tag.rb
|
151
|
+
- lib/puppeteer_entity/attributes/style_tag.rb
|
152
|
+
- lib/puppeteer_entity/attributes/viewport.rb
|
153
|
+
- lib/puppeteer_entity/attributes/wait_for_event.rb
|
154
|
+
- lib/puppeteer_entity/attributes/wait_for_function.rb
|
155
|
+
- lib/puppeteer_entity/attributes/wait_for_selector.rb
|
156
|
+
- lib/puppeteer_entity/base.rb
|
157
|
+
- lib/puppeteer_entity/content.rb
|
158
|
+
- lib/puppeteer_entity/pdf.rb
|
159
|
+
- lib/puppeteer_entity/screenshot.rb
|
160
|
+
- lib/puppeteer_entity/types.rb
|
161
|
+
- lib/puppeteer_entity/version.rb
|
162
|
+
homepage: https://github.com/tomasc/puppeteer_entity
|
163
|
+
licenses: []
|
164
|
+
metadata:
|
165
|
+
homepage_uri: https://github.com/tomasc/puppeteer_entity
|
166
|
+
source_code_uri: https://github.com/tomasc/puppeteer_entity
|
167
|
+
changelog_uri: https://github.com/tomasc/puppeteer_entity/blob/main/CHANGELOG.md
|
168
|
+
post_install_message:
|
169
|
+
rdoc_options: []
|
170
|
+
require_paths:
|
171
|
+
- lib
|
172
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
173
|
+
requirements:
|
174
|
+
- - ">="
|
175
|
+
- !ruby/object:Gem::Version
|
176
|
+
version: 3.1.0
|
177
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
178
|
+
requirements:
|
179
|
+
- - ">="
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '0'
|
182
|
+
requirements: []
|
183
|
+
rubygems_version: 3.5.16
|
184
|
+
signing_key:
|
185
|
+
specification_version: 4
|
186
|
+
summary: A Ruby gem for interacting with Puppeteer
|
187
|
+
test_files: []
|