pakyow-presenter 0.11.3 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +5 -5
  2. data/{pakyow-presenter/CHANGELOG.md → CHANGELOG.md} +0 -5
  3. data/LICENSE +4 -0
  4. data/{pakyow-presenter/README.md → README.md} +1 -2
  5. data/lib/pakyow/generators/presenter/presenter_generator.rb +28 -0
  6. data/lib/pakyow/generators/presenter/templates/presenter.rb.tt +2 -0
  7. data/lib/pakyow/plugin/helpers/rendering.rb +19 -0
  8. data/lib/pakyow/presenter/actions/auto_render.rb +15 -0
  9. data/lib/pakyow/presenter/attributes/attribute.rb +22 -0
  10. data/lib/pakyow/presenter/attributes/boolean.rb +24 -0
  11. data/lib/pakyow/presenter/attributes/hash.rb +89 -0
  12. data/lib/pakyow/presenter/attributes/set.rb +61 -0
  13. data/lib/pakyow/presenter/attributes/string.rb +38 -0
  14. data/lib/pakyow/presenter/attributes.rb +126 -0
  15. data/lib/pakyow/presenter/behavior/config.rb +29 -0
  16. data/lib/pakyow/presenter/behavior/error_rendering.rb +124 -0
  17. data/lib/pakyow/presenter/behavior/exposures.rb +29 -0
  18. data/lib/pakyow/presenter/behavior/implicit_rendering.rb +21 -0
  19. data/lib/pakyow/presenter/behavior/initializing.rb +37 -0
  20. data/lib/pakyow/presenter/behavior/modes.rb +117 -0
  21. data/lib/pakyow/presenter/behavior/versions.rb +71 -0
  22. data/lib/pakyow/presenter/behavior/watching.rb +21 -0
  23. data/lib/pakyow/presenter/binder.rb +115 -0
  24. data/lib/pakyow/presenter/binding_parts.rb +64 -0
  25. data/lib/pakyow/presenter/component.rb +74 -0
  26. data/lib/pakyow/presenter/composers/component.rb +78 -0
  27. data/lib/pakyow/presenter/composers/view.rb +73 -0
  28. data/lib/pakyow/presenter/errors.rb +63 -0
  29. data/lib/pakyow/presenter/framework.rb +203 -0
  30. data/lib/pakyow/presenter/front_matter_parser.rb +42 -0
  31. data/lib/pakyow/presenter/helpers/rendering.rb +18 -0
  32. data/lib/pakyow/presenter/presentable.rb +28 -0
  33. data/lib/pakyow/presenter/presentable_error.rb +19 -0
  34. data/lib/pakyow/presenter/presenter.rb +766 -0
  35. data/lib/pakyow/presenter/presenters/endpoint.rb +158 -0
  36. data/lib/pakyow/presenter/presenters/form.rb +522 -0
  37. data/lib/pakyow/presenter/processor.rb +61 -0
  38. data/lib/pakyow/presenter/renderable.rb +28 -0
  39. data/lib/pakyow/presenter/renderer.rb +269 -0
  40. data/lib/pakyow/presenter/rendering/actions/cleanup_prototype_nodes.rb +21 -0
  41. data/lib/pakyow/presenter/rendering/actions/cleanup_unbound_bindings.rb +35 -0
  42. data/lib/pakyow/presenter/rendering/actions/create_template_nodes.rb +27 -0
  43. data/lib/pakyow/presenter/rendering/actions/insert_prototype_bar.rb +101 -0
  44. data/lib/pakyow/presenter/rendering/actions/install_authenticity.rb +42 -0
  45. data/lib/pakyow/presenter/rendering/actions/place_in_mode.rb +56 -0
  46. data/lib/pakyow/presenter/rendering/actions/render_components.rb +279 -0
  47. data/lib/pakyow/presenter/rendering/actions/set_page_title.rb +35 -0
  48. data/lib/pakyow/presenter/rendering/actions/setup_endpoints.rb +62 -0
  49. data/lib/pakyow/presenter/rendering/actions/setup_forms.rb +174 -0
  50. data/lib/pakyow/presenter/significant_nodes.rb +309 -0
  51. data/lib/pakyow/presenter/templates.rb +229 -0
  52. data/lib/pakyow/presenter/versioned_view.rb +209 -0
  53. data/lib/pakyow/presenter/view.rb +586 -0
  54. data/lib/pakyow/presenter/views/form.rb +58 -0
  55. data/lib/pakyow/presenter/views/layout.rb +32 -0
  56. data/lib/pakyow/presenter/views/page.rb +72 -0
  57. data/lib/pakyow/presenter/views/partial.rb +28 -0
  58. data/lib/pakyow/presenter.rb +33 -0
  59. data/lib/pakyow/views/errors/layouts/development_error.html +102 -0
  60. data/lib/pakyow/views/errors/layouts/production_error.html +27 -0
  61. data/lib/pakyow/views/errors/pages/404.html +12 -0
  62. data/lib/pakyow/views/errors/pages/500.html +12 -0
  63. data/lib/pakyow/views/errors/pages/development/500.html +39 -0
  64. data/lib/string_doc/attributes.rb +109 -0
  65. data/lib/string_doc/meta_attributes.rb +48 -0
  66. data/lib/string_doc/meta_node.rb +328 -0
  67. data/lib/string_doc/node.rb +377 -0
  68. data/lib/string_doc.rb +642 -0
  69. metadata +95 -75
  70. data/pakyow-presenter/LICENSE +0 -20
  71. data/pakyow-presenter/lib/pakyow/presenter/attributes.rb +0 -228
  72. data/pakyow-presenter/lib/pakyow/presenter/base.rb +0 -38
  73. data/pakyow-presenter/lib/pakyow/presenter/binder.rb +0 -116
  74. data/pakyow-presenter/lib/pakyow/presenter/binder_set.rb +0 -94
  75. data/pakyow-presenter/lib/pakyow/presenter/binding_eval.rb +0 -37
  76. data/pakyow-presenter/lib/pakyow/presenter/config/presenter.rb +0 -42
  77. data/pakyow-presenter/lib/pakyow/presenter/container.rb +0 -6
  78. data/pakyow-presenter/lib/pakyow/presenter/doc_helpers.rb +0 -17
  79. data/pakyow-presenter/lib/pakyow/presenter/exceptions.rb +0 -11
  80. data/pakyow-presenter/lib/pakyow/presenter/ext/app.rb +0 -33
  81. data/pakyow-presenter/lib/pakyow/presenter/ext/call_context.rb +0 -28
  82. data/pakyow-presenter/lib/pakyow/presenter/helpers.rb +0 -46
  83. data/pakyow-presenter/lib/pakyow/presenter/page.rb +0 -110
  84. data/pakyow-presenter/lib/pakyow/presenter/partial.rb +0 -6
  85. data/pakyow-presenter/lib/pakyow/presenter/presenter.rb +0 -232
  86. data/pakyow-presenter/lib/pakyow/presenter/string_doc.rb +0 -380
  87. data/pakyow-presenter/lib/pakyow/presenter/string_doc_parser.rb +0 -144
  88. data/pakyow-presenter/lib/pakyow/presenter/string_doc_renderer.rb +0 -18
  89. data/pakyow-presenter/lib/pakyow/presenter/template.rb +0 -51
  90. data/pakyow-presenter/lib/pakyow/presenter/view.rb +0 -541
  91. data/pakyow-presenter/lib/pakyow/presenter/view_collection.rb +0 -330
  92. data/pakyow-presenter/lib/pakyow/presenter/view_composer.rb +0 -237
  93. data/pakyow-presenter/lib/pakyow/presenter/view_context.rb +0 -111
  94. data/pakyow-presenter/lib/pakyow/presenter/view_store.rb +0 -262
  95. data/pakyow-presenter/lib/pakyow/presenter/view_store_loader.rb +0 -43
  96. data/pakyow-presenter/lib/pakyow/presenter/view_version.rb +0 -113
  97. data/pakyow-presenter/lib/pakyow/presenter.rb +0 -8
  98. data/pakyow-presenter/lib/pakyow/views/errors/404.erb +0 -26
  99. data/pakyow-presenter/lib/pakyow/views/errors/500.erb +0 -23
  100. data/pakyow-presenter/lib/pakyow-presenter.rb +0 -1
