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.
@@ -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