trac-wiki 0.1.12 → 0.2.16

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ trac-wiki-*.gem
2
+ *.swp
data/Gemfile CHANGED
@@ -1,3 +1,4 @@
1
1
  source 'https://rubygems.org/'
2
2
  gemspec
3
3
  gem 'iconv'
4
+ gem 'sanitize'
data/Gemfile.lock ADDED
@@ -0,0 +1,26 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ trac-wiki (0.2.12)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ bacon (1.2.0)
10
+ iconv (1.0.3)
11
+ mini_portile (0.5.2)
12
+ nokogiri (1.6.1)
13
+ mini_portile (~> 0.5.0)
14
+ rake (10.0.4)
15
+ sanitize (2.0.6)
16
+ nokogiri (>= 1.4.4)
17
+
18
+ PLATFORMS
19
+ ruby
20
+
21
+ DEPENDENCIES
22
+ bacon
23
+ iconv
24
+ rake
25
+ sanitize
26
+ trac-wiki!
data/lib/trac-wiki.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'trac-wiki/parser'
2
+ require 'trac-wiki/tree'
2
3
  require 'trac-wiki/version'
3
4
 
4
5
  module TracWiki
@@ -45,7 +45,7 @@ module TracWiki
45
45
  attr_accessor :allowed_schemes
46
46
 
47
47
  attr_accessor :headings
48
-
48
+ attr_writer :base
49
49
 
50
50
  # Disable url escaping for local links
51
51
  # Escaping: [[/Test]] --> %2FTest
@@ -61,6 +61,12 @@ module TracWiki
61
61
  attr_writer :math
62
62
  def math?; @math; end
63
63
 
64
+ # allow {{{! ... html ... }}}
65
+ # html will be sanitized
66
+ # {{{!\n html here \n}}}\n
67
+ attr_writer :raw_html
68
+ def raw_html?; @raw_html; end
69
+
64
70
  attr_writer :edit_heading
65
71
  def edit_heading?; @edit_heading; end
66
72
 
@@ -79,6 +85,12 @@ module TracWiki
79
85
 
80
86
  # when id_from_heading, non ascii char are transliterated to ascii
81
87
  attr_writer :id_translit
