pakyow-presenter 1.0.0.rc3 → 1.0.0.rc4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/pakyow/presenter/component.rb +1 -0
- data/lib/pakyow/presenter/presenter.rb +30 -33
- data/lib/pakyow/presenter/presenters/endpoint.rb +36 -26
- data/lib/pakyow/presenter/presenters/form.rb +9 -8
- data/lib/pakyow/presenter/processor.rb +1 -1
- data/lib/pakyow/presenter/renderer/behavior/render_components.rb +8 -0
- data/lib/pakyow/presenter/renderer/behavior/setup_forms.rb +130 -118
- data/lib/pakyow/presenter/renderer.rb +1 -0
- data/lib/pakyow/presenter/significant_nodes.rb +1 -1
- data/lib/pakyow/presenter/versioned_view.rb +25 -125
- data/lib/pakyow/presenter/view.rb +11 -7
- data/lib/string_doc/meta_attributes.rb +2 -4
- data/lib/string_doc/meta_node.rb +81 -27
- data/lib/string_doc/node.rb +49 -11
- data/lib/string_doc.rb +35 -4
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 13fe32a06ee25c5db22efd7315240022a60ebe898879cf71577589073e7eebf9
|
4
|
+
data.tar.gz: ea6a93ad0aacccaa646332b2166b82d8eee0f8e705bc5dde0889c1624bb8f60f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 61102a1e5be58a90408451203129e44e87a43150d6fbc22e8bee588e1a4956f80497376e02ef2e202c108a225388986ba495330ac4f14be29310d31dcc648600
|
7
|
+
data.tar.gz: 064fe7f7bc471d8bb8e4ca7e83c00660b20d9995cf4f974a6f08715510bd058817ed2703d72b6d4c7beb8d172d92249c7f053b71127f01bdbf7f8d5306afec5b
|
@@ -254,23 +254,12 @@ module Pakyow
|
|
254
254
|
presenter.use_implicit_version
|
255
255
|
end
|
256
256
|
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
presenter.view.object.nodes.find { |node|
|
261
|
-
node.labeled?(:versioned)
|
262
|
-
}
|
263
|
-
)
|
264
|
-
else
|
265
|
-
presenter.view.versions.find { |version|
|
266
|
-
version.object.labeled?(:versioned)
|
267
|
-
}
|
268
|
-
end
|
269
|
-
|
270
|
-
used_view.binding_props.map { |binding_prop|
|
257
|
+
# Implicitly use binding props.
|
258
|
+
#
|
259
|
+
presenter.view.binding_props.map { |binding_prop|
|
271
260
|
binding_prop.label(:binding)
|
272
261
|
}.uniq.each do |binding_prop_name|
|
273
|
-
if found =
|
262
|
+
if found = presenter.view.find(binding_prop_name)
|
274
263
|
presenter_for(found).use_implicit_version unless found.used?
|
275
264
|
end
|
276
265
|
end
|
@@ -283,14 +272,14 @@ module Pakyow
|
|
283
272
|
}.each do |binding_node|
|
284
273
|
plural_binding_node_name = Support.inflector.pluralize(binding_node.label(:binding)).to_sym
|
285
274
|
|
286
|
-
nested_view = presenter.find(binding_node.label(:binding))
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
275
|
+
if nested_view = presenter.find(binding_node.label(:binding))
|
276
|
+
if binder.object.include?(binding_node.label(:binding))
|
277
|
+
nested_view.present(binder.object[binding_node.label(:binding)])
|
278
|
+
elsif binder.object.include?(plural_binding_node_name)
|
279
|
+
nested_view.present(binder.object[plural_binding_node_name])
|
280
|
+
else
|
281
|
+
nested_view.remove
|
282
|
+
end
|
294
283
|
end
|
295
284
|
end
|
296
285
|
end
|
@@ -389,7 +378,10 @@ module Pakyow
|
|
389
378
|
def to_html(output = String.new)
|
390
379
|
@view.object.to_html(output, context: self)
|
391
380
|
end
|
392
|
-
|
381
|
+
|
382
|
+
def to_s
|
383
|
+
@view.to_s
|
384
|
+
end
|
393
385
|
|
394
386
|
def presenter_for(view, type: nil)
|
395
387
|
if view.nil?
|
@@ -408,13 +400,23 @@ module Pakyow
|
|
408
400
|
|
409
401
|
# @api private
|
410
402
|
def endpoint(name)
|
403
|
+
found = []
|
404
|
+
|
411
405
|
object.each_significant_node(:endpoint) do |endpoint_node|
|
412
406
|
if endpoint_node.label(:endpoint) == name.to_sym
|
413
|
-
|
407
|
+
found << endpoint_node
|
414
408
|
end
|
415
409
|
end
|
416
410
|
|
417
|
-
|
411
|
+
if found.any?
|
412
|
+
if found[0].is_a?(StringDoc::MetaNode)
|
413
|
+
presenter_for(View.from_object(found[0]))
|
414
|
+
else
|
415
|
+
presenter_for(View.from_object(StringDoc::MetaNode.new(found)))
|
416
|
+
end
|
417
|
+
else
|
418
|
+
nil
|
419
|
+
end
|
418
420
|
end
|
419
421
|
|
420
422
|
# @api private
|
@@ -684,12 +686,7 @@ module Pakyow
|
|
684
686
|
end
|
685
687
|
|
686
688
|
views_with_renders.values.each do |view_with_renders, renders_for_view|
|
687
|
-
attach_to_node =
|
688
|
-
when VersionedView
|
689
|
-
StringDoc::MetaNode.new(view_with_renders.versions.map(&:object))
|
690
|
-
when View
|
691
|
-
view_with_renders.object
|
692
|
-
end
|
689
|
+
attach_to_node = view_with_renders.object
|
693
690
|
|
694
691
|
if attach_to_node.is_a?(StringDoc)
|
695
692
|
attach_to_node = attach_to_node.find_first_significant_node(:html)
|
@@ -725,7 +722,7 @@ module Pakyow
|
|
725
722
|
if node.nodes.any?
|
726
723
|
returning = node
|
727
724
|
presenter = context.presenter_for(
|
728
|
-
VersionedView.new(
|
725
|
+
VersionedView.new(View.from_object(node))
|
729
726
|
)
|
730
727
|
else
|
731
728
|
next node
|
@@ -8,15 +8,10 @@ module Pakyow
|
|
8
8
|
module Presenters
|
9
9
|
class Endpoint < DelegateClass(Presenter)
|
10
10
|
def setup
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
)
|
15
|
-
else
|
16
|
-
setup_endpoint(
|
17
|
-
path: endpoint_path,
|
18
|
-
method: endpoint_method
|
19
|
-
)
|
11
|
+
setup_endpoint(path: endpoint_path, method: endpoint_method)
|
12
|
+
|
13
|
+
unless endpoint_method == :get
|
14
|
+
setup_non_get_endpoint(path: endpoint_path, method: endpoint_method)
|
20
15
|
end
|
21
16
|
end
|
22
17
|
|
@@ -88,23 +83,38 @@ module Pakyow
|
|
88
83
|
end
|
89
84
|
end
|
90
85
|
|
91
|
-
def
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
86
|
+
def setup_non_get_endpoint(path:, method:)
|
87
|
+
unless object.tagname == "form"
|
88
|
+
object.attributes.delete(:"data-e")
|
89
|
+
|
90
|
+
if object.tagname == "a"
|
91
|
+
object.attributes[:href] = "javascript:void(0)"
|
92
|
+
end
|
93
|
+
|
94
|
+
# FIXME: Everything below could probably be streamlined and improved. Some ideas:
|
95
|
+
#
|
96
|
+
# * Build the form once, then attach a render that fills in the dynamic parts.
|
97
|
+
# * Define the presenter class once, attached to the view in step one.
|
98
|
+
# * Continue replacing with a string but all we'd be doing is building the string.
|
99
|
+
#
|
100
|
+
form_node = StringDoc.new(
|
101
|
+
<<~HTML
|
102
|
+
<form action="#{path}" method="post">
|
103
|
+
<input type="hidden" name="pw-http-method" value="#{method}">
|
104
|
+
#{object.render}
|
105
|
+
</form>
|
106
|
+
HTML
|
107
|
+
).nodes[0]
|
108
|
+
|
109
|
+
form_view = View.from_object(form_node)
|
110
|
+
Renderer::Behavior::SetupForms.build(form_view, __getobj__.app)
|
111
|
+
|
112
|
+
presenter_class = Class.new(Presenter)
|
113
|
+
Renderer::Behavior::SetupForms.attach(presenter_class, __getobj__.app)
|
114
|
+
|
115
|
+
presenter_class.attach(form_view)
|
116
|
+
form_presenter = presenter_class.new(form_view, app: __getobj__.app, presentables: __getobj__.presentables)
|
117
|
+
replace(html_safe(form_presenter.to_html))
|
108
118
|
end
|
109
119
|
end
|
110
120
|
|
@@ -86,7 +86,7 @@ module Pakyow
|
|
86
86
|
# Populates a select field with options.
|
87
87
|
#
|
88
88
|
def options_for(field, options = nil)
|
89
|
-
unless field_presenter = find(
|
89
|
+
unless field_presenter = find(Support.inflector.singularize(field)) || find(Support.inflector.pluralize(field))
|
90
90
|
raise ArgumentError.new("could not find field named `#{field}'")
|
91
91
|
end
|
92
92
|
|
@@ -211,7 +211,8 @@ module Pakyow
|
|
211
211
|
|
212
212
|
def use_binding_nodes
|
213
213
|
view.object.set_label(:bound, true)
|
214
|
-
|
214
|
+
|
215
|
+
view.object.each_significant_node(:binding, descend: true) do |object|
|
215
216
|
if Pakyow::Presenter::Views::Form::FIELD_TAGS.include?(object.tagname)
|
216
217
|
object.set_label(:bound, true)
|
217
218
|
end
|
@@ -337,8 +338,8 @@ module Pakyow
|
|
337
338
|
values = Array.ensure(values).compact
|
338
339
|
|
339
340
|
if values.any?
|
340
|
-
field_view =
|
341
|
-
field_template = field_view.
|
341
|
+
field_view = field_presenter.view
|
342
|
+
field_template = field_view.soft_copy
|
342
343
|
insertable_field = field_view
|
343
344
|
current_field = field_view
|
344
345
|
|
@@ -350,7 +351,7 @@ module Pakyow
|
|
350
351
|
insertable_field = current_field
|
351
352
|
end
|
352
353
|
|
353
|
-
current_field = field_template.
|
354
|
+
current_field = field_template.soft_copy
|
354
355
|
end
|
355
356
|
else
|
356
357
|
field_presenter.remove
|
@@ -361,8 +362,8 @@ module Pakyow
|
|
361
362
|
values = Array.ensure(original_values).compact
|
362
363
|
|
363
364
|
if values.any?
|
364
|
-
field_view =
|
365
|
-
template = field_view.
|
365
|
+
field_view = field_presenter.view
|
366
|
+
template = field_view.soft_copy
|
366
367
|
insertable = field_view
|
367
368
|
current = field_view
|
368
369
|
|
@@ -432,7 +433,7 @@ module Pakyow
|
|
432
433
|
end
|
433
434
|
|
434
435
|
current.object.set_label(:bound, true)
|
435
|
-
current = template.
|
436
|
+
current = template.soft_copy
|
436
437
|
end
|
437
438
|
else
|
438
439
|
field_presenter.remove
|
@@ -105,6 +105,14 @@ module Pakyow
|
|
105
105
|
component_connection = component_connection.class.from_connection(component_connection, :@app => component_connection.app.parent)
|
106
106
|
end
|
107
107
|
|
108
|
+
unless component[:class].inherit_values == true
|
109
|
+
component_connection.values.each_key do |key|
|
110
|
+
unless key.to_s.start_with?("__") || (component[:class].inherit_values && component[:class].inherit_values.include?(key))
|
111
|
+
component_connection.values.delete(key)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
108
116
|
component_instance = component[:class].new(
|
109
117
|
connection: component_connection,
|
110
118
|
config: component[:config]
|
@@ -15,158 +15,170 @@ module Pakyow
|
|
15
15
|
|
16
16
|
apply_extension do
|
17
17
|
build do |view, app:|
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
SetupForms.build(view, app)
|
19
|
+
end
|
20
|
+
|
21
|
+
attach do |presenter, app:|
|
22
|
+
SetupForms.attach(presenter, app)
|
23
|
+
end
|
24
|
+
|
25
|
+
expose do |connection|
|
26
|
+
connection.set(:__params, connection.params)
|
27
|
+
connection.set(:__endpoint, connection.endpoint)
|
28
|
+
connection.set(:__verifier, connection.verifier)
|
29
|
+
|
30
|
+
origin = if connection.set?(:__form)
|
31
|
+
connection.get(:__form)[:origin]
|
32
|
+
else
|
33
|
+
connection.fullpath
|
21
34
|
end
|
22
35
|
|
23
|
-
|
24
|
-
|
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
|
36
|
+
connection.set(:__origin, origin)
|
37
|
+
end
|
38
|
+
end
|
45
39
|
|
46
|
-
|
47
|
-
|
48
|
-
|
40
|
+
# @api private
|
41
|
+
def self.build(view, app)
|
42
|
+
forms = view.forms
|
43
|
+
if !view.object.is_a?(StringDoc) && view.object.significant?(:form)
|
44
|
+
forms << view
|
45
|
+
end
|
46
|
+
|
47
|
+
forms.each do |form|
|
48
|
+
# Allows app renders to set metadata values on forms.
|
49
|
+
#
|
50
|
+
form.object.set_label(:form, {})
|
51
|
+
|
52
|
+
# Set the form id.
|
53
|
+
#
|
54
|
+
form_id = SecureRandom.hex(24)
|
55
|
+
form.object.label(:form)[:id] = form_id
|
56
|
+
form.object.set_label(Presenters::Form::ID_LABEL, form_id)
|
57
|
+
|
58
|
+
# Set the form binding.
|
59
|
+
#
|
60
|
+
form.object.label(:form)[:binding] = form.object.label(:channeled_binding)
|
61
|
+
|
62
|
+
# Setup field names.
|
63
|
+
#
|
64
|
+
form.object.children.each_significant_node(:binding) do |binding_node|
|
65
|
+
if Pakyow::Presenter::Views::Form::FIELD_TAGS.include?(binding_node.tagname)
|
66
|
+
if binding_node.attributes[:name].to_s.empty?
|
67
|
+
binding_node.attributes[:name] = "#{form.object.label(:binding)}[#{binding_node.label(:binding)}]"
|
49
68
|
end
|
50
|
-
end
|
51
69
|
|
52
|
-
|
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)
|
70
|
+
if binding_node.tagname == "select" && binding_node.attributes[:multiple]
|
71
|
+
Presenters::Form.pluralize_field_name(binding_node)
|
57
72
|
end
|
58
73
|
end
|
74
|
+
end
|
59
75
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
76
|
+
# Connect labels.
|
77
|
+
#
|
78
|
+
form.object.children.each_significant_node(:label) do |label_node|
|
79
|
+
if label_node.attributes[:for] && input = form.find(*label_node.attributes[:for].to_s.split("."))
|
80
|
+
Presenters::Form.connect_input_to_label(input, label_node)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
form.prepend(
|
85
|
+
Support::SafeStringHelpers.html_safe(
|
86
|
+
"<input type=\"hidden\" name=\"pw-http-method\">"
|
87
|
+
)
|
88
|
+
)
|
89
|
+
|
90
|
+
form.prepend(
|
91
|
+
Support::SafeStringHelpers.html_safe(
|
92
|
+
"<input type=\"hidden\" name=\"pw-form\">"
|
64
93
|
)
|
94
|
+
)
|
65
95
|
|
96
|
+
if app.config.presenter.embed_authenticity_token
|
66
97
|
form.prepend(
|
67
98
|
Support::SafeStringHelpers.html_safe(
|
68
|
-
"<input type=\"hidden\" name=\"
|
99
|
+
"<input type=\"hidden\" name=\"#{app.config.security.csrf.param}\">"
|
69
100
|
)
|
70
101
|
)
|
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
102
|
end
|
80
103
|
end
|
104
|
+
end
|
81
105
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
106
|
+
# @api private
|
107
|
+
def self.attach(presenter, app)
|
108
|
+
presenter.render node: -> {
|
109
|
+
forms = self.forms
|
110
|
+
if !object.is_a?(StringDoc) && object.significant?(:form)
|
111
|
+
forms << self
|
112
|
+
end
|
88
113
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
end
|
114
|
+
forms
|
115
|
+
} do
|
116
|
+
unless setup?
|
117
|
+
if object = object_for_form
|
118
|
+
if app.class.includes_framework?(:data) && object.is_a?(Data::Proxy)
|
119
|
+
object = object.one
|
96
120
|
end
|
121
|
+
end
|
97
122
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
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
|
-
)
|
123
|
+
if !object.nil?
|
124
|
+
if labeled?(:endpoint)
|
125
|
+
setup(object)
|
126
|
+
else
|
127
|
+
if object.key?(:id)
|
128
|
+
update(object)
|
117
129
|
else
|
118
|
-
create
|
130
|
+
create(object)
|
119
131
|
end
|
120
132
|
end
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
+
elsif labeled?(:binding)
|
134
|
+
case presentables[:__endpoint_name]
|
135
|
+
when :edit
|
136
|
+
update(
|
137
|
+
__endpoint.params.each_with_object({}) { |(key, _), passed_params|
|
138
|
+
key = key.to_sym
|
139
|
+
passed_params[key] = __params[key]
|
140
|
+
}
|
141
|
+
)
|
142
|
+
else
|
143
|
+
create
|
144
|
+
end
|
145
|
+
else
|
146
|
+
# setup
|
133
147
|
end
|
134
148
|
end
|
135
149
|
|
136
|
-
|
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
|
-
}
|
150
|
+
view.object.label(:form)[:origin] = presentables[:__origin]
|
141
151
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
} do
|
146
|
-
attributes[:value] = presentables[:__verifier].sign(Support::MessageVerifier.key)
|
147
|
-
end
|
152
|
+
node = view.object.each_significant_node(:field).find { |field_node|
|
153
|
+
field_node.attributes[:name] == "pw-form"
|
154
|
+
}
|
148
155
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
} do
|
154
|
-
remove if attributes[:value].empty?
|
156
|
+
unless node.nil?
|
157
|
+
node.attributes[:value] = presentables[:__verifier].sign(
|
158
|
+
label(:form).to_json
|
159
|
+
)
|
155
160
|
end
|
156
161
|
end
|
157
162
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
163
|
+
presenter.render node: -> {
|
164
|
+
stringified_param = app.config.security.csrf.param.to_s
|
165
|
+
node = object.each_significant_node(:field, descend: true).find { |field_node|
|
166
|
+
field_node.attributes[:name] == stringified_param
|
167
|
+
}
|
162
168
|
|
163
|
-
|
164
|
-
|
165
|
-
else
|
166
|
-
connection.fullpath
|
169
|
+
unless node.nil?
|
170
|
+
View.from_object(node)
|
167
171
|
end
|
172
|
+
} do
|
173
|
+
attributes[:value] = presentables[:__verifier].sign(Support::MessageVerifier.key)
|
174
|
+
end
|
168
175
|
|
169
|
-
|
176
|
+
presenter.render node: -> {
|
177
|
+
object.each_significant_node(:method_override, descend: true).map { |node|
|
178
|
+
View.from_object(node)
|
179
|
+
}
|
180
|
+
} do
|
181
|
+
remove if attributes[:value].empty?
|
170
182
|
end
|
171
183
|
end
|
172
184
|
end
|
@@ -183,7 +183,7 @@ module Pakyow
|
|
183
183
|
StringDoc.significant :form, self, descend: false
|
184
184
|
|
185
185
|
def self.significant?(node)
|
186
|
-
node.is_a?(Oga::XML::Element) && node.
|
186
|
+
node.is_a?(Oga::XML::Element) && node.name == FORM_TAG
|
187
187
|
end
|
188
188
|
|
189
189
|
def self.decorate(node)
|
@@ -12,33 +12,24 @@ module Pakyow
|
|
12
12
|
|
13
13
|
attr_reader :names
|
14
14
|
|
15
|
-
def initialize(
|
16
|
-
|
17
|
-
@names =
|
18
|
-
determine_working_version
|
15
|
+
def initialize(view)
|
16
|
+
__setobj__(view)
|
17
|
+
@names = view.object.nodes.map { |node| node.label(:version) }
|
19
18
|
@used = false
|
20
19
|
end
|
21
20
|
|
22
21
|
def initialize_dup(_)
|
23
22
|
super
|
24
23
|
|
25
|
-
@versions = @versions.map(&:dup)
|
26
24
|
@names = @names.map(&:dup)
|
27
|
-
determine_working_version
|
28
25
|
end
|
29
26
|
|
30
27
|
# @api private
|
31
28
|
def soft_copy
|
32
29
|
instance = self.class.allocate
|
33
|
-
|
34
|
-
instance.instance_variable_set(:@versions, @versions.map { |version|
|
35
|
-
version.soft_copy
|
36
|
-
})
|
37
|
-
|
30
|
+
instance.__setobj__(__getobj__.soft_copy)
|
38
31
|
instance.instance_variable_set(:@names, @names)
|
39
32
|
instance.instance_variable_set(:@used, @used)
|
40
|
-
instance.send(:determine_working_version)
|
41
|
-
|
42
33
|
instance
|
43
34
|
end
|
44
35
|
|
@@ -51,17 +42,8 @@ module Pakyow
|
|
51
42
|
# Returns the view matching +version+.
|
52
43
|
#
|
53
44
|
def versioned(version)
|
54
|
-
if
|
55
|
-
|
56
|
-
when StringDoc::MetaNode
|
57
|
-
node = versioned.object.nodes.find { |n|
|
58
|
-
version == (n.label(:version) || DEFAULT_VERSION).to_sym
|
59
|
-
}
|
60
|
-
|
61
|
-
View.from_object(node)
|
62
|
-
else
|
63
|
-
versioned
|
64
|
-
end
|
45
|
+
if node = version_named(version.to_sym)
|
46
|
+
View.from_object(node)
|
65
47
|
else
|
66
48
|
nil
|
67
49
|
end
|
@@ -72,67 +54,25 @@ module Pakyow
|
|
72
54
|
def use(version)
|
73
55
|
version = version.to_sym
|
74
56
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
version == (node.label(:version) || DEFAULT_VERSION).to_sym
|
81
|
-
}
|
82
|
-
|
83
|
-
versioned_node.set_label(:versioned, true)
|
84
|
-
else
|
85
|
-
view.object.set_label(:versioned, true)
|
86
|
-
end
|
87
|
-
|
88
|
-
self.versioned_view = view
|
89
|
-
|
90
|
-
cleanup
|
91
|
-
else
|
92
|
-
cleanup(all: true)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def transform(object)
|
98
|
-
@versions.each do |version|
|
99
|
-
version.transform(object)
|
100
|
-
end
|
101
|
-
|
102
|
-
yield self, object if block_given?
|
103
|
-
end
|
104
|
-
|
105
|
-
def bind(object)
|
106
|
-
@versions.each do |version|
|
107
|
-
version.bind(object)
|
57
|
+
if node = version_named(version)
|
58
|
+
node.set_label(:versioned, true)
|
59
|
+
cleanup
|
60
|
+
else
|
61
|
+
cleanup(all: true)
|
108
62
|
end
|
109
63
|
|
110
|
-
|
64
|
+
self
|
111
65
|
end
|
112
66
|
|
113
67
|
def used?
|
114
|
-
|
115
|
-
|
116
|
-
when StringDoc::MetaNode
|
117
|
-
versioned_view.object.nodes.any? { |node|
|
118
|
-
node.labeled?(:versioned)
|
119
|
-
}
|
120
|
-
else
|
121
|
-
versioned_view.object.labeled?(:versioned)
|
122
|
-
end
|
68
|
+
__getobj__.object.internal_nodes.any? { |node|
|
69
|
+
node.labeled?(:versioned)
|
123
70
|
}
|
124
71
|
end
|
125
72
|
|
126
73
|
def versions
|
127
|
-
|
128
|
-
|
129
|
-
when StringDoc::MetaNode
|
130
|
-
versioned_view.object.nodes.each do |node|
|
131
|
-
versions << View.from_object(node)
|
132
|
-
end
|
133
|
-
else
|
134
|
-
versions << versioned_view
|
135
|
-
end
|
74
|
+
__getobj__.object.nodes.map { |node|
|
75
|
+
View.from_object(node)
|
136
76
|
}
|
137
77
|
end
|
138
78
|
|
@@ -146,65 +86,25 @@ module Pakyow
|
|
146
86
|
|
147
87
|
def cleanup(all: false)
|
148
88
|
if all
|
149
|
-
|
150
|
-
version.remove
|
151
|
-
end
|
89
|
+
remove
|
152
90
|
else
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
nodes_to_remove = []
|
159
|
-
|
160
|
-
versioned_view.object.internal_nodes.each do |node|
|
161
|
-
if !node.is_a?(StringDoc::MetaNode) && !node.labeled?(:versioned)
|
162
|
-
nodes_to_remove << node
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
nodes_to_remove.each(&:remove)
|
167
|
-
else
|
168
|
-
unless versioned_view.object.labeled?(:versioned)
|
169
|
-
versions_to_remove << versioned_view
|
170
|
-
end
|
91
|
+
nodes_to_remove = []
|
92
|
+
|
93
|
+
__getobj__.object.internal_nodes.each do |node|
|
94
|
+
unless node.is_a?(StringDoc::MetaNode) || node.labeled?(:versioned)
|
95
|
+
nodes_to_remove << node
|
171
96
|
end
|
172
97
|
end
|
173
98
|
|
174
|
-
|
175
|
-
versioned_view.remove; @versions.delete(versioned_view)
|
176
|
-
end
|
99
|
+
nodes_to_remove.each(&:remove)
|
177
100
|
end
|
178
101
|
end
|
179
102
|
|
180
|
-
def determine_working_version
|
181
|
-
self.versioned_view = default_version
|
182
|
-
end
|
183
|
-
|
184
|
-
def versioned_view=(view)
|
185
|
-
__setobj__(view)
|
186
|
-
end
|
187
|
-
|
188
|
-
def default_version
|
189
|
-
version_named(DEFAULT_VERSION) || first_version
|
190
|
-
end
|
191
|
-
|
192
103
|
def version_named(version)
|
193
|
-
|
194
|
-
|
195
|
-
when StringDoc::MetaNode
|
196
|
-
view.object.internal_nodes.any? { |node|
|
197
|
-
version == (node.label(:version) || DEFAULT_VERSION).to_sym
|
198
|
-
}
|
199
|
-
else
|
200
|
-
view.version == version
|
201
|
-
end
|
104
|
+
__getobj__.object.internal_nodes.find { |node|
|
105
|
+
version == (node.label(:version) || DEFAULT_VERSION).to_sym
|
202
106
|
}
|
203
107
|
end
|
204
|
-
|
205
|
-
def first_version
|
206
|
-
@versions[0]
|
207
|
-
end
|
208
108
|
end
|
209
109
|
end
|
210
110
|
end
|
@@ -122,15 +122,16 @@ module Pakyow
|
|
122
122
|
def find(*names)
|
123
123
|
if names.any?
|
124
124
|
named = names.shift.to_sym
|
125
|
-
|
126
|
-
found = each_binding(named).map { |node|
|
127
|
-
View.from_object(node)
|
128
|
-
}
|
125
|
+
found = each_binding(named).map(&:itself)
|
129
126
|
|
130
127
|
result = if names.empty? && !found.empty? # found everything; wrap it up
|
131
|
-
|
128
|
+
if found[0].is_a?(StringDoc::MetaNode)
|
129
|
+
VersionedView.new(View.from_object(found[0]))
|
130
|
+
else
|
131
|
+
VersionedView.new(View.from_object(StringDoc::MetaNode.new(found)))
|
132
|
+
end
|
132
133
|
elsif !found.empty? && names.count > 0 # descend further
|
133
|
-
found.
|
134
|
+
View.from_object(found[0]).find(*names)
|
134
135
|
else
|
135
136
|
nil
|
136
137
|
end
|
@@ -417,7 +418,10 @@ module Pakyow
|
|
417
418
|
def to_html
|
418
419
|
@object.to_html
|
419
420
|
end
|
420
|
-
|
421
|
+
|
422
|
+
def to_s
|
423
|
+
@object.to_s
|
424
|
+
end
|
421
425
|
|
422
426
|
# @api private
|
423
427
|
def binding_name
|
data/lib/string_doc/meta_node.rb
CHANGED
@@ -11,12 +11,20 @@ class StringDoc
|
|
11
11
|
attr_reader :doc, :transforms, :internal_nodes
|
12
12
|
|
13
13
|
def initialize(nodes)
|
14
|
-
nodes
|
15
|
-
|
16
|
-
nodes
|
17
|
-
#
|
14
|
+
# Reparent nodes that belong to the same parent.
|
15
|
+
#
|
16
|
+
nodes.group_by { |node| node.parent }.each_pair do |parent, children|
|
17
|
+
# If the children already belong to a meta node doc, don't reparent them again.
|
18
18
|
#
|
19
|
-
|
19
|
+
unless children.first.labeled?(:__meta_node)
|
20
|
+
parent.replace_node(children.first, self)
|
21
|
+
end
|
22
|
+
|
23
|
+
children[1..-1].each do |node|
|
24
|
+
# Remove the node, but don't make it appear to have been removed for transforms.
|
25
|
+
#
|
26
|
+
node.remove(false, false)
|
27
|
+
end
|
20
28
|
end
|
21
29
|
|
22
30
|
nodes.each do |node|
|
@@ -26,9 +34,7 @@ class StringDoc
|
|
26
34
|
@doc = StringDoc.from_nodes(nodes)
|
27
35
|
@transforms = { high: [], default: [], low: [] }
|
28
36
|
|
29
|
-
@internal_nodes = nodes.
|
30
|
-
!node.is_a?(MetaNode) && node.labeled?(:__meta_node)
|
31
|
-
}
|
37
|
+
@internal_nodes = nodes.dup
|
32
38
|
|
33
39
|
@pipeline = nil
|
34
40
|
end
|
@@ -37,15 +43,23 @@ class StringDoc
|
|
37
43
|
def initialize_copy(_)
|
38
44
|
super
|
39
45
|
|
40
|
-
|
46
|
+
nodes, internal_nodes = [], []
|
47
|
+
@doc.nodes.each do |current_node|
|
48
|
+
duped_node = current_node.dup
|
49
|
+
nodes << duped_node
|
50
|
+
|
51
|
+
if @internal_nodes.any? { |current_internal_node| current_internal_node.equal?(current_node) }
|
52
|
+
internal_nodes << duped_node
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
@doc = StringDoc.from_nodes(nodes)
|
41
57
|
|
42
58
|
@transforms = @transforms.each_with_object({}) { |(key, value), hash|
|
43
59
|
hash[key] = value.dup
|
44
60
|
}
|
45
61
|
|
46
|
-
@internal_nodes =
|
47
|
-
!node.is_a?(MetaNode) && node.labeled?(:__meta_node)
|
48
|
-
}
|
62
|
+
@internal_nodes = internal_nodes
|
49
63
|
|
50
64
|
@pipeline = nil
|
51
65
|
end
|
@@ -54,19 +68,32 @@ class StringDoc
|
|
54
68
|
def soft_copy
|
55
69
|
instance = self.class.allocate
|
56
70
|
|
57
|
-
|
58
|
-
|
71
|
+
nodes, internal_nodes = [], []
|
72
|
+
@doc.nodes.each do |current_node|
|
73
|
+
duped_node = current_node.soft_copy
|
74
|
+
nodes << duped_node
|
75
|
+
|
76
|
+
if @internal_nodes.any? { |current_internal_node| current_internal_node.equal?(current_node) }
|
77
|
+
internal_nodes << duped_node
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
instance.instance_variable_set(:@doc, StringDoc.from_nodes(nodes))
|
59
82
|
instance.instance_variable_set(:@transforms, @transforms)
|
60
83
|
|
61
|
-
instance.instance_variable_set(:@internal_nodes,
|
62
|
-
!node.is_a?(MetaNode) && node.labeled?(:__meta_node)
|
63
|
-
})
|
84
|
+
instance.instance_variable_set(:@internal_nodes, internal_nodes)
|
64
85
|
|
65
86
|
instance.instance_variable_set(:@pipeline, @pipeline.dup)
|
66
87
|
|
67
88
|
instance
|
68
89
|
end
|
69
90
|
|
91
|
+
def finalize_labels(keep: [])
|
92
|
+
nodes.each do |node|
|
93
|
+
node.finalize_labels(keep: keep)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
70
97
|
def freeze(*)
|
71
98
|
pipeline
|
72
99
|
super
|
@@ -128,10 +155,16 @@ class StringDoc
|
|
128
155
|
internal_nodes.each do |each_node|
|
129
156
|
each_node.replace(replacement)
|
130
157
|
end
|
158
|
+
|
159
|
+
@internal_nodes = StringDoc.nodes_from_doc_or_string(replacement)
|
131
160
|
end
|
132
161
|
|
133
|
-
def remove
|
134
|
-
internal_nodes.each
|
162
|
+
def remove(label = true, descend = true)
|
163
|
+
internal_nodes.each do |node|
|
164
|
+
node.remove(label, descend)
|
165
|
+
end
|
166
|
+
|
167
|
+
@internal_nodes = []
|
135
168
|
end
|
136
169
|
|
137
170
|
def text
|
@@ -217,8 +250,23 @@ class StringDoc
|
|
217
250
|
end
|
218
251
|
|
219
252
|
def each(descend: false, &block)
|
220
|
-
|
221
|
-
|
253
|
+
return enum_for(:each, descend: descend) unless block_given?
|
254
|
+
|
255
|
+
yield self
|
256
|
+
|
257
|
+
nodes.each do |node|
|
258
|
+
# Yield each node that isn't an internal node (e.g. added before/after).
|
259
|
+
#
|
260
|
+
unless @internal_nodes.any? { |internal_node| internal_node.equal?(node) }
|
261
|
+
case node
|
262
|
+
when MetaNode
|
263
|
+
node.each do |each_meta_node|
|
264
|
+
yield each_meta_node
|
265
|
+
end
|
266
|
+
else
|
267
|
+
yield node
|
268
|
+
end
|
269
|
+
end
|
222
270
|
end
|
223
271
|
end
|
224
272
|
|
@@ -268,6 +316,10 @@ class StringDoc
|
|
268
316
|
}
|
269
317
|
end
|
270
318
|
|
319
|
+
def removed?
|
320
|
+
internal_nodes.all?(&:removed?)
|
321
|
+
end
|
322
|
+
|
271
323
|
# Converts the node to an xml string.
|
272
324
|
#
|
273
325
|
def render(output = String.new, context: nil)
|
@@ -278,6 +330,8 @@ class StringDoc
|
|
278
330
|
each_node.render(output, context: context)
|
279
331
|
end
|
280
332
|
end
|
333
|
+
|
334
|
+
output
|
281
335
|
end
|
282
336
|
alias :to_html :render
|
283
337
|
alias :to_xml :render
|
@@ -313,17 +367,17 @@ class StringDoc
|
|
313
367
|
when StringDoc
|
314
368
|
return_value.render(string, context: context); return
|
315
369
|
when Node, MetaNode
|
316
|
-
|
370
|
+
if return_value.removed?
|
371
|
+
return
|
372
|
+
else
|
373
|
+
current = return_value
|
374
|
+
end
|
317
375
|
else
|
318
376
|
string << return_value.to_s; return
|
319
377
|
end
|
320
378
|
end
|
321
379
|
|
322
|
-
|
323
|
-
#
|
324
|
-
if !current.is_a?(Node) || !current.labeled?(:removed)
|
325
|
-
current.render(string, context: context)
|
326
|
-
end
|
380
|
+
current.render(string, context: context)
|
327
381
|
end
|
328
382
|
end
|
329
383
|
end
|
data/lib/string_doc/node.rb
CHANGED
@@ -35,7 +35,7 @@ class StringDoc
|
|
35
35
|
attr_reader :attributes
|
36
36
|
|
37
37
|
# @api private
|
38
|
-
attr_reader :node, :parent, :children, :tag_open_start, :tag_open_end, :tag_close, :transforms, :significance
|
38
|
+
attr_reader :node, :parent, :children, :tag_open_start, :tag_open_end, :tag_close, :transforms, :significance
|
39
39
|
|
40
40
|
# @api private
|
41
41
|
attr_writer :parent
|
@@ -50,6 +50,7 @@ class StringDoc
|
|
50
50
|
@parent, @labels, @significance = parent, labels, significance
|
51
51
|
@transforms = { high: [], default: [], low: [] }
|
52
52
|
@pipeline = nil
|
53
|
+
@finalized_labels = {}
|
53
54
|
end
|
54
55
|
|
55
56
|
# @api private
|
@@ -57,6 +58,7 @@ class StringDoc
|
|
57
58
|
super
|
58
59
|
|
59
60
|
@labels = @labels.deep_dup
|
61
|
+
@finalized_labels = @finalized_labels.deep_dup
|
60
62
|
@attributes = @attributes.dup
|
61
63
|
@children = @children.dup
|
62
64
|
@significance = @significance.dup
|
@@ -78,6 +80,7 @@ class StringDoc
|
|
78
80
|
instance.instance_variable_set(:@parent, @parent)
|
79
81
|
instance.instance_variable_set(:@significance, @significance)
|
80
82
|
instance.instance_variable_set(:@transforms, @transforms)
|
83
|
+
instance.instance_variable_set(:@finalized_labels, @finalized_labels)
|
81
84
|
|
82
85
|
instance.instance_variable_set(:@attributes, @attributes.dup)
|
83
86
|
instance.instance_variable_set(:@children, @children.is_a?(StringDoc) ? @children.soft_copy : @children.dup)
|
@@ -87,6 +90,21 @@ class StringDoc
|
|
87
90
|
instance
|
88
91
|
end
|
89
92
|
|
93
|
+
def finalize_labels(keep: [])
|
94
|
+
@finalized_labels = @labels
|
95
|
+
@labels = keep.each_with_object({}) { |key, hash|
|
96
|
+
hash[key] = @finalized_labels.delete(key).deep_dup
|
97
|
+
}
|
98
|
+
|
99
|
+
if children.is_a?(StringDoc)
|
100
|
+
children.finalize_labels(keep: keep)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def labels
|
105
|
+
@labels.merge(@finalized_labels)
|
106
|
+
end
|
107
|
+
|
90
108
|
def freeze(*)
|
91
109
|
pipeline
|
92
110
|
super
|
@@ -145,9 +163,18 @@ class StringDoc
|
|
145
163
|
|
146
164
|
# Removes the node.
|
147
165
|
#
|
148
|
-
def remove
|
149
|
-
|
166
|
+
def remove(label = true, descend = true)
|
167
|
+
if label
|
168
|
+
set_label(:removed, true)
|
169
|
+
end
|
170
|
+
|
150
171
|
@parent.remove_node(self)
|
172
|
+
|
173
|
+
if descend && children.is_a?(StringDoc)
|
174
|
+
children.each do |child|
|
175
|
+
child.remove(label, descend)
|
176
|
+
end
|
177
|
+
end
|
151
178
|
end
|
152
179
|
|
153
180
|
REGEX_TAGS = /<[^>]*>/
|
@@ -221,13 +248,18 @@ class StringDoc
|
|
221
248
|
# Returns the value for label with +name+.
|
222
249
|
#
|
223
250
|
def label(name)
|
224
|
-
|
251
|
+
name = name.to_sym
|
252
|
+
if @labels.key?(name)
|
253
|
+
@labels[name.to_sym]
|
254
|
+
else
|
255
|
+
@finalized_labels[name.to_sym]
|
256
|
+
end
|
225
257
|
end
|
226
258
|
|
227
259
|
# Returns true if label exists with +name+.
|
228
260
|
#
|
229
261
|
def labeled?(name)
|
230
|
-
@labels.key?(name.to_sym)
|
262
|
+
@labels.key?(name.to_sym) || @finalized_labels.key?(name.to_sym)
|
231
263
|
end
|
232
264
|
|
233
265
|
# Sets the label with +name+ and +value+.
|
@@ -236,6 +268,10 @@ class StringDoc
|
|
236
268
|
@labels[name.to_sym] = value
|
237
269
|
end
|
238
270
|
|
271
|
+
def removed?
|
272
|
+
labeled?(:removed)
|
273
|
+
end
|
274
|
+
|
239
275
|
# Delete the label with +name+.
|
240
276
|
#
|
241
277
|
def delete_label(name)
|
@@ -263,6 +299,8 @@ class StringDoc
|
|
263
299
|
|
264
300
|
output << tag_close
|
265
301
|
end
|
302
|
+
|
303
|
+
output
|
266
304
|
end
|
267
305
|
alias :to_html :render
|
268
306
|
alias :to_xml :render
|
@@ -358,17 +396,17 @@ class StringDoc
|
|
358
396
|
when StringDoc
|
359
397
|
return_value.render(string, context: context); return
|
360
398
|
when Node, MetaNode
|
361
|
-
|
399
|
+
if return_value.removed?
|
400
|
+
return
|
401
|
+
else
|
402
|
+
current = return_value
|
403
|
+
end
|
362
404
|
else
|
363
405
|
string << return_value.to_s; return
|
364
406
|
end
|
365
407
|
end
|
366
408
|
|
367
|
-
|
368
|
-
#
|
369
|
-
if !current.is_a?(Node) || !current.labeled?(:removed)
|
370
|
-
current.render(string, context: context)
|
371
|
-
end
|
409
|
+
current.render(string, context: context)
|
372
410
|
end
|
373
411
|
|
374
412
|
def string_nodes
|
data/lib/string_doc.rb
CHANGED
@@ -171,13 +171,26 @@ class StringDoc
|
|
171
171
|
instance
|
172
172
|
end
|
173
173
|
|
174
|
+
def finalize_labels(keep: [])
|
175
|
+
@nodes.each do |node|
|
176
|
+
node.finalize_labels(keep: keep)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
174
180
|
include Enumerable
|
175
181
|
|
176
182
|
def each(descend: false, &block)
|
177
183
|
return enum_for(:each, descend: descend) unless block_given?
|
178
184
|
|
179
185
|
@nodes.each do |node|
|
180
|
-
|
186
|
+
case node
|
187
|
+
when MetaNode
|
188
|
+
node.each do |each_meta_node|
|
189
|
+
yield each_meta_node
|
190
|
+
end
|
191
|
+
else
|
192
|
+
yield node
|
193
|
+
end
|
181
194
|
|
182
195
|
if descend || node.label(:descend) != false
|
183
196
|
if node.children.is_a?(StringDoc)
|
@@ -195,7 +208,18 @@ class StringDoc
|
|
195
208
|
return enum_for(:each_significant_node, type, descend: descend) unless block_given?
|
196
209
|
|
197
210
|
each(descend: descend) do |node|
|
198
|
-
|
211
|
+
case node
|
212
|
+
when MetaNode
|
213
|
+
if node.significant?(type)
|
214
|
+
node.each do |each_meta_node|
|
215
|
+
yield each_meta_node
|
216
|
+
end
|
217
|
+
end
|
218
|
+
when Node
|
219
|
+
if node.significant?(type)
|
220
|
+
yield node
|
221
|
+
end
|
222
|
+
end
|
199
223
|
end
|
200
224
|
end
|
201
225
|
|
@@ -207,7 +231,14 @@ class StringDoc
|
|
207
231
|
@nodes.each do |node|
|
208
232
|
if node.is_a?(Node) || node.is_a?(MetaNode)
|
209
233
|
if node.significant?(type)
|
210
|
-
|
234
|
+
case node
|
235
|
+
when MetaNode
|
236
|
+
node.each do |each_meta_node|
|
237
|
+
yield each_meta_node
|
238
|
+
end
|
239
|
+
when Node
|
240
|
+
yield node
|
241
|
+
end
|
211
242
|
else
|
212
243
|
if descend || node.label(:descend) != false
|
213
244
|
if node.children.is_a?(StringDoc)
|
@@ -367,7 +398,7 @@ class StringDoc
|
|
367
398
|
def remove_node(node_to_delete)
|
368
399
|
tap do
|
369
400
|
@nodes.delete_if { |node|
|
370
|
-
node.
|
401
|
+
node.equal?(node_to_delete)
|
371
402
|
}
|
372
403
|
end
|
373
404
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pakyow-presenter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.rc4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bryan Powell
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2019-07-
|
12
|
+
date: 2019-07-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: pakyow-core
|
@@ -17,42 +17,42 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - '='
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: 1.0.0.
|
20
|
+
version: 1.0.0.rc4
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - '='
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: 1.0.0.
|
27
|
+
version: 1.0.0.rc4
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: pakyow-routing
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
32
|
- - '='
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: 1.0.0.
|
34
|
+
version: 1.0.0.rc4
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - '='
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: 1.0.0.
|
41
|
+
version: 1.0.0.rc4
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: pakyow-support
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
46
|
- - '='
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: 1.0.0.
|
48
|
+
version: 1.0.0.rc4
|
49
49
|
type: :runtime
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - '='
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: 1.0.0.
|
55
|
+
version: 1.0.0.rc4
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: oga
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|