piko-lite-box 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. checksums.yaml +7 -0
  2. data/hanami-3.0.1/CHANGELOG.md +1701 -0
  3. data/hanami-3.0.1/LICENSE +20 -0
  4. data/hanami-3.0.1/README.md +89 -0
  5. data/hanami-3.0.1/hanami.gemspec +49 -0
  6. data/hanami-3.0.1/lib/hanami/app.rb +197 -0
  7. data/hanami-3.0.1/lib/hanami/boot.rb +5 -0
  8. data/hanami-3.0.1/lib/hanami/config/actions/content_security_policy.rb +140 -0
  9. data/hanami-3.0.1/lib/hanami/config/actions/cookies.rb +57 -0
  10. data/hanami-3.0.1/lib/hanami/config/actions/sessions.rb +83 -0
  11. data/hanami-3.0.1/lib/hanami/config/actions.rb +189 -0
  12. data/hanami-3.0.1/lib/hanami/config/assets.rb +84 -0
  13. data/hanami-3.0.1/lib/hanami/config/console.rb +79 -0
  14. data/hanami-3.0.1/lib/hanami/config/db.rb +35 -0
  15. data/hanami-3.0.1/lib/hanami/config/i18n.rb +138 -0
  16. data/hanami-3.0.1/lib/hanami/config/logger.rb +207 -0
  17. data/hanami-3.0.1/lib/hanami/config/null_config.rb +17 -0
  18. data/hanami-3.0.1/lib/hanami/config/router.rb +48 -0
  19. data/hanami-3.0.1/lib/hanami/config/views.rb +103 -0
  20. data/hanami-3.0.1/lib/hanami/config.rb +564 -0
  21. data/hanami-3.0.1/lib/hanami/constants.rb +62 -0
  22. data/hanami-3.0.1/lib/hanami/env.rb +52 -0
  23. data/hanami-3.0.1/lib/hanami/errors.rb +41 -0
  24. data/hanami-3.0.1/lib/hanami/extensions/action/i18n_helper.rb +64 -0
  25. data/hanami-3.0.1/lib/hanami/extensions/action/name_inferrer.rb +34 -0
  26. data/hanami-3.0.1/lib/hanami/extensions/action/slice_configured_action.rb +190 -0
  27. data/hanami-3.0.1/lib/hanami/extensions/action.rb +147 -0
  28. data/hanami-3.0.1/lib/hanami/extensions/db/repo.rb +108 -0
  29. data/hanami-3.0.1/lib/hanami/extensions/mailer/slice_configured_mailer.rb +134 -0
  30. data/hanami-3.0.1/lib/hanami/extensions/mailer.rb +28 -0
  31. data/hanami-3.0.1/lib/hanami/extensions/operation/slice_configured_db_operation.rb +90 -0
  32. data/hanami-3.0.1/lib/hanami/extensions/operation.rb +33 -0
  33. data/hanami-3.0.1/lib/hanami/extensions/router/errors.rb +58 -0
  34. data/hanami-3.0.1/lib/hanami/extensions/view/context.rb +298 -0
  35. data/hanami-3.0.1/lib/hanami/extensions/view/part.rb +92 -0
  36. data/hanami-3.0.1/lib/hanami/extensions/view/scope.rb +36 -0
  37. data/hanami-3.0.1/lib/hanami/extensions/view/slice_configured_context.rb +73 -0
  38. data/hanami-3.0.1/lib/hanami/extensions/view/slice_configured_helpers.rb +55 -0
  39. data/hanami-3.0.1/lib/hanami/extensions/view/slice_configured_part.rb +73 -0
  40. data/hanami-3.0.1/lib/hanami/extensions/view/slice_configured_view.rb +243 -0
  41. data/hanami-3.0.1/lib/hanami/extensions/view/standard_helpers.rb +26 -0
  42. data/hanami-3.0.1/lib/hanami/extensions/view.rb +38 -0
  43. data/hanami-3.0.1/lib/hanami/extensions.rb +30 -0
  44. data/hanami-3.0.1/lib/hanami/helpers/assets_helper.rb +804 -0
  45. data/hanami-3.0.1/lib/hanami/helpers/form_helper/form_builder.rb +1389 -0
  46. data/hanami-3.0.1/lib/hanami/helpers/form_helper/values.rb +75 -0
  47. data/hanami-3.0.1/lib/hanami/helpers/form_helper.rb +213 -0
  48. data/hanami-3.0.1/lib/hanami/helpers/i18n_helper.rb +241 -0
  49. data/hanami-3.0.1/lib/hanami/logger/rack_formatter.rb +73 -0
  50. data/hanami-3.0.1/lib/hanami/logger/sql_formatter.rb +80 -0
  51. data/hanami-3.0.1/lib/hanami/logger/sql_logger.rb +48 -0
  52. data/hanami-3.0.1/lib/hanami/middleware/assets.rb +21 -0
  53. data/hanami-3.0.1/lib/hanami/middleware/content_security_policy_nonce.rb +53 -0
  54. data/hanami-3.0.1/lib/hanami/middleware/public_errors_app.rb +75 -0
  55. data/hanami-3.0.1/lib/hanami/middleware/render_errors.rb +90 -0
  56. data/hanami-3.0.1/lib/hanami/port.rb +45 -0
  57. data/hanami-3.0.1/lib/hanami/prepare.rb +5 -0
  58. data/hanami-3.0.1/lib/hanami/provider/source.rb +16 -0
  59. data/hanami-3.0.1/lib/hanami/provider_registrar.rb +28 -0
  60. data/hanami-3.0.1/lib/hanami/providers/assets.rb +28 -0
  61. data/hanami-3.0.1/lib/hanami/providers/db/adapter.rb +75 -0
  62. data/hanami-3.0.1/lib/hanami/providers/db/adapters.rb +66 -0
  63. data/hanami-3.0.1/lib/hanami/providers/db/config.rb +44 -0
  64. data/hanami-3.0.1/lib/hanami/providers/db/gateway.rb +87 -0
  65. data/hanami-3.0.1/lib/hanami/providers/db/sql_adapter.rb +100 -0
  66. data/hanami-3.0.1/lib/hanami/providers/db.rb +325 -0
  67. data/hanami-3.0.1/lib/hanami/providers/db_logging.rb +19 -0
  68. data/hanami-3.0.1/lib/hanami/providers/i18n/backend.rb +373 -0
  69. data/hanami-3.0.1/lib/hanami/providers/i18n/locale/en.yml +57 -0
  70. data/hanami-3.0.1/lib/hanami/providers/i18n.rb +114 -0
  71. data/hanami-3.0.1/lib/hanami/providers/inflector.rb +17 -0
  72. data/hanami-3.0.1/lib/hanami/providers/logger.rb +41 -0
  73. data/hanami-3.0.1/lib/hanami/providers/mailers.rb +101 -0
  74. data/hanami-3.0.1/lib/hanami/providers/rack.rb +47 -0
  75. data/hanami-3.0.1/lib/hanami/providers/relations.rb +31 -0
  76. data/hanami-3.0.1/lib/hanami/providers/routes.rb +29 -0
  77. data/hanami-3.0.1/lib/hanami/rake_tasks.rb +54 -0
  78. data/hanami-3.0.1/lib/hanami/routes.rb +146 -0
  79. data/hanami-3.0.1/lib/hanami/settings/composite_store.rb +53 -0
  80. data/hanami-3.0.1/lib/hanami/settings/env_store.rb +32 -0
  81. data/hanami-3.0.1/lib/hanami/settings.rb +234 -0
  82. data/hanami-3.0.1/lib/hanami/setup.rb +6 -0
  83. data/hanami-3.0.1/lib/hanami/slice/router.rb +280 -0
  84. data/hanami-3.0.1/lib/hanami/slice/routes_helper.rb +37 -0
  85. data/hanami-3.0.1/lib/hanami/slice/routing/middleware/stack.rb +216 -0
  86. data/hanami-3.0.1/lib/hanami/slice/routing/resolver.rb +88 -0
  87. data/hanami-3.0.1/lib/hanami/slice/view_name_inferrer.rb +63 -0
  88. data/hanami-3.0.1/lib/hanami/slice.rb +1239 -0
  89. data/hanami-3.0.1/lib/hanami/slice_configurable.rb +72 -0
  90. data/hanami-3.0.1/lib/hanami/slice_name.rb +111 -0
  91. data/hanami-3.0.1/lib/hanami/slice_registrar.rb +215 -0
  92. data/hanami-3.0.1/lib/hanami/universal_logger.rb +250 -0
  93. data/hanami-3.0.1/lib/hanami/version.rb +45 -0
  94. data/hanami-3.0.1/lib/hanami/web/rack_logger.rb +126 -0
  95. data/hanami-3.0.1/lib/hanami/web/welcome.html.erb +584 -0
  96. data/hanami-3.0.1/lib/hanami/web/welcome.rb +46 -0
  97. data/hanami-3.0.1/lib/hanami.rb +276 -0
  98. data/piko-lite-box.gemspec +11 -0
  99. metadata +137 -0
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hanami
4
+ module Extensions
5
+ module Operation
6
+ # Extends operations to support the database.
7
+ #
8
+ # Add an initializer accepting a `rom:` dependency, which is supplied automatically from the
9
+ # `"db.rom"` component in the operation's slice.
10
+ #
11
+ # @api private
12
+ class SliceConfiguredDBOperation < Module
13
+ attr_reader :slice
14
+
15
+ def initialize(slice)
16
+ super()
17
+ @slice = slice
18
+ end
19
+
20
+ def extended(operation_class)
21
+ require "dry/operation/extensions/rom"
22
+ operation_class.include Dry::Operation::Extensions::ROM
23
+
24
+ operation_class.include InstanceMethods
25
+ operation_class.include SliceInstanceMethods.new(slice)
26
+ define_new
27
+ end
28
+
29
+ def inspect
30
+ "#<#{self.class.name}[#{slice.name}>"
31
+ end
32
+
33
+ private
34
+
35
+ def define_new
36
+ resolve_rom = method(:resolve_rom)
37
+
38
+ define_method(:new) do |**kwargs|
39
+ super(
40
+ **kwargs,
41
+ rom: kwargs.fetch(:rom) { resolve_rom.() },
42
+ )
43
+ end
44
+ end
45
+
46
+ def resolve_rom
47
+ slice["db.rom"] if slice.key?("db.rom")
48
+ end
49
+
50
+ module InstanceMethods
51
+ attr_reader :rom
52
+
53
+ def initialize(rom:, **)
54
+ super()
55
+ @rom = rom
56
+ end
57
+ end
58
+
59
+ class SliceInstanceMethods < Module
60
+ attr_reader :slice
61
+
62
+ def initialize(slice)
63
+ super()
64
+ @slice = slice
65
+ end
66
+
67
+ def included(operation_class)
68
+ define_transaction
69
+ end
70
+
71
+ private
72
+
73
+ def define_transaction
74
+ slice = self.slice
75
+ define_method(:transaction) do |**kwargs, &block|
76
+ unless rom
77
+ msg = <<~TEXT.strip
78
+ A configured db for #{slice} is required to run transactions.
79
+ TEXT
80
+ raise Hanami::ComponentLoadError, msg
81
+ end
82
+
83
+ super(**kwargs, &block)
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/operation"
4
+
5
+ module Hanami
6
+ module Extensions
7
+ # Integrated behavior for `Dry::Operation` classes within Hanami apps.
8
+ #
9
+ # @see https://github.com/dry-rb/dry-operation
10
+ #
11
+ # @api public
12
+ # @since 2.2.0
13
+ module Operation
14
+ require_relative "operation/slice_configured_db_operation"
15
+
16
+ # @api private
17
+ def self.extended(operation_class)
18
+ super
19
+
20
+ operation_class.extend(Hanami::SliceConfigurable)
21
+ end
22
+
23
+ # private
24
+
25
+ # @api private
26
+ def configure_for_slice(slice)
27
+ extend SliceConfiguredDBOperation.new(slice) if Hanami.bundled?("hanami-db")
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ Dry::Operation.extend(Hanami::Extensions::Operation)
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/router"
4
+
5
+ module Hanami
6
+ class Router
7
+ # Error raised when a request is made for a missing route.
8
+ #
9
+ # Raised only when using hanami-router as part of a full Hanami app. When using hanami-router
10
+ # standalone, the behavior for such requests is to return a "Not Found" response.
11
+ #
12
+ # @api public
13
+ # @since 2.1.0
14
+ class NotFoundError < Hanami::Router::Error
15
+ # @return [Hash] the Rack environment for the request
16
+ #
17
+ # @api public
18
+ # @since 2.1.0
19
+ attr_reader :env
20
+
21
+ def initialize(env)
22
+ @env = env
23
+
24
+ message = "No route found for #{env["REQUEST_METHOD"]} #{env["PATH_INFO"]}"
25
+ super(message)
26
+ end
27
+ end
28
+
29
+ # Error raised when a request is made for a route using a HTTP method not allowed on the route.
30
+ #
31
+ # Raised only when using hanami-router as part of a full Hanami app. When using hanami-router
32
+ # standalone, the behavior for such requests is to return a "Method Not Allowed" response.
33
+ #
34
+ # @api public
35
+ # @since 2.1.0
36
+ class NotAllowedError < Hanami::Router::Error
37
+ # @return [Hash] the Rack environment for the request
38
+ #
39
+ # @api public
40
+ # @since 2.1.0
41
+ attr_reader :env
42
+
43
+ # @return [Array<String>] the allowed methods for the route
44
+ #
45
+ # @api public
46
+ # @since 2.1.0
47
+ attr_reader :allowed_methods
48
+
49
+ def initialize(env, allowed_methods)
50
+ @env = env
51
+ @allowed_methods = allowed_methods
52
+
53
+ message = "Only #{allowed_methods.join(', ')} requests are allowed at #{env["PATH_INFO"]}"
54
+ super(message)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,298 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../errors"
4
+ require_relative "slice_configured_context"
5
+
6
+ module Hanami
7
+ module Extensions
8
+ module View
9
+ # View context for views in Hanami apps.
10
+ #
11
+ # @api public
12
+ # @since 2.1.0
13
+ module Context
14
+ class << self
15
+ # Returns a context class for the given slice. If a context class is not defined, defines
16
+ # a class named `Views::Context` within the slice's namespace.
17
+ #
18
+ # @api private
19
+ # @since 2.1.0
20
+ def context_class(slice)
21
+ views_namespace = views_namespace(slice)
22
+
23
+ if views_namespace.const_defined?(:Context)
24
+ return views_namespace.const_get(:Context)
25
+ end
26
+
27
+ views_namespace.const_set(:Context, Class.new(context_superclass(slice)).tap { |klass|
28
+ # Call configure_for_slice explicitly, since this is an anonymous class at this point,
29
+ # so the slice cannot be inferred from its name.
30
+ klass.configure_for_slice(slice)
31
+ })
32
+ end
33
+
34
+ private
35
+
36
+ # @api private
37
+ # @since 2.1.0
38
+ def context_superclass(slice)
39
+ return Hanami::View::Context if Hanami.app.equal?(slice)
40
+
41
+ begin
42
+ slice.inflector.constantize(
43
+ slice.inflector.camelize("#{slice.app.slice_name.name}/views/context")
44
+ )
45
+ rescue NameError => exception
46
+ raise exception unless %i[Views Context].include?(exception.name)
47
+
48
+ Hanami::View::Context
49
+ end
50
+ end
51
+
52
+ # @api private
53
+ # @since 2.1.0
54
+ def views_namespace(slice)
55
+ # TODO: this could be moved into the top-level Extensions::View
56
+ if slice.namespace.const_defined?(:Views)
57
+ slice.namespace.const_get(:Views)
58
+ else
59
+ slice.namespace.const_set(:Views, Module.new)
60
+ end
61
+ end
62
+ end
63
+
64
+ # @api private
65
+ # @since 2.1.0
66
+ module ClassExtension
67
+ def self.included(context_class)
68
+ super
69
+
70
+ context_class.extend(Hanami::SliceConfigurable)
71
+ context_class.extend(ClassMethods)
72
+ context_class.prepend(InstanceMethods)
73
+ end
74
+
75
+ # @api private
76
+ # @since 2.1.0
77
+ module ClassMethods
78
+ # @api private
79
+ # @since 2.1.0
80
+ def configure_for_slice(slice)
81
+ extend SliceConfiguredContext.new(slice)
82
+ end
83
+ end
84
+
85
+ # @api public
86
+ # @since 2.1.0
87
+ module InstanceMethods
88
+ # Returns the app's inflector.
89
+ #
90
+ # @return [Dry::Inflector] the inflector
91
+ #
92
+ # @api public
93
+ # @since 2.1.0
94
+ attr_reader :inflector
95
+
96
+ # @see SliceConfiguredContext#define_new
97
+ #
98
+ # @api private
99
+ # @since 2.1.0
100
+ def initialize(
101
+ inflector: nil,
102
+ routes: nil,
103
+ assets: nil,
104
+ request: nil,
105
+ i18n: nil,
106
+ **args
107
+ )
108
+ @inflector = inflector
109
+ @routes = routes
110
+ @assets = assets
111
+ @request = request
112
+ @i18n = i18n
113
+
114
+ @content_for = {}
115
+
116
+ super(**args)
117
+ end
118
+
119
+ # @api private
120
+ # @since 2.1.0
121
+ def initialize_copy(source)
122
+ # The standard implementation of initialize_copy will make shallow copies of all
123
+ # instance variables from the source. This is fine for most of our ivars.
124
+ super
125
+
126
+ # Dup any objects that will be mutated over a given rendering to ensure no leakage of
127
+ # state across distinct view renderings.
128
+ @content_for = source.instance_variable_get(:@content_for).dup
129
+ end
130
+
131
+ # Returns the app's assets.
132
+ #
133
+ # @return [Hanami::Assets] the assets
134
+ #
135
+ # @raise [Hanami::ComponentLoadError] if the hanami-assets gem is not bundled
136
+ #
137
+ # @api public
138
+ # @since 2.1.0
139
+ def assets
140
+ unless @assets
141
+ msg =
142
+ if Hanami.bundled?("hanami-assets")
143
+ "Have you put files into your assets directory?"
144
+ else
145
+ "The hanami-assets gem is required to access assets."
146
+ end
147
+
148
+ raise Hanami::ComponentLoadError, "Assets not available. #{msg}"
149
+ end
150
+
151
+ @assets
152
+ end
153
+
154
+ # Returns the current request, if the view is rendered from within an action.
155
+ #
156
+ # @return [Hanami::Action::Request] the request
157
+ #
158
+ # @raise [Hanami::ComponentLoadError] if the view is not rendered from within a request
159
+ #
160
+ # @api public
161
+ # @since 2.1.0
162
+ def request
163
+ unless @request
164
+ raise Hanami::ComponentLoadError, <<~STR
165
+ Request not available. Only views rendered from Hanami::Action instances have a request.
166
+ STR
167
+ end
168
+
169
+ @request
170
+ end
171
+
172
+ # Returns true if the view is rendered from within an action and a request is available.
173
+ #
174
+ # @return [Boolean]
175
+ #
176
+ # @api public
177
+ # @since 2.3.0
178
+ def request?
179
+ !!@request
180
+ end
181
+
182
+ # Returns the app's routes helper.
183
+ #
184
+ # @return [Hanami::Slice::RoutesHelper] the routes helper
185
+ #
186
+ # @raise [Hanami::ComponentLoadError] if the hanami-router gem is not bundled or routes
187
+ # are not defined
188
+ #
189
+ # @api public
190
+ # @since 2.1.0
191
+ def routes
192
+ unless @routes
193
+ raise Hanami::ComponentLoadError, "the hanami-router gem is required to access routes"
194
+ end
195
+
196
+ @routes
197
+ end
198
+
199
+ # Returns the slice's i18n backend.
200
+ #
201
+ # @return [Hanami::Providers::I18n::Backend] the i18n backend
202
+ #
203
+ # @raise [Hanami::ComponentLoadError] if the i18n gem is not bundled
204
+ #
205
+ # @api public
206
+ # @since 3.0.0
207
+ def i18n
208
+ unless @i18n
209
+ raise Hanami::ComponentLoadError, "the i18n gem is required to access translations"
210
+ end
211
+
212
+ @i18n
213
+ end
214
+
215
+ # @overload content_for(key, value = nil, &block)
216
+ # Stores a string or block of template markup for later use.
217
+ #
218
+ # @param key [Symbol] the content key, for later retrieval
219
+ # @param value [String, nil] the content, if no block is given
220
+ #
221
+ # @return [String] the content
222
+ #
223
+ # @example
224
+ # content_for(:page_title, "Hello world")
225
+ #
226
+ # @example In a template
227
+ # <%= content_for :page_title do %>
228
+ # <h1>Hello world</h1>
229
+ # <% end %>
230
+ #
231
+ # @overload content_for(key)
232
+ # Returns the previously stored content for the given key.
233
+ #
234
+ # @param key [Symbol] the content key
235
+ #
236
+ # @return [String, nil] the content, or nil if no content previously stored with the
237
+ # key
238
+ #
239
+ # @api public
240
+ # @since 2.1.0
241
+ def content_for(key, value = nil)
242
+ if block_given?
243
+ @content_for[key] = yield
244
+ nil
245
+ elsif value
246
+ @content_for[key] = value
247
+ nil
248
+ else
249
+ @content_for[key]
250
+ end
251
+ end
252
+
253
+ # Returns the current request's CSRF token.
254
+ #
255
+ # @return [String] the token
256
+ #
257
+ # @raise [Hanami::ComponentLoadError] if the view is not rendered from within a request
258
+ # @raise [Hanami::Action::MissingSessionError] if sessions are not enabled
259
+ #
260
+ # @api public
261
+ # @since 2.1.0
262
+ def csrf_token
263
+ request.session[Hanami::Action::CSRFProtection::CSRF_TOKEN]
264
+ end
265
+
266
+ # Returns the session for the current request.
267
+ #
268
+ # @return [Rack::Session::Abstract::SessionHash] the session hash
269
+ #
270
+ # @raise [Hanami::ComponentLoadError] if the view is not rendered from within a request
271
+ # @raise [Hanami::Action::MissingSessionError] if sessions are not enabled
272
+ #
273
+ # @api public
274
+ # @since 2.1.0
275
+ def session
276
+ request.session
277
+ end
278
+
279
+ # Returns the flash hash for the current request.
280
+ #
281
+ # @return []
282
+ #
283
+ # @raise [Hanami::ComponentLoadError] if the view is not rendered from within a request
284
+ # @raise [Hanami::Action::MissingSessionError] if sessions are not enabled
285
+ #
286
+ # @api public
287
+ # @since 2.1.0
288
+ def flash
289
+ request.flash
290
+ end
291
+ end
292
+ end
293
+ end
294
+ end
295
+ end
296
+ end
297
+
298
+ Hanami::View::Context.include(Hanami::Extensions::View::Context::ClassExtension)
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "standard_helpers"
4
+ require_relative "slice_configured_part"
5
+
6
+ module Hanami
7
+ module Extensions
8
+ module View
9
+ # @api public
10
+ # @since 2.1.0
11
+ module Part
12
+ # @api private
13
+ # @since 2.1.0
14
+ def self.included(part_class)
15
+ super
16
+
17
+ part_class.extend(Hanami::SliceConfigurable)
18
+ part_class.extend(ClassMethods)
19
+ end
20
+
21
+ # @api private
22
+ # @since 2.1.0
23
+ module ClassMethods
24
+ # @api private
25
+ # @since 2.1.0
26
+ def configure_for_slice(slice)
27
+ extend SliceConfiguredPart.new(slice)
28
+
29
+ const_set :PartHelpers, Class.new(PartHelpers) { |klass|
30
+ # Call configure_for_slice explicitly, since this is an anonymous class at this point,
31
+ # so the slice cannot be inferred from its name.
32
+ klass.configure_for_slice(slice)
33
+ }
34
+ end
35
+ end
36
+
37
+ # Returns an object including the default Hanami helpers as well as the user-defined helpers
38
+ # for the part's slice.
39
+ #
40
+ # Use this when you need to access helpers inside your part classes.
41
+ #
42
+ # @return [Object] the helpers object
43
+ #
44
+ # @api public
45
+ # @since 2.1.0
46
+ def helpers
47
+ @helpers ||= self.class.const_get(:PartHelpers).new(context: _context)
48
+ end
49
+ end
50
+
51
+ # Standalone helpers class including both {StandardHelpers} as well as the user-defined
52
+ # helpers for the slice.
53
+ #
54
+ # Used where helpers should be addressed via an intermediary object (i.e. in parts),
55
+ # rather than mixed into a class directly.
56
+ #
57
+ # @api private
58
+ # @since 2.1.0
59
+ class PartHelpers
60
+ extend Hanami::SliceConfigurable
61
+
62
+ include StandardHelpers
63
+
64
+ # @api private
65
+ # @since 2.1.0
66
+ def self.configure_for_slice(slice)
67
+ extend SliceConfiguredHelpers.new(slice)
68
+ end
69
+
70
+ # Returns the context for the current view rendering.
71
+ #
72
+ # @return [Hanami::View::Context] the context
73
+ #
74
+ # @api public
75
+ # @since 2.1.0
76
+ attr_reader :_context
77
+
78
+ # @api public
79
+ # @since 2.1.0
80
+ alias_method :context, :_context
81
+
82
+ # @api private
83
+ # @since 2.1.0
84
+ def initialize(context:)
85
+ @_context = context
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ Hanami::View::Part.include(Hanami::Extensions::View::Part)
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "slice_configured_helpers"
4
+ require_relative "standard_helpers"
5
+
6
+ module Hanami
7
+ module Extensions
8
+ module View
9
+ # @api private
10
+ # @since 2.1.0
11
+ module Scope
12
+ # @api private
13
+ # @since 2.1.0
14
+ def self.included(scope_class)
15
+ super
16
+
17
+ scope_class.extend(Hanami::SliceConfigurable)
18
+ scope_class.include(StandardHelpers)
19
+ scope_class.extend(ClassMethods)
20
+ end
21
+
22
+ # @api private
23
+ # @since 2.1.0
24
+ module ClassMethods
25
+ # @api private
26
+ # @since 2.1.0
27
+ def configure_for_slice(slice)
28
+ extend SliceConfiguredHelpers.new(slice)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ Hanami::View::Scope.include(Hanami::Extensions::View::Scope)
@@ -0,0 +1,73 @@
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 context class defined within
7
+ # a slice's module namespace.
8
+ #
9
+ # @api public
10
+ # @since 2.1.0
11
+ class SliceConfiguredContext < 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(_context_class)
24
+ define_new
25
+ end
26
+
27
+ # @api public
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 context class that resolves key components from the app
36
+ # container and provides them to {#initialize} as injected dependencies.
37
+ #
38
+ # This includes the following app components:
39
+ # - the configured inflector as `inflector`
40
+ # - "routes" from the app container as `routes`
41
+ # - "assets" from the app container as `assets`
42
+ # - "i18n" from the slice container as `i18n`
43
+ def define_new
44
+ inflector = slice.inflector
45
+ resolve_routes = method(:resolve_routes)
46
+ resolve_assets = method(:resolve_assets)
47
+ resolve_i18n = method(:resolve_i18n)
48
+
49
+ define_method :new do |**kwargs|
50
+ kwargs[:inflector] ||= inflector
51
+ kwargs[:routes] ||= resolve_routes.()
52
+ kwargs[:assets] ||= resolve_assets.()
53
+ kwargs[:i18n] ||= resolve_i18n.()
54
+
55
+ super(**kwargs)
56
+ end
57
+ end
58
+
59
+ def resolve_routes
60
+ slice["routes"] if slice.key?("routes")
61
+ end
62
+
63
+ def resolve_assets
64
+ slice["assets"] if slice.key?("assets")
65
+ end
66
+
67
+ def resolve_i18n
68
+ slice["i18n"] if slice.key?("i18n")
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end