88
+
89
+ # string begins with macro
90
+ MACRO_BEG_REX = /\A\{\{ ( [\$]?\w+ | \#\w* ) /x
91
+ MACRO_BEG_INSIDE_REX = /(.*?)(?<!\{)\{\{ ( \$\w+ | \#\w* | \w+ ) /x
92
+ # find end of marcro or begin of inner macro
93
+ MACRO_END_REX = /\A(.*?) ( \}\} | \{\{ (\$\w+|\#\w*|\w+) )/mx
82
94
  def id_translit?; @id_translit; end
83
95
 
84
96
  # Create a new Parser instance.
@@ -87,9 +99,14 @@ module TracWiki
87
99
  @anames = {}
88
100
  @text = text
89
101
  @no_escape = nil
102
+ @base = ''
90
103
  options.each_pair {|k,v| send("#{k}=", v) }
104
+ @base += '/' if !@base.empty? && @base[-1] != '/'
91
105
  end
92
106
 
107
+ # th(macroname) -> template_text
108
+ attr_writer :template_handler
109
+
93
110
  @was_math = false
94
111
  def was_math?; @was_math; end
95
112
 
@@ -103,7 +120,7 @@ module TracWiki
103
120
  # parser.to_html
104
121
  # #=> "<p><strong>Hello <em>World</em></strong></p>"
105
122
  def to_html
106
- @out = ''
123
+ @tree = TracWiki::Tree.new
107
124
  @edit_heading_class = 'editheading'
108
125
  @headings = [ {level: 0, sline: 1 } ]
109
126
  @p = false
@@ -112,12 +129,13 @@ module TracWiki
112
129
  @was_math = false
113
130
  @line_no = 1
114
131
  parse_block(@text)
115
- @out
132
+ @tree.to_html
116
133
  end
117
134
 
118
135
  def make_toc_html
119
- @out = ''
136
+ @tree = TracWiki::Tree.new
120
137
  parse_block(make_toc)
138
+ @tree.to_html
121
139
  end
122
140
 
123
141
  protected
@@ -130,7 +148,7 @@ module TracWiki
130
148
  end
131
149
 
132
150
  def self.escapeHTML(string)
133
- string.gsub(/&/n, '&amp;').gsub(/\"/n, '&quot;').gsub(/>/n, '&gt;').gsub(/</n, '&lt;')
151
+ string.gsub(/&/, '&amp;').gsub(/\"/, '&quot;').gsub(/>/, '&gt;').gsub(/</, '&lt;')
134
152
  end
135
153
 
136
154
  # Escape any characters with special meaning in URLs using URL
@@ -139,16 +157,16 @@ module TracWiki
139
157
  CGI::escape(string)
140
158
  end
141
159
 
142
- def start_tag(tag, args = '', lindent = nil)
160
+ def start_tag(tag, args = {}, lindent = nil)
143
161
  lindent = @stacki.last || -1 if lindent.nil?
144
162
 
145
163
  @stack.push(tag)
146
164
  @stacki.push(lindent)
147
165
 
148
166
  if tag == 'strongem'
149
- @out << '<strong><em>'
167
+ @tree.tag_beg(:strong).tag_beg(:em)
150
168
  else
151
- @out << '<' << tag << args << '>'
169
+ @tree.tag_beg(tag, args)
152
170
  end
153
171
  end
154
172
 
@@ -156,11 +174,11 @@ module TracWiki
156
174
  tag = @stack.pop
157
175
  tagi = @stacki.pop
158
176
  if tag == 'strongem'
159
- @out << '</em></strong>'
177
+ @tree.tag_end(:em).tag_end(:strong);
160
178
  elsif tag == 'p'
161
- @out << "</p>\n"
179
+ @tree.tag_end(:p)
162
180
  else
163
- @out << "</#{tag}>"
181
+ @tree.tag_end(tag)
164
182
  end
165
183
  end
166
184
 
@@ -169,7 +187,7 @@ module TracWiki
169
187
  if @stack.last == tag
170
188
  end_tag
171
189
  else
172
- @out << escape_html(match)
190
+ @tree.add(match)
173
191
  end
174
192
  else
175
193
  start_tag(tag)
@@ -183,7 +201,8 @@ module TracWiki
183
201
 
184
202
  def start_paragraph
185
203
  if @p
186
- @out << ' ' if @out[-1] != ?\s
204
+ #FIXME: multiple space s
205
+ @tree.add_spc
187
206
  else
188
207
  end_paragraph
189
208
  start_tag('p')
@@ -210,10 +229,10 @@ module TracWiki
210
229
  # make_local_link("LocalLink") #=> "/LocalLink"
211
230
  # make_local_link("Wikipedia:Bread") #=> "http://en.wikipedia.org/wiki/Bread"
212
231
  def make_local_link(link) #:doc:
213
- return link if no_escape?
232
+ return "#{@base}#{link}" if no_escape?
214
233
  link, anch = link.split(/#/, 2)
215
- return escape_url(link) if ! anch
216
- "#{escape_url(link)}##{escape_url(anch)}"
234
+ return "#{@base}#{escape_url(link)}" if ! anch
235
+ "#{@base}#{escape_url(link)}##{escape_url(anch)}"
217
236
  end
218
237
 
219
238
  # Sanatize a direct url (e.g. http://wikipedia.org/). The default
@@ -252,13 +271,14 @@ module TracWiki
252
271
  # markup, for example to add html additional attributes or
253
272
  # to put divs around the imgs.
254
273
  def make_image(uri, attrs='')
255
- "<img src=\"#{make_explicit_link(uri)}\"#{make_image_attrs(attrs)}/>"
274
+ #"<img src=\"#{make_explicit_link(uri)}\"#{make_image_attrs(attrs)}/>"
275
+ @tree.tag(:img, make_image_attrs(uri, attrs))
256
276
  end
257
277
 
258
- def make_image_attrs(attrs)
259
- return '' if ! attrs
260
- a = {}
278
+ def make_image_attrs(uri, attrs)
279
+ a = {src: make_explicit_link(uri)}
261
280
  style = []
281
+ attrs ||= ''
262
282
  attrs.strip.split(/\s*,\s*/).each do |opt|
263
283
  case opt
264
284
  when /^\d+[^\d]*$/
@@ -277,28 +297,25 @@ module TracWiki
277
297
  style.push($1 + ':' + escape_url($3))
278
298
  end
279
299
  end
280
- a['style'] = style.join(';') if ! style.empty?
281
- return '' if a.empty?
282
- return ' ' + a.map{|k,v| "#{k}=\"#{v}\"" }.sort.join(' ')
300
+ a[:style] = style.join(';') if ! style.empty?
301
+ return {} if a.empty?
302
+ return a;
283
303
  end
284
304
 
285
305
  def make_headline(level, text, aname)
286
- ret = "<h#{level}"
287
- if aname
288
- ret += " id=\"#{ escape_html(aname) }\""
289
- end
290
- ret += ">" + escape_html(text)
291
306
 
307
+ hN = "h#{level}".to_sym
308
+
309
+ @tree.tag_beg(hN, { id: aname } )
310
+ parse_inline(text)
292
311
  if edit_heading?
293
- ret += edit_heading_link(@headings.size - 1)
312
+ edit_heading_link(@headings.size - 1)
294
313
  end
295
-
296
- ret += "</h#{level}>"
297
- ret
314
+ @tree.tag_end(hN)
298
315
  end
299
316
 
300
317
  def edit_heading_link(section)
301
- "<a class='#{@edit_heading_class}' href=\"?edit=#{section}\">edit</a>"
318
+ @tree.tag(:a, { class: @edit_heading_class, href: "?edit=#{section}"}, "edit")
302
319
  end
303
320
 
304
321
  def make_explicit_link(link)
@@ -329,18 +346,18 @@ module TracWiki
329
346
  when /\A(!)?((https?|ftps?):\/\/\S+?)(?=([\]\,.?!:;"'\)]+)?(\s|$))/
330
347
  str = $'
331
348
  if $1
332
- @out << escape_html($2)
349
+ @tree.add($2)
333
350
  else
334
351
  if uri = make_direct_link($2)
335
- @out << '<a href="' << escape_html(uri) << '">' << escape_html($2) << '</a>'
352
+ @tree.tag(:a, {href:uri}, $2)
336
353
  else
337
- @out << escape_html($&)
354
+ @tree.add($&)
338
355
  end
339
356
  end
340
357
  # [[Image(pic.jpg|tag)]]
341
358
  when /\A\[\[Image\(([^,]*?)(,(.*?))?\)\]\]/ # image
342
359
  str = $'
343
- @out << make_image($1, $3)
360
+ make_image($1, $3)
344
361
  # [[link]]
345
362
  # [ link1 | text2 ]
346
363
  when /\A \[ \s* ([^\[|]*?) \s* (\|\s*(.*?))? \s* \] /mx
@@ -361,58 +378,55 @@ module TracWiki
361
378
  def make_link(link, content, whole)
362
379
  # specail "link" [[BR]]:
363
380
  if link =~ /^br$/i
364
- @out << '<br/>'
381
+ @tree.tag(:br)
365
382
  return
366
383
  end
367
384
  uri = make_explicit_link(link)
368
385
  if not uri
369
- @out << escape_html(whole)
386
+ @tree.add(whole)
370
387
  return
371
388
  end
372
389
 
373
390
  if no_link?
374
391
  if uri !~ /^(ftp|https?):/
375
- @out << escape_html(whole)
392
+ @tree.add(whole)
376
393
  return
377
394
  end
378
395
  end
379
396
 
380
- @out << '<a href="' << escape_html(uri) << '">'
397
+ @tree.tag_beg(:a, {href:uri})
381
398
  if content
382
399
  until content.empty?
383
400
  content = parse_inline_tag(content)
384
401
  end
385
402
  else
386
- @out << escape_html(link)
403
+ @tree.add(link)
387
404
  end
388
- @out << '</a>'
405
+ @tree.tag_end(:a)
389
406
  end
390
407
 
391
408
  def parse_inline_tag(str)
392
409
  case
393
410
  when str =~ /\A\{\{\{(.*?\}*)\}\}\}/ # inline pre (tt)
394
- @out << '<tt>' << escape_html($1) << '</tt>'
411
+ @tree.tag(:tt, $1)
412
+ when str =~ MACRO_BEG_REX # macro {{
413
+ str, lines = parse_macro($1, $')
414
+ #print "MACRO.inline(#{$1})"
415
+ return str
395
416
  when str =~ /\A`(.*?)`/ # inline pre (tt)
396
- @out << '<tt>' << escape_html($1) << '</tt>'
397
-
417
+ @tree.tag(:tt, $1)
398
418
  when math? && str =~ /\A\$(.+?)\$/ # inline math (tt)
399
- @out << '\( ' << escape_html($1) << ' \)'
419
+ @tree.add("\\( #{$1} \\)")
420
+ #@tree.add("$#{$1}$")
421
+ #@tree.tag(:span, {class:'math'}, $1)
400
422
  @was_math = true
401
-
402
- # when /\A\[\[Image\(([^|].*?)(\|(.*?))?\)\]\]/ # image
403
- # @out << make_image($1, $3)
404
-
405
- # when /\A\{\{\s*(.*?)\s*(\|\s*(.*?)\s*)?\}\}/
406
- # if uri = make_image_link($1)
407
- # @out << make_image(uri, $3)
408
- # else
409
- # @out << escape_html($&)
410
- # end # link
411
-
423
+ when str =~ /\A(\&\w*;)/ # html entity
424
+ print "add html ent: #{$1}\n"
425
+ @tree.add_raw($1)
412
426
  when str =~ /\A([:alpha:]|[:digit:])+/
413
- @out << $& # word
427
+ @tree.add($&) # word
414
428
  when str =~ /\A\s+/
415
- @out << ' ' if @out[-1] != ?\s # spaces
429
+ @tree.add_spc
416
430
  when str =~ /\A'''''/
417
431
  toggle_tag 'strongem', $& # bolditallic
418
432
  when str =~ /\A\*\*/ || str =~ /\A'''/
@@ -420,25 +434,122 @@ module TracWiki
420
434
  when str =~ /\A''/ || str =~ /\A\/\//
421
435
  toggle_tag 'em', $& # italic
422
436
  when str =~ /\A\\\\/ || str =~ /\A\[\[br\]\]/i
423
- @out << '<br/>' # newline
437
+ @tree.tag(:br) # newline
424
438
  when str =~ /\A__/
425
439
  toggle_tag 'u', $& # underline
426
440
  when str =~ /\A~~/
427
441
  toggle_tag 'del', $& # delete
442
+ when str =~ /\A~/
443
+ @tree.add_raw('&nbsp;') # tilde
428
444
  # when /\A\+\+/
429
445
  # toggle_tag 'ins', $& # insert
430
446
  when str =~ /\A\^/
431
447
  toggle_tag 'sup', $& # ^{}
432
448
  when str =~ /\A,,/
433
449
  toggle_tag 'sub', $& # _{}
434
- when str =~ /\A!([^\s])/
435
- @out << escape_html($1) # !neco
450
+ when str =~ /\A!(\{\{|[^\s])/
451
+ @tree.add($1) # !neco !{{
436
452
  when str =~ /./
437
- @out << escape_html($&) # ordinal char
453
+ @tree.add($&) # ordinal char
438
454
  end
439
455
  return $'
440
456
  end
441
457
 
458
+ # r: expanded macro + rest of str, count lines taken from str
459
+ # sideefect: parse result of macro
460
+ def parse_macro(macro_name, str)
461
+ begin
462
+ mac_out, rest, lines = parse_macro_arg(macro_name, str, {})
463
+ #parse_inline(mac)
464
+ #@tree.add(mac)
465
+ #print "MACOUT:'#{mac_out}'\n"
466
+ return mac_out + rest, lines
467
+ rescue Exception => a
468
+ return "TOO_LONG_EXPANSION_OF_MACRO(#{macro_name})QUIT"
469
+ end
470
+ end
471
+
472
+ # read to args to }} (while balancing {{ and }})
473
+ # ret: (arg, rest, lines)
474
+ # mac_out -- string to }} (macros inside expanded)
475
+ # rest -- str aftrer }}
476
+ # lines -- howmany \n eaten from str (from begining to }})
477
+ def parse_macro_arg(macro_name, str, env)
478
+
479
+ lines = 0
480
+ arg = ''
481
+ # FIXME: MACRO_REX
482
+ # prefix }}... {{macro_name
483
+ while str =~ MACRO_END_REX
484
+ prefix, bracket, sub_macro_name, str = $1, $2, $3, $'
485
+ arg << prefix
486
+ lines += prefix.count("\n")
487
+ if bracket == '}}'
488
+ #print "prefix: #{prefix}\n"
489
+ env = do_macro_arg_to_env(arg, env[:depth])
490
+ return do_macro(macro_name, env), str, lines
491
+ end
492
+
493
+ # we need to go deeper!
494
+ mac_out, str, l = parse_macro_arg(sub_macro_name, str, env)
495
+ arg << mac_out
496
+ lines += l
497
+ end
498
+ raise "Error parsing macro near '#{str}' (arg:#{arg}, lines=#{lines})"
499
+ end
500
+
501
+ # expand macro `macro_name` with `args`
502
+ # afer expansion all {{macros}} will be expanded recursively
503
+ # r: expanded string
504
+ def do_macro(macro_name, env)
505
+ return "!{{toc}}" if macro_name == 'toc'
506
+ return env[:arg].strip if macro_name == '#echo'
507
+ return '' if macro_name == '#'
508
+
509
+ return do_macro_var(macro_name, env) if macro_name =~ /^\$/
510
+
511
+
512
+ if ! @template_handler.nil?
513
+ text = @template_handler.call(macro_name, env)
514
+ if !text.nil?
515
+ #print "dep:#{env[:depth]}(#{macro_name}, #{text})\n"
516
+ if env[:depth] > 32
517
+ return "TOO_DEEP_RECURSION(`#{text}`)\n"
518
+ #return "TOO_DEEP_RECURSION"
519
+ end
520
+ # FIXME: melo by nahlasit jestli to chce expandovat | wiki expadnovat |raw html
521
+ #print "temp(#{macro_name}) --> : #{text}\n"
522
+ text = do_macro_expand_result(text, env)
523
+ #print "af expand:#{text}\n"
524
+
525
+ return text
526
+ end
527
+ end
528
+ "UMACRO(#{macro_name}#{env[:arg]})"
529
+ end
530
+
531
+ def do_macro_var(macro_name, env)
532
+ "VAR(#{macro_name})"
533
+ end
534
+
535
+ def do_macro_arg_to_env(arg, depth)
536
+ { arg: arg , depth: (depth||0) + 1 }
537
+ end
538
+
539
+ # template expand
540
+ def do_macro_expand_result(text, env)
541
+ ret = ''
542
+ while text =~ MACRO_BEG_INSIDE_REX
543
+ prefix, macro_name2, text = $1, $2, $'
544
+ ret << prefix
545
+ mac_out, text, lines = parse_macro_arg(macro_name2, text, env)
546
+ ret << mac_out
547
+ raise "Too long macro expadion" if ret.size > 1_000_000
548
+ end
549
+ return ret + text
550
+ end
551
+
552
+
442
553
  def parse_table_row(str)
443
554
  start_tag('tr') if !@stack.include?('tr')
444
555
  colspan = 1
@@ -457,17 +568,17 @@ module TracWiki
457
568
  next
458
569
  end
459
570
 
460
- style = ''
571
+ style = nil
461
572
  if txt =~ /\S(\s*)$/
462
573
  ri = $1.size
463
574
  ri += 100 if tail.empty? # do not right when last || omnited
464
- style = " style='text-align:right'" if ri == 0 && le >= 1
465
- style = " style='text-align:center'" if le >= 2 && ri >= 2
575
+ style = 'text-align:right' if ri == 0 && le >= 1
576
+ style = 'text-align:center' if le >= 2 && ri >= 2
466
577
  #print "le#{le} ri#{ri} st:#{style}\n"
467
578
  end
468
579
 
469
- colspan_txt = colspan > 1 ? " colspan='#{colspan}'" : ''
470
- start_tag(tdth, style + colspan_txt);
580
+ colspan = colspan > 1 ? colspan : nil;
581
+ start_tag(tdth, { style:style, colspan: colspan});
471
582
  colspan = 1
472
583
 
473
584
  parse_inline(txt.strip) if txt
@@ -510,14 +621,15 @@ module TracWiki
510
621
  if @stacki.empty? || @stacki.last < spc_size
511
622
  bullet.gsub!(/\.$/,'')
512
623
  ulol = bullet =~ /[-*]/ ? 'ul' : 'ol';
513
- attr = ""
514
- attr = " type='i'" if bullet =~ /i/i;
515
- attr = " type='a'" if bullet =~ /a/i;
516
624
 
517
- if bullet =~ /^\d+$/ && bullet != '1'
518
- attr += " start='#{bullet}'"
519
- end
520
- start_tag(ulol, attr, spc_size)
625
+ type = nil
626
+ type = 'i' if bullet =~ /i/i;
627
+ type = 'a' if bullet =~ /a/i;
628
+
629
+ start = nil
630
+ start = bullet if bullet =~ /^\d+$/ && bullet != '1'
631
+
632
+ start_tag(ulol, {type: type, start: start}, spc_size)
521
633
  end
522
634
 
523
635
  start_tag('li')
@@ -528,7 +640,7 @@ module TracWiki
528
640
  def blockquote_level_to(level)
529
641
  cur_level = @stack.count('blockquote')
530
642
  if cur_level == level
531
- @out << ' '
643
+ @tree.add(' ')
532
644
  return
533
645
  end
534
646
  while cur_level < level
@@ -541,100 +653,132 @@ module TracWiki
541
653
  end
542
654
  end
543
655
 
656
+ def do_math(text)
657
+ end_paragraph
658
+ @tree.add("$$#{text}$$\n")
659
+ @was_math = true
660
+ end
661
+ def do_merge(merge_type, who)
662
+ merge_class = case merge_type[0]
663
+ when '<' ; 'merge-mine'
664
+ when '=' ; 'merge-split'
665
+ when '|' ; 'merge-orig'
666
+ when '>' ; 'merge-your'
667
+ end
668
+ end_paragraph
669
+ @tree.tag(:div, { class: "merge #{merge_class}" }, who)
670
+ end
671
+ def do_pre(text)
672
+ end_paragraph
673
+ nowikiblock = make_nowikiblock(text)
674
+ @tree.tag(:pre, nowikiblock)
675
+ end
676
+
677
+ def do_raw_html(text)
678
+ end_paragraph
679
+ @tree.add_raw(text)
680
+ end
681
+
682
+ def do_hr
683
+ end_paragraph
684
+ @tree.tag(:hr)
685
+ end
686
+
687
+ def do_heading(level, title, aname)
688
+ aname= aname_nice(aname, title)
689
+ @headings.last[:eline] = @line_no - 1
690
+ @headings.push({ :title => title, :sline => @line_no, :aname => aname, :level => level, })
691
+ end_paragraph
692
+ make_headline(level, title, aname)
693
+ end
694
+ def do_table_row(text)
695
+ if !@stack.include?('table')
696
+ end_paragraph
697
+ start_tag('table')
698
+ end
699
+ parse_table_row(text)
700
+ end
701
+ def do_term(term)
702
+ start_tag('dl')
703
+ start_tag('dt')
704
+ @tree.add(term)
705
+ end_tag
706
+ start_tag('dd')
707
+ end
708
+
709
+ def do_citation(level, quote)
710
+ start_paragraph if !@stack.include? 'p'
711
+ blockquote_level_to(level)
712
+ parse_inline(quote.strip)
713
+ end
714
+
715
+ def do_ord_line(spc_size, text)
716
+ text.rstrip!
717
+
718
+ if @stack.include?('li') || @stack.include?('dl')
719
+
720
+ # dl, li continuation
721
+ parse_inline(' ')
722
+ parse_inline(text)
723
+
724
+ elsif spc_size > 0
725
+ # quote continuation
726
+ start_paragraph if !@stack.include? 'p'
727
+ blockquote_level_to(1)
728
+ parse_inline(text)
729
+
730
+ else
731
+ # real ordinary line
732
+ start_paragraph
733
+ parse_inline(text)
734
+ end
735
+ end
736
+
544
737
  def parse_block(str)
738
+ #print "BLOCK.str(#{str})\n"
545
739
  until str.empty?
546
740
  case
547
- # pre {{{ ... }}}
741
+ # macro
742
+ when str =~ MACRO_BEG_REX
743
+ str, lines = parse_macro($1, $')
744
+ #print "MACRO.block(#{$1})\n"
745
+ next
746
+ # display math $$
548
747
  when math? && str =~ /\A\$\$(.*?)\$\$/m
549
- end_paragraph
550
- nowikiblock = make_nowikiblock($1)
551
- @out << "$$" << escape_html(nowikiblock) << "$$\n"
552
- @was_math = true
748
+ do_math($1)
749
+ # merge
553
750
  when merge? && str =~ /\A(<{7}|={7}|>{7}|\|{7}) *(\S*).*$(\r?\n)?/
554
- who = $2
555
- merge_class = case $1[0]
556
- when '<' ; 'merge-mine'
557
- when '=' ; 'merge-split'
558
- when '|' ; 'merge-orig'
559
- when '>' ; 'merge-your'
560
- end
561
- end_paragraph
562
- @out << "<div class='merge #{merge_class}'>" << escape_html(who) << "</div>\n"
751
+ do_merge($1, $2)
752
+ # raw_html {{{! ... }}}
753
+ when raw_html? && str =~ /\A\{\{\{!\r?\n(.*?)\r?\n\}\}\}/m
754
+ do_raw_html($1)
755
+ # pre {{{ ... }}}
563
756
  when str =~ /\A\{\{\{\r?\n(.*?)\r?\n\}\}\}/m
564
- end_paragraph
565
- nowikiblock = make_nowikiblock($1)
566
- @out << '<pre>' << escape_html(nowikiblock) << '</pre>'
567
-
757
+ do_pre($1)
568
758
  # horizontal rule
569
759
  when str =~ /\A\s*-{4,}\s*$/
570
- end_paragraph
571
- @out << '<hr/>'
572
-
760
+ do_hr()
573
761
  # heading == Wiki Ruless ==
574
762
  # heading == Wiki Ruless == #tag
575
763
  when str =~ /\A[[:blank:]]*(={1,6})\s*(.*?)\s*=*\s*(#(\S*))?\s*$(\r?\n)?/
576
- level = $1.size
577
- title= $2
578
- aname= aname_nice($4, title)
579
- @headings.last[:eline] = @line_no - 1
580
- @headings.push({ :title => title, :sline => @line_no, :aname => aname, :level => level, })
581
- end_paragraph
582
- @out << make_headline(level, title, aname)
583
-
584
- # table row
764
+ do_heading($1.size, $2, $4)
765
+ # table row ||
585
766
  when str =~ /\A[ \t]*\|\|(.*)$(\r?\n)?/
586
- if !@stack.include?('table')
587
- end_paragraph
588
- start_tag('table')
589
- end
590
- parse_table_row($1)
591
-
767
+ do_table_row($1)
592
768
  # empty line
593
769
  when str =~ /\A\s*$(\r?\n)?/
594
770
  end_paragraph
595
771
  when str =~ /\A([:\w\s]+)::(\s+|\r?\n)/
596
- term = $1
597
- start_tag('dl')
598
- start_tag('dt')
599
- @out << escape_html(term)
600
- end_tag
601
- start_tag('dd')
602
-
772
+ do_term($1)
603
773
  # li
604
774
  when str =~ /\A(\s*)([*-]|[aAIi\d]\.)\s+(.*?)$(\r?\n)?/
605
775
  parse_li_line($1.size, $2, $3)
606
-
776
+ # citation
607
777
  when str =~ /\A(>[>\s]*)(.*?)$(\r?\n)?/
608
- # citation
609
- level, quote = $1.count('>'), $2
610
-
611
- start_paragraph if !@stack.include? 'p'
612
- blockquote_level_to(level)
613
- parse_inline(quote.strip)
614
-
615
-
778
+ do_citation($1.count('>'), $2)
616
779
  # ordinary line
617
780
  when str =~ /\A(\s*)(\S+.*?)$(\r?\n)?/
618
- spc_size, text = $1.size, $2
619
- text.rstrip!
620
-
621
- if @stack.include?('li') ||@stack.include?('dl')
622
-
623
- # dl, li continuation
624
- parse_inline(' ')
625
- parse_inline(text)
626
-
627
- elsif spc_size > 0
628
- # quote continuation
629
- start_paragraph if !@stack.include? 'p'
630
- blockquote_level_to(1)
631
- parse_inline(text)
632
-
633
- else
634
- # real ordinary line
635
- start_paragraph
636
- parse_inline(text)
637
- end
781
+ do_ord_line($1.size, $2)
638
782
  else # case str
639
783
  raise "Parse error at #{str[0,30].inspect}"
640
784
  end
@@ -643,7 +787,6 @@ module TracWiki
643
787
  end
644
788
  end_paragraph
645
789
  @headings.last[:eline] = @line_no - 1
646
- @out
647
790
  end
648
791
 
649
792
  def aname_nice(aname, title)
@@ -664,8 +807,5 @@ module TracWiki
664
807
  @anames[aname] = true
665
808
  aname
666
809
  end
667
-
668
-
669
-
670
810
  end
671
811
  end
@@ -0,0 +1,162 @@
1
+ require 'pp'
2
+ require 'sanitize'
3
+ module TracWiki
4
+
5
+ class RawHtml
6
+ def initialize(text)
7
+ @text = text
8
+ end
9
+ def to_s
10
+ @text
11
+ end
12
+ end
13
+
14
+ class Node
15
+ attr_accessor :tag
16
+ attr_accessor :par
17
+ attr_accessor :cont
18
+ attr_accessor :attrs
19
+ def initialize(tag_name, par=nil, attrs={}, cont=[])
20
+ @tag = nil
21
+ @tag = tag_name.to_sym if tag_name
22
+ @par = par
23
+ cont = [ cont ] if cont.is_a? String
24
+ @cont = cont || []
25
+ @attrs = attrs || {}
26
+ end
27
+
28
+ def add(cont)
29
+ @cont << cont
30
+ end
31
+ end
32
+ class Tree
33
+
34
+ def initialize
35
+ @root = Node.new(nil)
36
+ @cur = @root
37
+ end
38
+
39
+ def tag(tag, attrs = nil, cont = nil)
40
+ if cont.nil? && ! attrs.is_a?(Hash)
41
+ # tag(:b, "ahoj") -> tag(:b, {}, "ahoj")
42
+ cont = attrs
43
+ attrs = nil
44
+ end
45
+ cont = [ cont ] if cont.is_a? String
46
+ @cur.add(Node.new(tag, @cur, attrs, cont))
47
+ self
48
+ end
49
+
50
+ def tag_beg(tag_name, attrs = nil, cont = nil)
51
+ node = Node.new(tag_name, @cur, attrs, cont)
52
+ @cur.add(node)
53
+ @cur = node
54
+ self
55
+ end
56
+
57
+ def tag_end(tag_name)
58
+ if @cur.tag == tag_name.to_sym
59
+ @cur = @cur.par
60
+ else
61
+ raise "tag_end: cur tag is not <#{tag_name}>, but <#{@cur.tag}>"
62
+ end
63
+ self
64
+ end
65
+
66
+ # add space if needed
67
+ def add_spc
68
+ if @cur.cont.size > 0
69
+ last = @cur.cont.last
70
+ if last.is_a?(String) && last[-1] == ?\s
71
+ return
72
+ end
73
+ end
74
+ add(' ')
75
+ end
76
+
77
+ def add(cont)
78
+ @cur.add(cont)
79
+ self
80
+ end
81
+
82
+ def add_raw(cont)
83
+ cont_san = Sanitize.clean(cont, san_conf)
84
+ @cur.add(RawHtml.new(cont_san))
85
+ self
86
+ end
87
+
88
+
89
+ def find_par(tag_name, node = nil)
90
+ node = @cur if node.nil?
91
+ while ! node.par.nil?
92
+ if node.tag == tag_name
93
+ return node.par
94
+ end
95
+ node = node.par
96
+ end
97
+ nil
98
+ end
99
+
100
+ def to_html
101
+ tree_to_html(@root)
102
+ end
103
+
104
+ def tree_to_html(node)
105
+ tag = node.tag
106
+ if tag.nil?
107
+ return cont_to_s(node.cont)
108
+ end
109
+
110
+ nl = ""
111
+ #nl = "\n" if [:div, :h1, :h2, :h3, :h4, :h5, :p].include? tag
112
+ nl = "\n" if [:div, :p].include? tag
113
+
114
+ if node.cont.size == 0
115
+ if [:a, :td, :h1, :h2, :h3, :h4, :h5, :h6,:strong, :script].include? tag
116
+ return "<#{tag}#{attrs_to_s(node.attrs)}></#{tag}>"
117
+ end
118
+ return "<#{tag}#{attrs_to_s(node.attrs)}/>#{nl}"
119
+ end
120
+
121
+ return "<#{tag}#{attrs_to_s(node.attrs)}>#{cont_to_s(node.cont)}</#{tag}>#{nl}"
122
+ end
123
+
124
+ def cont_to_s(cont)
125
+ cont = [cont] if cont.is_a? String
126
+ cont.map do |c|
127
+ if c.is_a? Node
128
+ tree_to_html(c)
129
+ elsif c.is_a? RawHtml
130
+ c.to_s
131
+ else
132
+ TracWiki::Parser.escapeHTML(c.to_s)
133
+ end
134
+ end.join('')
135
+ end
136
+
137
+ def attrs_to_s(attrs)
138
+ return '' if attrs.nil? || attrs.size == 0
139
+ ret = ['']
140
+ attrs.each_pair do |k,v|
141
+ ret.push "#{TracWiki::Parser.escapeHTML(k.to_s)}=\"#{TracWiki::Parser.escapeHTML(v.to_s)}\"" if !v.nil?
142
+ end
143
+ return ret.sort.join(' ')
144
+ end
145
+
146
+ def san_conf
147
+ return @san_conf if @san_conf
148
+ conf = { elements: ['form', 'input'],
149
+ attributes: { 'form' => ['action', 'meth'],
150
+ 'input' => ['type', 'value'],
151
+ },
152
+ }
153
+
154
+ @san_conf = conf.merge(Sanitize::Config::RELAXED){|k,o,n| o.is_a?(Hash) ? o.merge(n) :
155
+ o.is_a?(Array) ? o + n :
156
+ n }
157
+
158
+ #pp @san_conf
159
+ @san_conf
160
+ end
161
+ end
162
+ end
@@ -1,3 +1,3 @@
1
1
  module TracWiki
2
- VERSION = '0.1.12'
2
+ VERSION = '0.2.16'
3
3
  end
data/test/parser_test.rb CHANGED
@@ -1,11 +1,30 @@
1
+ # encoding: UTF-8
1
2
  require 'trac-wiki'
2
3
  require 'pp'
3
4
 
4
5
 
5
6
  class Bacon::Context
6
7
  def tc(html, wiki, options = {})
8
+ #options[:template_handler] = proc {|tname,env| template_handler(tname, env) }
9
+ options[:template_handler] = self.method(:template_handler)
7
10
  TracWiki.render(wiki, options).should.equal html
8
11
  end
12
+
13
+ def template_handler(tname, env)
14
+ case tname
15
+ when 'test'
16
+ "{{west}}"
17
+ when 'west'
18
+ "WEST"
19
+ when 'deep'
20
+ "{{deep}}"
21
+ when 'wide'
22
+ "0123456789{{wide}}" * 10
23
+ else
24
+ nil
25
+ #"UNK_TEMPL(#{tname})"
26
+ end
27
+ end
9
28
  def h(hash, wiki, opts = {})
10
29
  parser = TracWiki.parser(wiki, opts)
11
30
  parser.to_html
@@ -58,7 +77,8 @@ describe TracWiki::Parser do
58
77
  it 'should be toc' do
59
78
  tc "<p>{{toc}}</p>\n", "{{toc}}"
60
79
  tc "<h2>ahoj</h2><p>{{toc}}</p>\n<h2>ahoj</h2>", "==ahoj==\n{{toc}}\n\n==ahoj==\n"
61
- tc "<h2>ahoj</h2><p>{{toc}}</p>\n<h2>ahoj</h2>", "==ahoj==\r\n{{toc}}\r\n\r\n==ahoj==\r\n"
80
+ #tc "{{toc}}", "{{toc}}"
81
+ #tc "<h2>ahoj</h2>{{toc}}<h2>ahoj</h2>", "==ahoj==\r\n{{toc}}\r\n\r\n==ahoj==\r\n"
62
82
  end
63
83
 
64
84
  it 'should parse bolditalic' do
@@ -70,6 +90,7 @@ describe TracWiki::Parser do
70
90
  end
71
91
  it 'should parse monospace' do
72
92
  tc "<p>This is <tt>monospace</tt>.</p>\n", "This is {{{monospace}}}."
93
+ tc "<p>This is not {{{monospace}}}.</p>\n", "This is not !{{{monospace}}}."
73
94
  tc "<p>This is <tt>mon**o**space</tt>.</p>\n", "This is {{{mon**o**space}}}."
74
95
  tc "<p>This is <tt>mon&lt;o&gt;space</tt>.</p>\n", "This is {{{mon<o>space}}}."
75
96
  tc "<p>This is <tt>mon''o''space</tt>.</p>\n", "This is {{{mon''o''space}}}."
@@ -149,6 +170,7 @@ describe TracWiki::Parser do
149
170
  tc "<h1>Heading 1</h1>", "= Heading 1 ="
150
171
  tc "<h2>Heading 2</h2>", "== Heading 2 =="
151
172
  tc "<h3>Heading 3</h3>", "=== Heading 3 ==="
173
+ tc "<h3>Heading 3\u00a0B</h3>", "=== Heading 3~B ==="
152
174
  tc "<h3 id=\"HE3\">Heading 3</h3>", "=== Heading 3 === #HE3"
153
175
  tc "<h3 id=\"Heading-3\">Heading 3</h3>", "=== Heading 3 === #Heading-3"
154
176
  tc "<h3 id=\"Heading/3\">Heading 3</h3>", "=== Heading 3 === #Heading/3"
@@ -192,6 +214,8 @@ describe TracWiki::Parser do
192
214
  it 'should parse links' do
193
215
  # Links
194
216
  tc "<p><a href=\"link\">link</a></p>\n", "[[link]]"
217
+ tc "<p><a href=\"BASE/link\">link</a></p>\n", "[[link]]", base: 'BASE'
218
+ tc "<p><a href=\"BASE/link\">link</a></p>\n", "[[link]]", base: 'BASE/'
195
219
  tc "<p><a href=\"link#link\">link#link</a></p>\n", "[[link#link]]"
196
220
  tc "<p><a href=\"#link\">#link</a></p>\n", "[[#link]]"
197
221
 
@@ -217,7 +241,7 @@ describe TracWiki::Parser do
217
241
 
218
242
  # WRNING: Parsing markup within a link is optional
219
243
  tc "<p><a href=\"Weird+Stuff\"><strong>Weird</strong> <em>Stuff</em></a></p>\n", "[[Weird Stuff|**Weird** ''Stuff'']]"
220
- #tc("<p><a href=\"http://example.org/\"><img src='image.jpg'/></a></p>\n", "[[http://example.org/|{{image.jpg}}]]")
244
+ #tc("<p><a href=\"http://example.org/\"><img src=\"image.jpg\"/></a></p>\n", "[[http://example.org/|{{image.jpg}}]]")
221
245
 
222
246
  # Inside bold
223
247
  tc "<p><strong><a href=\"link\">link</a></strong></p>\n", "**[[link]]**"
@@ -252,6 +276,7 @@ describe TracWiki::Parser do
252
276
  it 'should parse paragraphs' do
253
277
  # One or more blank lines end paragraphs.
254
278
  tc "<p>This is my text.</p>\n<p>This is more text.</p>\n", "This is\nmy text.\n\nThis is\nmore text."
279
+ tc "<p>This is my text.</p>\n<p>This is more text.</p>\n", "This is \nmy text.\n\nThis is\nmore text."
255
280
  tc "<p>This is my text.</p>\n<p>This is more text.</p>\n", "This is\nmy text.\n\n\nThis is\nmore text."
256
281
  tc "<p>This is my text.</p>\n<p>This is more text.</p>\n", "This is\nmy text.\n\n\n\nThis is\nmore text."
257
282
 
@@ -459,6 +484,7 @@ describe TracWiki::Parser do
459
484
  it 'should parse ambiguious bold and lists' do
460
485
  tc "<p><strong> bold text </strong></p>\n", "** bold text **"
461
486
  tc "<p><blockquote><strong> bold text </strong></blockquote></p>\n", " ** bold text **"
487
+ tc "<p><blockquote><strong> bold text </strong></blockquote></p>\n", " ** bold\ntext **"
462
488
  end
463
489
 
464
490
  it 'should parse nowiki' do
@@ -498,8 +524,8 @@ describe TracWiki::Parser do
498
524
  # Image tags should be escape
499
525
  tc("<p><img src=\"image.jpg\"/></p>\n", "[[Image(image.jpg)]]")
500
526
  tc("<p><img src=\"image.jpg\"/></p>\n", "[[Image(image.jpg)]]", :no_link=>true)
501
- tc("<p><img src=\"image.jpg\" alt=\"a%22tag%22\"/></p>\n", "[[Image(image.jpg,alt=a\"tag\")]]")
502
- tc("<p><img src=\"image.jpg\" alt=\"a%22tag%22\"/></p>\n", "[[Image(image.jpg,alt=a\"tag\")]]", :no_link=>true)
527
+ tc("<p><img alt=\"a%22tag%22\" src=\"image.jpg\"/></p>\n", "[[Image(image.jpg,alt=a\"tag\")]]")
528
+ tc("<p><img alt=\"a%22tag%22\" src=\"image.jpg\"/></p>\n", "[[Image(image.jpg,alt=a\"tag\")]]", :no_link=>true)
503
529
 
504
530
  # Malicious links should not be converted.
505
531
  tc("<p><a href=\"javascript%3Aalert%28%22Boo%21%22%29\">Click</a></p>\n", "[[javascript:alert(\"Boo!\")|Click]]")
@@ -510,7 +536,7 @@ describe TracWiki::Parser do
510
536
  tc "<p>// Not Italic //</p>\n", "!// Not Italic !//"
511
537
  tc "<p>* Not Bullet</p>\n", "!* Not Bullet"
512
538
  # Following char is not a blank (space or line feed)
513
- tc "<p>Hello ~ world</p>\n", "Hello ~ world\n"
539
+ tc "<p>Hello \u00a0 world</p>\n", "Hello ~ world\n"
514
540
  tc "<p>Hello ! world</p>\n", "Hello ! world\n"
515
541
  tc "<p>Hello ! world</p>\n", "Hello ! world\n"
516
542
  tc "<p>Hello ! world</p>\n", "Hello !\nworld\n"
@@ -550,19 +576,19 @@ describe TracWiki::Parser do
550
576
  tc "<table><tr><td>Hello</td><td>World!</td></tr></table>", "||Hello||World!||"
551
577
  tc "<table><tr><td>Hello</td><td>World!</td></tr></table>", "||Hello||\\\n||World!||"
552
578
  tc "<table><tr><td>He</td><td>llo</td><td>World!</td></tr></table>", "||He||llo||\\\n||World!||"
553
- tc "<table><tr><td>Hello</td><td colspan='2'>World!</td></tr></table>", "||Hello||||World!||"
554
- tc "<table><tr><td>Hello</td><td colspan='2'>kuk</td><td>World!</td></tr></table>", "||Hello||||kuk||\\\n||World!||"
555
- tc "<table><tr><td>1</td><td>2</td><td>3</td></tr><tr><td colspan='2'>1-2</td><td>3</td></tr><tr><td>1</td><td colspan='2'>2-3</td></tr><tr><td colspan='3'>1-2-3</td></tr></table>", "|| 1 || 2 || 3 ||\n|||| 1-2 || 3 ||\n|| 1 |||| 2-3 ||\n|||||| 1-2-3 ||\n"
579
+ tc "<table><tr><td>Hello</td><td colspan=\"2\">World!</td></tr></table>", "||Hello||||World!||"
580
+ tc "<table><tr><td>Hello</td><td colspan=\"2\">kuk</td><td>World!</td></tr></table>", "||Hello||||kuk||\\\n||World!||"
581
+ tc "<table><tr><td>1</td><td>2</td><td>3</td></tr><tr><td colspan=\"2\">1-2</td><td>3</td></tr><tr><td>1</td><td colspan=\"2\">2-3</td></tr><tr><td colspan=\"3\">1-2-3</td></tr></table>", "|| 1 || 2 || 3 ||\n|||| 1-2 || 3 ||\n|| 1 |||| 2-3 ||\n|||||| 1-2-3 ||\n"
556
582
 
557
- tc "<table><tr><td>table</td><td style='text-align:center'>center</td></tr></table>", "||table|| center ||"
558
- tc "<table><tr><td>table</td><td style='text-align:right'>right</td></tr></table>", "||table|| right||"
559
- tc "<table><tr><td>table</td><td style='text-align:center'>center</td><td style='text-align:right'>right</td></tr></table>", "||table|| center || right||"
583
+ tc "<table><tr><td>table</td><td style=\"text-align:center\">center</td></tr></table>", "||table|| center ||"
584
+ tc "<table><tr><td>table</td><td style=\"text-align:right\">right</td></tr></table>", "||table|| right||"
585
+ tc "<table><tr><td>table</td><td style=\"text-align:center\">center</td><td style=\"text-align:right\">right</td></tr></table>", "||table|| center || right||"
560
586
 
561
587
  tc "<table><tr><td>Hello, World!</td></tr></table>", "||Hello, World!||"
562
- tc "<table><tr><td style='text-align:right'>Hello, Right World!</td></tr></table>", "|| Hello, Right World!||"
563
- tc "<table><tr><th style='text-align:right'>Hello, Right World!</th></tr></table>", "||= Hello, Right World!=||"
564
- tc "<table><tr><td style='text-align:center'>Hello, Centered World!</td></tr></table>", "|| Hello, Centered World! ||"
565
- tc "<table><tr><th style='text-align:center'>Hello, Centered World!</th></tr></table>", "||= Hello, Centered World! =||"
588
+ tc "<table><tr><td style=\"text-align:right\">Hello, Right World!</td></tr></table>", "|| Hello, Right World!||"
589
+ tc "<table><tr><th style=\"text-align:right\">Hello, Right World!</th></tr></table>", "||= Hello, Right World!=||"
590
+ tc "<table><tr><td style=\"text-align:center\">Hello, Centered World!</td></tr></table>", "|| Hello, Centered World! ||"
591
+ tc "<table><tr><th style=\"text-align:center\">Hello, Centered World!</th></tr></table>", "||= Hello, Centered World! =||"
566
592
  # Multiple columns
567
593
  tc "<table><tr><td>c1</td><td>c2</td><td>c3</td></tr></table>", "||c1||c2||c3||"
568
594
  # Multiple rows
@@ -757,16 +783,16 @@ describe TracWiki::Parser do
757
783
 
758
784
  it 'should parse image' do
759
785
  tc("<p><img src=\"image.jpg\"/></p>\n", "[[Image(image.jpg)]]")
760
- tc("<p><img src=\"javascript%3Aimage.jpg\" alt=\"tag\"/></p>\n", "[[Image(javascript:image.jpg,alt=tag)]]")
761
- tc("<p><img src=\"image.jpg\" alt=\"tag\"/></p>\n", "[[Image(image.jpg,alt=tag)]]")
786
+ tc("<p><img alt=\"tag\" src=\"javascript%3Aimage.jpg\"/></p>\n", "[[Image(javascript:image.jpg,alt=tag)]]")
787
+ tc("<p><img alt=\"tag\" src=\"image.jpg\"/></p>\n", "[[Image(image.jpg,alt=tag)]]")
762
788
  tc("<p><img src=\"image.jpg\" width=\"120px\"/></p>\n", "[[Image(image.jpg, 120px )]]")
763
789
  tc("<p><img src=\"image.jpg\" width=\"120px\"/></p>\n", "[[Image(image.jpg, \t120px )]]")
764
- tc("<p><img src=\"image.jpg\" align=\"right\"/></p>\n", "[[Image(image.jpg, right)]]")
765
- tc("<p><img src=\"image.jpg\" align=\"right\" valign=\"top\"/></p>\n", "[[Image(image.jpg, right,top)]]")
766
- tc("<p><img src=\"image.jpg\" align=\"right\" valign=\"top\"/></p>\n", "[[Image(image.jpg, top,right)]]")
790
+ tc("<p><img align=\"right\" src=\"image.jpg\"/></p>\n", "[[Image(image.jpg, right)]]")
791
+ tc("<p><img align=\"right\" src=\"image.jpg\" valign=\"top\"/></p>\n", "[[Image(image.jpg, right,top)]]")
792
+ tc("<p><img align=\"right\" src=\"image.jpg\" valign=\"top\"/></p>\n", "[[Image(image.jpg, top,right)]]")
767
793
  tc("<p><img src=\"image.jpg\" valign=\"top\"/></p>\n", "[[Image(image.jpg, top)]]")
768
794
  tc("<p><img src=\"image.jpg\" valign=\"top\"/></p>\n", "[[Image(image.jpg, valign=top)]]")
769
- tc("<p><img src=\"image.jpg\" align=\"center\"/></p>\n", "[[Image(image.jpg, center)]]")
795
+ tc("<p><img align=\"center\" src=\"image.jpg\"/></p>\n", "[[Image(image.jpg, center)]]")
770
796
  tc("<p><img src=\"image.jpg\" valign=\"middle\"/></p>\n", "[[Image(image.jpg, middle)]]")
771
797
  tc("<p><img src=\"image.jpg\" title=\"houhouhou\"/></p>\n", "[[Image(image.jpg, title=houhouhou)]]")
772
798
  tc("<p><img src=\"image.jpg\" width=\"120px\"/></p>\n", "[[Image(image.jpg,width=120px)]]")
@@ -807,12 +833,12 @@ describe TracWiki::Parser do
807
833
  tc("<p><a href=\"a/b/c\">a/b/c</a></p>\n", "[[a/b/c]]", :no_escape => true)
808
834
  end
809
835
  it 'should support merge' do
810
- tc "<div class='merge merge-orig'>orig</div>\n", "||||||| orig", :merge => true
811
- tc "<div class='merge merge-mine'>mine</div>\n", "<<<<<<< mine", :merge => true
812
- tc "<div class='merge merge-your'>your</div>\n", ">>>>>>> your", :merge => true
813
- tc "<p>bhoj</p>\n<div class='merge merge-your'>your</div>\n<p>ahoj</p>\n", "bhoj\n>>>>>>> your\nahoj", :merge => true
814
- tc "<div class='merge merge-split'></div>\n<p>ahoj</p>\n", "=======\nahoj\n", :merge => true
815
- tc "<div class='merge merge-split'>split</div>\n", "======= split", :merge => true
836
+ tc "<div class=\"merge merge-orig\">orig</div>\n", "||||||| orig", :merge => true
837
+ tc "<div class=\"merge merge-mine\">mine</div>\n", "<<<<<<< mine", :merge => true
838
+ tc "<div class=\"merge merge-your\">your</div>\n", ">>>>>>> your", :merge => true
839
+ tc "<p>bhoj</p>\n<div class=\"merge merge-your\">your</div>\n<p>ahoj</p>\n", "bhoj\n>>>>>>> your\nahoj", :merge => true
840
+ tc "<div class=\"merge merge-split\"></div>\n<p>ahoj</p>\n", "=======\nahoj\n", :merge => true
841
+ tc "<div class=\"merge merge-split\">split</div>\n", "======= split", :merge => true
816
842
 
817
843
  tc "<h6></h6><p>ahoj</p>\n", "=======\nahoj\n", :merge => false
818
844
  end
@@ -853,6 +879,52 @@ kuk
853
879
 
854
880
  eos
855
881
 
882
+
883
+ it 'should support macro' do
884
+ tc "<p>ahoj</p>\n" , "{{#echo \nahoj\n}}"
885
+ tc "<h2>H2</h2>" , "{{#echo == H2 ==}}"
886
+ tc "<h2>H2</h2>" , "{{#echo =={{#echo H2}}==}}"
887
+ tc "<h3 id=\"test\">H3</h3>" , "{{#echo =={{#echo =H3=}}=={{#echo #test}}}}"
888
+
889
+ tc "<p>This is correct</p>\n" , "This is {{# NOT}} correct"
890
+ tc "<h1>h1</h1>" , "{{# comment }}\n= h1 =\n"
891
+ tc "<h1>h1</h1>" , "{{# comment }}\n\n\n= h1 =\n"
892
+ tc "<h1>h1</h1>" , "{{# comment }}\n\n\n= h1 =\n{{# Comment2}}\n"
893
+
894
+ tc "<h1>h1</h1>" , "{{# co{{HUU}}mment }}\n\n\n= h1 =\n{{# Comment2}}\n"
895
+
896
+ tc "<p>UMACRO(macr ahoj )</p>\n" , "{{macr\nahoj\n}}"
897
+ tc "<p>ahoj UMACRO(macrUMACRO(o))</p>\n" , "ahoj {{macr{{o}}}}"
898
+ tc "<p>ahoj UMACRO(macro)</p>\n" , "ahoj {{macro}}"
899
+ tc "<p>ahoj {{%macrUMACRO(o)}}</p>\n" , "ahoj {{%macr{{o}}}}"
900
+ tc "<p>ahoj UMACRO(macrUMACRO(mac <strong>o</strong>))</p>\n" , "ahoj {{macr{{mac **o**}}}}"
901
+ tc "<p>ahoj VAR($mac)</p>\n" , "ahoj {{$mac|ahoj}}"
902
+ end
903
+
904
+ it 'should do temlate' do
905
+ tc "<p>1WEST</p>\n", "1{{west}}"
906
+ tc "<p>2WEST</p>\n", "2{{test}}"
907
+
908
+ # macro errors:
909
+ tc "<p>TOO_DEEP_RECURSION(<tt>{{deep}}</tt>) 3</p>\n", "{{deep}}3"
910
+ tc "<p>TOO_LONG_EXPANSION_OF_MACRO(wide)QUIT</p>\n", "{{wide}}3"
911
+ tc "<p>UMACRO(unknown)3</p>\n", "{{unknown}}3"
912
+ end
913
+ it 'should support options' do
914
+ tc "<h3>h1<a class=\"editheading\" href=\"?edit=1\">edit</a></h3>", "=== h1 ==", edit_heading: true
915
+ end
916
+ it 'should not html' do
917
+ tc "<p>{{{! &lt;a&gt;&lt;/a&gt; }}}</p>\n", "{{{!\n<a></a>\n}}}\n"
918
+ tc '<a></a>', "{{{!\n<a></a>\n}}}\n", raw_html: true
919
+ tc '<a></a>', "{{{!\n<a></a>\n}}}\n", raw_html: true
920
+ tc "<form meth=\"POST\" action=\"http://www.example.com\"><input type=\"hidden\" value=\"VAL\"></form>",
921
+ "{{{!\n<form meth=\"POST\" action=\"http://www.example.com\"><input type=\"hidden\" value=\"VAL\"/></form>\n}}}\n", raw_html: true
922
+ tc 'alert(444);', "{{{!\n<script>alert(444);</script>\n}}}\n", raw_html: true
923
+ end
924
+ it 'should not entity' do
925
+ tc "<p>\u00a0</p>\n", "&nbsp;"
926
+ tc "<p>„text“</p>\n", "&bdquo;text&ldquo;"
927
+ end
856
928
  end
857
929
  end
858
930
  # vim: tw=0
data/test/tree_test.rb ADDED
@@ -0,0 +1,35 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'trac-wiki'
4
+ require 'pp'
5
+
6
+ class Bacon::Context
7
+ end
8
+ describe TracWiki::Parser do
9
+ it 'should work' do
10
+ t = TracWiki::Tree.new
11
+ t.tag_beg(:html)
12
+ t.tag_beg(:body, {hus:'JAN', mistr: nil})
13
+ t.tag(:div, {ahoj: "ahoj", bhoj: "BHOJ"})
14
+ t.tag(:br)
15
+ t.add("bye")
16
+ t.add_spc
17
+ t.add("bye ")
18
+ t.add_spc
19
+ t.add("bye")
20
+ t.tag_end(:body)
21
+ t.tag_end(:html)
22
+ t.add('\bye')
23
+ t.add_raw('&gt;')
24
+ t.add_raw('&nbsp;')
25
+ t.add_raw('&bdquo;')
26
+
27
+ res = "<html><body hus=\"JAN\"><div ahoj=\"ahoj\" bhoj=\"BHOJ\"/>\n<br/>bye bye bye</body></html>\\bye"
28
+ res += "&gt;"
29
+ res += "\u00a0"
30
+ res += "„"
31
+
32
+ #print "\n#{t.to_html}\n#{res}"
33
+ t.to_html.should.equal res
34
+ end
35
+ end
metadata CHANGED
@@ -1,41 +1,46 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trac-wiki
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.12
4
+ version: 0.2.16
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Vitas Stradal
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2013-10-06 00:00:00.000000000 Z
12
+ date: 2013-12-27 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: bacon
15
16
  requirement: !ruby/object:Gem::Requirement
17
+ none: false
16
18
  requirements:
17
- - - '>='
19
+ - - ! '>='
18
20
  - !ruby/object:Gem::Version
19
21
  version: '0'
20
22
  type: :development
21
23
  prerelease: false
22
24
  version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
23
26
  requirements:
24
- - - '>='
27
+ - - ! '>='
25
28
  - !ruby/object:Gem::Version
26
29
  version: '0'
27
30
  - !ruby/object:Gem::Dependency
28
31
  name: rake
29
32
  requirement: !ruby/object:Gem::Requirement
33
+ none: false
30
34
  requirements:
31
- - - '>='
35
+ - - ! '>='
32
36
  - !ruby/object:Gem::Version
33
37
  version: '0'
34
38
  type: :development
35
39
  prerelease: false
36
40
  version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
37
42
  requirements:
38
- - - '>='
43
+ - - ! '>='
39
44
  - !ruby/object:Gem::Version
40
45
  version: '0'
41
46
  description: TracWiki markup language render (http://trac.edgewall.org/wiki/WikiFormatting
@@ -48,37 +53,42 @@ extensions: []
48
53
  extra_rdoc_files:
49
54
  - README
50
55
  files:
56
+ - .gitignore
51
57
  - Gemfile
58
+ - Gemfile.lock
52
59
  - README
53
60
  - Rakefile
54
61
  - bin/trac-wiki.rb
55
62
  - lib/trac-wiki.rb
56
63
  - lib/trac-wiki/parser.rb
64
+ - lib/trac-wiki/tree.rb
57
65
  - lib/trac-wiki/version.rb
58
66
  - test/parser_test.rb
67
+ - test/tree_test.rb
59
68
  - trac-wiki.gemspec
60
69
  homepage: http://github.com/vitstradal/trac-wiki
61
70
  licenses:
62
71
  - GPL-2
63
- metadata: {}
64
72
  post_install_message:
65
73
  rdoc_options: []
66
74
  require_paths:
67
75
  - lib
68
76
  required_ruby_version: !ruby/object:Gem::Requirement
77
+ none: false
69
78
  requirements:
70
- - - '>='
79
+ - - ! '>='
71
80
  - !ruby/object:Gem::Version
72
81
  version: '0'
73
82
  required_rubygems_version: !ruby/object:Gem::Requirement
83
+ none: false
74
84
  requirements:
75
- - - '>='
85
+ - - ! '>='
76
86
  - !ruby/object:Gem::Version
77
87
  version: '0'
78
88
  requirements: []
79
89
  rubyforge_project: trac-wiki
80
- rubygems_version: 2.0.3
90
+ rubygems_version: 1.8.23
81
91
  signing_key:
82
- specification_version: 4
92
+ specification_version: 3
83
93
  summary: Trac Wiki markup language
84
94
  test_files: []
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA1:
3
- metadata.gz: 5c3c0e79552d6d60ecbb77c54fbaa434d208ca56
4
- data.tar.gz: dd2e9ab2b74410c6b3abf6265d43185fcaec19cd
5
- SHA512:
6
- metadata.gz: c173fe3e96fdceaa1e587c2a41e75e50fa731bfb3403270463d3352014e8223dd459ba7df0e5ea9d6377be54d701d19ec3a00dfb3b259583cd70325ab9d5bc15
7
- data.tar.gz: b7c6a4d413d44ea1bb30d9e49454420a5ecd639601ea79ef19f80a73e1831c1165bac4d94b9da75757d5ca440fc301ff5a062554329293f8bb5821e41a296e0f