runo 0.2.0 → 0.2.1
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.
- 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
|