runo 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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(/.+?(?=\$|\w|<|\z)/m)
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(/(.*?)(<#{name}|<\/#{name}>|\z)/m)
217
- gen += 1 if s[2] == "<#{name}"
218
- gen -= 1 if s[2] == "</#{name}>"
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 ]*<\/#{name}>\z/, '')
234
+ contents.gsub!(/[\t ]*#{Regexp.quote(close_tag)}\z/, '')
222
235
  [contents, $&]
223
236
  end
224
237
 
@@ -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],
@@ -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">
@@ -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
- - 0
9
- version: 0.2.0
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-20 00:00:00 +09:00
17
+ date: 2010-07-28 00:00:00 +09:00
18
18
  default_executable: runo
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency