puppeteer_entity 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Test](https://github.com/tomasc/puppeteer_entity/actions/workflows/test.yml/badge.svg)](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: []
|