runo 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/_parser.rb +19 -6
- data/lib/set/_set.rb +4 -3
- data/t/test_parser.rb +192 -0
- data/t/test_set_static.rb +23 -0
- metadata +3 -3
data/lib/_parser.rb
CHANGED
@@ -69,13 +69,14 @@ module Runo::Parser
|
|
69
69
|
out = ''
|
70
70
|
s = StringScanner.new html
|
71
71
|
until s.eos?
|
72
|
+
out << skip_comment(s)
|
72
73
|
if s.scan rex_open_tag
|
73
74
|
open_tag = s[0]
|
74
75
|
inner_html, close_tag = scan_inner_html(s, s[1])
|
75
76
|
close_tag << "\n" if s.scan /\n/
|
76
77
|
out << block.call(open_tag, inner_html, close_tag)
|
77
78
|
else
|
78
|
-
out << s.scan(/.+?(?=\t| |<|\z)/m)
|
79
|
+
out << s.scan(/.+?(?=\t| |<|\z)/m).to_s
|
79
80
|
end
|
80
81
|
end
|
81
82
|
out
|
@@ -85,15 +86,24 @@ module Runo::Parser
|
|
85
86
|
out = ''
|
86
87
|
s = StringScanner.new html
|
87
88
|
until s.eos?
|
89
|
+
out << skip_comment(s)
|
88
90
|
if s.scan /\$\((\w+)(?:\s+|\s*=\s*)([\w\-]+)\s*/m
|
89
91
|
out << block.call(s[1], {:klass => s[2]}.merge(scan_tokens(s)))
|
90
92
|
else
|
91
|
-
out << s.scan(/.+?(
|
93
|
+
out << s.scan(/.+?(?=\$|<!|\z)/m).to_s
|
92
94
|
end
|
93
95
|
end
|
94
96
|
out
|
95
97
|
end
|
96
98
|
|
99
|
+
def skip_comment(s)
|
100
|
+
if s.scan /\s*<(!--|!\[CDATA\[)\n*/
|
101
|
+
s[0] + scan_inner_html(s, s[1]).join + (s.scan(/\n/) || '')
|
102
|
+
else
|
103
|
+
''
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
97
107
|
def scrape_meta(html)
|
98
108
|
meta = {}
|
99
109
|
html.gsub!(/(?:^\s+)?<meta[^>]*name="runo-([^"]+)[^>]*content="([^"]+).*?>\n?/i) {
|
@@ -210,15 +220,18 @@ module Runo::Parser
|
|
210
220
|
end
|
211
221
|
|
212
222
|
def scan_inner_html(s, name)
|
223
|
+
open_tag = "<#{name}"
|
224
|
+
close_tag = {'!--' => '-->', '<![CDATA[' => ']]>'}[name] || "</#{name}>"
|
213
225
|
contents = ''
|
226
|
+
rex = /(.*?)(#{Regexp.quote(open_tag)}|#{Regexp.quote(close_tag)}|\z)/m
|
214
227
|
gen = 1
|
215
228
|
until s.eos? || (gen < 1)
|
216
|
-
contents << s.scan(
|
217
|
-
gen += 1 if s[2] ==
|
218
|
-
gen -= 1 if s[2] ==
|
229
|
+
contents << s.scan(rex)
|
230
|
+
gen += 1 if s[2] == open_tag
|
231
|
+
gen -= 1 if s[2] == close_tag
|
219
232
|
end
|
220
233
|
contents.gsub!(/\A\n+/, '')
|
221
|
-
contents.gsub!(/[\t ]
|
234
|
+
contents.gsub!(/[\t ]*#{Regexp.quote(close_tag)}\z/, '')
|
222
235
|
[contents, $&]
|
223
236
|
end
|
224
237
|
|
data/lib/set/_set.rb
CHANGED
@@ -103,14 +103,15 @@ module Runo::Set
|
|
103
103
|
|
104
104
|
def _get_by_tmpl(arg, tmpl = '')
|
105
105
|
tmpl.gsub(/@\((.+?)\)/) {
|
106
|
+
tag = $&
|
106
107
|
steps = $1.split '-'
|
107
108
|
id = steps.pop
|
108
109
|
item = item steps
|
109
|
-
item ? item[id.intern] :
|
110
|
+
item ? item[id.intern] : tag
|
110
111
|
}.gsub(/_\((.+?)\)/) {
|
111
112
|
_ $1
|
112
113
|
}.gsub(/\$\((.*?)(?:\.([\w\-]+))?\)/) {
|
113
|
-
name, action = $1, $2
|
114
|
+
tag, name, action = $&, $1, $2
|
114
115
|
if name == ''
|
115
116
|
self_arg = action ?
|
116
117
|
arg.merge(:orig_action => arg[:action], :action => action.intern) : arg
|
@@ -120,7 +121,7 @@ module Runo::Set
|
|
120
121
|
item_arg = item_arg(arg, steps)
|
121
122
|
item = item steps
|
122
123
|
if item.nil?
|
123
|
-
|
124
|
+
tag
|
124
125
|
elsif action
|
125
126
|
item_arg = item_arg.merge(
|
126
127
|
:orig_action => item_arg[:action],
|
data/t/test_parser.rb
CHANGED
@@ -77,6 +77,34 @@ _html
|
|
77
77
|
)
|
78
78
|
end
|
79
79
|
|
80
|
+
def test_parse_empty_tag_in_comment
|
81
|
+
html = 'hello <!-- $(foo = bar "baz baz") --> world'
|
82
|
+
result = Runo::Parser.parse_html html
|
83
|
+
assert_equal(
|
84
|
+
{},
|
85
|
+
result[:item],
|
86
|
+
'Parser.parse_html should skip runo tags in a comment'
|
87
|
+
)
|
88
|
+
assert_equal(
|
89
|
+
{:index => html},
|
90
|
+
result[:tmpl],
|
91
|
+
'Parser.parse_html should skip runo tags in a comment'
|
92
|
+
)
|
93
|
+
|
94
|
+
html = '<script><![CDATA[ $(foo = bar "baz baz") ]]></script>'
|
95
|
+
result = Runo::Parser.parse_html html
|
96
|
+
assert_equal(
|
97
|
+
{},
|
98
|
+
result[:item],
|
99
|
+
'Parser.parse_html should skip runo tags in a comment'
|
100
|
+
)
|
101
|
+
assert_equal(
|
102
|
+
{:index => html},
|
103
|
+
result[:tmpl],
|
104
|
+
'Parser.parse_html should skip runo tags in a comment'
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
80
108
|
def test_obscure_markup
|
81
109
|
result = Runo::Parser.parse_html('hello $(foo = bar $(baz=1) baz) world')
|
82
110
|
assert_equal(
|
@@ -366,6 +394,44 @@ _html
|
|
366
394
|
)
|
367
395
|
end
|
368
396
|
|
397
|
+
def test_scan_comment
|
398
|
+
s = StringScanner.new 'baz -->'
|
399
|
+
inner_html, close_tag = Runo::Parser.scan_inner_html(s, '!--')
|
400
|
+
assert_equal(
|
401
|
+
'baz',
|
402
|
+
inner_html,
|
403
|
+
'Parser.scan_inner_html should parse html comments'
|
404
|
+
)
|
405
|
+
assert_equal(
|
406
|
+
' -->',
|
407
|
+
close_tag,
|
408
|
+
'Parser.scan_inner_html should parse html comments'
|
409
|
+
)
|
410
|
+
|
411
|
+
s = StringScanner.new "baz\n <!--bar-->\n-->"
|
412
|
+
inner_html, close_tag = Runo::Parser.scan_inner_html(s, '!--')
|
413
|
+
assert_equal(
|
414
|
+
"baz\n <!--bar-->\n",
|
415
|
+
inner_html,
|
416
|
+
'Parser.scan_inner_html should parse nested comments'
|
417
|
+
)
|
418
|
+
end
|
419
|
+
|
420
|
+
def test_scan_cdata
|
421
|
+
s = StringScanner.new 'baz ]]>'
|
422
|
+
inner_html, close_tag = Runo::Parser.scan_inner_html(s, '<![CDATA[')
|
423
|
+
assert_equal(
|
424
|
+
'baz',
|
425
|
+
inner_html,
|
426
|
+
'Parser.scan_inner_html should parse CDATA section'
|
427
|
+
)
|
428
|
+
assert_equal(
|
429
|
+
' ]]>',
|
430
|
+
close_tag,
|
431
|
+
'Parser.scan_inner_html should parse CDATA section'
|
432
|
+
)
|
433
|
+
end
|
434
|
+
|
369
435
|
def test_parse_block_tag
|
370
436
|
result = Runo::Parser.parse_html <<'_html'
|
371
437
|
<ul class="app-blog" id="foo"><li>hello</li></ul>
|
@@ -462,12 +528,109 @@ _tmpl
|
|
462
528
|
assert_equal(
|
463
529
|
{:index => <<'_html'},
|
464
530
|
hello$(foo.message)$(foo) world
|
531
|
+
_html
|
532
|
+
result[:tmpl],
|
533
|
+
'Parser.parse_html[:tmpl] should be a proper template'
|
534
|
+
)
|
535
|
+
|
536
|
+
result = Runo::Parser.parse_html <<'_html'
|
537
|
+
hello <!-- cruel --> <ul class="app-blog" id="foo"><li>hello</li></ul> world
|
538
|
+
_html
|
539
|
+
assert_equal(
|
540
|
+
{
|
541
|
+
'foo' => {
|
542
|
+
:klass => 'set-dynamic',
|
543
|
+
:workflow => 'blog',
|
544
|
+
:tmpl => {
|
545
|
+
:index => <<'_tmpl'.chomp,
|
546
|
+
<ul class="app-blog" id="@(name)">$()</ul>$(.navi)$(.submit)$(.action_create)
|
547
|
+
_tmpl
|
548
|
+
},
|
549
|
+
:item => {
|
550
|
+
'default' => {
|
551
|
+
:label => nil,
|
552
|
+
:tmpl => {:index => '<li>hello</li>'},
|
553
|
+
:item => {},
|
554
|
+
},
|
555
|
+
},
|
556
|
+
},
|
557
|
+
},
|
558
|
+
result[:item],
|
559
|
+
'Parser.parse_html should be able to parse block runo tags'
|
560
|
+
)
|
561
|
+
assert_equal(
|
562
|
+
{:index => <<'_html'},
|
563
|
+
hello <!-- cruel -->$(foo.message)$(foo) world
|
465
564
|
_html
|
466
565
|
result[:tmpl],
|
467
566
|
'Parser.parse_html[:tmpl] should be a proper template'
|
468
567
|
)
|
469
568
|
end
|
470
569
|
|
570
|
+
def test_parse_block_tag_in_comment
|
571
|
+
[
|
572
|
+
<<'_html',
|
573
|
+
hello <!--<ul class="app-blog" id="test1"><li>hello</li></ul>--> world
|
574
|
+
_html
|
575
|
+
<<'_html',
|
576
|
+
<!--
|
577
|
+
<ul class="app-blog" id="test2">
|
578
|
+
<li>hello</li>
|
579
|
+
</ul>
|
580
|
+
-->
|
581
|
+
_html
|
582
|
+
<<'_html',
|
583
|
+
foo <!--
|
584
|
+
<ul class="app-blog" id="test3">
|
585
|
+
<li>hello</li>
|
586
|
+
</ul>
|
587
|
+
--> bar
|
588
|
+
_html
|
589
|
+
<<'_html',
|
590
|
+
foo <!--
|
591
|
+
<ul class="app-blog" id="test4">
|
592
|
+
<li>hello</li>
|
593
|
+
</ul>
|
594
|
+
--> bar
|
595
|
+
_html
|
596
|
+
<<'_html',
|
597
|
+
foo <!--
|
598
|
+
<ul class="app-blog" id="test5">
|
599
|
+
<!-- may_preview -->
|
600
|
+
<li>hello</li>
|
601
|
+
</ul>
|
602
|
+
--> bar
|
603
|
+
_html
|
604
|
+
<<'_html',
|
605
|
+
<![CDATA[
|
606
|
+
<ul class="app-blog" id="test6">
|
607
|
+
<!-- may_preview -->
|
608
|
+
<li>hello</li>
|
609
|
+
</ul>
|
610
|
+
]]>
|
611
|
+
_html
|
612
|
+
<<'_html',
|
613
|
+
<!--
|
614
|
+
<ul class="app-blog" id="test7">
|
615
|
+
<!-- may_preview -->
|
616
|
+
<li>hello</li>
|
617
|
+
</ul>
|
618
|
+
_html
|
619
|
+
].each {|html|
|
620
|
+
result = Runo::Parser.parse_html html
|
621
|
+
assert_equal(
|
622
|
+
{},
|
623
|
+
result[:item],
|
624
|
+
'Parser.parse_html should skip runo tags in a comment'
|
625
|
+
)
|
626
|
+
assert_equal(
|
627
|
+
{:index => html},
|
628
|
+
result[:tmpl],
|
629
|
+
'Parser.parse_html should skip runo tags in a comment'
|
630
|
+
)
|
631
|
+
}
|
632
|
+
end
|
633
|
+
|
471
634
|
def test_parse_block_tag_obsolete_runo_class
|
472
635
|
result = Runo::Parser.parse_html <<'_html'
|
473
636
|
<ul class="runo-blog" id="foo"><li>hello</li></ul>
|
@@ -1260,6 +1423,35 @@ _html
|
|
1260
1423
|
)
|
1261
1424
|
end
|
1262
1425
|
|
1426
|
+
def test_action_tmpl_in_comment
|
1427
|
+
result = Runo::Parser.parse_html <<'_html'
|
1428
|
+
<ul id="foo" class="app-blog">
|
1429
|
+
<li class="model">$(text)</li>
|
1430
|
+
<!--
|
1431
|
+
<div class="navi"><span class="navi_prev">prev</span></div>
|
1432
|
+
-->
|
1433
|
+
</ul>
|
1434
|
+
_html
|
1435
|
+
assert_nil(
|
1436
|
+
result[:item]['foo'][:tmpl][:navi],
|
1437
|
+
'Parser.parse_html should skip action templates in a comment'
|
1438
|
+
)
|
1439
|
+
|
1440
|
+
result = Runo::Parser.parse_html <<'_html'
|
1441
|
+
<ul id="foo" class="app-blog">
|
1442
|
+
<li class="model">$(text)</li>
|
1443
|
+
<div class="navi"><!--<span class="navi_prev">prev</span>--></div>
|
1444
|
+
</ul>
|
1445
|
+
_html
|
1446
|
+
assert_equal(
|
1447
|
+
<<'_html',
|
1448
|
+
<div class="navi"><!--<span class="navi_prev">prev</span>--></div>
|
1449
|
+
_html
|
1450
|
+
result[:item]['foo'][:tmpl][:navi],
|
1451
|
+
'Parser.parse_html should skip action templates in a comment'
|
1452
|
+
)
|
1453
|
+
end
|
1454
|
+
|
1263
1455
|
def test_supplement_sd
|
1264
1456
|
result = Runo::Parser.parse_html <<'_html'
|
1265
1457
|
<ul id="foo" class="app-blog">
|
data/t/test_set_static.rb
CHANGED
@@ -242,6 +242,29 @@ _html
|
|
242
242
|
)
|
243
243
|
end
|
244
244
|
|
245
|
+
def test_get_tmpl_non_existing_meta
|
246
|
+
ss = Runo::Set::Static.new(:html => '')
|
247
|
+
assert_equal(
|
248
|
+
'foo @(foo-bar) foo',
|
249
|
+
ss.send(:_get_by_tmpl, {}, 'foo @(foo-bar) foo'),
|
250
|
+
'Set#_get_by_tmpl should keep @() of non-existing item as is'
|
251
|
+
)
|
252
|
+
assert_equal(
|
253
|
+
'foo foo',
|
254
|
+
ss.send(:_get_by_tmpl, {}, 'foo @(bar) foo'),
|
255
|
+
'Set#_get_by_tmpl should evaluate non-existing @()'
|
256
|
+
)
|
257
|
+
end
|
258
|
+
|
259
|
+
def test_get_tmpl_non_existing_item
|
260
|
+
ss = Runo::Set::Static.new(:html => '')
|
261
|
+
assert_equal(
|
262
|
+
'foo $(foo) foo',
|
263
|
+
ss.send(:_get_by_tmpl, {}, 'foo $(foo) foo'),
|
264
|
+
'Set#_get_by_tmpl should keep non-existing $() as is'
|
265
|
+
)
|
266
|
+
end
|
267
|
+
|
245
268
|
def test_recursive_tmpl
|
246
269
|
ss = Runo::Set::Static.new(:html => <<'_html')
|
247
270
|
<li>$()</li>
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 2
|
8
|
-
-
|
9
|
-
version: 0.2.
|
8
|
+
- 1
|
9
|
+
version: 0.2.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Akira FUNAI
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-07-
|
17
|
+
date: 2010-07-28 00:00:00 +09:00
|
18
18
|
default_executable: runo
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|