trac-wiki 0.1.12 → 0.2.16

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