pakyow-presenter 0.10.2 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/pakyow-presenter/CHANGELOG.md +16 -0
- data/pakyow-presenter/lib/pakyow-presenter.rb +1 -11
- data/pakyow-presenter/lib/pakyow/presenter.rb +8 -0
- data/pakyow-presenter/lib/{presenter → pakyow/presenter}/attributes.rb +21 -14
- data/pakyow-presenter/lib/pakyow/presenter/base.rb +38 -0
- data/pakyow-presenter/lib/{presenter → pakyow/presenter}/binder.rb +19 -6
- data/pakyow-presenter/lib/{presenter → pakyow/presenter}/binder_set.rb +18 -21
- data/pakyow-presenter/lib/{presenter → pakyow/presenter}/binding_eval.rb +14 -0
- data/pakyow-presenter/lib/{presenter → pakyow/presenter}/config/presenter.rb +12 -6
- data/pakyow-presenter/lib/{presenter → pakyow/presenter}/container.rb +0 -0
- data/pakyow-presenter/lib/{presenter → pakyow/presenter}/doc_helpers.rb +0 -0
- data/pakyow-presenter/lib/{presenter → pakyow/presenter}/exceptions.rb +0 -0
- data/pakyow-presenter/lib/pakyow/presenter/ext/app.rb +33 -0
- data/pakyow-presenter/lib/pakyow/presenter/ext/call_context.rb +28 -0
- data/pakyow-presenter/lib/pakyow/presenter/helpers.rb +46 -0
- data/pakyow-presenter/lib/{presenter → pakyow/presenter}/page.rb +0 -0
- data/pakyow-presenter/lib/{presenter → pakyow/presenter}/partial.rb +0 -0
- data/pakyow-presenter/lib/{presenter → pakyow/presenter}/presenter.rb +14 -9
- data/pakyow-presenter/lib/{presenter → pakyow/presenter}/string_doc.rb +35 -9
- data/pakyow-presenter/lib/{presenter → pakyow/presenter}/string_doc_parser.rb +41 -30
- data/pakyow-presenter/lib/{presenter → pakyow/presenter}/string_doc_renderer.rb +0 -0
- data/pakyow-presenter/lib/{presenter → pakyow/presenter}/template.rb +0 -0
- data/pakyow-presenter/lib/{presenter → pakyow/presenter}/view.rb +79 -36
- data/pakyow-presenter/lib/{presenter → pakyow/presenter}/view_collection.rb +10 -4
- data/pakyow-presenter/lib/{presenter → pakyow/presenter}/view_composer.rb +43 -3
- data/pakyow-presenter/lib/{presenter → pakyow/presenter}/view_context.rb +12 -8
- data/pakyow-presenter/lib/{presenter → pakyow/presenter}/view_store.rb +3 -1
- data/pakyow-presenter/lib/{presenter → pakyow/presenter}/view_store_loader.rb +0 -0
- data/pakyow-presenter/lib/{presenter → pakyow/presenter}/view_version.rb +19 -3
- data/pakyow-presenter/lib/pakyow/views/errors/404.erb +26 -0
- data/pakyow-presenter/lib/pakyow/views/errors/500.erb +23 -0
- metadata +39 -38
- data/pakyow-presenter/lib/presenter/base.rb +0 -27
- data/pakyow-presenter/lib/presenter/ext/app.rb +0 -63
- data/pakyow-presenter/lib/presenter/helpers.rb +0 -40
- data/pakyow-presenter/lib/views/errors/404.html +0 -5
- data/pakyow-presenter/lib/views/errors/500.html +0 -0
File without changes
|
File without changes
|
@@ -18,7 +18,11 @@ module Pakyow
|
|
18
18
|
return contents
|
19
19
|
end
|
20
20
|
|
21
|
-
|
21
|
+
processed = processor.call(contents)
|
22
|
+
|
23
|
+
# reprocess html content unless we just did that
|
24
|
+
return processed if format == :html
|
25
|
+
process(processed, :html)
|
22
26
|
end
|
23
27
|
end
|
24
28
|
|
@@ -33,11 +37,15 @@ module Pakyow
|
|
33
37
|
}
|
34
38
|
|
35
39
|
Pakyow::App.after(:route) {
|
36
|
-
if
|
37
|
-
@found
|
38
|
-
@context.response.body = [@presenter.content]
|
40
|
+
if Config.presenter.require_route && !found?
|
41
|
+
@found
|
39
42
|
else
|
40
|
-
@
|
43
|
+
if @presenter.presented?
|
44
|
+
@found = true
|
45
|
+
@context.response.body = [@presenter.content]
|
46
|
+
else
|
47
|
+
@found = false unless found?
|
48
|
+
end
|
41
49
|
end
|
42
50
|
}
|
43
51
|
|
@@ -163,10 +171,7 @@ module Pakyow
|
|
163
171
|
end
|
164
172
|
|
165
173
|
def compose_at(path, opts = {}, &block)
|
166
|
-
composer = ViewComposer.from_path(store, path, opts, &block)
|
167
|
-
return composer unless opts.empty? || block_given?
|
168
|
-
|
169
|
-
@composer = composer
|
174
|
+
@composer = ViewComposer.from_path(store, path, opts, &block)
|
170
175
|
end
|
171
176
|
|
172
177
|
def has_path?
|
@@ -51,6 +51,10 @@ module Pakyow
|
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
+
def attribute?(name)
|
55
|
+
attributes.key?(name.to_sym)
|
56
|
+
end
|
57
|
+
|
54
58
|
def set_attribute(name, value)
|
55
59
|
return if attributes.nil?
|
56
60
|
attributes[name.to_sym] = value
|
@@ -65,9 +69,24 @@ module Pakyow
|
|
65
69
|
attributes.delete(name.to_sym)
|
66
70
|
end
|
67
71
|
|
72
|
+
def has_attribute?(name)
|
73
|
+
attributes.key?(name)
|
74
|
+
end
|
75
|
+
|
68
76
|
def remove
|
69
77
|
@structure.delete_if { |n| n.equal?(node) }
|
70
|
-
|
78
|
+
|
79
|
+
if @node.nil?
|
80
|
+
@node = ['', {}, [['', {}, []]]]
|
81
|
+
else
|
82
|
+
@node[0] = ''
|
83
|
+
@node[1] = {}
|
84
|
+
@node[2][0][0] = ''
|
85
|
+
@node[2][0][1] = {}
|
86
|
+
@node[2][0][2] = []
|
87
|
+
@node[2].slice!(1..-1)
|
88
|
+
end
|
89
|
+
|
71
90
|
@removed = true
|
72
91
|
end
|
73
92
|
|
@@ -184,6 +203,7 @@ module Pakyow
|
|
184
203
|
end
|
185
204
|
|
186
205
|
def to_html
|
206
|
+
StringDocRenderer.render((@node && !@removed) ? [@node] : @structure)
|
187
207
|
StringDocRenderer.render(@node ? [@node] : @structure)
|
188
208
|
end
|
189
209
|
alias :to_s :to_html
|
@@ -195,7 +215,7 @@ module Pakyow
|
|
195
215
|
end
|
196
216
|
|
197
217
|
def node
|
198
|
-
return @structure if @structure.empty?
|
218
|
+
return @structure if @structure.empty? && !@removed
|
199
219
|
return @node || @structure[0]
|
200
220
|
end
|
201
221
|
|
@@ -241,12 +261,8 @@ module Pakyow
|
|
241
261
|
node[1]
|
242
262
|
end
|
243
263
|
|
244
|
-
def has_attribute?(name)
|
245
|
-
attributes.key?(name)
|
246
|
-
end
|
247
|
-
|
248
264
|
def children
|
249
|
-
if @structure.empty?
|
265
|
+
if @structure.empty? && !@removed
|
250
266
|
@structure
|
251
267
|
else
|
252
268
|
node[2][0][2]
|
@@ -267,7 +283,7 @@ module Pakyow
|
|
267
283
|
def find_partials(structure, primary_structure = @structure, partials = {})
|
268
284
|
structure.inject(partials) { |s, e|
|
269
285
|
if e[1].has_key?(:partial)
|
270
|
-
s[e[1][:partial]]
|
286
|
+
(s[e[1][:partial]] ||= []) << StringDoc.from_structure(primary_structure, node: e)
|
271
287
|
end
|
272
288
|
find_partials(e[2], e[2], s)
|
273
289
|
s
|
@@ -308,10 +324,20 @@ module Pakyow
|
|
308
324
|
|
309
325
|
def find_node_props(node, primary_structure = @structure, props = [])
|
310
326
|
if node[1].has_key?(:'data-prop')
|
311
|
-
|
327
|
+
prop = {
|
312
328
|
doc: StringDoc.from_structure(primary_structure, node: node),
|
313
329
|
prop: node[1][:'data-prop'].to_sym,
|
330
|
+
parts: {},
|
314
331
|
}
|
332
|
+
|
333
|
+
if node[1].has_key?(:'data-parts')
|
334
|
+
prop[:parts][:include] = node[1][:'data-parts'].split(/\s+/).map(&:to_sym)
|
335
|
+
end
|
336
|
+
|
337
|
+
if node[1].has_key?(:'data-parts-exclude')
|
338
|
+
prop[:parts][:exclude] = node[1][:'data-parts-exclude'].split(/\s+/).map(&:to_sym)
|
339
|
+
end
|
340
|
+
props << prop
|
315
341
|
end
|
316
342
|
|
317
343
|
unless node[1].has_key?(:'data-scope')
|
@@ -3,6 +3,7 @@ module Pakyow
|
|
3
3
|
class StringDocParser
|
4
4
|
PARTIAL_REGEX = /<!--\s*@include\s*([a-zA-Z0-9\-_]*)\s*-->/
|
5
5
|
CONTAINER_REGEX = /@container( ([a-zA-Z0-9\-_]*))*/
|
6
|
+
SIGNIFICANT = [:scope?, :prop?, :container?, :partial?, :option?, :component?]
|
6
7
|
|
7
8
|
def initialize(html)
|
8
9
|
@html = html
|
@@ -20,45 +21,51 @@ module Pakyow
|
|
20
21
|
def parse(doc)
|
21
22
|
structure = []
|
22
23
|
|
23
|
-
|
24
|
+
unless doc.is_a?(Oga::XML::Element) || !doc.respond_to?(:doctype) || doc.doctype.nil?
|
24
25
|
structure << ['<!DOCTYPE html>', {}, []]
|
25
26
|
end
|
26
27
|
|
27
28
|
breadth_first(doc) do |node, queue|
|
28
29
|
if node == doc
|
29
|
-
queue.concat(node.children)
|
30
|
+
queue.concat(node.children.to_a)
|
30
31
|
next
|
31
32
|
end
|
32
33
|
|
33
|
-
children = node.children.reject {|n| n.is_a?(
|
34
|
-
|
34
|
+
children = node.children.reject {|n| n.is_a?(Oga::XML::Text)}
|
35
|
+
|
36
|
+
if node.is_a?(Oga::XML::Element)
|
37
|
+
attributes = node.attributes
|
38
|
+
else
|
39
|
+
attributes = []
|
40
|
+
end
|
41
|
+
|
35
42
|
if !structure.empty? && children.empty? && !significant?(node)
|
36
|
-
structure << [node.
|
43
|
+
structure << [node.to_xml, {}, []]
|
37
44
|
else
|
38
45
|
if significant?(node)
|
39
|
-
if
|
46
|
+
if container?(node)
|
47
|
+
match = node.text.strip.match(CONTAINER_REGEX)
|
48
|
+
name = (match[2] || :default).to_sym
|
49
|
+
structure << [node.to_xml, { container: name }, []]
|
50
|
+
elsif partial?(node)
|
51
|
+
next unless match = node.to_xml.strip.match(PARTIAL_REGEX)
|
52
|
+
name = match[1].to_sym
|
53
|
+
structure << [node.to_xml, { partial: name }, []]
|
54
|
+
else
|
40
55
|
attr_structure = attributes.inject({}) do |attrs, attr|
|
41
|
-
attrs[attr
|
56
|
+
attrs[attr.name.to_sym] = attr.value
|
42
57
|
attrs
|
43
58
|
end
|
44
59
|
|
45
60
|
closing = [['>', {}, parse(node)]]
|
46
61
|
closing << ["</#{node.name}>", {}, []] unless self_closing?(node.name)
|
47
62
|
structure << ["<#{node.name} ", attr_structure, closing]
|
48
|
-
elsif container?(node)
|
49
|
-
match = node.text.strip.match(CONTAINER_REGEX)
|
50
|
-
name = (match[2] || :default).to_sym
|
51
|
-
structure << [node.to_html, { container: name }, []]
|
52
|
-
elsif partial?(node)
|
53
|
-
next unless match = node.to_html.strip.match(PARTIAL_REGEX)
|
54
|
-
name = match[1].to_sym
|
55
|
-
structure << [node.to_html, { partial: name }, []]
|
56
63
|
end
|
57
64
|
else
|
58
|
-
if node.is_a?(
|
59
|
-
structure << [node.
|
65
|
+
if node.is_a?(Oga::XML::Text) || node.is_a?(Oga::XML::Comment)
|
66
|
+
structure << [node.to_xml, {}, []]
|
60
67
|
else
|
61
|
-
attr_s = attributes.inject('') { |s, a| s << " #{a
|
68
|
+
attr_s = attributes.inject('') { |s, a| s << " #{a.name}=\"#{a.value}\""; s }
|
62
69
|
closing = [['>', {}, parse(node)]]
|
63
70
|
closing << ['</' + node.name + '>', {}, []] unless self_closing?(node.name)
|
64
71
|
structure << ['<' + node.name + attr_s, {}, closing]
|
@@ -71,37 +78,45 @@ module Pakyow
|
|
71
78
|
end
|
72
79
|
|
73
80
|
def significant?(node)
|
74
|
-
|
81
|
+
SIGNIFICANT.each do |method|
|
82
|
+
return true if send(method, node)
|
83
|
+
end
|
84
|
+
|
85
|
+
false
|
75
86
|
end
|
76
87
|
|
77
88
|
def scope?(node)
|
78
|
-
return false unless node
|
89
|
+
return false unless node.is_a?(Oga::XML::Element)
|
90
|
+
return false unless node.attribute('data-scope')
|
79
91
|
return true
|
80
92
|
end
|
81
93
|
|
82
94
|
def prop?(node)
|
83
|
-
return false unless node
|
95
|
+
return false unless node.is_a?(Oga::XML::Element)
|
96
|
+
return false unless node.attribute('data-prop')
|
84
97
|
return true
|
85
98
|
end
|
86
99
|
|
87
100
|
def container?(node)
|
88
|
-
return false unless node.is_a?(
|
101
|
+
return false unless node.is_a?(Oga::XML::Comment)
|
89
102
|
return false unless node.text.strip.match(CONTAINER_REGEX)
|
90
103
|
return true
|
91
104
|
end
|
92
105
|
|
93
106
|
def partial?(node)
|
94
|
-
return false unless node.is_a?(
|
95
|
-
return false unless node.
|
107
|
+
return false unless node.is_a?(Oga::XML::Comment)
|
108
|
+
return false unless node.to_xml.strip.match(PARTIAL_REGEX)
|
96
109
|
return true
|
97
110
|
end
|
98
111
|
|
99
112
|
def option?(node)
|
113
|
+
return false unless node.is_a?(Oga::XML::Element)
|
100
114
|
node.name == 'option'
|
101
115
|
end
|
102
116
|
|
103
117
|
def component?(node)
|
104
|
-
return false unless node
|
118
|
+
return false unless node.is_a?(Oga::XML::Element)
|
119
|
+
return false unless node.attribute('data-ui')
|
105
120
|
return true
|
106
121
|
end
|
107
122
|
|
@@ -116,11 +131,7 @@ module Pakyow
|
|
116
131
|
end
|
117
132
|
|
118
133
|
def doc_from_string(string)
|
119
|
-
|
120
|
-
Nokogiri::HTML::Document.parse(string)
|
121
|
-
else
|
122
|
-
Nokogiri::HTML.fragment(string)
|
123
|
-
end
|
134
|
+
Oga.parse_html(string)
|
124
135
|
end
|
125
136
|
|
126
137
|
SELF_CLOSING = %w[area base basefont br hr input img link meta]
|
File without changes
|
File without changes
|
@@ -43,7 +43,6 @@ module Pakyow
|
|
43
43
|
# Creates a view from a doc.
|
44
44
|
#
|
45
45
|
# @see StringDoc
|
46
|
-
# @see NokogiriDoc
|
47
46
|
#
|
48
47
|
def self.from_doc(doc)
|
49
48
|
view = new
|
@@ -289,21 +288,31 @@ module Pakyow
|
|
289
288
|
end
|
290
289
|
|
291
290
|
def includes(partial_map)
|
292
|
-
|
291
|
+
doc_partials = @doc.partials
|
293
292
|
partial_map = partial_map.dup
|
294
293
|
|
295
294
|
# mixin all the partials
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
295
|
+
doc_partials.each do |partial_name, partial_docs|
|
296
|
+
partials = Array.ensure(partial_map[partial_name])
|
297
|
+
|
298
|
+
partial_docs.each_with_index do |partial_doc, i|
|
299
|
+
replacement = partials[i]
|
300
|
+
next if replacement.nil?
|
301
|
+
|
302
|
+
if replacement.is_a?(ViewCollection)
|
303
|
+
partial_doc.replace(replacement.views.first.doc.dup)
|
304
|
+
partials = replacement.views
|
305
|
+
else
|
306
|
+
partial_doc.replace(replacement.doc)
|
307
|
+
end
|
308
|
+
end
|
300
309
|
end
|
301
310
|
|
302
311
|
# refind the partials
|
303
|
-
|
312
|
+
doc_partials = @doc.partials
|
304
313
|
|
305
314
|
# if mixed in partials included partials, we want to run includes again with a new map
|
306
|
-
if
|
315
|
+
if doc_partials.count > 0 && (partial_map.keys - doc_partials.keys).count < partial_map.keys.count
|
307
316
|
includes(partial_map)
|
308
317
|
end
|
309
318
|
|
@@ -324,8 +333,29 @@ module Pakyow
|
|
324
333
|
attrs.send(:'data-ui').value
|
325
334
|
end
|
326
335
|
|
336
|
+
# Convenience method for parity with Presenter::ViewCollection.
|
337
|
+
#
|
338
|
+
def length
|
339
|
+
1
|
340
|
+
end
|
341
|
+
|
342
|
+
# Convenience method for parity with Presenter::ViewCollection.
|
343
|
+
#
|
344
|
+
def first
|
345
|
+
self
|
346
|
+
end
|
347
|
+
|
327
348
|
private
|
328
349
|
|
350
|
+
def adjust_value_parts(value, parts)
|
351
|
+
return value unless value.is_a?(Hash)
|
352
|
+
|
353
|
+
parts_to_keep = parts.fetch(:include, value.keys)
|
354
|
+
parts_to_keep -= parts.fetch(:exclude, [])
|
355
|
+
|
356
|
+
value.keep_if { |part, _| parts_to_keep.include?(part) }
|
357
|
+
end
|
358
|
+
|
329
359
|
def bind_data_to_scope(data, scope_info, bindings, ctx)
|
330
360
|
return unless data
|
331
361
|
return unless scope_info
|
@@ -335,8 +365,9 @@ module Pakyow
|
|
335
365
|
|
336
366
|
scope_info[:props].each do |prop_info|
|
337
367
|
catch(:unbound) do
|
338
|
-
prop
|
339
|
-
doc
|
368
|
+
prop = prop_info[:prop]
|
369
|
+
doc = prop_info[:doc]
|
370
|
+
parts = prop_info[:parts]
|
340
371
|
|
341
372
|
if DocHelpers.form_field?(doc.tagname)
|
342
373
|
set_form_field_name(doc, scope, prop)
|
@@ -344,6 +375,7 @@ module Pakyow
|
|
344
375
|
|
345
376
|
if data_has_prop?(data, prop) || Binder.instance.has_scoped_prop?(scope, prop, bindings)
|
346
377
|
value = Binder.instance.value_for_scoped_prop(scope, prop, data, bindings, ctx)
|
378
|
+
value = adjust_value_parts(value, parts)
|
347
379
|
|
348
380
|
if DocHelpers.form_field?(doc.tagname)
|
349
381
|
bind_to_form_field(doc, scope, prop, value, data, ctx)
|
@@ -423,30 +455,38 @@ module Pakyow
|
|
423
455
|
options = Binder.instance.options_for_scoped_prop(scope, prop, bindable, ctx)
|
424
456
|
return if options.nil?
|
425
457
|
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
458
|
+
nodes = Oga::XML::Document.new
|
459
|
+
|
460
|
+
until options.length == 0
|
461
|
+
catch :optgroup do
|
462
|
+
o = options.first
|
463
|
+
|
464
|
+
# an array containing value/content
|
465
|
+
if o.is_a?(Array)
|
466
|
+
node = Oga::XML::Element.new(name: 'option')
|
467
|
+
node.inner_text = o[1].to_s
|
468
|
+
node.set('value', o[0].to_s)
|
469
|
+
nodes.children << node
|
470
|
+
options.shift
|
471
|
+
else # likely an object (e.g. string); start a group
|
472
|
+
node_group = Oga::XML::Element.new(name: 'optgroup')
|
473
|
+
node_group.set('label', o.to_s)
|
474
|
+
nodes.children << node_group
|
431
475
|
|
432
|
-
|
433
|
-
|
434
|
-
|
476
|
+
options.shift
|
477
|
+
|
478
|
+
options[0..-1].each_with_index { |o2,i2|
|
479
|
+
# starting a new group
|
480
|
+
throw :optgroup unless o2.is_a?(Array)
|
481
|
+
|
482
|
+
h.option o2[1].to_s, value: o2[0].to_s
|
483
|
+
|
484
|
+
node = Oga::XML::Element.new(name: 'option')
|
485
|
+
node.inner_text = o2[1].to_s
|
486
|
+
node.set('value', o2[0].to_s)
|
487
|
+
node_group.children << node
|
435
488
|
options.shift
|
436
|
-
|
437
|
-
else
|
438
|
-
h.optgroup(label: o) {
|
439
|
-
options.shift
|
440
|
-
|
441
|
-
options[0..-1].each_with_index { |o2,i2|
|
442
|
-
# starting a new group
|
443
|
-
throw :optgroup unless o2.is_a?(Array)
|
444
|
-
|
445
|
-
h.option o2[1], value: o2[0]
|
446
|
-
options.shift
|
447
|
-
}
|
448
|
-
}
|
449
|
-
end
|
489
|
+
}
|
450
490
|
end
|
451
491
|
end
|
452
492
|
end
|
@@ -455,7 +495,7 @@ module Pakyow
|
|
455
495
|
doc.clear
|
456
496
|
|
457
497
|
# add generated options
|
458
|
-
doc.append(
|
498
|
+
doc.append(nodes.to_xml)
|
459
499
|
end
|
460
500
|
|
461
501
|
def select_option_with_value(doc, value)
|
@@ -483,12 +523,15 @@ module Pakyow
|
|
483
523
|
attrs = Attributes.new(doc)
|
484
524
|
|
485
525
|
if v.respond_to?(:to_proc)
|
486
|
-
|
487
|
-
v.to_proc.call(
|
526
|
+
attribute = attrs.send(attr)
|
527
|
+
ret = v.to_proc.call(attribute)
|
528
|
+
value = ret.respond_to?(:value) ? ret.value : ret
|
529
|
+
|
530
|
+
attrs.send("#{attr}=", value)
|
488
531
|
elsif v.nil?
|
489
532
|
doc.remove_attribute(attr)
|
490
533
|
else
|
491
|
-
attrs.send(
|
534
|
+
attrs.send("#{attr}=", v)
|
492
535
|
end
|
493
536
|
end
|
494
537
|
end
|