pakyow-presenter 1.0.0.rc3 → 1.0.0.rc4
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/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
|