playwright-ruby-client 0.6.0 → 0.6.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/documentation/README.md +33 -0
- data/documentation/babel.config.js +3 -0
- data/documentation/docs/api/accessibility.md +7 -0
- data/documentation/docs/api/browser.md +188 -0
- data/documentation/docs/api/browser_context.md +397 -0
- data/documentation/docs/api/browser_type.md +158 -0
- data/documentation/docs/api/cdp_session.md +7 -0
- data/documentation/docs/api/console_message.md +41 -0
- data/documentation/docs/api/dialog.md +71 -0
- data/documentation/docs/api/element_handle.md +618 -0
- data/documentation/docs/api/experimental/_category_.yml +3 -0
- data/documentation/docs/api/experimental/android.md +26 -0
- data/documentation/docs/api/experimental/android_device.md +92 -0
- data/documentation/docs/api/experimental/android_input.md +38 -0
- data/documentation/docs/api/experimental/android_socket.md +7 -0
- data/documentation/docs/api/experimental/android_web_view.md +7 -0
- data/documentation/docs/api/file_chooser.md +50 -0
- data/documentation/docs/api/frame.md +866 -0
- data/documentation/docs/api/js_handle.md +113 -0
- data/documentation/docs/api/keyboard.md +157 -0
- data/documentation/docs/api/mouse.md +69 -0
- data/documentation/docs/api/page.md +1402 -0
- data/documentation/docs/api/playwright.md +63 -0
- data/documentation/docs/api/request.md +188 -0
- data/documentation/docs/api/response.md +97 -0
- data/documentation/docs/api/route.md +79 -0
- data/documentation/docs/api/selectors.md +23 -0
- data/documentation/docs/api/touchscreen.md +8 -0
- data/documentation/docs/api/tracing.md +47 -0
- data/documentation/docs/api/web_socket.md +7 -0
- data/documentation/docs/api/worker.md +24 -0
- data/documentation/docs/article/api_coverage.mdx +11 -0
- data/documentation/docs/article/getting_started.md +152 -0
- data/documentation/docs/article/guides/_category_.yml +3 -0
- data/documentation/docs/article/guides/download_playwright_driver.md +49 -0
- data/documentation/docs/article/guides/launch_browser.md +119 -0
- data/documentation/docs/article/guides/rails_integration.md +205 -0
- data/documentation/docs/article/guides/recording_video.md +79 -0
- data/{docs → documentation/docs/include}/api_coverage.md +4 -3
- data/documentation/docusaurus.config.js +107 -0
- data/documentation/package.json +39 -0
- data/documentation/sidebars.js +15 -0
- data/documentation/src/components/HomepageFeatures.js +61 -0
- data/documentation/src/components/HomepageFeatures.module.css +13 -0
- data/documentation/src/css/custom.css +44 -0
- data/documentation/src/pages/index.js +50 -0
- data/documentation/src/pages/index.module.css +41 -0
- data/documentation/src/pages/markdown-page.md +7 -0
- data/documentation/static/.nojekyll +0 -0
- data/documentation/static/img/playwright-logo.svg +9 -0
- data/documentation/static/img/undraw_dropdown_menu.svg +1 -0
- data/documentation/static/img/undraw_web_development.svg +1 -0
- data/documentation/static/img/undraw_windows.svg +1 -0
- data/documentation/yarn.lock +8785 -0
- data/lib/playwright/channel_owners/binding_call.rb +33 -0
- data/lib/playwright/channel_owners/browser.rb +15 -27
- data/lib/playwright/channel_owners/browser_context.rb +15 -7
- data/lib/playwright/channel_owners/browser_type.rb +23 -8
- data/lib/playwright/channel_owners/element_handle.rb +2 -10
- data/lib/playwright/channel_owners/frame.rb +6 -28
- data/lib/playwright/channel_owners/js_handle.rb +2 -10
- data/lib/playwright/channel_owners/page.rb +18 -8
- data/lib/playwright/channel_owners/worker.rb +4 -0
- data/lib/playwright/input_files.rb +0 -8
- data/lib/playwright/javascript.rb +0 -10
- data/lib/playwright/javascript/expression.rb +2 -7
- data/lib/playwright/playwright_api.rb +16 -1
- data/lib/playwright/tracing_impl.rb +9 -9
- data/lib/playwright/version.rb +1 -1
- data/lib/playwright_api/accessibility.rb +7 -89
- data/lib/playwright_api/android.rb +10 -66
- data/lib/playwright_api/android_device.rb +10 -9
- data/lib/playwright_api/browser.rb +21 -172
- data/lib/playwright_api/browser_context.rb +54 -617
- data/lib/playwright_api/browser_type.rb +20 -108
- data/lib/playwright_api/cdp_session.rb +2 -25
- data/lib/playwright_api/console_message.rb +6 -6
- data/lib/playwright_api/dialog.rb +11 -92
- data/lib/playwright_api/element_handle.rb +60 -362
- data/lib/playwright_api/file_chooser.rb +0 -28
- data/lib/playwright_api/frame.rb +74 -713
- data/lib/playwright_api/js_handle.rb +16 -90
- data/lib/playwright_api/keyboard.rb +21 -213
- data/lib/playwright_api/mouse.rb +1 -45
- data/lib/playwright_api/page.rb +181 -1647
- data/lib/playwright_api/playwright.rb +14 -117
- data/lib/playwright_api/request.rb +15 -121
- data/lib/playwright_api/response.rb +7 -7
- data/lib/playwright_api/route.rb +8 -105
- data/lib/playwright_api/selectors.rb +6 -97
- data/lib/playwright_api/tracing.rb +7 -73
- data/lib/playwright_api/web_socket.rb +1 -1
- data/lib/playwright_api/worker.rb +28 -42
- metadata +57 -4
- data/lib/playwright/javascript/function.rb +0 -67
@@ -3,5 +3,38 @@ module Playwright
|
|
3
3
|
def name
|
4
4
|
@initializer['name']
|
5
5
|
end
|
6
|
+
|
7
|
+
def call_async(callback)
|
8
|
+
Thread.new(callback) { call(callback) }
|
9
|
+
end
|
10
|
+
|
11
|
+
# @param callback [Proc]
|
12
|
+
def call(callback)
|
13
|
+
frame = ChannelOwners::Frame.from(@initializer['frame'])
|
14
|
+
# It is not desired to use PlaywrightApi.wrap directly.
|
15
|
+
# However it is a little difficult to define wrapper for `source` parameter in generate_api.
|
16
|
+
# Just a workaround...
|
17
|
+
source = {
|
18
|
+
context: PlaywrightApi.wrap(frame.page.context),
|
19
|
+
page: PlaywrightApi.wrap(frame.page),
|
20
|
+
frame: PlaywrightApi.wrap(frame),
|
21
|
+
}
|
22
|
+
args =
|
23
|
+
if @initializer['handle']
|
24
|
+
handle = ChannelOwners::ElementHandle.from(@initializer['handle'])
|
25
|
+
[handle]
|
26
|
+
else
|
27
|
+
@initializer['args'].map do |arg|
|
28
|
+
JavaScript::ValueParser.new(arg).parse
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
begin
|
33
|
+
result = PlaywrightApi.unwrap(callback.call(source, *args))
|
34
|
+
@channel.send_message_to_server('resolve', result: JavaScript::ValueSerializer.new(result).serialize)
|
35
|
+
rescue => err
|
36
|
+
@channel.send_message_to_server('reject', error: { error: { message: err.message, name: 'Error' }})
|
37
|
+
end
|
38
|
+
end
|
6
39
|
end
|
7
40
|
end
|
@@ -7,7 +7,7 @@ module Playwright
|
|
7
7
|
private def after_initialize
|
8
8
|
@connected = true
|
9
9
|
@closed_or_closing = false
|
10
|
-
@remote =
|
10
|
+
@remote = false
|
11
11
|
|
12
12
|
@contexts = Set.new
|
13
13
|
@channel.on('close', method(:on_close))
|
@@ -30,36 +30,32 @@ module Playwright
|
|
30
30
|
@contexts << context
|
31
31
|
context.browser = self
|
32
32
|
context.options = params
|
33
|
+
return context unless block
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
context.close
|
39
|
-
end
|
40
|
-
else
|
41
|
-
context
|
35
|
+
begin
|
36
|
+
block.call(context)
|
37
|
+
ensure
|
38
|
+
context.close
|
42
39
|
end
|
43
40
|
end
|
44
41
|
|
45
|
-
def new_page(**options)
|
42
|
+
def new_page(**options, &block)
|
46
43
|
context = new_context(**options)
|
47
44
|
page = context.new_page
|
48
45
|
page.owned_context = context
|
49
46
|
context.owner_page = page
|
50
|
-
|
47
|
+
|
48
|
+
return page unless block
|
49
|
+
|
50
|
+
begin
|
51
|
+
block.call(page)
|
52
|
+
ensure
|
53
|
+
page.close
|
54
|
+
end
|
51
55
|
end
|
52
56
|
|
53
57
|
def close
|
54
58
|
return if @closed_or_closing
|
55
|
-
if @remote
|
56
|
-
@contexts.each do |context|
|
57
|
-
context.pages.each do |page|
|
58
|
-
page.send(:on_close)
|
59
|
-
end
|
60
|
-
context.send(:on_close)
|
61
|
-
end
|
62
|
-
end
|
63
59
|
@closed_or_closing = true
|
64
60
|
@channel.send_message_to_server('close')
|
65
61
|
nil
|
@@ -89,14 +85,6 @@ module Playwright
|
|
89
85
|
|
90
86
|
private def on_close(_ = {})
|
91
87
|
@connected = false
|
92
|
-
if @remote
|
93
|
-
@contexts.each do |context|
|
94
|
-
context.pages.each do |page|
|
95
|
-
page.send(:on_close)
|
96
|
-
end
|
97
|
-
context.send(:on_close)
|
98
|
-
end
|
99
|
-
end
|
100
88
|
emit(Events::Browser::Disconnected, self)
|
101
89
|
@closed_or_closing = true
|
102
90
|
end
|
@@ -46,6 +46,8 @@ module Playwright
|
|
46
46
|
ChannelOwners::Request.from_nullable(params['page']),
|
47
47
|
)
|
48
48
|
})
|
49
|
+
|
50
|
+
@closed_promise = Concurrent::Promises.resolvable_future
|
49
51
|
end
|
50
52
|
|
51
53
|
private def on_page(page)
|
@@ -67,9 +69,9 @@ module Playwright
|
|
67
69
|
end
|
68
70
|
|
69
71
|
private def on_binding(binding_call)
|
70
|
-
func = @
|
72
|
+
func = @bindings[binding_call.name]
|
71
73
|
if func
|
72
|
-
binding_call.
|
74
|
+
binding_call.call_async(func)
|
73
75
|
end
|
74
76
|
end
|
75
77
|
|
@@ -111,10 +113,17 @@ module Playwright
|
|
111
113
|
end
|
112
114
|
|
113
115
|
# @returns [Playwright::Page]
|
114
|
-
def new_page
|
116
|
+
def new_page(&block)
|
115
117
|
raise 'Please use browser.new_context' if @owner_page
|
116
118
|
resp = @channel.send_message_to_server('newPage')
|
117
|
-
ChannelOwners::Page.from(resp)
|
119
|
+
page = ChannelOwners::Page.from(resp)
|
120
|
+
return page unless block
|
121
|
+
|
122
|
+
begin
|
123
|
+
block.call(page)
|
124
|
+
ensure
|
125
|
+
page.close
|
126
|
+
end
|
118
127
|
end
|
119
128
|
|
120
129
|
def cookies(urls: nil)
|
@@ -223,15 +232,14 @@ module Playwright
|
|
223
232
|
end
|
224
233
|
|
225
234
|
private def on_close
|
226
|
-
@closed_or_closing = true
|
227
235
|
@browser&.send(:remove_context, self)
|
228
236
|
emit(Events::BrowserContext::Close)
|
237
|
+
@closed_promise.fulfill(true)
|
229
238
|
end
|
230
239
|
|
231
240
|
def close
|
232
|
-
return if @closed_or_closing
|
233
|
-
@closed_or_closing = true
|
234
241
|
@channel.send_message_to_server('close')
|
242
|
+
@closed_promise.value!
|
235
243
|
nil
|
236
244
|
rescue => err
|
237
245
|
raise unless safe_close_error?(err)
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module Playwright
|
2
2
|
define_channel_owner :BrowserType do
|
3
|
+
include Utils::PrepareBrowserContextOptions
|
4
|
+
|
3
5
|
def name
|
4
6
|
@initializer['name']
|
5
7
|
end
|
@@ -11,15 +13,28 @@ module Playwright
|
|
11
13
|
def launch(options, &block)
|
12
14
|
resp = @channel.send_message_to_server('launch', options.compact)
|
13
15
|
browser = ChannelOwners::Browser.from(resp)
|
16
|
+
return browser unless block
|
14
17
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
begin
|
19
|
+
block.call(browser)
|
20
|
+
ensure
|
21
|
+
browser.close
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def launch_persistent_context(userDataDir, **options, &block)
|
26
|
+
params = options.dup
|
27
|
+
prepare_browser_context_options(params)
|
28
|
+
params['userDataDir'] = userDataDir
|
29
|
+
|
30
|
+
resp = @channel.send_message_to_server('launchPersistentContext', params.compact)
|
31
|
+
context = ChannelOwners::Browser.from(resp)
|
32
|
+
return context unless block
|
33
|
+
|
34
|
+
begin
|
35
|
+
block.call(context)
|
36
|
+
ensure
|
37
|
+
context.close
|
23
38
|
end
|
24
39
|
end
|
25
40
|
|
@@ -301,19 +301,11 @@ module Playwright
|
|
301
301
|
end
|
302
302
|
|
303
303
|
def eval_on_selector(selector, pageFunction, arg: nil)
|
304
|
-
|
305
|
-
JavaScript::Function.new(pageFunction, arg).eval_on_selector(@channel, selector)
|
306
|
-
else
|
307
|
-
JavaScript::Expression.new(pageFunction).eval_on_selector(@channel, selector)
|
308
|
-
end
|
304
|
+
JavaScript::Expression.new(pageFunction, arg).eval_on_selector(@channel, selector)
|
309
305
|
end
|
310
306
|
|
311
307
|
def eval_on_selector_all(selector, pageFunction, arg: nil)
|
312
|
-
|
313
|
-
JavaScript::Function.new(pageFunction, arg).eval_on_selector_all(@channel, selector)
|
314
|
-
else
|
315
|
-
JavaScript::Expression.new(pageFunction).eval_on_selector_all(@channel, selector)
|
316
|
-
end
|
308
|
+
JavaScript::Expression.new(pageFunction, arg).eval_on_selector_all(@channel, selector)
|
317
309
|
end
|
318
310
|
|
319
311
|
def wait_for_element_state(state, timeout: nil)
|
@@ -132,19 +132,11 @@ module Playwright
|
|
132
132
|
end
|
133
133
|
|
134
134
|
def evaluate(pageFunction, arg: nil)
|
135
|
-
|
136
|
-
JavaScript::Function.new(pageFunction, arg).evaluate(@channel)
|
137
|
-
else
|
138
|
-
JavaScript::Expression.new(pageFunction).evaluate(@channel)
|
139
|
-
end
|
135
|
+
JavaScript::Expression.new(pageFunction, arg).evaluate(@channel)
|
140
136
|
end
|
141
137
|
|
142
138
|
def evaluate_handle(pageFunction, arg: nil)
|
143
|
-
|
144
|
-
JavaScript::Function.new(pageFunction, arg).evaluate_handle(@channel)
|
145
|
-
else
|
146
|
-
JavaScript::Expression.new(pageFunction).evaluate_handle(@channel)
|
147
|
-
end
|
139
|
+
JavaScript::Expression.new(pageFunction, arg).evaluate_handle(@channel)
|
148
140
|
end
|
149
141
|
|
150
142
|
def query_selector(selector)
|
@@ -208,19 +200,11 @@ module Playwright
|
|
208
200
|
end
|
209
201
|
|
210
202
|
def eval_on_selector(selector, pageFunction, arg: nil)
|
211
|
-
|
212
|
-
JavaScript::Function.new(pageFunction, arg).eval_on_selector(@channel, selector)
|
213
|
-
else
|
214
|
-
JavaScript::Expression.new(pageFunction).eval_on_selector(@channel, selector)
|
215
|
-
end
|
203
|
+
JavaScript::Expression.new(pageFunction, arg).eval_on_selector(@channel, selector)
|
216
204
|
end
|
217
205
|
|
218
206
|
def eval_on_selector_all(selector, pageFunction, arg: nil)
|
219
|
-
|
220
|
-
JavaScript::Function.new(pageFunction, arg).eval_on_selector_all(@channel, selector)
|
221
|
-
else
|
222
|
-
JavaScript::Expression.new(pageFunction).eval_on_selector_all(@channel, selector)
|
223
|
-
end
|
207
|
+
JavaScript::Expression.new(pageFunction, arg).eval_on_selector_all(@channel, selector)
|
224
208
|
end
|
225
209
|
|
226
210
|
def content
|
@@ -531,14 +515,8 @@ module Playwright
|
|
531
515
|
raise ArgumentError.new("Unknown polling option: #{polling}")
|
532
516
|
end
|
533
517
|
|
534
|
-
|
535
|
-
|
536
|
-
JavaScript::Function.new(pageFunction, arg)
|
537
|
-
else
|
538
|
-
JavaScript::Expression.new(pageFunction)
|
539
|
-
end
|
540
|
-
|
541
|
-
function_or_expression.wait_for_function(@channel, polling: polling, timeout: timeout)
|
518
|
+
expression = JavaScript::Expression.new(pageFunction, arg)
|
519
|
+
expression.wait_for_function(@channel, polling: polling, timeout: timeout)
|
542
520
|
end
|
543
521
|
|
544
522
|
def title
|
@@ -14,19 +14,11 @@ module Playwright
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def evaluate(pageFunction, arg: nil)
|
17
|
-
|
18
|
-
JavaScript::Function.new(pageFunction, arg).evaluate(@channel)
|
19
|
-
else
|
20
|
-
JavaScript::Expression.new(pageFunction).evaluate(@channel)
|
21
|
-
end
|
17
|
+
JavaScript::Expression.new(pageFunction, arg).evaluate(@channel)
|
22
18
|
end
|
23
19
|
|
24
20
|
def evaluate_handle(pageFunction, arg: nil)
|
25
|
-
|
26
|
-
JavaScript::Function.new(pageFunction, arg).evaluate_handle(@channel)
|
27
|
-
else
|
28
|
-
JavaScript::Expression.new(pageFunction).evaluate_handle(@channel)
|
29
|
-
end
|
21
|
+
JavaScript::Expression.new(pageFunction, arg).evaluate_handle(@channel)
|
30
22
|
end
|
31
23
|
|
32
24
|
def get_properties
|
@@ -30,6 +30,7 @@ module Playwright
|
|
30
30
|
@frames << @main_frame
|
31
31
|
@opener = ChannelOwners::Page.from_nullable(@initializer['opener'])
|
32
32
|
|
33
|
+
@channel.on('bindingCall', ->(params) { on_binding(ChannelOwners::BindingCall.from(params['binding'])) })
|
33
34
|
@channel.once('close', ->(_) { on_close })
|
34
35
|
@channel.on('console', ->(params) {
|
35
36
|
console_message = ChannelOwners::ConsoleMessage.from(params['message'])
|
@@ -64,7 +65,8 @@ module Playwright
|
|
64
65
|
emit(Events::Page::WebSocket, ChannelOwners::WebSocket.from(params['webSocket']))
|
65
66
|
})
|
66
67
|
@channel.on('worker', ->(params) {
|
67
|
-
|
68
|
+
worker = ChannelOwners::Worker.from(params['worker'])
|
69
|
+
# on_worker(worker)
|
68
70
|
})
|
69
71
|
end
|
70
72
|
|
@@ -100,6 +102,14 @@ module Playwright
|
|
100
102
|
end
|
101
103
|
end
|
102
104
|
|
105
|
+
private def on_binding(binding_call)
|
106
|
+
func = @bindings[binding_call.name]
|
107
|
+
if func
|
108
|
+
binding_call.call_async(func)
|
109
|
+
end
|
110
|
+
@browser_context.send(:on_binding, binding_call)
|
111
|
+
end
|
112
|
+
|
103
113
|
private def on_close
|
104
114
|
@closed = true
|
105
115
|
@browser_context.send(:remove_page, self)
|
@@ -306,7 +316,7 @@ module Playwright
|
|
306
316
|
timeout: timeout,
|
307
317
|
waitUntil: waitUntil,
|
308
318
|
}.compact
|
309
|
-
resp = @channel.send_message_to_server('
|
319
|
+
resp = @channel.send_message_to_server('reload', params)
|
310
320
|
ChannelOwners::Response.from_nullable(resp)
|
311
321
|
end
|
312
322
|
|
@@ -330,10 +340,11 @@ module Playwright
|
|
330
340
|
ChannelOwners::Response.from_nullable(resp)
|
331
341
|
end
|
332
342
|
|
333
|
-
def emulate_media(colorScheme: nil, media: nil)
|
343
|
+
def emulate_media(colorScheme: nil, media: nil, reducedMotion: nil)
|
334
344
|
params = {
|
335
345
|
colorScheme: colorScheme,
|
336
346
|
media: media,
|
347
|
+
reducedMotion: reducedMotion,
|
337
348
|
}.compact
|
338
349
|
@channel.send_message_to_server('emulateMedia', params)
|
339
350
|
|
@@ -704,7 +715,6 @@ module Playwright
|
|
704
715
|
end
|
705
716
|
|
706
717
|
wait_helper.wait_for_event(self, event, predicate: predicate)
|
707
|
-
|
708
718
|
block&.call
|
709
719
|
|
710
720
|
wait_helper.promise.value!
|
@@ -734,7 +744,7 @@ module Playwright
|
|
734
744
|
expect_event(Events::Page::Popup, predicate: predicate, timeout: timeout, &block)
|
735
745
|
end
|
736
746
|
|
737
|
-
def expect_request(urlOrPredicate, timeout: nil)
|
747
|
+
def expect_request(urlOrPredicate, timeout: nil, &block)
|
738
748
|
predicate =
|
739
749
|
case urlOrPredicate
|
740
750
|
when String, Regexp
|
@@ -746,10 +756,10 @@ module Playwright
|
|
746
756
|
-> (_) { true }
|
747
757
|
end
|
748
758
|
|
749
|
-
expect_event(Events::Page::Request, predicate: predicate, timeout: timeout)
|
759
|
+
expect_event(Events::Page::Request, predicate: predicate, timeout: timeout, &block)
|
750
760
|
end
|
751
761
|
|
752
|
-
def expect_response(urlOrPredicate, timeout: nil)
|
762
|
+
def expect_response(urlOrPredicate, timeout: nil, &block)
|
753
763
|
predicate =
|
754
764
|
case urlOrPredicate
|
755
765
|
when String, Regexp
|
@@ -761,7 +771,7 @@ module Playwright
|
|
761
771
|
-> (_) { true }
|
762
772
|
end
|
763
773
|
|
764
|
-
expect_event(Events::Page::Response, predicate: predicate, timeout: timeout)
|
774
|
+
expect_event(Events::Page::Response, predicate: predicate, timeout: timeout, &block)
|
765
775
|
end
|
766
776
|
|
767
777
|
# called from Frame with send(:timeout_settings)
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'base64'
|
2
|
-
require 'mime/types'
|
3
2
|
|
4
3
|
module Playwright
|
5
4
|
class InputFiles
|
@@ -19,13 +18,11 @@ module Playwright
|
|
19
18
|
when String
|
20
19
|
{
|
21
20
|
name: File.basename(file),
|
22
|
-
mimeType: mime_type_for(file),
|
23
21
|
buffer: Base64.strict_encode64(File.read(file)),
|
24
22
|
}
|
25
23
|
when File
|
26
24
|
{
|
27
25
|
name: File.basename(file.path),
|
28
|
-
mimeType: mime_type_for(file.path),
|
29
26
|
buffer: Base64.strict_encode64(file.read),
|
30
27
|
}
|
31
28
|
else
|
@@ -33,10 +30,5 @@ module Playwright
|
|
33
30
|
end
|
34
31
|
end
|
35
32
|
end
|
36
|
-
|
37
|
-
private def mime_type_for(filepath)
|
38
|
-
mime_types = MIME::Types.type_for(filepath)
|
39
|
-
mime_types.first.to_s || 'application/octet-stream'
|
40
|
-
end
|
41
33
|
end
|
42
34
|
end
|