hanami-view 2.3.0 → 3.0.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 +404 -183
- data/LICENSE +20 -0
- data/README.md +17 -22
- data/hanami-view.gemspec +19 -19
- data/lib/hanami/view/context.rb +11 -0
- data/lib/hanami/view/decorated_attributes.rb +0 -2
- data/lib/hanami/view/erb/filters/block.rb +2 -1
- data/lib/hanami/view/erb/filters/trimming.rb +14 -8
- data/lib/hanami/view/erb/parser.rb +5 -1
- data/lib/hanami/view/exposure.rb +16 -10
- data/lib/hanami/view/exposures.rb +6 -2
- data/lib/hanami/view/helpers/escape_helper.rb +3 -2
- data/lib/hanami/view/helpers/number_formatting_helper.rb +2 -4
- data/lib/hanami/view/helpers/tag_helper/tag_builder.rb +10 -7
- data/lib/hanami/view/helpers/tag_helper.rb +1 -3
- data/lib/hanami/view/html.rb +0 -2
- data/lib/hanami/view/html_safe_string_buffer.rb +1 -1
- data/lib/hanami/view/part.rb +2 -5
- data/lib/hanami/view/part_builder.rb +7 -9
- data/lib/hanami/view/renderer.rb +78 -28
- data/lib/hanami/view/rendering.rb +38 -22
- data/lib/hanami/view/rendering_missing.rb +11 -14
- data/lib/hanami/view/scope.rb +29 -15
- data/lib/hanami/view/scope_builder.rb +6 -6
- data/lib/hanami/view/tilt/haml_adapter.rb +1 -1
- data/lib/hanami/view/tilt/slim_adapter.rb +1 -1
- data/lib/hanami/view/version.rb +1 -2
- data/lib/hanami/view.rb +63 -31
- metadata +14 -53
data/lib/hanami/view.rb
CHANGED
|
@@ -22,7 +22,6 @@ module Hanami
|
|
|
22
22
|
# @since 2.1.0
|
|
23
23
|
class View
|
|
24
24
|
# @api private
|
|
25
|
-
# @since 2.1.0
|
|
26
25
|
def self.gem_loader
|
|
27
26
|
@gem_loader ||= Zeitwerk::Loader.new.tap do |loader|
|
|
28
27
|
root = File.expand_path("..", __dir__)
|
|
@@ -31,13 +30,13 @@ module Hanami
|
|
|
31
30
|
loader.ignore(
|
|
32
31
|
"#{root}/hanami-view.rb",
|
|
33
32
|
"#{root}/hanami/view/version.rb",
|
|
34
|
-
"#{root}/hanami/view/errors.rb"
|
|
33
|
+
"#{root}/hanami/view/errors.rb"
|
|
35
34
|
)
|
|
36
35
|
loader.inflector = Zeitwerk::GemInflector.new("#{root}/hanami-view.rb")
|
|
37
36
|
loader.inflector.inflect(
|
|
38
37
|
"erb" => "ERB",
|
|
39
38
|
"html" => "HTML",
|
|
40
|
-
"html_safe_string_buffer" => "HTMLSafeStringBuffer"
|
|
39
|
+
"html_safe_string_buffer" => "HTMLSafeStringBuffer"
|
|
41
40
|
)
|
|
42
41
|
end
|
|
43
42
|
end
|
|
@@ -45,7 +44,6 @@ module Hanami
|
|
|
45
44
|
gem_loader.setup
|
|
46
45
|
|
|
47
46
|
# @api private
|
|
48
|
-
# @since 2.1.0
|
|
49
47
|
DEFAULT_RENDERER_OPTIONS = {default_encoding: "utf-8"}.freeze
|
|
50
48
|
|
|
51
49
|
include Dry::Equalizer(:config, :exposures)
|
|
@@ -235,6 +233,23 @@ module Hanami
|
|
|
235
233
|
# @!scope class
|
|
236
234
|
setting :inflector, default: Dry::Inflector.new
|
|
237
235
|
|
|
236
|
+
# @overload config.decorate_exposures=(value)
|
|
237
|
+
# Controls whether exposures are decorated by default.
|
|
238
|
+
#
|
|
239
|
+
# When set to `true`, all exposures will be decorated with matching Parts unless explicitly
|
|
240
|
+
# marked with `decorate: false`.
|
|
241
|
+
#
|
|
242
|
+
# When set to `false` (the default), exposures will not be decorated unless explicitly marked
|
|
243
|
+
# with `decorate: true`, or declared with `decorate`.
|
|
244
|
+
#
|
|
245
|
+
# Defaults to `false`.
|
|
246
|
+
#
|
|
247
|
+
# @param value [Boolean] whether to decorate exposures by default
|
|
248
|
+
# @api public
|
|
249
|
+
# @since x.x.x
|
|
250
|
+
# @!scope class
|
|
251
|
+
setting :decorate_exposures, default: false
|
|
252
|
+
|
|
238
253
|
# @overload config.renderer_options=(options)
|
|
239
254
|
# A hash of options to pass to the template engine. Template engines are
|
|
240
255
|
# provided by Tilt; see Tilt's documentation for what options your
|
|
@@ -273,7 +288,6 @@ module Hanami
|
|
|
273
288
|
# @!endgroup
|
|
274
289
|
|
|
275
290
|
# @api private
|
|
276
|
-
# @since 2.1.0
|
|
277
291
|
def self.inherited(klass)
|
|
278
292
|
super
|
|
279
293
|
|
|
@@ -288,13 +302,13 @@ module Hanami
|
|
|
288
302
|
# @param options [Hash] the exposure's options
|
|
289
303
|
# @option options [Boolean] :layout expose this value to the layout (defaults to false)
|
|
290
304
|
# @option options [Boolean] :decorate decorate this value in a matching Part (defaults to
|
|
291
|
-
#
|
|
305
|
+
# false, or the value of `config.decorate_exposures`)
|
|
292
306
|
# @option options [Symbol, Class] :as an alternative name or class to use when finding a
|
|
293
307
|
# matching Part
|
|
294
308
|
|
|
295
309
|
# @overload expose(name, **options, &block)
|
|
296
310
|
# Define a value to be passed to the template. The return value of the
|
|
297
|
-
# block will be
|
|
311
|
+
# block will be passed to the template.
|
|
298
312
|
#
|
|
299
313
|
# The block will be evaluated with the view instance as its `self`. The
|
|
300
314
|
# block's parameters will determine what it is given:
|
|
@@ -329,8 +343,8 @@ module Hanami
|
|
|
329
343
|
#
|
|
330
344
|
# @overload expose(name, **options)
|
|
331
345
|
# Define a value to be passed to the template, provided by an instance
|
|
332
|
-
# method matching the name. The method's return value will be
|
|
333
|
-
#
|
|
346
|
+
# method matching the name. The method's return value will be passed to
|
|
347
|
+
# the template.
|
|
334
348
|
#
|
|
335
349
|
# The method's parameters will determine what it is given:
|
|
336
350
|
#
|
|
@@ -342,7 +356,7 @@ module Hanami
|
|
|
342
356
|
# default values for these parameters to make the corresponding input
|
|
343
357
|
# keys optional
|
|
344
358
|
# - To receive the Context object, provide a `context:` keyword parameter
|
|
345
|
-
# - To receive the view's input arguments in their
|
|
359
|
+
# - To receive the view's input arguments in their entirety, provide a
|
|
346
360
|
# keywords splat parameter (i.e. `**input`)
|
|
347
361
|
#
|
|
348
362
|
# @example Accessing input arguments
|
|
@@ -369,8 +383,8 @@ module Hanami
|
|
|
369
383
|
#
|
|
370
384
|
# @overload expose(name, **options)
|
|
371
385
|
# Define a single value to pass through from the input data (when there is
|
|
372
|
-
# no instance method matching the `name`). This value will be
|
|
373
|
-
#
|
|
386
|
+
# no instance method matching the `name`). This value will be passed to
|
|
387
|
+
# the template.
|
|
374
388
|
#
|
|
375
389
|
# @param name [Symbol] name for the exposure
|
|
376
390
|
# @macro exposure_options
|
|
@@ -380,7 +394,7 @@ module Hanami
|
|
|
380
394
|
# @overload expose(*names, **options)
|
|
381
395
|
# Define multiple values to pass through from the input data (when there
|
|
382
396
|
# is no instance methods matching their names). These values will be
|
|
383
|
-
#
|
|
397
|
+
# passed through to the template.
|
|
384
398
|
#
|
|
385
399
|
# The provided options will be applied to all the exposures.
|
|
386
400
|
#
|
|
@@ -411,12 +425,23 @@ module Hanami
|
|
|
411
425
|
expose(*names, **options, private: true, &block)
|
|
412
426
|
end
|
|
413
427
|
|
|
428
|
+
# Defines an exposure that will be decorated with a matching Part.
|
|
429
|
+
#
|
|
430
|
+
# This is a shorthand for `expose(..., decorate: true)`.
|
|
431
|
+
#
|
|
432
|
+
# @see expose
|
|
433
|
+
#
|
|
434
|
+
# @api public
|
|
435
|
+
# @since 2.1.0
|
|
436
|
+
def self.decorate(*names, **options, &block)
|
|
437
|
+
expose(*names, **options, decorate: true, &block)
|
|
438
|
+
end
|
|
439
|
+
|
|
414
440
|
# Returns the defined exposures. These are unbound, since bound exposures
|
|
415
441
|
# are only created when initializing a View instance.
|
|
416
442
|
#
|
|
417
443
|
# @return [Exposures]
|
|
418
444
|
# @api private
|
|
419
|
-
# @since 2.1.0
|
|
420
445
|
def self.exposures
|
|
421
446
|
@exposures ||= Exposures.new
|
|
422
447
|
end
|
|
@@ -512,13 +537,6 @@ module Hanami
|
|
|
512
537
|
# @!endgroup
|
|
513
538
|
|
|
514
539
|
# @api private
|
|
515
|
-
# @since 2.1.0
|
|
516
|
-
def self.layout_path(layout)
|
|
517
|
-
File.join(*[config.layouts_dir, layout].compact)
|
|
518
|
-
end
|
|
519
|
-
|
|
520
|
-
# @api private
|
|
521
|
-
# @since 2.1.0
|
|
522
540
|
def self.cache
|
|
523
541
|
Cache
|
|
524
542
|
end
|
|
@@ -534,6 +552,7 @@ module Hanami
|
|
|
534
552
|
self.class.config.finalize!
|
|
535
553
|
ensure_config
|
|
536
554
|
|
|
555
|
+
@config_data = config.to_data
|
|
537
556
|
@exposures = self.class.exposures.bind(self)
|
|
538
557
|
end
|
|
539
558
|
|
|
@@ -550,8 +569,7 @@ module Hanami
|
|
|
550
569
|
# @return [Exposures]
|
|
551
570
|
#
|
|
552
571
|
# @api private
|
|
553
|
-
#
|
|
554
|
-
def exposures
|
|
572
|
+
def exposures # rubocop:disable Style/TrivialAccessors
|
|
555
573
|
@exposures
|
|
556
574
|
end
|
|
557
575
|
|
|
@@ -566,16 +584,20 @@ module Hanami
|
|
|
566
584
|
#
|
|
567
585
|
# @api public
|
|
568
586
|
# @since 2.1.0
|
|
569
|
-
def call(format:
|
|
587
|
+
def call(format: config_data.default_format,
|
|
588
|
+
context: config_data.default_context,
|
|
589
|
+
layout: config_data.layout,
|
|
590
|
+
**input)
|
|
570
591
|
rendering = self.rendering(format: format, context: context)
|
|
592
|
+
scope_class = config_data.scope
|
|
571
593
|
|
|
572
594
|
locals = locals(rendering, input)
|
|
573
|
-
output = rendering.template(
|
|
595
|
+
output = rendering.template(config_data.template, rendering.scope(scope_class, locals))
|
|
574
596
|
|
|
575
597
|
if layout
|
|
576
598
|
output = rendering.template(
|
|
577
|
-
|
|
578
|
-
rendering.scope(
|
|
599
|
+
layout_path(layout),
|
|
600
|
+
rendering.scope(scope_class, layout_locals(locals))
|
|
579
601
|
) { output }
|
|
580
602
|
end
|
|
581
603
|
|
|
@@ -583,13 +605,18 @@ module Hanami
|
|
|
583
605
|
end
|
|
584
606
|
|
|
585
607
|
# @api private
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
Rendering.new(config: config, format: format, context: context)
|
|
608
|
+
def rendering(format: config_data.default_format, context: config_data.default_context)
|
|
609
|
+
Rendering.new(config_data:, format:, context:)
|
|
589
610
|
end
|
|
590
611
|
|
|
591
612
|
private
|
|
592
613
|
|
|
614
|
+
# Frozen Data snapshot of the view's resolved configuration values.
|
|
615
|
+
# Used for fast hot-path reads during rendering.
|
|
616
|
+
#
|
|
617
|
+
# @api private
|
|
618
|
+
attr_reader :config_data
|
|
619
|
+
|
|
593
620
|
def ensure_config
|
|
594
621
|
raise UndefinedConfigError, :paths unless Array(config.paths).any?
|
|
595
622
|
raise UndefinedConfigError, :template unless config.template
|
|
@@ -597,7 +624,7 @@ module Hanami
|
|
|
597
624
|
|
|
598
625
|
def locals(rendering, input)
|
|
599
626
|
exposures.(context: rendering.context, **input) do |value, exposure|
|
|
600
|
-
if exposure.decorate? && value
|
|
627
|
+
if exposure.decorate?(default: config_data.decorate_exposures) && value
|
|
601
628
|
rendering.part(exposure.name, value, as: exposure.options[:as])
|
|
602
629
|
else
|
|
603
630
|
value
|
|
@@ -605,6 +632,11 @@ module Hanami
|
|
|
605
632
|
end
|
|
606
633
|
end
|
|
607
634
|
|
|
635
|
+
# @api private
|
|
636
|
+
def layout_path(layout)
|
|
637
|
+
File.join(*[config_data.layouts_dir, layout].compact)
|
|
638
|
+
end
|
|
639
|
+
|
|
608
640
|
def layout_locals(locals)
|
|
609
641
|
locals.each_with_object({}) do |(key, value), layout_locals|
|
|
610
642
|
layout_locals[key] = value if exposures[key].for_layout?
|
metadata
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hanami-view
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 3.0.0.rc1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Hanakai team
|
|
8
|
-
bindir:
|
|
8
|
+
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - "~>"
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: '1.
|
|
18
|
+
version: '1.4'
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - "~>"
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: '1.
|
|
25
|
+
version: '1.4'
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: dry-core
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -105,57 +105,19 @@ dependencies:
|
|
|
105
105
|
- - "~>"
|
|
106
106
|
- !ruby/object:Gem::Version
|
|
107
107
|
version: '2.6'
|
|
108
|
-
- !ruby/object:Gem::Dependency
|
|
109
|
-
name: bundler
|
|
110
|
-
requirement: !ruby/object:Gem::Requirement
|
|
111
|
-
requirements:
|
|
112
|
-
- - ">="
|
|
113
|
-
- !ruby/object:Gem::Version
|
|
114
|
-
version: '0'
|
|
115
|
-
type: :development
|
|
116
|
-
prerelease: false
|
|
117
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
118
|
-
requirements:
|
|
119
|
-
- - ">="
|
|
120
|
-
- !ruby/object:Gem::Version
|
|
121
|
-
version: '0'
|
|
122
|
-
- !ruby/object:Gem::Dependency
|
|
123
|
-
name: rake
|
|
124
|
-
requirement: !ruby/object:Gem::Requirement
|
|
125
|
-
requirements:
|
|
126
|
-
- - ">="
|
|
127
|
-
- !ruby/object:Gem::Version
|
|
128
|
-
version: '0'
|
|
129
|
-
type: :development
|
|
130
|
-
prerelease: false
|
|
131
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
132
|
-
requirements:
|
|
133
|
-
- - ">="
|
|
134
|
-
- !ruby/object:Gem::Version
|
|
135
|
-
version: '0'
|
|
136
|
-
- !ruby/object:Gem::Dependency
|
|
137
|
-
name: rspec
|
|
138
|
-
requirement: !ruby/object:Gem::Requirement
|
|
139
|
-
requirements:
|
|
140
|
-
- - ">="
|
|
141
|
-
- !ruby/object:Gem::Version
|
|
142
|
-
version: '0'
|
|
143
|
-
type: :development
|
|
144
|
-
prerelease: false
|
|
145
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
146
|
-
requirements:
|
|
147
|
-
- - ">="
|
|
148
|
-
- !ruby/object:Gem::Version
|
|
149
|
-
version: '0'
|
|
150
108
|
description: A complete, standalone view rendering system that gives you everything
|
|
151
109
|
you need to write well-factored view code
|
|
152
110
|
email:
|
|
153
111
|
- info@hanakai.org
|
|
154
112
|
executables: []
|
|
155
113
|
extensions: []
|
|
156
|
-
extra_rdoc_files:
|
|
114
|
+
extra_rdoc_files:
|
|
115
|
+
- CHANGELOG.md
|
|
116
|
+
- LICENSE
|
|
117
|
+
- README.md
|
|
157
118
|
files:
|
|
158
119
|
- CHANGELOG.md
|
|
120
|
+
- LICENSE
|
|
159
121
|
- README.md
|
|
160
122
|
- hanami-view.gemspec
|
|
161
123
|
- lib/hanami-view.rb
|
|
@@ -194,11 +156,10 @@ homepage: https://hanamirb.org
|
|
|
194
156
|
licenses:
|
|
195
157
|
- MIT
|
|
196
158
|
metadata:
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
bug_tracker_uri: https://github.com/hanami/view/issues
|
|
159
|
+
changelog_uri: https://github.com/hanami/hanami-view/blob/main/CHANGELOG.md
|
|
160
|
+
source_code_uri: https://github.com/hanami/hanami-view
|
|
161
|
+
bug_tracker_uri: https://github.com/hanami/hanami-view/issues
|
|
162
|
+
funding_uri: https://github.com/sponsors/hanami
|
|
202
163
|
rdoc_options: []
|
|
203
164
|
require_paths:
|
|
204
165
|
- lib
|
|
@@ -206,7 +167,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
206
167
|
requirements:
|
|
207
168
|
- - ">="
|
|
208
169
|
- !ruby/object:Gem::Version
|
|
209
|
-
version: '3.
|
|
170
|
+
version: '3.3'
|
|
210
171
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
211
172
|
requirements:
|
|
212
173
|
- - ">="
|