hanami 2.1.0.beta2.1 → 2.1.0.rc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +30 -0
- data/hanami.gemspec +3 -3
- data/lib/hanami/config/actions.rb +16 -3
- data/lib/hanami/config/assets.rb +1 -1
- data/lib/hanami/config/views.rb +10 -2
- data/lib/hanami/config.rb +21 -12
- data/lib/hanami/extensions/action/slice_configured_action.rb +5 -5
- data/lib/hanami/extensions/action.rb +4 -4
- data/lib/hanami/extensions/view/context.rb +111 -19
- data/lib/hanami/extensions/view/part.rb +64 -3
- data/lib/hanami/extensions/view/scope.rb +7 -0
- data/lib/hanami/extensions/view/slice_configured_context.rb +12 -8
- data/lib/hanami/extensions/view/slice_configured_helpers.rb +12 -1
- data/lib/hanami/extensions/view/slice_configured_part.rb +71 -0
- data/lib/hanami/extensions/view/slice_configured_view.rb +14 -6
- data/lib/hanami/extensions/view/standard_helpers.rb +4 -0
- data/lib/hanami/extensions/view.rb +5 -3
- data/lib/hanami/helpers/assets_helper.rb +47 -79
- data/lib/hanami/routes.rb +33 -2
- data/lib/hanami/slice.rb +12 -2
- data/lib/hanami/slice_registrar.rb +48 -23
- data/lib/hanami/version.rb +1 -1
- data/lib/hanami/web/rack_logger.rb +70 -2
- data/lib/hanami/web/welcome.html.erb +203 -0
- data/lib/hanami/web/welcome.rb +46 -0
- data/spec/integration/assets/assets_spec.rb +14 -3
- data/spec/integration/logging/request_logging_spec.rb +65 -7
- data/spec/integration/rack_app/method_override_spec.rb +97 -0
- data/spec/integration/slices_spec.rb +275 -5
- data/spec/integration/view/context/assets_spec.rb +0 -8
- data/spec/integration/view/context/inflector_spec.rb +0 -8
- data/spec/integration/view/context/settings_spec.rb +0 -8
- data/spec/integration/view/helpers/part_helpers_spec.rb +2 -2
- data/spec/integration/view/helpers/user_defined_helpers/part_helpers_spec.rb +10 -10
- data/spec/integration/view/parts/default_rendering_spec.rb +138 -0
- data/spec/integration/web/welcome_view_spec.rb +84 -0
- data/spec/support/app_integration.rb +22 -4
- data/spec/unit/hanami/config/render_detailed_errors_spec.rb +1 -1
- data/spec/unit/hanami/helpers/assets_helper/{audio_spec.rb → audio_tag_spec.rb} +10 -14
- data/spec/unit/hanami/helpers/assets_helper/{favicon_spec.rb → favicon_tag_spec.rb} +7 -11
- data/spec/unit/hanami/helpers/assets_helper/{image_spec.rb → image_tag_spec.rb} +8 -12
- data/spec/unit/hanami/helpers/assets_helper/{javascript_spec.rb → javascript_tag_spec.rb} +14 -18
- data/spec/unit/hanami/helpers/assets_helper/{stylesheet_spec.rb → stylesheet_tag_spec.rb} +12 -16
- data/spec/unit/hanami/helpers/assets_helper/{video_spec.rb → video_tag_spec.rb} +11 -11
- data/spec/unit/hanami/version_spec.rb +1 -1
- metadata +28 -19
@@ -3,19 +3,30 @@
|
|
3
3
|
module Hanami
|
4
4
|
module Extensions
|
5
5
|
module View
|
6
|
-
#
|
6
|
+
# Provides slice-specific helper methods any view object requiring access to helpers.
|
7
|
+
#
|
8
|
+
# @api public
|
9
|
+
# @since 2.1.0
|
7
10
|
class SliceConfiguredHelpers < Module
|
8
11
|
attr_reader :slice
|
9
12
|
|
13
|
+
# @api private
|
14
|
+
# @since 2.1.0
|
10
15
|
def initialize(slice)
|
11
16
|
super()
|
12
17
|
@slice = slice
|
13
18
|
end
|
14
19
|
|
20
|
+
# @api private
|
21
|
+
# @since 2.1.0
|
15
22
|
def extended(klass)
|
16
23
|
include_helpers(klass)
|
17
24
|
end
|
18
25
|
|
26
|
+
# @return [String]
|
27
|
+
#
|
28
|
+
# @api public
|
29
|
+
# @since 2.1.0
|
19
30
|
def inspect
|
20
31
|
"#<#{self.class.name}[#{slice.name}]>"
|
21
32
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hanami
|
4
|
+
module Extensions
|
5
|
+
module View
|
6
|
+
# Provides slice-specific configuration and behavior for any view part class defined within a
|
7
|
+
# slice's module namespace.
|
8
|
+
#
|
9
|
+
# @api public
|
10
|
+
# @since 2.1.0
|
11
|
+
class SliceConfiguredPart < Module
|
12
|
+
attr_reader :slice
|
13
|
+
|
14
|
+
# @api private
|
15
|
+
# @since 2.1.0
|
16
|
+
def initialize(slice)
|
17
|
+
super()
|
18
|
+
@slice = slice
|
19
|
+
end
|
20
|
+
|
21
|
+
# @api private
|
22
|
+
# @since 2.1.0
|
23
|
+
def extended(klass)
|
24
|
+
define_new
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [String]
|
28
|
+
#
|
29
|
+
# @api public
|
30
|
+
# @since 2.1.0
|
31
|
+
def inspect
|
32
|
+
"#<#{self.class.name}[#{slice.name}]>"
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# Defines a `.new` method on the part class that provides a default `rendering:` argument of
|
38
|
+
# a rendering coming from a view configured for the slice. This means that any part can be
|
39
|
+
# initialized standalone (with a `value:` only) and still have access to all the integrated
|
40
|
+
# view facilities from the slice, such as helpers. This is helpful when unit testing parts.
|
41
|
+
#
|
42
|
+
# @example
|
43
|
+
# module MyApp::Views::Parts
|
44
|
+
# class Post < MyApp::View::Part
|
45
|
+
# def title_tag
|
46
|
+
# helpers.h1(value.title)
|
47
|
+
# end
|
48
|
+
# end
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# # Useful when unit testing parts
|
52
|
+
# part = MyApp::Views::Parts::Post.new(value: hello_world_post)
|
53
|
+
# part.title_tag # => "<h1>Hello world</h1>"
|
54
|
+
def define_new
|
55
|
+
slice = self.slice
|
56
|
+
|
57
|
+
define_method(:new) do |**args|
|
58
|
+
return super(**args) if args.key?(:rendering)
|
59
|
+
|
60
|
+
slice_rendering = Class.new(Hanami::View)
|
61
|
+
.configure_for_slice(slice)
|
62
|
+
.new
|
63
|
+
.rendering
|
64
|
+
|
65
|
+
super(rendering: slice_rendering, **args)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -3,11 +3,11 @@
|
|
3
3
|
module Hanami
|
4
4
|
module Extensions
|
5
5
|
module View
|
6
|
-
# Provides slice-specific configuration and behavior for any view class defined
|
7
|
-
#
|
6
|
+
# Provides slice-specific configuration and behavior for any view class defined within a
|
7
|
+
# slice's module namespace.
|
8
8
|
#
|
9
|
-
# @api
|
10
|
-
# @since 2.
|
9
|
+
# @api public
|
10
|
+
# @since 2.1.0
|
11
11
|
class SliceConfiguredView < Module
|
12
12
|
TEMPLATES_DIR = "templates"
|
13
13
|
VIEWS_DIR = "views"
|
@@ -16,17 +16,25 @@ module Hanami
|
|
16
16
|
|
17
17
|
attr_reader :slice
|
18
18
|
|
19
|
+
# @api private
|
20
|
+
# @since 2.1.0
|
19
21
|
def initialize(slice)
|
20
22
|
super()
|
21
23
|
@slice = slice
|
22
24
|
end
|
23
25
|
|
26
|
+
# @api private
|
27
|
+
# @since 2.1.0
|
24
28
|
def extended(view_class)
|
25
29
|
load_app_view
|
26
30
|
configure_view(view_class)
|
27
31
|
define_inherited
|
28
32
|
end
|
29
33
|
|
34
|
+
# @return [String]
|
35
|
+
#
|
36
|
+
# @api public
|
37
|
+
# @since 2.1.0
|
30
38
|
def inspect
|
31
39
|
"#<#{self.class.name}[#{slice.name}]>"
|
32
40
|
end
|
@@ -108,7 +116,7 @@ module Hanami
|
|
108
116
|
# - We are a slice, and the view's inherited `paths` is identical to the parent's config
|
109
117
|
# (which would result in the view in a slice erroneously trying to find templates in
|
110
118
|
# the app)
|
111
|
-
if
|
119
|
+
if view_class.config.paths.empty? ||
|
112
120
|
(slice.parent && view_class.config.paths.map(&:dir) == [templates_path(slice.parent)])
|
113
121
|
view_class.config.paths = templates_path(slice)
|
114
122
|
end
|
@@ -178,7 +186,7 @@ module Hanami
|
|
178
186
|
else
|
179
187
|
views_namespace.const_set(:Part, Class.new(part_superclass).tap { |klass|
|
180
188
|
# Give the slice to `configure_for_slice`, since it cannot be inferred when it is
|
181
|
-
# called via `.inherited`,
|
189
|
+
# called via `.inherited`, because the class is anonymous at this point
|
182
190
|
klass.configure_for_slice(slice)
|
183
191
|
})
|
184
192
|
end
|
@@ -3,6 +3,10 @@
|
|
3
3
|
module Hanami
|
4
4
|
module Extensions
|
5
5
|
module View
|
6
|
+
# Module including the standard library of Hanami helpers
|
7
|
+
#
|
8
|
+
# @api public
|
9
|
+
# @since 2.1.0
|
6
10
|
module StandardHelpers
|
7
11
|
include Hanami::View::Helpers::EscapeHelper
|
8
12
|
include Hanami::View::Helpers::NumberFormattingHelper
|
@@ -7,13 +7,13 @@ module Hanami
|
|
7
7
|
module Extensions
|
8
8
|
# Integrated behavior for `Hanami::View` classes within Hanami apps.
|
9
9
|
#
|
10
|
-
# This is NOT RELEASED as of 2.0.0.
|
11
|
-
#
|
12
10
|
# @see Hanami::View
|
13
11
|
#
|
14
|
-
# @api
|
12
|
+
# @api public
|
13
|
+
# @since 2.1.0
|
15
14
|
module View
|
16
15
|
# @api private
|
16
|
+
# @since 2.1.0
|
17
17
|
def self.included(view_class)
|
18
18
|
super
|
19
19
|
|
@@ -22,8 +22,10 @@ module Hanami
|
|
22
22
|
end
|
23
23
|
|
24
24
|
# @api private
|
25
|
+
# @since 2.1.0
|
25
26
|
module ClassMethods
|
26
27
|
# @api private
|
28
|
+
# @since 2.1.0
|
27
29
|
def configure_for_slice(slice)
|
28
30
|
extend SliceConfiguredView.new(slice)
|
29
31
|
end
|
@@ -99,62 +99,62 @@ module Hanami
|
|
99
99
|
#
|
100
100
|
# @example Single Asset
|
101
101
|
#
|
102
|
-
# <%=
|
102
|
+
# <%= javascript_tag "application" %>
|
103
103
|
#
|
104
104
|
# # <script src="/assets/application.js" type="text/javascript"></script>
|
105
105
|
#
|
106
106
|
# @example Multiple Assets
|
107
107
|
#
|
108
|
-
# <%=
|
108
|
+
# <%= javascript_tag "application", "dashboard" %>
|
109
109
|
#
|
110
110
|
# # <script src="/assets/application.js" type="text/javascript"></script>
|
111
111
|
# # <script src="/assets/dashboard.js" type="text/javascript"></script>
|
112
112
|
#
|
113
113
|
# @example Asynchronous Execution
|
114
114
|
#
|
115
|
-
# <%=
|
115
|
+
# <%= javascript_tag "application", async: true %>
|
116
116
|
#
|
117
117
|
# # <script src="/assets/application.js" type="text/javascript" async="async"></script>
|
118
118
|
#
|
119
119
|
# @example Subresource Integrity
|
120
120
|
#
|
121
|
-
# <%=
|
121
|
+
# <%= javascript_tag "application" %>
|
122
122
|
#
|
123
123
|
# # <script src="/assets/application-28a6b886de2372ee3922fcaf3f78f2d8.js"
|
124
124
|
# # type="text/javascript" integrity="sha384-oqVu...Y8wC" crossorigin="anonymous"></script>
|
125
125
|
#
|
126
126
|
# @example Subresource Integrity for 3rd Party Scripts
|
127
127
|
#
|
128
|
-
# <%=
|
128
|
+
# <%= javascript_tag "https://example.com/assets/example.js", integrity: "sha384-oqVu...Y8wC" %>
|
129
129
|
#
|
130
130
|
# # <script src="https://example.com/assets/example.js" type="text/javascript"
|
131
131
|
# # integrity="sha384-oqVu...Y8wC" crossorigin="anonymous"></script>
|
132
132
|
#
|
133
133
|
# @example Deferred Execution
|
134
134
|
#
|
135
|
-
# <%=
|
135
|
+
# <%= javascript_tag "application", defer: true %>
|
136
136
|
#
|
137
137
|
# # <script src="/assets/application.js" type="text/javascript" defer="defer"></script>
|
138
138
|
#
|
139
139
|
# @example Absolute URL
|
140
140
|
#
|
141
|
-
# <%=
|
141
|
+
# <%= javascript_tag "https://code.jquery.com/jquery-2.1.4.min.js" %>
|
142
142
|
#
|
143
143
|
# # <script src="https://code.jquery.com/jquery-2.1.4.min.js" type="text/javascript"></script>
|
144
144
|
#
|
145
145
|
# @example Fingerprint Mode
|
146
146
|
#
|
147
|
-
# <%=
|
147
|
+
# <%= javascript_tag "application" %>
|
148
148
|
#
|
149
149
|
# # <script src="/assets/application-28a6b886de2372ee3922fcaf3f78f2d8.js" type="text/javascript"></script>
|
150
150
|
#
|
151
151
|
# @example CDN Mode
|
152
152
|
#
|
153
|
-
# <%=
|
153
|
+
# <%= javascript_tag "application" %>
|
154
154
|
#
|
155
155
|
# # <script src="https://assets.bookshelf.org/assets/application-28a6b886de2372ee3922fcaf3f78f2d8.js"
|
156
156
|
# # type="text/javascript"></script>
|
157
|
-
def
|
157
|
+
def javascript_tag(*source_paths, **options)
|
158
158
|
options = options.reject { |k, _| k.to_sym == :src }
|
159
159
|
|
160
160
|
_safe_tags(*source_paths) do |source|
|
@@ -173,14 +173,6 @@ module Hanami
|
|
173
173
|
end
|
174
174
|
end
|
175
175
|
|
176
|
-
# @api public
|
177
|
-
# @since 2.1.0
|
178
|
-
alias_method :js, :javascript
|
179
|
-
|
180
|
-
# @api public
|
181
|
-
# @since 2.1.0
|
182
|
-
alias_method :javascript_tag, :javascript
|
183
|
-
|
184
176
|
# Generate `link` tag for given source(s)
|
185
177
|
#
|
186
178
|
# It accepts one or more strings representing the name of the asset, if it
|
@@ -211,51 +203,51 @@ module Hanami
|
|
211
203
|
#
|
212
204
|
# @example Single Asset
|
213
205
|
#
|
214
|
-
# <%=
|
206
|
+
# <%= stylesheet_tag "application" %>
|
215
207
|
#
|
216
208
|
# # <link href="/assets/application.css" type="text/css" rel="stylesheet">
|
217
209
|
#
|
218
210
|
# @example Multiple Assets
|
219
211
|
#
|
220
|
-
# <%=
|
212
|
+
# <%= stylesheet_tag "application", "dashboard" %>
|
221
213
|
#
|
222
214
|
# # <link href="/assets/application.css" type="text/css" rel="stylesheet">
|
223
215
|
# # <link href="/assets/dashboard.css" type="text/css" rel="stylesheet">
|
224
216
|
#
|
225
217
|
# @example Subresource Integrity
|
226
218
|
#
|
227
|
-
# <%=
|
219
|
+
# <%= stylesheet_tag "application" %>
|
228
220
|
#
|
229
221
|
# # <link href="/assets/application-28a6b886de2372ee3922fcaf3f78f2d8.css"
|
230
222
|
# # type="text/css" integrity="sha384-oqVu...Y8wC" crossorigin="anonymous"></script>
|
231
223
|
#
|
232
224
|
# @example Subresource Integrity for 3rd Party Assets
|
233
225
|
#
|
234
|
-
# <%=
|
226
|
+
# <%= stylesheet_tag "https://example.com/assets/example.css", integrity: "sha384-oqVu...Y8wC" %>
|
235
227
|
#
|
236
228
|
# # <link href="https://example.com/assets/example.css"
|
237
229
|
# # type="text/css" rel="stylesheet" integrity="sha384-oqVu...Y8wC" crossorigin="anonymous"></script>
|
238
230
|
#
|
239
231
|
# @example Absolute URL
|
240
232
|
#
|
241
|
-
# <%=
|
233
|
+
# <%= stylesheet_tag "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" %>
|
242
234
|
#
|
243
235
|
# # <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"
|
244
236
|
# # type="text/css" rel="stylesheet">
|
245
237
|
#
|
246
238
|
# @example Fingerprint Mode
|
247
239
|
#
|
248
|
-
# <%=
|
240
|
+
# <%= stylesheet_tag "application" %>
|
249
241
|
#
|
250
242
|
# # <link href="/assets/application-28a6b886de2372ee3922fcaf3f78f2d8.css" type="text/css" rel="stylesheet">
|
251
243
|
#
|
252
244
|
# @example CDN Mode
|
253
245
|
#
|
254
|
-
# <%=
|
246
|
+
# <%= stylesheet_tag "application" %>
|
255
247
|
#
|
256
248
|
# # <link href="https://assets.bookshelf.org/assets/application-28a6b886de2372ee3922fcaf3f78f2d8.css"
|
257
249
|
# # type="text/css" rel="stylesheet">
|
258
|
-
def
|
250
|
+
def stylesheet_tag(*source_paths, **options)
|
259
251
|
options = options.reject { |k, _| k.to_sym == :href }
|
260
252
|
|
261
253
|
_safe_tags(*source_paths) do |source_path|
|
@@ -275,14 +267,6 @@ module Hanami
|
|
275
267
|
end
|
276
268
|
end
|
277
269
|
|
278
|
-
# @api public
|
279
|
-
# @since 2.1.0
|
280
|
-
alias_method :css, :stylesheet
|
281
|
-
|
282
|
-
# @api public
|
283
|
-
# @since 2.1.0
|
284
|
-
alias_method :stylesheet_link_tag, :stylesheet
|
285
|
-
|
286
270
|
# Generate `img` tag for given source
|
287
271
|
#
|
288
272
|
# It accepts one string representing the name of the asset, if it comes
|
@@ -313,40 +297,40 @@ module Hanami
|
|
313
297
|
#
|
314
298
|
# @example Basic Usage
|
315
299
|
#
|
316
|
-
# <%=
|
300
|
+
# <%= image_tag "logo.png" %>
|
317
301
|
#
|
318
302
|
# # <img src="/assets/logo.png" alt="Logo">
|
319
303
|
#
|
320
304
|
# @example Custom alt Attribute
|
321
305
|
#
|
322
|
-
# <%=
|
306
|
+
# <%= image_tag "logo.png", alt: "Application Logo" %>
|
323
307
|
#
|
324
308
|
# # <img src="/assets/logo.png" alt="Application Logo">
|
325
309
|
#
|
326
310
|
# @example Custom HTML Attributes
|
327
311
|
#
|
328
|
-
# <%=
|
312
|
+
# <%= image_tag "logo.png", id: "logo", class: "image" %>
|
329
313
|
#
|
330
314
|
# # <img src="/assets/logo.png" alt="Logo" id="logo" class="image">
|
331
315
|
#
|
332
316
|
# @example Absolute URL
|
333
317
|
#
|
334
|
-
# <%=
|
318
|
+
# <%= image_tag "https://example-cdn.com/images/logo.png" %>
|
335
319
|
#
|
336
320
|
# # <img src="https://example-cdn.com/images/logo.png" alt="Logo">
|
337
321
|
#
|
338
322
|
# @example Fingerprint Mode
|
339
323
|
#
|
340
|
-
# <%=
|
324
|
+
# <%= image_tag "logo.png" %>
|
341
325
|
#
|
342
326
|
# # <img src="/assets/logo-28a6b886de2372ee3922fcaf3f78f2d8.png" alt="Logo">
|
343
327
|
#
|
344
328
|
# @example CDN Mode
|
345
329
|
#
|
346
|
-
# <%=
|
330
|
+
# <%= image_tag "logo.png" %>
|
347
331
|
#
|
348
332
|
# # <img src="https://assets.bookshelf.org/assets/logo-28a6b886de2372ee3922fcaf3f78f2d8.png" alt="Logo">
|
349
|
-
def
|
333
|
+
def image_tag(source, options = {})
|
350
334
|
options = options.reject { |k, _| k.to_sym == :src }
|
351
335
|
attributes = {
|
352
336
|
src: asset_url(source),
|
@@ -357,10 +341,6 @@ module Hanami
|
|
357
341
|
tag.img(**attributes)
|
358
342
|
end
|
359
343
|
|
360
|
-
# @api public
|
361
|
-
# @since 2.1.0
|
362
|
-
alias_method :image_tag, :image
|
363
|
-
|
364
344
|
# Generate `link` tag application favicon.
|
365
345
|
#
|
366
346
|
# If no argument is given, it assumes `favico.ico` from the application.
|
@@ -388,35 +368,35 @@ module Hanami
|
|
388
368
|
#
|
389
369
|
# @example Basic Usage
|
390
370
|
#
|
391
|
-
# <%=
|
371
|
+
# <%= favicon_tag %>
|
392
372
|
#
|
393
373
|
# # <link href="/assets/favicon.ico" rel="shortcut icon" type="image/x-icon">
|
394
374
|
#
|
395
375
|
# @example Custom Path
|
396
376
|
#
|
397
|
-
# <%=
|
377
|
+
# <%= favicon_tag "fav.ico" %>
|
398
378
|
#
|
399
379
|
# # <link href="/assets/fav.ico" rel="shortcut icon" type="image/x-icon">
|
400
380
|
#
|
401
381
|
# @example Custom HTML Attributes
|
402
382
|
#
|
403
|
-
# <%=
|
383
|
+
# <%= favicon_tag "favicon.ico", id: "fav" %>
|
404
384
|
#
|
405
385
|
# # <link id: "fav" href="/assets/favicon.ico" rel="shortcut icon" type="image/x-icon">
|
406
386
|
#
|
407
387
|
# @example Fingerprint Mode
|
408
388
|
#
|
409
|
-
# <%=
|
389
|
+
# <%= favicon_tag %>
|
410
390
|
#
|
411
391
|
# # <link href="/assets/favicon-28a6b886de2372ee3922fcaf3f78f2d8.ico" rel="shortcut icon" type="image/x-icon">
|
412
392
|
#
|
413
393
|
# @example CDN Mode
|
414
394
|
#
|
415
|
-
# <%=
|
395
|
+
# <%= favicon_tag %>
|
416
396
|
#
|
417
397
|
# # <link href="https://assets.bookshelf.org/assets/favicon-28a6b886de2372ee3922fcaf3f78f2d8.ico"
|
418
398
|
# rel="shortcut icon" type="image/x-icon">
|
419
|
-
def
|
399
|
+
def favicon_tag(source = DEFAULT_FAVICON, options = {})
|
420
400
|
options = options.reject { |k, _| k.to_sym == :href }
|
421
401
|
|
422
402
|
attributes = {
|
@@ -429,10 +409,6 @@ module Hanami
|
|
429
409
|
tag.link(**attributes)
|
430
410
|
end
|
431
411
|
|
432
|
-
# @api public
|
433
|
-
# @since 2.1.0
|
434
|
-
alias_method :favicon_link_tag, :favicon
|
435
|
-
|
436
412
|
# Generate `video` tag for given source
|
437
413
|
#
|
438
414
|
# It accepts one string representing the name of the asset, if it comes
|
@@ -466,19 +442,19 @@ module Hanami
|
|
466
442
|
#
|
467
443
|
# @example Basic Usage
|
468
444
|
#
|
469
|
-
# <%=
|
445
|
+
# <%= video_tag "movie.mp4" %>
|
470
446
|
#
|
471
447
|
# # <video src="/assets/movie.mp4"></video>
|
472
448
|
#
|
473
449
|
# @example Absolute URL
|
474
450
|
#
|
475
|
-
# <%=
|
451
|
+
# <%= video_tag "https://example-cdn.com/assets/movie.mp4" %>
|
476
452
|
#
|
477
453
|
# # <video src="https://example-cdn.com/assets/movie.mp4"></video>
|
478
454
|
#
|
479
455
|
# @example Custom HTML Attributes
|
480
456
|
#
|
481
|
-
# <%=
|
457
|
+
# <%= video_tag("movie.mp4", autoplay: true, controls: true) %>
|
482
458
|
#
|
483
459
|
# # <video src="/assets/movie.mp4" autoplay="autoplay" controls="controls"></video>
|
484
460
|
#
|
@@ -509,36 +485,32 @@ module Hanami
|
|
509
485
|
#
|
510
486
|
# @example Without Any Argument
|
511
487
|
#
|
512
|
-
# <%=
|
488
|
+
# <%= video_tag %>
|
513
489
|
#
|
514
490
|
# # ArgumentError
|
515
491
|
#
|
516
492
|
# @example Without src And Without Block
|
517
493
|
#
|
518
|
-
# <%=
|
494
|
+
# <%= video_tag(content: true) %>
|
519
495
|
#
|
520
496
|
# # ArgumentError
|
521
497
|
#
|
522
498
|
# @example Fingerprint Mode
|
523
499
|
#
|
524
|
-
# <%=
|
500
|
+
# <%= video_tag "movie.mp4" %>
|
525
501
|
#
|
526
502
|
# # <video src="/assets/movie-28a6b886de2372ee3922fcaf3f78f2d8.mp4"></video>
|
527
503
|
#
|
528
504
|
# @example CDN Mode
|
529
505
|
#
|
530
|
-
# <%=
|
506
|
+
# <%= video_tag "movie.mp4" %>
|
531
507
|
#
|
532
508
|
# # <video src="https://assets.bookshelf.org/assets/movie-28a6b886de2372ee3922fcaf3f78f2d8.mp4"></video>
|
533
|
-
def
|
509
|
+
def video_tag(source = nil, options = {}, &blk)
|
534
510
|
options = _source_options(source, options, &blk)
|
535
511
|
tag.video(**options, &blk)
|
536
512
|
end
|
537
513
|
|
538
|
-
# @api public
|
539
|
-
# @since 2.1.0
|
540
|
-
alias_method :video_tag, :video
|
541
|
-
|
542
514
|
# Generate `audio` tag for given source
|
543
515
|
#
|
544
516
|
# It accepts one string representing the name of the asset, if it comes
|
@@ -572,19 +544,19 @@ module Hanami
|
|
572
544
|
#
|
573
545
|
# @example Basic Usage
|
574
546
|
#
|
575
|
-
# <%=
|
547
|
+
# <%= audio_tag "song.ogg" %>
|
576
548
|
#
|
577
549
|
# # <audio src="/assets/song.ogg"></audio>
|
578
550
|
#
|
579
551
|
# @example Absolute URL
|
580
552
|
#
|
581
|
-
# <%=
|
553
|
+
# <%= audio_tag "https://example-cdn.com/assets/song.ogg" %>
|
582
554
|
#
|
583
555
|
# # <audio src="https://example-cdn.com/assets/song.ogg"></audio>
|
584
556
|
#
|
585
557
|
# @example Custom HTML Attributes
|
586
558
|
#
|
587
|
-
# <%=
|
559
|
+
# <%= audio_tag("song.ogg", autoplay: true, controls: true) %>
|
588
560
|
#
|
589
561
|
# # <audio src="/assets/song.ogg" autoplay="autoplay" controls="controls"></audio>
|
590
562
|
#
|
@@ -615,36 +587,32 @@ module Hanami
|
|
615
587
|
#
|
616
588
|
# @example Without Any Argument
|
617
589
|
#
|
618
|
-
# <%=
|
590
|
+
# <%= audio_tag %>
|
619
591
|
#
|
620
592
|
# # ArgumentError
|
621
593
|
#
|
622
594
|
# @example Without src And Without Block
|
623
595
|
#
|
624
|
-
# <%=
|
596
|
+
# <%= audio_tag(controls: true) %>
|
625
597
|
#
|
626
598
|
# # ArgumentError
|
627
599
|
#
|
628
600
|
# @example Fingerprint Mode
|
629
601
|
#
|
630
|
-
# <%=
|
602
|
+
# <%= audio_tag "song.ogg" %>
|
631
603
|
#
|
632
604
|
# # <audio src="/assets/song-28a6b886de2372ee3922fcaf3f78f2d8.ogg"></audio>
|
633
605
|
#
|
634
606
|
# @example CDN Mode
|
635
607
|
#
|
636
|
-
# <%=
|
608
|
+
# <%= audio_tag "song.ogg" %>
|
637
609
|
#
|
638
610
|
# # <audio src="https://assets.bookshelf.org/assets/song-28a6b886de2372ee3922fcaf3f78f2d8.ogg"></audio>
|
639
|
-
def
|
611
|
+
def audio_tag(source = nil, options = {}, &blk)
|
640
612
|
options = _source_options(source, options, &blk)
|
641
613
|
tag.audio(**options, &blk)
|
642
614
|
end
|
643
615
|
|
644
|
-
# @api public
|
645
|
-
# @since 2.1.0
|
646
|
-
alias_method :audio_tag, :audio
|
647
|
-
|
648
616
|
# It generates the relative or absolute URL for the given asset.
|
649
617
|
# It automatically decides if it has to use the relative or absolute
|
650
618
|
# depending on the configuration and current environment.
|
data/lib/hanami/routes.rb
CHANGED
@@ -60,6 +60,35 @@ module Hanami
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
+
# Wrapper class for the (otherwise opaque) proc returned from {.routes}, adding an `#empty?`
|
64
|
+
# method that returns true if no routes were defined.
|
65
|
+
#
|
66
|
+
# This is useful when needing to determine behaviour based on the presence of user-defined
|
67
|
+
# routes, such as determining whether to show the Hanami welcome page in {Slice#load_router}.
|
68
|
+
#
|
69
|
+
# @api private
|
70
|
+
# @since 2.1.0
|
71
|
+
class RoutesProc < DelegateClass(Proc)
|
72
|
+
# @api private
|
73
|
+
# @since 2.1.0
|
74
|
+
def self.empty
|
75
|
+
new(proc {}, empty: true)
|
76
|
+
end
|
77
|
+
|
78
|
+
# @api private
|
79
|
+
# @since 2.1.0
|
80
|
+
def initialize(proc, empty: false)
|
81
|
+
@empty = empty
|
82
|
+
super(proc)
|
83
|
+
end
|
84
|
+
|
85
|
+
# @api private
|
86
|
+
# @since 2.1.0
|
87
|
+
def empty?
|
88
|
+
!!@empty
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
63
92
|
# @api private
|
64
93
|
def self.routes
|
65
94
|
@routes ||= build_routes
|
@@ -68,9 +97,9 @@ module Hanami
|
|
68
97
|
class << self
|
69
98
|
# @api private
|
70
99
|
def build_routes(definitions = self.definitions)
|
71
|
-
return if definitions.empty?
|
100
|
+
return RoutesProc.empty if definitions.empty?
|
72
101
|
|
73
|
-
proc do
|
102
|
+
routes_proc = proc do
|
74
103
|
definitions.each do |(name, args, kwargs, block)|
|
75
104
|
if block
|
76
105
|
public_send(name, *args, **kwargs, &block)
|
@@ -79,6 +108,8 @@ module Hanami
|
|
79
108
|
end
|
80
109
|
end
|
81
110
|
end
|
111
|
+
|
112
|
+
RoutesProc.new(routes_proc)
|
82
113
|
end
|
83
114
|
|
84
115
|
# @api private
|