pakyow-presenter 1.0.0.rc2 → 1.0.0.rc3
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/lib/pakyow/{presenter/actions → actions/presenter}/auto_render.rb +2 -2
- data/lib/pakyow/plugin/helpers/rendering.rb +15 -2
- data/lib/pakyow/presenter.rb +1 -1
- data/lib/pakyow/presenter/attributes.rb +8 -0
- data/lib/pakyow/presenter/attributes/attribute.rb +0 -1
- data/lib/pakyow/presenter/attributes/boolean.rb +0 -1
- data/lib/pakyow/presenter/behavior/error_rendering.rb +1 -0
- data/lib/pakyow/presenter/behavior/initializing.rb +1 -1
- data/lib/pakyow/presenter/behavior/modes.rb +1 -0
- data/lib/pakyow/presenter/binder.rb +2 -0
- data/lib/pakyow/presenter/binding_parts.rb +1 -0
- data/lib/pakyow/presenter/component.rb +1 -4
- data/lib/pakyow/presenter/composers/component.rb +1 -0
- data/lib/pakyow/presenter/composers/view.rb +1 -0
- data/lib/pakyow/presenter/errors.rb +2 -2
- data/lib/pakyow/presenter/framework.rb +22 -25
- data/lib/pakyow/presenter/presenter.rb +5 -0
- data/lib/pakyow/presenter/presenters/endpoint.rb +3 -3
- data/lib/pakyow/presenter/presenters/form.rb +5 -5
- data/lib/pakyow/presenter/processor.rb +42 -38
- data/lib/pakyow/presenter/renderer.rb +6 -1
- data/lib/pakyow/presenter/renderer/behavior/cleanup_prototype_nodes.rb +23 -0
- data/lib/pakyow/presenter/renderer/behavior/cleanup_unbound_bindings.rb +37 -0
- data/lib/pakyow/presenter/renderer/behavior/create_template_nodes.rb +29 -0
- data/lib/pakyow/presenter/renderer/behavior/insert_prototype_bar.rb +103 -0
- data/lib/pakyow/presenter/renderer/behavior/install_authenticity.rb +44 -0
- data/lib/pakyow/presenter/renderer/behavior/place_in_mode.rb +58 -0
- data/lib/pakyow/presenter/renderer/behavior/render_components.rb +281 -0
- data/lib/pakyow/presenter/renderer/behavior/set_page_title.rb +37 -0
- data/lib/pakyow/presenter/renderer/behavior/setup_endpoints.rb +64 -0
- data/lib/pakyow/presenter/renderer/behavior/setup_forms.rb +176 -0
- data/lib/pakyow/presenter/significant_nodes.rb +2 -2
- data/lib/pakyow/presenter/templates.rb +24 -15
- data/lib/pakyow/presenter/versioned_view.rb +1 -0
- data/lib/pakyow/presenter/view.rb +11 -9
- data/lib/pakyow/presenter/views/form.rb +39 -35
- data/lib/pakyow/presenter/views/layout.rb +20 -18
- data/lib/pakyow/presenter/views/page.rb +47 -45
- data/lib/pakyow/presenter/views/partial.rb +17 -15
- data/lib/string_doc.rb +3 -1
- data/lib/string_doc/attributes.rb +1 -0
- data/lib/string_doc/meta_attributes.rb +1 -0
- data/lib/string_doc/meta_node.rb +1 -0
- data/lib/string_doc/node.rb +1 -0
- metadata +19 -20
- data/lib/pakyow/presenter/presentable_error.rb +0 -19
- data/lib/pakyow/presenter/rendering/actions/cleanup_prototype_nodes.rb +0 -21
- data/lib/pakyow/presenter/rendering/actions/cleanup_unbound_bindings.rb +0 -35
- data/lib/pakyow/presenter/rendering/actions/create_template_nodes.rb +0 -27
- data/lib/pakyow/presenter/rendering/actions/insert_prototype_bar.rb +0 -101
- data/lib/pakyow/presenter/rendering/actions/install_authenticity.rb +0 -42
- data/lib/pakyow/presenter/rendering/actions/place_in_mode.rb +0 -56
- data/lib/pakyow/presenter/rendering/actions/render_components.rb +0 -279
- data/lib/pakyow/presenter/rendering/actions/set_page_title.rb +0 -35
- data/lib/pakyow/presenter/rendering/actions/setup_endpoints.rb +0 -62
- data/lib/pakyow/presenter/rendering/actions/setup_forms.rb +0 -174
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pakyow/support/extension"
|
4
|
+
|
5
|
+
module Pakyow
|
6
|
+
module Presenter
|
7
|
+
class Renderer
|
8
|
+
module Behavior
|
9
|
+
module SetPageTitle
|
10
|
+
extend Support::Extension
|
11
|
+
|
12
|
+
apply_extension do
|
13
|
+
attach do |presenter|
|
14
|
+
presenter.render node: -> {
|
15
|
+
if title_value = info(:title)
|
16
|
+
title.object.set_label(:title_template, title_value); title
|
17
|
+
end
|
18
|
+
} do
|
19
|
+
self.html = html_safe(
|
20
|
+
Support::StringBuilder.new(object.label(:title_template), html_safe: true) { |object_value|
|
21
|
+
if respond_to?(object_value)
|
22
|
+
send(object_value, :title) || send(object_value)
|
23
|
+
elsif @presentables.key?(object_value)
|
24
|
+
@presentables[object_value]
|
25
|
+
else
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
}.build
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,64 @@
|
|
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
|
+
class Renderer
|
10
|
+
module Behavior
|
11
|
+
module SetupEndpoints
|
12
|
+
extend Support::Extension
|
13
|
+
|
14
|
+
apply_extension do
|
15
|
+
build do |view, app:|
|
16
|
+
view.object.find_significant_nodes(:endpoint, descend: true).each do |node|
|
17
|
+
if endpoint = app.endpoints.find(name: node.label(:endpoint))
|
18
|
+
node.set_label(:endpoint_object, endpoint)
|
19
|
+
node.set_label(:endpoint_params, {})
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
attach do |presenter|
|
25
|
+
if Pakyow.env?(:prototype)
|
26
|
+
presenter.render node: -> {
|
27
|
+
object.find_significant_nodes(:endpoint, descend: true).map { |node|
|
28
|
+
View.from_object(node)
|
29
|
+
}
|
30
|
+
}, priority: :low do
|
31
|
+
setup
|
32
|
+
end
|
33
|
+
else
|
34
|
+
# Setup non-binding endpoints (binding endpoints are setup dynamically in presenter).
|
35
|
+
#
|
36
|
+
presenter.render node: -> {
|
37
|
+
nodes = []
|
38
|
+
nodes << object if object.is_a?(StringDoc::Node) && object.significant?(:endpoint)
|
39
|
+
nodes.concat(object.find_significant_nodes(:endpoint))
|
40
|
+
nodes.select { |node|
|
41
|
+
node.labeled?(:endpoint_object)
|
42
|
+
}.map { |node|
|
43
|
+
View.from_object(node)
|
44
|
+
}
|
45
|
+
}, priority: :low do
|
46
|
+
case self
|
47
|
+
when Presenters::Form
|
48
|
+
Presenters::Endpoint.new(__getobj__).setup
|
49
|
+
when Presenters::Endpoint
|
50
|
+
setup
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
expose do |connection|
|
57
|
+
connection.set(:__endpoint, connection.endpoint)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,176 @@
|
|
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
|
+
class Renderer
|
12
|
+
module Behavior
|
13
|
+
module SetupForms
|
14
|
+
extend Support::Extension
|
15
|
+
|
16
|
+
apply_extension do
|
17
|
+
build do |view, app:|
|
18
|
+
forms = view.forms
|
19
|
+
if !view.object.is_a?(StringDoc) && view.object.significant?(:form)
|
20
|
+
forms << view
|
21
|
+
end
|
22
|
+
|
23
|
+
forms.each do |form|
|
24
|
+
# Allows app renders to set metadata values on forms.
|
25
|
+
#
|
26
|
+
form.object.set_label(:form, {})
|
27
|
+
|
28
|
+
# Set the form id.
|
29
|
+
#
|
30
|
+
form_id = SecureRandom.hex(24)
|
31
|
+
form.object.label(:form)[:id] = form_id
|
32
|
+
form.object.set_label(Presenters::Form::ID_LABEL, form_id)
|
33
|
+
|
34
|
+
# Set the form binding.
|
35
|
+
#
|
36
|
+
form.object.label(:form)[:binding] = form.object.label(:channeled_binding)
|
37
|
+
|
38
|
+
# Setup field names.
|
39
|
+
#
|
40
|
+
form.object.children.each_significant_node(:binding) do |binding_node|
|
41
|
+
if Pakyow::Presenter::Views::Form::FIELD_TAGS.include?(binding_node.tagname)
|
42
|
+
if binding_node.attributes[:name].to_s.empty?
|
43
|
+
binding_node.attributes[:name] = "#{form.object.label(:binding)}[#{binding_node.label(:binding)}]"
|
44
|
+
end
|
45
|
+
|
46
|
+
if binding_node.tagname == "select" && binding_node.attributes[:multiple]
|
47
|
+
Presenters::Form.pluralize_field_name(binding_node)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Connect labels.
|
53
|
+
#
|
54
|
+
form.object.children.each_significant_node(:label) do |label_node|
|
55
|
+
if label_node.attributes[:for] && input = form.find(*label_node.attributes[:for].to_s.split("."))
|
56
|
+
Presenters::Form.connect_input_to_label(input, label_node)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
form.prepend(
|
61
|
+
Support::SafeStringHelpers.html_safe(
|
62
|
+
"<input type=\"hidden\" name=\"pw-http-method\">"
|
63
|
+
)
|
64
|
+
)
|
65
|
+
|
66
|
+
form.prepend(
|
67
|
+
Support::SafeStringHelpers.html_safe(
|
68
|
+
"<input type=\"hidden\" name=\"pw-form\">"
|
69
|
+
)
|
70
|
+
)
|
71
|
+
|
72
|
+
if app.config.presenter.embed_authenticity_token
|
73
|
+
form.prepend(
|
74
|
+
Support::SafeStringHelpers.html_safe(
|
75
|
+
"<input type=\"hidden\" name=\"#{app.config.security.csrf.param}\">"
|
76
|
+
)
|
77
|
+
)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
attach do |presenter, app:|
|
83
|
+
presenter.render node: -> {
|
84
|
+
forms = self.forms
|
85
|
+
if !object.is_a?(StringDoc) && object.significant?(:form)
|
86
|
+
forms << self
|
87
|
+
end
|
88
|
+
|
89
|
+
forms
|
90
|
+
} do
|
91
|
+
unless setup?
|
92
|
+
if object = object_for_form
|
93
|
+
if app.class.includes_framework?(:data) && object.is_a?(Data::Proxy)
|
94
|
+
object = object.one
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
if !object.nil?
|
99
|
+
if labeled?(:endpoint)
|
100
|
+
setup(object)
|
101
|
+
else
|
102
|
+
if object.key?(:id)
|
103
|
+
update(object)
|
104
|
+
else
|
105
|
+
create(object)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
elsif labeled?(:binding)
|
109
|
+
case presentables[:__endpoint_name]
|
110
|
+
when :edit
|
111
|
+
update(
|
112
|
+
__endpoint.params.each_with_object({}) { |(key, _), passed_params|
|
113
|
+
key = key.to_sym
|
114
|
+
passed_params[key] = __params[key]
|
115
|
+
}
|
116
|
+
)
|
117
|
+
else
|
118
|
+
create
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
view.object.label(:form)[:origin] = presentables[:__origin]
|
124
|
+
|
125
|
+
node = view.object.each_significant_node(:field).find { |field_node|
|
126
|
+
field_node.attributes[:name] == "pw-form"
|
127
|
+
}
|
128
|
+
|
129
|
+
unless node.nil?
|
130
|
+
node.attributes[:value] = presentables[:__verifier].sign(
|
131
|
+
label(:form).to_json
|
132
|
+
)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
presenter.render node: -> {
|
137
|
+
stringified_param = app.config.security.csrf.param.to_s
|
138
|
+
node = object.each_significant_node(:field, descend: true).find { |field_node|
|
139
|
+
field_node.attributes[:name] == stringified_param
|
140
|
+
}
|
141
|
+
|
142
|
+
unless node.nil?
|
143
|
+
View.from_object(node)
|
144
|
+
end
|
145
|
+
} do
|
146
|
+
attributes[:value] = presentables[:__verifier].sign(Support::MessageVerifier.key)
|
147
|
+
end
|
148
|
+
|
149
|
+
presenter.render node: -> {
|
150
|
+
object.each_significant_node(:method_override, descend: true).map { |node|
|
151
|
+
View.from_object(node)
|
152
|
+
}
|
153
|
+
} do
|
154
|
+
remove if attributes[:value].empty?
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
expose do |connection|
|
159
|
+
connection.set(:__params, connection.params)
|
160
|
+
connection.set(:__endpoint, connection.endpoint)
|
161
|
+
connection.set(:__verifier, connection.verifier)
|
162
|
+
|
163
|
+
origin = if connection.set?(:__form)
|
164
|
+
connection.get(:__form)[:origin]
|
165
|
+
else
|
166
|
+
connection.fullpath
|
167
|
+
end
|
168
|
+
|
169
|
+
connection.set(:__origin, origin)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -188,7 +188,7 @@ module Pakyow
|
|
188
188
|
|
189
189
|
def self.decorate(node)
|
190
190
|
node.set_label(:presenter_type, Presenters::Form)
|
191
|
-
node.set_label(:view_type, Form)
|
191
|
+
node.set_label(:view_type, Views::Form)
|
192
192
|
end
|
193
193
|
end
|
194
194
|
|
@@ -224,7 +224,7 @@ module Pakyow
|
|
224
224
|
StringDoc.significant :method_override, self
|
225
225
|
|
226
226
|
def self.significant?(node)
|
227
|
-
node.is_a?(Oga::XML::Element) && node.name == INPUT_TAG && node.attribute(:name).to_s == "
|
227
|
+
node.is_a?(Oga::XML::Element) && node.name == INPUT_TAG && node.attribute(:name).to_s == "pw-http-method"
|
228
228
|
end
|
229
229
|
end
|
230
230
|
|
@@ -9,7 +9,7 @@ module Pakyow
|
|
9
9
|
using Support::DeepDup
|
10
10
|
using Support::Refinements::String::Normalization
|
11
11
|
|
12
|
-
attr_reader :name, :path, :layouts, :pages, :includes, :config
|
12
|
+
attr_reader :name, :path, :processor, :layouts, :pages, :includes, :config
|
13
13
|
|
14
14
|
DEFAULT_LAYOUTS_PATH = "layouts"
|
15
15
|
DEFAULT_PARTIALS_PATH = "includes"
|
@@ -109,8 +109,9 @@ module Pakyow
|
|
109
109
|
@layouts = if File.exist?(layouts_path)
|
110
110
|
layouts_path.children.each_with_object({}) { |file, layouts|
|
111
111
|
next unless template?(file)
|
112
|
-
layout = load_view_of_type_at_path(Layout, file)
|
113
|
-
|
112
|
+
if layout = load_view_of_type_at_path(Views::Layout, file)
|
113
|
+
layouts[layout.name] = layout
|
114
|
+
end
|
114
115
|
}
|
115
116
|
else
|
116
117
|
{}
|
@@ -121,8 +122,9 @@ module Pakyow
|
|
121
122
|
@includes = if File.exist?(partials_path)
|
122
123
|
partials_path.children.each_with_object({}) { |file, partials|
|
123
124
|
next unless template?(file)
|
124
|
-
partial = load_view_of_type_at_path(Partial, file, normalize_path(file))
|
125
|
-
|
125
|
+
if partial = load_view_of_type_at_path(Views::Partial, file, normalize_path(file))
|
126
|
+
partials[partial.name] = partial
|
127
|
+
end
|
126
128
|
}
|
127
129
|
else
|
128
130
|
{}
|
@@ -140,7 +142,7 @@ module Pakyow
|
|
140
142
|
|
141
143
|
begin
|
142
144
|
if page = page_at_path(path)
|
143
|
-
@info[File.join(@config[:prefix], normalize_path(path, pages_path))] = {
|
145
|
+
@info[String.normalize_path(File.join(@config[:prefix], normalize_path(path, pages_path)))] = {
|
144
146
|
page: page,
|
145
147
|
layout: layout_with_name(page.info(:layout)),
|
146
148
|
partials: @includes.merge(partials_at_path(path))
|
@@ -168,7 +170,7 @@ module Pakyow
|
|
168
170
|
index_page_at_path(path)
|
169
171
|
end
|
170
172
|
else
|
171
|
-
load_view_of_type_at_path(Page, path, normalize_path(path))
|
173
|
+
load_view_of_type_at_path(Views::Page, path, normalize_path(path))
|
172
174
|
end
|
173
175
|
end
|
174
176
|
|
@@ -208,21 +210,28 @@ module Pakyow
|
|
208
210
|
parent_path.children.select { |child|
|
209
211
|
child.basename.to_s.start_with?("_")
|
210
212
|
}.each_with_object(partials) { |child, child_partials|
|
211
|
-
partial = load_view_of_type_at_path(Partial, child, normalize_path(child))
|
212
|
-
|
213
|
+
if partial = load_view_of_type_at_path(Views::Partial, child, normalize_path(child))
|
214
|
+
child_partials[partial.name] ||= partial
|
215
|
+
end
|
213
216
|
}
|
214
217
|
}
|
215
218
|
end
|
216
219
|
|
217
220
|
def load_view_of_type_at_path(type, path, logical_path = nil)
|
218
|
-
|
219
|
-
info, content = FrontMatterParser.parse_and_scrub(content)
|
221
|
+
extension = File.extname(path)
|
220
222
|
|
221
|
-
if @processor
|
222
|
-
content =
|
223
|
-
|
223
|
+
if extension.end_with?(".html") || @processor&.process?(extension)
|
224
|
+
content = File.read(path)
|
225
|
+
info, content = FrontMatterParser.parse_and_scrub(content)
|
224
226
|
|
225
|
-
|
227
|
+
if @processor
|
228
|
+
content = @processor.process(content, extension.delete(".").to_sym)
|
229
|
+
end
|
230
|
+
|
231
|
+
type.load(path, info: info, content: content, logical_path: logical_path)
|
232
|
+
else
|
233
|
+
nil
|
234
|
+
end
|
226
235
|
end
|
227
236
|
end
|
228
237
|
end
|
@@ -43,6 +43,7 @@ module Pakyow
|
|
43
43
|
instance
|
44
44
|
end
|
45
45
|
|
46
|
+
# @api private
|
46
47
|
def from_view_or_string(view_or_string)
|
47
48
|
case view_or_string
|
48
49
|
when View, VersionedView
|
@@ -62,18 +63,15 @@ module Pakyow
|
|
62
63
|
|
63
64
|
def_delegators :@object, :type, :text, :html, :label, :labeled?
|
64
65
|
|
65
|
-
# The object responsible for
|
66
|
-
# the underlying HTML document for the view.
|
66
|
+
# The object responsible for transforming and rendering the underlying document or node.
|
67
67
|
#
|
68
|
-
|
68
|
+
# @api private
|
69
|
+
attr_accessor :object
|
69
70
|
|
70
71
|
# The logical path to the view template.
|
71
72
|
#
|
72
73
|
attr_reader :logical_path
|
73
74
|
|
74
|
-
# @api private
|
75
|
-
attr_writer :object
|
76
|
-
|
77
75
|
# Creates a view with +html+.
|
78
76
|
#
|
79
77
|
def initialize(html, info: {}, logical_path: nil)
|
@@ -100,6 +98,7 @@ module Pakyow
|
|
100
98
|
end
|
101
99
|
end
|
102
100
|
|
101
|
+
# @api private
|
103
102
|
def soft_copy
|
104
103
|
instance = self.class.allocate
|
105
104
|
|
@@ -148,6 +147,7 @@ module Pakyow
|
|
148
147
|
|
149
148
|
# Finds all view bindings by name, returning an array of {View} objects.
|
150
149
|
#
|
150
|
+
# @api private
|
151
151
|
def find_all(named)
|
152
152
|
each_binding(named).map { |node|
|
153
153
|
View.from_object(node)
|
@@ -158,7 +158,7 @@ module Pakyow
|
|
158
158
|
#
|
159
159
|
def form(name)
|
160
160
|
@object.each_significant_node(:form) do |form_node|
|
161
|
-
return Form.from_object(form_node) if form_node.label(:binding) == name
|
161
|
+
return Views::Form.from_object(form_node) if form_node.label(:binding) == name
|
162
162
|
end
|
163
163
|
|
164
164
|
nil
|
@@ -166,9 +166,10 @@ module Pakyow
|
|
166
166
|
|
167
167
|
# Returns all forms.
|
168
168
|
#
|
169
|
+
# @api private
|
169
170
|
def forms
|
170
171
|
@object.each_significant_node(:form, descend: true).map { |node|
|
171
|
-
Form.from_object(node)
|
172
|
+
Views::Form.from_object(node)
|
172
173
|
}
|
173
174
|
end
|
174
175
|
|
@@ -185,6 +186,7 @@ module Pakyow
|
|
185
186
|
|
186
187
|
# Returns all components.
|
187
188
|
#
|
189
|
+
# @api private
|
188
190
|
def components(renderable: false)
|
189
191
|
@object.each_significant_node_without_descending_into_type(:component, descend: true).select { |node|
|
190
192
|
!renderable || node.label(:components).any? { |component| component[:renderable] }
|
@@ -567,7 +569,7 @@ module Pakyow
|
|
567
569
|
}
|
568
570
|
end
|
569
571
|
|
570
|
-
|
572
|
+
private
|
571
573
|
|
572
574
|
def bind_value_to_node(value, node)
|
573
575
|
tag = node.tagname
|