@@ -0,0 +1,279 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pakyow/support/extension"
4
+
5
+ require "pakyow/presenter/composers/component"
6
+
7
+ module Pakyow
8
+ module Presenter
9
+ module Actions
10
+ module RenderComponents
11
+ extend Support::Extension
12
+
13
+ apply_extension do
14
+ build do |view, app:, composer:, modes:|
15
+ unless Pakyow.env?(:prototype)
16
+ initial_path = case composer
17
+ when Composers::Component
18
+ composer.component_path
19
+ else
20
+ []
21
+ end
22
+
23
+ component_view = case composer
24
+ when Composers::Component
25
+ composer.class.follow_path(composer.component_path, view)
26
+ else
27
+ view
28
+ end
29
+
30
+ RenderComponents.initialize_renderable_components(
31
+ component_view, app: app, composer: composer, modes: modes, path: initial_path
32
+ )
33
+ end
34
+ end
35
+
36
+ expose do |connection|
37
+ # Prevent state from leaking from the component to the rest of the app.
38
+ #
39
+ component_connection = connection.dup
40
+
41
+ # Expose the component connection for performing from each component.
42
+ #
43
+ connection.set(:__component_connection, component_connection)
44
+ end
45
+ end
46
+
47
+ # @api private
48
+ def self.initialize_renderable_components(view, app:, composer:, modes:, path: [])
49
+ view.components.each_with_index do |component_view, i|
50
+ current_path = path.dup
51
+ current_path << i
52
+
53
+ # If view will be rendered from the app, look for the component on the app.
54
+ #
55
+ component_state = if app.is_a?(Plugin) && app.parent.view?(composer.view_path)
56
+ app.parent.state(:component)
57
+ else
58
+ app.state(:component)
59
+ end
60
+
61
+ components = component_view.object.label(:components).each_with_object([]) { |component_label, arr|
62
+ component_class = component_state.find { |component|
63
+ component.__object_name.name == component_label[:name]
64
+ }
65
+
66
+ if component_class
67
+ # Turn the component into a renderable component. Once an instance is attached on the
68
+ # backend, the component will not be traversed by renders from its parent instead being
69
+ # rendered by its own renderer instance.
70
+ #
71
+ # We don't want the same restriction for non-renderable components because a change to
72
+ # the view should not affect how things work on the backend.
73
+ #
74
+ component_label[:renderable] = true
75
+
76
+ arr << {
77
+ class: component_class,
78
+ config: component_label[:config]
79
+ }
80
+ end
81
+ }
82
+
83
+ if components.any?
84
+ # Since one or more attached components is renderable, we no longer want to descend.
85
+ #
86
+ component_view.object.set_label(:descend, false)
87
+
88
+ # Define the render function that calls the component and renders it at render time.
89
+ #
90
+ component_render = app.isolated(:Presenter).send(:render_proc, component_view) { |node, _context, string|
91
+ presentable_component_connection = presentables[:__component_connection]
92
+ component_connection = presentable_component_connection.dup
93
+
94
+ components.each do |component|
95
+ presentables.each do |key, value|
96
+ if key.to_s.start_with?("__")
97
+ component_connection.set(key, value)
98
+ end
99
+ end
100
+
101
+ # If the component was defined in an app but being called inside a plugin, set the app to the app instead of the plugin.
102
+ #
103
+ if component_connection.app.is_a?(Plugin) && component[:class].ancestors.include?(component_connection.app.parent.isolated(:Component))
104
+ component_connection = component_connection.class.from_connection(component_connection, :@app => component_connection.app.parent)
105
+ end
106
+
107
+ component_instance = component[:class].new(
108
+ connection: component_connection,
109
+ config: component[:config]
110
+ )
111
+
112
+ # Call the component.
113
+ #
114
+ component_instance.perform
115
+ end
116
+
117
+ # Build a compound component presenter.
118
+ #
119
+ component_presenter = if components.length > 1
120
+ RenderComponents.find_compound_presenter(
121
+ app, components.map { |c| c[:class] }
122
+ )
123
+ else
124
+ components.first[:class].__presenter_class
125
+ end
126
+
127
+ # Setup the renderer for the component.
128
+ #
129
+ renderer = app.isolated(:Renderer).new(
130
+ app: app,
131
+ presentables: component_connection.values,
132
+ presenter_class: component_presenter,
133
+ composer: Composers::Component.new(
134
+ composer.view_path, current_path, app: app, labels: node.labels
135
+ ),
136
+ modes: modes
137
+ )
138
+
139
+ # Render to the main buffer.
140
+ #
141
+ renderer.perform(string)
142
+
143
+ # Return nil so nothing else gets written.
144
+ #
145
+ nil
146
+ }
147
+
148
+ # Attach the above render function to the render node.
149
+ #
150
+ component_view.object.transform do |node, context, string|
151
+ component_render.call(node, context, string); nil
152
+ end
153
+ else
154
+ initialize_renderable_components(
155
+ component_view, app: app, composer: composer, modes: modes, path: current_path
156
+ )
157
+ end
158
+ end
159
+ end
160
+
161
+ # @api private
162
+ def self.find_renderable_components(view, components = [])
163
+ view.components.each do |component_view|
164
+ find_renderable_components(component_view, components)
165
+
166
+ if component_view.object.label(:components).any? { |c| c[:renderable] }
167
+ components << component_view
168
+ end
169
+ end
170
+
171
+ components
172
+ end
173
+
174
+ # @api private
175
+ def self.wrap_block(block, context_class)
176
+ Proc.new do
177
+ @app.presenter_for_context(
178
+ context_class.__presenter_class, self
179
+ ).instance_eval(&block)
180
+ end
181
+ end
182
+
183
+ # @api private
184
+ def self.find_compound_presenter(app, component_classes)
185
+ compound_name = component_classes.map { |component_class|
186
+ component_class.__object_name.name.to_s
187
+ }.join("_")
188
+
189
+ object_name = Support::ObjectName.namespace(
190
+ app.class.__object_name.namespace.parts[0], :components, compound_name, :presenter
191
+ )
192
+
193
+ if const_defined?(object_name.constant)
194
+ const_get(object_name.constant)
195
+ else
196
+ nil
197
+ end
198
+ end
199
+
200
+ # @api private
201
+ #
202
+ def self.find_or_build_compound_presenter(app, component_classes)
203
+ compound_name = component_classes.map { |component_class|
204
+ component_class.__object_name.name.to_s
205
+ }.join("_")
206
+
207
+ object_name = Support::ObjectName.namespace(
208
+ app.class.__object_name.namespace.parts[0], :components, compound_name, :presenter
209
+ )
210
+
211
+ if const_defined?(object_name.constant)
212
+ const_get(object_name.constant)
213
+ else
214
+ component_presenter = Class.new(app.isolated(:Presenter))
215
+ Support::ObjectMaker.define_const_for_object_with_name(component_presenter, object_name)
216
+
217
+ component_classes.each do |component_class|
218
+ # Copy unique attached renders.
219
+ #
220
+ component_class.__presenter_class.__attached_renders.each_with_index do |attached_render, i|
221
+ component_presenter.__attached_renders.insert(i, {
222
+ binding_path: attached_render[:binding_path],
223
+ channel: attached_render[:channel],
224
+ node: attached_render[:node],
225
+ priority: attached_render[:priority],
226
+ block: wrap_block(attached_render[:block], component_class),
227
+ })
228
+ end
229
+
230
+ # Copy unique global options.
231
+ #
232
+ component_class.__presenter_class.__global_options.each do |form_binding, field_binding_values|
233
+ field_binding_values.each do |field_binding, field_binding_value|
234
+ component_presenter.options_for(
235
+ form_binding,
236
+ field_binding,
237
+ field_binding_value[:options],
238
+ &wrap_block(field_binding_value[:block], component_class)
239
+ )
240
+ end
241
+ end
242
+
243
+ # Copy unique presentation logic.
244
+ #
245
+ component_class.__presenter_class.__presentation_logic.each do |binding_name, logic_arr|
246
+ unless component_presenter.__presentation_logic.include?(binding_name)
247
+ component_presenter.__presentation_logic[binding_name] = []
248
+ end
249
+
250
+ logic_arr.each_with_index do |logic, i|
251
+ component_presenter.__presentation_logic[binding_name].insert(i, {
252
+ block: wrap_block(logic[:block], component_class),
253
+ channel: logic[:channel]
254
+ })
255
+ end
256
+ end
257
+
258
+ # Copy unique versioning logic.
259
+ #
260
+ component_class.__presenter_class.__versioning_logic.each do |binding_name, logic_arr|
261
+ unless component_presenter.__versioning_logic.include?(binding_name)
262
+ component_presenter.__versioning_logic[binding_name] = []
263
+ end
264
+
265
+ logic_arr.each_with_index do |logic, i|
266
+ component_presenter.__versioning_logic[binding_name].insert(i, {
267
+ block: wrap_block(logic[:block], component_class)
268
+ })
269
+ end
270
+ end
271
+ end
272
+
273
+ component_presenter
274
+ end
275
+ end
276
+ end
277
+ end
278
+ end
279
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pakyow/support/extension"
4
+
5
+ module Pakyow
6
+ module Presenter
7
+ module Actions
8
+ module SetPageTitle
9
+ extend Support::Extension
10
+
11
+ apply_extension do
12
+ attach do |presenter|
13
+ presenter.render node: -> {
14
+ if title_value = info(:title)
15
+ title.object.set_label(:title_template, title_value); title
16
+ end
17
+ } do
18
+ self.html = html_safe(
19
+ Support::StringBuilder.new(object.label(:title_template), html_safe: true) { |object_value|
20
+ if respond_to?(object_value)
21
+ send(object_value, :title) || send(object_value)
22
+ elsif @presentables.key?(object_value)
23
+ @presentables[object_value]
24
+ else
25
+ nil
26
+ end
27
+ }.build
28
+ )
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pakyow/support/extension"
4
+
5
+ require "pakyow/presenter/presenters/endpoint"
6
+
7
+ module Pakyow
8
+ module Presenter
9
+ module Actions
10
+ module SetupEndpoints
11
+ extend Support::Extension
12
+
13
+ apply_extension do
14
+ build do |view, app:|
15
+ view.object.find_significant_nodes(:endpoint, descend: true).each do |node|
16
+ if endpoint = app.endpoints.find(name: node.label(:endpoint))
17
+ node.set_label(:endpoint_object, endpoint)
18
+ node.set_label(:endpoint_params, {})
19
+ end
20
+ end
21
+ end
22
+
23
+ attach do |presenter|
24
+ if Pakyow.env?(:prototype)
25
+ presenter.render node: -> {
26
+ object.find_significant_nodes(:endpoint, descend: true).map { |node|
27
+ View.from_object(node)
28
+ }
29
+ }, priority: :low do
30
+ setup
31
+ end
32
+ else
33
+ # Setup non-binding endpoints (binding endpoints are setup dynamically in presenter).
34
+ #
35
+ presenter.render node: -> {
36
+ nodes = []
37
+ nodes << object if object.is_a?(StringDoc::Node) && object.significant?(:endpoint)
38
+ nodes.concat(object.find_significant_nodes(:endpoint))
39
+ nodes.select { |node|
40
+ node.labeled?(:endpoint_object)
41
+ }.map { |node|
42
+ View.from_object(node)
43
+ }
44
+ }, priority: :low do
45
+ case self
46
+ when Presenters::Form
47
+ Presenters::Endpoint.new(__getobj__).setup
48
+ when Presenters::Endpoint
49
+ setup
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ expose do |connection|
56
+ connection.set(:__endpoint, connection.endpoint)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,174 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pakyow/support/extension"
4
+ require "pakyow/support/message_verifier"
5
+ require "pakyow/support/safe_string"
6
+
7
+ require "pakyow/presenter/presenters/form"
8
+
9
+ module Pakyow
10
+ module Presenter
11
+ module Actions
12
+ module SetupForms
13
+ extend Support::Extension
14
+
15
+ apply_extension do
16
+ build do |view, app:|
17
+ forms = view.forms
18
+ if !view.object.is_a?(StringDoc) && view.object.significant?(:form)
19
+ forms << view
20
+ end
21
+
22
+ forms.each do |form|
23
+ # Allows app renders to set metadata values on forms.
24
+ #
25
+ form.object.set_label(:form, {})
26
+
27
+ # Set the form id.
28
+ #
29
+ form_id = SecureRandom.hex(24)
30
+ form.object.label(:form)[:id] = form_id
31
+ form.object.set_label(Presenters::Form::ID_LABEL, form_id)
32
+
33
+ # Set the form binding.
34
+ #
35
+ form.object.label(:form)[:binding] = form.object.label(:channeled_binding)
36
+
37
+ # Setup field names.
38
+ #
39
+ form.object.children.each_significant_node(:binding) do |binding_node|
40
+ if Pakyow::Presenter::Form::FIELD_TAGS.include?(binding_node.tagname)
41
+ if binding_node.attributes[:name].to_s.empty?
42
+ binding_node.attributes[:name] = "#{form.object.label(:binding)}[#{binding_node.label(:binding)}]"
43
+ end
44
+
45
+ if binding_node.tagname == "select" && binding_node.attributes[:multiple]
46
+ Presenters::Form.pluralize_field_name(binding_node)
47
+ end
48
+ end
49
+ end
50
+
51
+ # Connect labels.
52
+ #
53
+ form.object.children.each_significant_node(:label) do |label_node|
54
+ if label_node.attributes[:for] && input = form.find(*label_node.attributes[:for].to_s.split("."))
55
+ Presenters::Form.connect_input_to_label(input, label_node)
56
+ end
57
+ end
58
+
59
+ form.prepend(
60
+ Support::SafeStringHelpers.html_safe(
61
+ "<input type=\"hidden\" name=\"_method\">"
62
+ )
63
+ )
64
+
65
+ form.prepend(
66
+ Support::SafeStringHelpers.html_safe(
67
+ "<input type=\"hidden\" name=\"_form\">"
68
+ )
69
+ )
70
+
71
+ if app.config.presenter.embed_authenticity_token
72
+ form.prepend(
73
+ Support::SafeStringHelpers.html_safe(
74
+ "<input type=\"hidden\" name=\"#{app.config.security.csrf.param}\">"
75
+ )
76
+ )
77
+ end
78
+ end
79
+ end
80
+
81
+ attach do |presenter, app:|
82
+ presenter.render node: -> {
83
+ forms = self.forms
84
+ if !object.is_a?(StringDoc) && object.significant?(:form)
85
+ forms << self
86
+ end
87
+
88
+ forms
89
+ } do
90
+ unless setup?
91
+ if object = object_for_form
92
+ if app.class.includes_framework?(:data) && object.is_a?(Data::Proxy)
93
+ object = object.one
94
+ end
95
+ end
96
+
97
+ if !object.nil?
98
+ if labeled?(:endpoint)
99
+ setup(object)
100
+ else
101
+ if object.key?(:id)
102
+ update(object)
103
+ else
104
+ create(object)
105
+ end
106
+ end
107
+ elsif labeled?(:binding)
108
+ case presentables[:__endpoint_name]
109
+ when :edit
110
+ update(
111
+ __endpoint.params.each_with_object({}) { |(key, _), passed_params|
112
+ key = key.to_sym
113
+ passed_params[key] = __params[key]
114
+ }
115
+ )
116
+ else
117
+ create
118
+ end
119
+ end
120
+ end
121
+
122
+ view.object.label(:form)[:origin] = presentables[:__origin]
123
+
124
+ node = view.object.each_significant_node(:field).find { |field_node|
125
+ field_node.attributes[:name] == "_form"
126
+ }
127
+
128
+ unless node.nil?
129
+ node.attributes[:value] = presentables[:__verifier].sign(
130
+ label(:form).to_json
131
+ )
132
+ end
133
+ end
134
+
135
+ presenter.render node: -> {
136
+ stringified_param = app.config.security.csrf.param.to_s
137
+ node = object.each_significant_node(:field, descend: true).find { |field_node|
138
+ field_node.attributes[:name] == stringified_param
139
+ }
140
+
141
+ unless node.nil?
142
+ View.from_object(node)
143
+ end
144
+ } do
145
+ attributes[:value] = presentables[:__verifier].sign(Support::MessageVerifier.key)
146
+ end
147
+
148
+ presenter.render node: -> {
149
+ object.each_significant_node(:method_override, descend: true).map { |node|
150
+ View.from_object(node)
151
+ }
152
+ } do
153
+ remove if attributes[:value].empty?
154
+ end
155
+ end
156
+
157
+ expose do |connection|
158
+ connection.set(:__params, connection.params)
159
+ connection.set(:__endpoint, connection.endpoint)
160
+ connection.set(:__verifier, connection.verifier)
161
+
162
+ origin = if connection.set?(:__form)
163
+ connection.get(:__form)[:origin]
164
+ else
165
+ connection.fullpath
166
+ end
167
+
168
+ connection.set(:__origin, origin)
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end