hanami 2.1.0.beta2 → 2.1.0.rc1
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 +41 -9
- data/hanami.gemspec +1 -1
- data/lib/hanami/config/actions.rb +14 -0
- 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 +0 -11
- data/lib/hanami/extensions/view/part.rb +51 -2
- data/lib/hanami/extensions/view/slice_configured_part.rb +72 -0
- data/lib/hanami/extensions/view/slice_configured_view.rb +2 -2
- data/lib/hanami/helpers/assets_helper.rb +31 -43
- 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/helpers/assets_helper/audio_tag_spec.rb +2 -2
- data/spec/unit/hanami/helpers/assets_helper/{favicon_link_tag_spec.rb → favicon_tag_spec.rb} +8 -12
- data/spec/unit/hanami/helpers/assets_helper/image_tag_spec.rb +1 -1
- data/spec/unit/hanami/helpers/assets_helper/javascript_tag_spec.rb +3 -3
- data/spec/unit/hanami/helpers/assets_helper/{stylesheet_link_tag_spec.rb → stylesheet_tag_spec.rb} +13 -13
- data/spec/unit/hanami/helpers/assets_helper/video_tag_spec.rb +5 -1
- data/spec/unit/hanami/version_spec.rb +1 -1
- metadata +15 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3ba29263713547809e78df051e0138f202d947ce6e9cf2bc9d06c5bf79438cb7
|
4
|
+
data.tar.gz: 0677ae36e85bbb92ed1bdde4ae48e92ac062ccf89f6d77b86b85578fd8975a06
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f24d67421d88e019d3fdf1d282fd55cff3a303e59fa7195fc8b152a6b85d1990aafe1cf3c583eeb2b561cfcae4b76e4120ef9863f12cee424c8372526cfb178a
|
7
|
+
data.tar.gz: 8e9ab011e12426e7d2e03ed784858309f7ca33fa8aa84d23ae84cd7d9435563998f38cb9d53322e2631c017334465cec10e0b2f65a58d8dcb0290c360dff5b1c
|
data/CHANGELOG.md
CHANGED
@@ -2,26 +2,58 @@
|
|
2
2
|
|
3
3
|
The web, with simplicity.
|
4
4
|
|
5
|
+
## v2.1.0.rc1 - 2023-11-01
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
- [Aaron Moodie & Tim Riley] Render a welcome page when no routes are defined (#1353)
|
10
|
+
- [Luca Guidi] Allow _Method Override_ by default, by mounting `Rack::MethodOverride` middleware. (#1344)
|
11
|
+
|
12
|
+
### Fixed
|
13
|
+
|
14
|
+
- [Luca Guidi] Ensure compatibility with Ruby Logger from stdlib (#1352)
|
15
|
+
|
16
|
+
### Changed
|
17
|
+
|
18
|
+
- [Philip Arndt] Add support for a slice's class definition file to exist inside either `config/slices/[slice_name].rb` or `slices/[slice_name]/config/slice.rb`, in that order of precedence, so that a slice can provide its own definition which the app, or the slice's parent slice if that exists, can override if needed.
|
19
|
+
- [Tim Riley] Use `helpers` prefix to access helper methods from view parts (e.g. `helpers.format_number`)
|
20
|
+
- [Tim Riley] Make it possible to directly initialize view parts to ease their unit tests (#1357)
|
21
|
+
- [Tim Riley] Remove short names for assets helpers (#1356):
|
22
|
+
- Keep `javascript_tag` (remove `javascript` and `js` aliases)
|
23
|
+
- Keep `stylesheet_tag` (renamed from `stylesheet_link_tag`; remove `stylesheet` and `css` aliases)
|
24
|
+
- Keep `favicon_tag` (renamed from `favicon_link_tag`; remove `favicon` alias)
|
25
|
+
- Keep `image_tag` (remove `image` alias)
|
26
|
+
- Keep `video_tag` (remove `video` alias)
|
27
|
+
- Keep `audio_tag` (remove `audio` alias)
|
28
|
+
|
29
|
+
|
30
|
+
## v2.1.0.beta2.1 - 2023-10-04
|
31
|
+
|
32
|
+
### Added
|
33
|
+
|
34
|
+
- [Tim Riley, Luca Guidi] Added assets helpers aliases (#1319, #1339):
|
35
|
+
- Added `#js` and `#javascript_tag` as alias for `#javascript`
|
36
|
+
- Added `#css` and `#stylesheet_link_tag` as alias for `#stylesheet`
|
37
|
+
- Added `#image_tag` as alias for `#image`
|
38
|
+
- Added `#favicon_link_tag` as alias for `#favicon`
|
39
|
+
- Added `#video_tag` as alias for `#video`
|
40
|
+
- Added `#audio_tag` as alias for `#audio`
|
41
|
+
|
5
42
|
## v2.1.0.beta2 - 2023-10-04
|
6
43
|
|
7
44
|
### Added
|
8
45
|
|
9
46
|
- [Luca Guidi, Tim Riley] Reimplement assets integration (#1319, #1332, #1333, #1336)
|
10
47
|
- [Tim Riley] Introduce `Hanami::Helpers::AssetsHelper`, automatically included in view templates, scopes and parts when hanami-assets is bundled (#1319)
|
11
|
-
- [Tim Riley] Renamed assets helpers (#1319):
|
12
|
-
- Removed `#asset_path` in favour of `#asset_url` only
|
13
|
-
- Renamed `#javascript` to `#javascript_tag`, retaining `#js` alias
|
14
|
-
- Renamed `#stylesheet` to `#stylesheet_link_tag`, retaining `#css` alias
|
15
|
-
- Renamed `#image` to `#image_tag`
|
16
|
-
- Renamed `#favicon` to `#favicon_link_tag`, with `#favicon` retained as an alias
|
17
|
-
- Renamed `#video` to `#video_tag`
|
18
|
-
- Renamed `#audio` to `#audio_tag`
|
19
|
-
|
20
48
|
|
21
49
|
### Fixed
|
22
50
|
|
23
51
|
- [Tim Riley] Return appropriate response statuses based on error type (#1330)
|
24
52
|
|
53
|
+
### Changed
|
54
|
+
|
55
|
+
- [Tim Riley] Removed `#asset_path` in favour of `#asset_url` only (#1319)
|
56
|
+
|
25
57
|
## v2.1.0.beta1 - 2023-06-29
|
26
58
|
|
27
59
|
### Added
|
data/hanami.gemspec
CHANGED
@@ -74,6 +74,20 @@ module Hanami
|
|
74
74
|
# @since 2.0.0
|
75
75
|
attr_accessor :content_security_policy
|
76
76
|
|
77
|
+
# @!attribute [rw] method_override
|
78
|
+
# Sets or returns whether HTTP method override should be enabled for action classes.
|
79
|
+
#
|
80
|
+
# Defaults to true. You can override this by explicitly setting a
|
81
|
+
# true or false value.
|
82
|
+
#
|
83
|
+
# When true, this will mount `Rack::MethodOverride` in the Rack middleware stack of the App.
|
84
|
+
#
|
85
|
+
# @return [Boolean]
|
86
|
+
#
|
87
|
+
# @api public
|
88
|
+
# @since 2.1.0
|
89
|
+
setting :method_override, default: true
|
90
|
+
|
77
91
|
# The following settings are for view and assets integration with actions, and are NOT
|
78
92
|
# publicly released as of 2.0.0. We'll make full documentation available when these become
|
79
93
|
# public in a subsequent release.
|
@@ -31,14 +31,14 @@ module Hanami
|
|
31
31
|
# @see Hanami::Extensions::Action::InstanceMethods#initialize
|
32
32
|
def define_new
|
33
33
|
resolve_view = method(:resolve_paired_view)
|
34
|
-
|
34
|
+
view_context_class = method(:view_context_class)
|
35
35
|
resolve_routes = method(:resolve_routes)
|
36
36
|
resolve_rack_monitor = method(:resolve_rack_monitor)
|
37
37
|
|
38
38
|
define_method(:new) do |**kwargs|
|
39
39
|
super(
|
40
40
|
view: kwargs.fetch(:view) { resolve_view.(self) },
|
41
|
-
|
41
|
+
view_context_class: kwargs.fetch(:view_context_class) { view_context_class.() },
|
42
42
|
routes: kwargs.fetch(:routes) { resolve_routes.() },
|
43
43
|
rack_monitor: kwargs.fetch(:rack_monitor) { resolve_rack_monitor.() },
|
44
44
|
**kwargs,
|
@@ -128,9 +128,9 @@ module Hanami
|
|
128
128
|
nil
|
129
129
|
end
|
130
130
|
|
131
|
-
def
|
131
|
+
def view_context_class
|
132
132
|
if Hanami.bundled?("hanami-view")
|
133
|
-
return Extensions::View::Context.context_class(slice)
|
133
|
+
return Extensions::View::Context.context_class(slice)
|
134
134
|
end
|
135
135
|
|
136
136
|
# If hanami-view isn't bundled, try and find a possible third party context class with the
|
@@ -139,7 +139,7 @@ module Hanami
|
|
139
139
|
views_namespace = slice.namespace.const_get(:Views)
|
140
140
|
|
141
141
|
if views_namespace.const_defined?(:Context)
|
142
|
-
views_namespace.const_get(:Context)
|
142
|
+
views_namespace.const_get(:Context)
|
143
143
|
end
|
144
144
|
end
|
145
145
|
end
|
@@ -40,7 +40,7 @@ module Hanami
|
|
40
40
|
attr_reader :view
|
41
41
|
|
42
42
|
# @api private
|
43
|
-
attr_reader :
|
43
|
+
attr_reader :view_context_class
|
44
44
|
|
45
45
|
# Returns the app or slice's {Hanami::Slice::RoutesHelper RoutesHelper} for use within
|
46
46
|
# action instance methods.
|
@@ -70,9 +70,9 @@ module Hanami
|
|
70
70
|
#
|
71
71
|
# @api public
|
72
72
|
# @since 2.0.0
|
73
|
-
def initialize(view: nil,
|
73
|
+
def initialize(view: nil, view_context_class: nil, rack_monitor: nil, routes: nil, **kwargs)
|
74
74
|
@view = view
|
75
|
-
@
|
75
|
+
@view_context_class = view_context_class
|
76
76
|
@routes = routes
|
77
77
|
@rack_monitor = rack_monitor
|
78
78
|
|
@@ -104,7 +104,7 @@ module Hanami
|
|
104
104
|
|
105
105
|
# @api private
|
106
106
|
def view_options(request, response)
|
107
|
-
{context:
|
107
|
+
{context: view_context_class&.new(**view_context_options(request, response))}.compact
|
108
108
|
end
|
109
109
|
|
110
110
|
# @api private
|
@@ -104,17 +104,6 @@ module Hanami
|
|
104
104
|
@content_for = source.instance_variable_get(:@content_for).dup
|
105
105
|
end
|
106
106
|
|
107
|
-
def with(**args)
|
108
|
-
self.class.new(
|
109
|
-
inflector: @inflector,
|
110
|
-
settings: @settings,
|
111
|
-
assets: @assets,
|
112
|
-
routes: @routes,
|
113
|
-
request: @request,
|
114
|
-
**args
|
115
|
-
)
|
116
|
-
end
|
117
|
-
|
118
107
|
def assets
|
119
108
|
unless @assets
|
120
109
|
raise Hanami::ComponentLoadError, "the hanami-assets gem is required to access assets"
|
@@ -4,20 +4,69 @@ module Hanami
|
|
4
4
|
module Extensions
|
5
5
|
module View
|
6
6
|
# @api private
|
7
|
+
# @since 2.1.0
|
7
8
|
module Part
|
8
9
|
def self.included(part_class)
|
9
10
|
super
|
10
11
|
|
11
12
|
part_class.extend(Hanami::SliceConfigurable)
|
12
|
-
part_class.include(StandardHelpers)
|
13
13
|
part_class.extend(ClassMethods)
|
14
14
|
end
|
15
15
|
|
16
16
|
module ClassMethods
|
17
17
|
def configure_for_slice(slice)
|
18
|
-
extend
|
18
|
+
extend SliceConfiguredPart.new(slice)
|
19
|
+
|
20
|
+
const_set :PartHelpers, Class.new(PartHelpers) { |klass|
|
21
|
+
klass.configure_for_slice(slice)
|
22
|
+
}
|
19
23
|
end
|
20
24
|
end
|
25
|
+
|
26
|
+
# Returns an object including the default Hanami helpers as well as the user-defined helpers
|
27
|
+
# for the part's slice.
|
28
|
+
#
|
29
|
+
# Use this when you need to access helpers inside your part classes.
|
30
|
+
#
|
31
|
+
# @return PartHelpers
|
32
|
+
#
|
33
|
+
# @api public
|
34
|
+
# @since 2.1.0
|
35
|
+
def helpers
|
36
|
+
@helpers ||= self.class.const_get(:PartHelpers).new(context: _context)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Standalone helpers class including both {StandardHelpers} as well as the user-defined
|
41
|
+
# helpers for the slice.
|
42
|
+
#
|
43
|
+
# Used used where helpers should be addressed via an intermediary object (i.e. in parts),
|
44
|
+
# rather than mixed into a class directly.
|
45
|
+
#
|
46
|
+
# @api private
|
47
|
+
# @since 2.1.0
|
48
|
+
class PartHelpers
|
49
|
+
extend Hanami::SliceConfigurable
|
50
|
+
|
51
|
+
include StandardHelpers
|
52
|
+
|
53
|
+
def self.configure_for_slice(slice)
|
54
|
+
extend SliceConfiguredHelpers.new(slice)
|
55
|
+
end
|
56
|
+
|
57
|
+
# @api public
|
58
|
+
# @since 2.1.0
|
59
|
+
attr_reader :_context
|
60
|
+
|
61
|
+
# @api public
|
62
|
+
# @since 2.1.0
|
63
|
+
alias_method :context, :_context
|
64
|
+
|
65
|
+
# @api private
|
66
|
+
# @since 2.1.0
|
67
|
+
def initialize(context:)
|
68
|
+
@_context = context
|
69
|
+
end
|
21
70
|
end
|
22
71
|
end
|
23
72
|
end
|
@@ -0,0 +1,72 @@
|
|
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 private
|
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
|
+
# @api private
|
28
|
+
# @since 2.1.0
|
29
|
+
def inspect
|
30
|
+
"#<#{self.class.name}[#{slice.name}]>"
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# Defines a `.new` method on the part class that provides a default `rendering:` argument of
|
36
|
+
# a rendering coming from a view configured for the slice. This means that any part can be
|
37
|
+
# initialized standalone (with a `value:` only) and still have access to all the integrated
|
38
|
+
# view facilities from the slice, such as helpers. This is helpful when unit testing parts.
|
39
|
+
#
|
40
|
+
# @example
|
41
|
+
# module MyApp::Views::Parts
|
42
|
+
# class Post < MyApp::View::Part
|
43
|
+
# def title_tag
|
44
|
+
# helpers.h1(value.title)
|
45
|
+
# end
|
46
|
+
# end
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# # Useful when unit testing parts
|
50
|
+
# part = MyApp::Views::Parts::Post.new(value: hello_world_post)
|
51
|
+
# part.title_tag # => "<h1>Hello world</h1>"
|
52
|
+
#
|
53
|
+
# @api private
|
54
|
+
# @since 2.1.0
|
55
|
+
def define_new
|
56
|
+
slice = self.slice
|
57
|
+
|
58
|
+
define_method(:new) do |**args|
|
59
|
+
return super(**args) if args.key?(:rendering)
|
60
|
+
|
61
|
+
slice_rendering = Class.new(Hanami::View)
|
62
|
+
.configure_for_slice(slice)
|
63
|
+
.new
|
64
|
+
.rendering
|
65
|
+
|
66
|
+
super(rendering: slice_rendering, **args)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -108,7 +108,7 @@ module Hanami
|
|
108
108
|
# - We are a slice, and the view's inherited `paths` is identical to the parent's config
|
109
109
|
# (which would result in the view in a slice erroneously trying to find templates in
|
110
110
|
# the app)
|
111
|
-
if
|
111
|
+
if view_class.config.paths.empty? ||
|
112
112
|
(slice.parent && view_class.config.paths.map(&:dir) == [templates_path(slice.parent)])
|
113
113
|
view_class.config.paths = templates_path(slice)
|
114
114
|
end
|
@@ -178,7 +178,7 @@ module Hanami
|
|
178
178
|
else
|
179
179
|
views_namespace.const_set(:Part, Class.new(part_superclass).tap { |klass|
|
180
180
|
# Give the slice to `configure_for_slice`, since it cannot be inferred when it is
|
181
|
-
# called via `.inherited`,
|
181
|
+
# called via `.inherited`, because the class is anonymous at this point
|
182
182
|
klass.configure_for_slice(slice)
|
183
183
|
})
|
184
184
|
end
|
@@ -173,10 +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_tag
|
179
|
-
|
180
176
|
# Generate `link` tag for given source(s)
|
181
177
|
#
|
182
178
|
# It accepts one or more strings representing the name of the asset, if it
|
@@ -251,7 +247,7 @@ module Hanami
|
|
251
247
|
#
|
252
248
|
# # <link href="https://assets.bookshelf.org/assets/application-28a6b886de2372ee3922fcaf3f78f2d8.css"
|
253
249
|
# # type="text/css" rel="stylesheet">
|
254
|
-
def
|
250
|
+
def stylesheet_tag(*source_paths, **options)
|
255
251
|
options = options.reject { |k, _| k.to_sym == :href }
|
256
252
|
|
257
253
|
_safe_tags(*source_paths) do |source_path|
|
@@ -271,10 +267,6 @@ module Hanami
|
|
271
267
|
end
|
272
268
|
end
|
273
269
|
|
274
|
-
# @api public
|
275
|
-
# @since 2.1.0
|
276
|
-
alias_method :css, :stylesheet_link_tag
|
277
|
-
|
278
270
|
# Generate `img` tag for given source
|
279
271
|
#
|
280
272
|
# It accepts one string representing the name of the asset, if it comes
|
@@ -305,37 +297,37 @@ module Hanami
|
|
305
297
|
#
|
306
298
|
# @example Basic Usage
|
307
299
|
#
|
308
|
-
# <%=
|
300
|
+
# <%= image "logo.png" %>
|
309
301
|
#
|
310
302
|
# # <img src="/assets/logo.png" alt="Logo">
|
311
303
|
#
|
312
304
|
# @example Custom alt Attribute
|
313
305
|
#
|
314
|
-
# <%=
|
306
|
+
# <%= image "logo.png", alt: "Application Logo" %>
|
315
307
|
#
|
316
308
|
# # <img src="/assets/logo.png" alt="Application Logo">
|
317
309
|
#
|
318
310
|
# @example Custom HTML Attributes
|
319
311
|
#
|
320
|
-
# <%=
|
312
|
+
# <%= image "logo.png", id: "logo", class: "image" %>
|
321
313
|
#
|
322
314
|
# # <img src="/assets/logo.png" alt="Logo" id="logo" class="image">
|
323
315
|
#
|
324
316
|
# @example Absolute URL
|
325
317
|
#
|
326
|
-
# <%=
|
318
|
+
# <%= image "https://example-cdn.com/images/logo.png" %>
|
327
319
|
#
|
328
320
|
# # <img src="https://example-cdn.com/images/logo.png" alt="Logo">
|
329
321
|
#
|
330
322
|
# @example Fingerprint Mode
|
331
323
|
#
|
332
|
-
# <%=
|
324
|
+
# <%= image "logo.png" %>
|
333
325
|
#
|
334
326
|
# # <img src="/assets/logo-28a6b886de2372ee3922fcaf3f78f2d8.png" alt="Logo">
|
335
327
|
#
|
336
328
|
# @example CDN Mode
|
337
329
|
#
|
338
|
-
# <%=
|
330
|
+
# <%= image "logo.png" %>
|
339
331
|
#
|
340
332
|
# # <img src="https://assets.bookshelf.org/assets/logo-28a6b886de2372ee3922fcaf3f78f2d8.png" alt="Logo">
|
341
333
|
def image_tag(source, options = {})
|
@@ -376,35 +368,35 @@ module Hanami
|
|
376
368
|
#
|
377
369
|
# @example Basic Usage
|
378
370
|
#
|
379
|
-
# <%=
|
371
|
+
# <%= favicon %>
|
380
372
|
#
|
381
373
|
# # <link href="/assets/favicon.ico" rel="shortcut icon" type="image/x-icon">
|
382
374
|
#
|
383
375
|
# @example Custom Path
|
384
376
|
#
|
385
|
-
# <%=
|
377
|
+
# <%= favicon "fav.ico" %>
|
386
378
|
#
|
387
379
|
# # <link href="/assets/fav.ico" rel="shortcut icon" type="image/x-icon">
|
388
380
|
#
|
389
381
|
# @example Custom HTML Attributes
|
390
382
|
#
|
391
|
-
# <%=
|
383
|
+
# <%= favicon "favicon.ico", id: "fav" %>
|
392
384
|
#
|
393
385
|
# # <link id: "fav" href="/assets/favicon.ico" rel="shortcut icon" type="image/x-icon">
|
394
386
|
#
|
395
387
|
# @example Fingerprint Mode
|
396
388
|
#
|
397
|
-
# <%=
|
389
|
+
# <%= favicon %>
|
398
390
|
#
|
399
391
|
# # <link href="/assets/favicon-28a6b886de2372ee3922fcaf3f78f2d8.ico" rel="shortcut icon" type="image/x-icon">
|
400
392
|
#
|
401
393
|
# @example CDN Mode
|
402
394
|
#
|
403
|
-
# <%=
|
395
|
+
# <%= favicon %>
|
404
396
|
#
|
405
397
|
# # <link href="https://assets.bookshelf.org/assets/favicon-28a6b886de2372ee3922fcaf3f78f2d8.ico"
|
406
398
|
# rel="shortcut icon" type="image/x-icon">
|
407
|
-
def
|
399
|
+
def favicon_tag(source = DEFAULT_FAVICON, options = {})
|
408
400
|
options = options.reject { |k, _| k.to_sym == :href }
|
409
401
|
|
410
402
|
attributes = {
|
@@ -417,10 +409,6 @@ module Hanami
|
|
417
409
|
tag.link(**attributes)
|
418
410
|
end
|
419
411
|
|
420
|
-
# @api public
|
421
|
-
# @since 2.1.0
|
422
|
-
alias_method :favicon, :favicon_link_tag
|
423
|
-
|
424
412
|
# Generate `video` tag for given source
|
425
413
|
#
|
426
414
|
# It accepts one string representing the name of the asset, if it comes
|
@@ -454,26 +442,26 @@ module Hanami
|
|
454
442
|
#
|
455
443
|
# @example Basic Usage
|
456
444
|
#
|
457
|
-
# <%=
|
445
|
+
# <%= video "movie.mp4" %>
|
458
446
|
#
|
459
447
|
# # <video src="/assets/movie.mp4"></video>
|
460
448
|
#
|
461
449
|
# @example Absolute URL
|
462
450
|
#
|
463
|
-
# <%=
|
451
|
+
# <%= video "https://example-cdn.com/assets/movie.mp4" %>
|
464
452
|
#
|
465
453
|
# # <video src="https://example-cdn.com/assets/movie.mp4"></video>
|
466
454
|
#
|
467
455
|
# @example Custom HTML Attributes
|
468
456
|
#
|
469
|
-
# <%=
|
457
|
+
# <%= video("movie.mp4", autoplay: true, controls: true) %>
|
470
458
|
#
|
471
459
|
# # <video src="/assets/movie.mp4" autoplay="autoplay" controls="controls"></video>
|
472
460
|
#
|
473
461
|
# @example Fallback Content
|
474
462
|
#
|
475
463
|
# <%=
|
476
|
-
#
|
464
|
+
# video("movie.mp4") do
|
477
465
|
# "Your browser does not support the video tag"
|
478
466
|
# end
|
479
467
|
# %>
|
@@ -485,7 +473,7 @@ module Hanami
|
|
485
473
|
# @example Tracks
|
486
474
|
#
|
487
475
|
# <%=
|
488
|
-
#
|
476
|
+
# video("movie.mp4") do
|
489
477
|
# tag.track(kind: "captions", src: asset_url("movie.en.vtt"),
|
490
478
|
# srclang: "en", label: "English")
|
491
479
|
# end
|
@@ -497,25 +485,25 @@ module Hanami
|
|
497
485
|
#
|
498
486
|
# @example Without Any Argument
|
499
487
|
#
|
500
|
-
# <%=
|
488
|
+
# <%= video %>
|
501
489
|
#
|
502
490
|
# # ArgumentError
|
503
491
|
#
|
504
492
|
# @example Without src And Without Block
|
505
493
|
#
|
506
|
-
# <%=
|
494
|
+
# <%= video(content: true) %>
|
507
495
|
#
|
508
496
|
# # ArgumentError
|
509
497
|
#
|
510
498
|
# @example Fingerprint Mode
|
511
499
|
#
|
512
|
-
# <%=
|
500
|
+
# <%= video "movie.mp4" %>
|
513
501
|
#
|
514
502
|
# # <video src="/assets/movie-28a6b886de2372ee3922fcaf3f78f2d8.mp4"></video>
|
515
503
|
#
|
516
504
|
# @example CDN Mode
|
517
505
|
#
|
518
|
-
# <%=
|
506
|
+
# <%= video "movie.mp4" %>
|
519
507
|
#
|
520
508
|
# # <video src="https://assets.bookshelf.org/assets/movie-28a6b886de2372ee3922fcaf3f78f2d8.mp4"></video>
|
521
509
|
def video_tag(source = nil, options = {}, &blk)
|
@@ -556,26 +544,26 @@ module Hanami
|
|
556
544
|
#
|
557
545
|
# @example Basic Usage
|
558
546
|
#
|
559
|
-
# <%=
|
547
|
+
# <%= audio "song.ogg" %>
|
560
548
|
#
|
561
549
|
# # <audio src="/assets/song.ogg"></audio>
|
562
550
|
#
|
563
551
|
# @example Absolute URL
|
564
552
|
#
|
565
|
-
# <%=
|
553
|
+
# <%= audio "https://example-cdn.com/assets/song.ogg" %>
|
566
554
|
#
|
567
555
|
# # <audio src="https://example-cdn.com/assets/song.ogg"></audio>
|
568
556
|
#
|
569
557
|
# @example Custom HTML Attributes
|
570
558
|
#
|
571
|
-
# <%=
|
559
|
+
# <%= audio("song.ogg", autoplay: true, controls: true) %>
|
572
560
|
#
|
573
561
|
# # <audio src="/assets/song.ogg" autoplay="autoplay" controls="controls"></audio>
|
574
562
|
#
|
575
563
|
# @example Fallback Content
|
576
564
|
#
|
577
565
|
# <%=
|
578
|
-
#
|
566
|
+
# audio("song.ogg") do
|
579
567
|
# "Your browser does not support the audio tag"
|
580
568
|
# end
|
581
569
|
# %>
|
@@ -587,7 +575,7 @@ module Hanami
|
|
587
575
|
# @example Tracks
|
588
576
|
#
|
589
577
|
# <%=
|
590
|
-
#
|
578
|
+
# audio("song.ogg") do
|
591
579
|
# tag.track(kind: "captions", src: asset_url("song.pt-BR.vtt"),
|
592
580
|
# srclang: "pt-BR", label: "Portuguese")
|
593
581
|
# end
|
@@ -599,25 +587,25 @@ module Hanami
|
|
599
587
|
#
|
600
588
|
# @example Without Any Argument
|
601
589
|
#
|
602
|
-
# <%=
|
590
|
+
# <%= audio %>
|
603
591
|
#
|
604
592
|
# # ArgumentError
|
605
593
|
#
|
606
594
|
# @example Without src And Without Block
|
607
595
|
#
|
608
|
-
# <%=
|
596
|
+
# <%= audio(controls: true) %>
|
609
597
|
#
|
610
598
|
# # ArgumentError
|
611
599
|
#
|
612
600
|
# @example Fingerprint Mode
|
613
601
|
#
|
614
|
-
# <%=
|
602
|
+
# <%= audio "song.ogg" %>
|
615
603
|
#
|
616
604
|
# # <audio src="/assets/song-28a6b886de2372ee3922fcaf3f78f2d8.ogg"></audio>
|
617
605
|
#
|
618
606
|
# @example CDN Mode
|
619
607
|
#
|
620
|
-
# <%=
|
608
|
+
# <%= audio "song.ogg" %>
|
621
609
|
#
|
622
610
|
# # <audio src="https://assets.bookshelf.org/assets/song-28a6b886de2372ee3922fcaf3f78f2d8.ogg"></audio>
|
623
611
|
def audio_tag(source = nil, options = {}, &blk)
|
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
|