trac-wiki 0.2.20 → 0.2.21

Sign up to get free protection for your applications and to get access to all the features.
@@ -65,9 +65,8 @@ module TracWiki
65
65
  attr_writer :math
66
66
  def math?; @math; end
67
67
 
68
- # allow {{{! ... html ... }}}
68
+ # allow some <b> <form> <html>
69
69
  # html will be sanitized
70
- # {{{!\n html here \n}}}\n
71
70
  attr_writer :raw_html
72
71
  def raw_html?; @raw_html; end
73
72
 
@@ -120,7 +119,7 @@ module TracWiki
120
119
  '!set' => proc { |env| env[env.expand_arg(0)] = env.expand_arg(1); '' },
121
120
  '!yset' => proc { |env| env[env.expand_arg(0)] = YAML.load(env.arg(1)); '' },
122
121
 
123
- '!html' => proc { |env| "\n{{{!\n#{env.arg(0)}\n}}}\n" },
122
+ # '!html' => proc { |env| "\n{{{!\n#{env.arg(0)}\n}}}\n" },
124
123
  '!sub' => proc { |env| pat = env.expand_arg(1)
125
124
  pat = Regexp.new(pat[1..-2]) if pat =~ /\A\/.*\/\Z/
126
125
  env.expand_arg(0).gsub(pat, env.expand_arg(2))
@@ -461,8 +460,9 @@ module TracWiki
461
460
 
462
461
  def parse_inline_tag(str)
463
462
  case
464
- when raw_html? && str =~ /\A\{\{\{!(.*?\}*)\}\}\}/ # inline {{{! raw html }}}
465
- do_raw_html($1, true)
463
+ when raw_html? && str =~ /\A<(\/)?(\w+)(?:([^>]*?))?(\/\s*)?>/ # single inline <html> tag
464
+ eot, tag, args, closed = $1, $2, $3, $4
465
+ do_raw_tag(eot, tag, args, closed, $'.size)
466
466
  when str =~ /\A\{\{\{(.*?\}*)\}\}\}/ # inline {{{ }}} pre (tt)
467
467
  @tree.tag(:tt, $1)
468
468
  when str =~ MACRO_BEG_REX # macro {{
@@ -658,9 +658,32 @@ module TracWiki
658
658
  @tree.tag(:pre, nowikiblock)
659
659
  end
660
660
 
661
- def do_raw_html(text, inline=false)
662
- end_paragraph if !inline
663
- @tree.add_raw(text)
661
+ def do_raw_tag(eot, tag, attrs, closed, tail_size)
662
+ if !eot
663
+ end_paragraph if tag == 'p' || tag == 'div'
664
+ #print "open tag #{tag},'#{attrs}'\n"
665
+ attrs_h = _parse_attrs_to_hash(attrs)
666
+ @tree.tag_beg(tag, attrs_h)
667
+ @tree.tag_end(tag) if closed
668
+ else
669
+ #print "close tag #{tag}\n"
670
+ @tree.tag_end(tag)
671
+ if tag == 'p' || tag == 'div'
672
+ end_paragraph
673
+ start_paragraph if tail_size > 0
674
+ end
675
+ end
676
+ end
677
+
678
+ def _parse_attrs_to_hash(str)
679
+ ret = {}
680
+ while str =~ /\A\s*(\w+)\s*=\s*'([^>']*)'/ ||
681
+ str =~ /\A\s*(\w+)\s*=\s*"([^>"]*)"/ ||
682
+ str =~ /\A\s*(\w+)\s*=\s*(\S*)/
683
+ ret[$1] = $2
684
+ str = $'
685
+ end
686
+ ret
664
687
  end
665
688
 
666
689
  def do_hr
@@ -734,9 +757,6 @@ module TracWiki
734
757
  # merge
735
758
  when merge? && str =~ /\A(<{7}|={7}|>{7}|\|{7}) *(\S*).*$(\r?\n)?/
736
759
  do_merge($1, $2)
737
- # raw_html {{{! ... }}}
738
- when raw_html? && str =~ /\A\{\{\{!\r?\n(.*?)\r?\n\}\}\}/m
739
- do_raw_html($1)
740
760
  # pre {{{ ... }}}
741
761
  when str =~ /\A\{\{\{\r?\n(.*?)\r?\n\}\}\}/m
742
762
  do_pre($1)
@@ -55,12 +55,24 @@ module TracWiki
55
55
  end
56
56
 
57
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}>"
58
+ c = @cur
59
+ ts = tag_name.to_sym
60
+ while c.tag != ts
61
+ c = c.par
62
+ if c.nil?
63
+ return "no such tag in stack, ingoring "
64
+ end
62
65
  end
66
+ @cur = c.par
63
67
  self
68
+
69
+ # if @cur.tag == tag_name.to_sym
70
+ # @cur = @cur.par
71
+ # else
72
+ # #pp(@root)
73
+ # raise "tag_end: cur tag is not <#{tag_name}>, but <#{@cur.tag}>"
74
+ # end
75
+ # self
64
76
  end
65
77
 
66
78
  # add space if needed
@@ -80,8 +92,8 @@ module TracWiki
80
92
  end
81
93
 
82
94
  def add_raw(cont)
83
- cont_san = Sanitize.clean(cont, san_conf)
84
- @cur.add(RawHtml.new(cont_san))
95
+ #cont_san = Sanitize.clean(cont, san_conf)
96
+ @cur.add(RawHtml.new(cont))
85
97
  self
86
98
  end
87
99
 
@@ -98,27 +110,80 @@ module TracWiki
98
110
  end
99
111
 
100
112
  def to_html
101
- tree_to_html(@root)
113
+ ret = tree_to_html(@root)
114
+ #print "bf san:", ret, "\n"
115
+ #ret = Sanitize.clean(ret, san_conf)
116
+ #print "af san:", ret, "\n"
117
+ #ret + "\n"
118
+ ret
102
119
  end
103
-
104
120
  def tree_to_html(node)
105
121
  tag = node.tag
106
122
  if tag.nil?
107
123
  return cont_to_s(node.cont)
108
124
  end
109
125
 
110
- nl = ""
111
- #nl = "\n" if [:div, :h1, :h2, :h3, :h4, :h5, :p].include? tag
112
- nl = "\n" if [:div, :p].include? tag
126
+ nl = ''
127
+ nl = "\n" if TAGS_APPEND_NL.include? tag
113
128
 
129
+ if ! TAGS_ALLOVED.include? tag
130
+ return '' if node.cont.size == 0
131
+ return cont_to_s(node.cont)
132
+ end
114
133
  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}>"
134
+ if TAGS_SKIP_EMPTY.include? tag
135
+ return ''
136
+ end
137
+ if TAGS_FORCE_PAIR.include? tag
138
+ return "<#{tag}#{attrs_to_s(tag, node.attrs)}></#{tag}>#{nl}"
117
139
  end
118
- return "<#{tag}#{attrs_to_s(node.attrs)}/>#{nl}"
140
+ return "<#{tag}#{attrs_to_s(tag, node.attrs)}/>#{nl}"
119
141
  end
120
142
 
121
- return "<#{tag}#{attrs_to_s(node.attrs)}>#{cont_to_s(node.cont)}</#{tag}>#{nl}"
143
+ return "<#{tag}#{attrs_to_s(tag, node.attrs)}>#{cont_to_s(node.cont)}</#{tag}>#{nl}"
144
+ end
145
+
146
+
147
+ TAGS_APPEND_NL = [:div, :p]
148
+ TAGS_FORCE_PAIR = [:a, :td, :h1, :h2, :h3, :h4, :h5, :h6, :div, :strong, :script]
149
+ TAGS_ALLOVED = [:a,
150
+ :h1, :h2, :h3, :h4, :h5, :h6,
151
+ :div, :span, :p, :pre,
152
+ :li, :ul, :ol, :dl, :dt, :dd,
153
+ :b, :tt, :u, :del, :blockquote, :strong, :em, :sup, :sub,
154
+ :table, :tr, :td, :th,
155
+ :br , :img, :hr,
156
+ :form, :textarea, :input, :select, :option,
157
+ ]
158
+ TAGS_SKIP_EMPTY = [ :p ]
159
+ ATTRIBUTES_ALLOWED = { :form => [:action, :meth],
160
+ :input => [:size, :type, :value, :name],
161
+ :select => [:multiple, :name],
162
+ :option => [:disabled, :selected, :label, :value, :name],
163
+ :a => [:name, :href],
164
+ :img => [:src, :width, :height, :align, :valign, :style, :alt, :title],
165
+ :td => [:colspan, :rowspan, :style],
166
+ :th => [:colspan, :rowspan, :style],
167
+ :_all => [:class, :id],
168
+ }
169
+
170
+ ATTRIBUTE_STYLE_REX = /\A( text-align:(center|right|left) |
171
+ margin: \d+(px|em)? |
172
+ ;
173
+ )+\Z/x
174
+ def attrs_to_s(tag, attrs)
175
+ return '' if attrs.nil? || attrs.size == 0
176
+ ret = ['']
177
+ tag_attrs = ATTRIBUTES_ALLOWED[tag] || []
178
+ attrs.each_pair do |k,v|
179
+ next if v.nil?
180
+ k_sym = k.to_sym
181
+ next if ! ATTRIBUTES_ALLOWED[:_all].include?(k_sym) && ! tag_attrs.include?(k_sym)
182
+ next if k == :style && v !~ ATTRIBUTE_STYLE_REX
183
+ #print "style: #{v}\n" if k == :style
184
+ ret.push "#{TracWiki::Parser.escapeHTML(k.to_s)}=\"#{TracWiki::Parser.escapeHTML(v.to_s)}\""
185
+ end
186
+ return ret.sort.join(' ')
122
187
  end
123
188
 
124
189
  def cont_to_s(cont)
@@ -134,26 +199,20 @@ module TracWiki
134
199
  end.join('')
135
200
  end
136
201
 
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
202
  def san_conf
147
203
  return @san_conf if @san_conf
148
- conf = { elements: ['form', 'input', 'span', 'div'],
204
+ conf = { elements: ['tt', 'form', 'input', 'span', 'div'],
205
+ output: :xhtml,
149
206
  attributes: { 'form' => ['action', 'meth'],
150
207
  'input' => ['type', 'value'],
151
- 'span' => ['class'],
152
- 'div' => ['class'],
208
+ 'span' => ['class', 'id'],
209
+ 'div' => ['class', 'id'],
210
+ 'a' => ['class', 'id', 'name', 'href'],
211
+ :all => ['class', 'id'],
153
212
  },
154
213
  }
155
214
 
156
- @san_conf = conf.merge(Sanitize::Config::RELAXED){|k,o,n| o.is_a?(Hash) ? o.merge(n) :
215
+ @san_conf = Sanitize::Config::RELAXED.merge(conf){|k,o,n| o.is_a?(Hash) ? o.merge(n) :
157
216
  o.is_a?(Array) ? o + n :
158
217
  n }
159
218
 
@@ -1,3 +1,3 @@
1
1
  module TracWiki
2
- VERSION = '0.2.20'
2
+ VERSION = '0.2.21'
3
3
  end
data/test/parser_test.rb CHANGED
@@ -33,8 +33,6 @@ class Bacon::Context
33
33
  "{{deep}}"
34
34
  when 'wide'
35
35
  "0123456789{{wide}}" * 10
36
- when 'fortest'
37
- "{{$y.data.a}},({{!for i|y.data|AHOJ({{$i}})\n{{$y.data.$i}};\n}}),{{$y.data.a}}"
38
36
  else
39
37
  nil
40
38
  #"UNK_TEMPL(#{tname})"
@@ -185,7 +183,8 @@ describe TracWiki::Parser do
185
183
  tc "<h1>Heading 1</h1>", "= Heading 1 ="
186
184
  tc "<h2>Heading 2</h2>", "== Heading 2 =="
187
185
  tc "<h3>Heading 3</h3>", "=== Heading 3 ==="
188
- tc "<h3>Heading 3\u00a0B</h3>", "=== Heading 3~B ==="
186
+ #tc "<h3>Heading 3\u00a0B</h3>", "=== Heading 3~B ==="
187
+ tc "<h3>Heading 3&nbsp;B</h3>", "=== Heading 3~B ==="
189
188
  tc "<h3 id=\"HE3\">Heading 3</h3>", "=== Heading 3 === #HE3"
190
189
  tc "<h3 id=\"Heading-3\">Heading 3</h3>", "=== Heading 3 === #Heading-3"
191
190
  tc "<h3 id=\"Heading/3\">Heading 3</h3>", "=== Heading 3 === #Heading/3"
@@ -551,7 +550,8 @@ describe TracWiki::Parser do
551
550
  tc "<p>// Not Italic //</p>\n", "!// Not Italic !//"
552
551
  tc "<p>* Not Bullet</p>\n", "!* Not Bullet"
553
552
  # Following char is not a blank (space or line feed)
554
- tc "<p>Hello \u00a0 world</p>\n", "Hello ~ world\n"
553
+ #tc "<p>Hello \u00a0 world</p>\n", "Hello ~ world\n"
554
+ tc "<p>Hello &nbsp; world</p>\n", "Hello ~ world\n"
555
555
  tc "<p>Hello ! world</p>\n", "Hello ! world\n"
556
556
  tc "<p>Hello ! world</p>\n", "Hello ! world\n"
557
557
  tc "<p>Hello ! world</p>\n", "Hello !\nworld\n"
@@ -939,16 +939,14 @@ eos
939
939
  tc "<h3>h1<a class=\"editheading\" href=\"?edit=1\">edit</a></h3>", "=== h1 ==", edit_heading: true
940
940
  end
941
941
  it 'should not html' do
942
- #tc "<p>{{{! &lt;a&gt;&lt;/a&gt; }}}</p>\n", "{{{!\n<a></a>\n}}}\n"
943
- tc '<a></a>', "{{{!\n<a></a>\n}}}\n", raw_html: true
944
- tc '<a></a>', "{{{!\n<a></a>\n}}}\n", raw_html: true
945
- tc "<form meth=\"POST\" action=\"http://www.example.com\"><input type=\"hidden\" value=\"VAL\"></form>",
946
- "{{{!\n<form meth=\"POST\" action=\"http://www.example.com\"><input type=\"hidden\" value=\"VAL\"/></form>\n}}}\n", raw_html: true
947
- tc 'alert(444);', "{{{!\n<script>alert(444);</script>\n}}}\n", raw_html: true
942
+ tc "<p>&lt;b&gt;&lt;/b&gt;</p>\n", "<b></b>\n"
943
+ tc "<p>&lt;div&gt;&lt;script&gt;alert(666)&lt;/script&gt;&lt;/div&gt;</p>\n", "<div><script>alert(666)</script></div>\n"
948
944
  end
949
945
  it 'should entity' do
950
- tc "<p>\u00a0</p>\n", "&nbsp;"
951
- tc "<p>„text“</p>\n", "&bdquo;text&ldquo;"
946
+ #tc "<p>\u00a0</p>\n", "&nbsp;"
947
+ #tc "<p>„text“</p>\n", "&bdquo;text&ldquo;"
948
+ tc "<p>&nbsp;</p>\n", "&nbsp;"
949
+ tc "<p>&bdquo;text&ldquo;</p>\n", "&bdquo;text&ldquo;"
952
950
  end
953
951
  it 'should plugin' do
954
952
  tc "<p>AHOJTE!</p>\n", "{{!print AHOJTE}}"
@@ -979,30 +977,29 @@ eos
979
977
  tc "<p>,TRUE</p>\n", "{{!yset data|[1,2]}},{{!ifdef data.1|TRUE|FALSE}}"
980
978
  tc "<p>,TRUE</p>\n", "{{!yset data|{a: 1, b: 2} }},{{!ifdef data.a|TRUE|FALSE}}"
981
979
  tc "<p>,FALSE</p>\n", "{{!yset data|{a: 1, b: 2} }},{{!ifdef data.q|TRUE|FALSE}}"
982
- tc "<p>,1,(1;2;),1</p>\n", "{{!yset data|{a: 1, b: 2} }},{{$data.a}},({{!for i|data|{{$data.$i}};}}),{{$data.a}}"
983
- tc "<p>1,(AHOJ(a) 1; AHOJ(b) 2; ),1</p>\n", "{{fortest data:\n a: 1\n b: 2 }}"
984
- end
985
-
986
- it 'should {{!sub}}' do
987
- tc "<p>ahoj_you_one</p>\n", "{{!sub ahoj you one| |_}}"
988
- tc "<p>-h-j --- -n-</p>\n", "{{!sub ahoj you one|/[aeiouy]/|-}}"
989
- tc "<p>ahoj MATCH(you) one</p>\n", "{{!sub ahoj you one|/(y.u)/|MATCH(\\1)}}"
990
- end
991
-
992
- it 'should {{!html}}' do
993
- tc "alert(666)", "{{!html <script>alert(666)</script>}}", raw_html: true
994
- tc "<p><b>T</b>E</p>", "{{!html <p><b>T</b>E</p>}}\n", raw_html: true
995
- tc "<span>Span</span>", "{{!html <span>Span</span>}}\n", raw_html: true
996
- #tc "<span>Span</span>", "**{{!html <span>Span</span>}}**\n", raw_html: true
997
- tc "<div class=\"ahoj\">Div</div>", "{{!html <div class=\"ahoj\">Div</div>}}\n", raw_html: true
998
- tc "<span>Span</span><span>Span</span>", "{{!html <span>Span</span>}}{{!html <span>Span</span>}}\n", raw_html: true
999
- tc "<p>ahoj <span class=\"spanclass\">span</span> bhoj dhoj choj</p>\n", "ahoj {{{!<span class=\"spanclass\">span</span> bhoj}}} dhoj \nchoj\n", raw_html: true
1000
- tc "<p>ahoj Q<span class=\"spanclass\">span</span> bhojQ dhoj choj</p>\n", "ahoj Q{{{!<span class=\"spanclass\">span</span> bhoj}}}Q dhoj \nchoj\n", raw_html: true
1001
- end
1002
- # it 'last test' do
1003
- # #tc "<p>1,(AHOJ(a) 1; AHOJ(b) 2; ),1</p>\n", "{{fortest data:\n a: 1\n b: 2 }}"
1004
- #
1005
- # end
980
+ end
981
+
982
+ it 'should parse html' do
983
+ tc "<p>alert(666)</p>\n", "<script>alert(666)</script>", raw_html: true
984
+ tc "<p><b>T</b>E</p>\n", "<p><b>T</b>E</p>", raw_html: true
985
+ tc "<p><span>Span</span></p>\n", "<span>Span</span>\n", raw_html: true
986
+ tc "<p><strong><span>Span</span></strong></p>\n", "**<span>Span</span>**\n", raw_html: true
987
+ tc "<div class=\"ahoj\">Div</div>\n", "<div class=\"ahoj\">Div</div>\n", raw_html: true
988
+ tc "<p><strong>ahoj</strong></p>\n<div class=\"ahoj\">Div</div>\n", "**ahoj<div class=\"ahoj\">Div</div>\n", raw_html: true
989
+ tc "<p><span>Span</span><span>Span</span></p>\n", "<span>Span</span><span>Span</span>\n", raw_html: true
990
+ tc "<p><em><b>boldoitali</b></em>cE</p>\n", "<p>''<b>boldoitali''c</b>E</p>", raw_html: true
991
+ tc "<p><b>blabla</b></p>\n<p>endE</p>\n", "<p><b>bla</html>bla</p>end</b>E</p>", raw_html: true
992
+ tc "<p>baf</p>\n", "\n\n\nbaf\n\n\n", raw_html: true
993
+ tc "<div class=\"ahoj\">Div</div>\n<p>baf</p>\n", "<div class=\"ahoj\">Div</div>\nbaf\n", raw_html: true
994
+
995
+ tc "<p><b>BOLD</b></p>\n", "<b>BOLD</b>\n", raw_html: true
996
+ tc "<p><br/></p>\n", "<br/>\n", raw_html: true
997
+ tc "<p><br/></p>\n", "<br></br>\n", raw_html: true
998
+ tc "<p><b class=\"bclass\">BOLD</b></p>\n", "<b class=\"bclass\">BOLD</b>\n", raw_html: true
999
+ tc "<p><b class=\"bclass\">BOLD</b></p>\n", "<b bad=\"bad\" class=\"bclass\">BOLD</b>\n", raw_html: true
1000
+ tc "<p><b class=\"bclass\">BOLD</b></p>\n", "<b bad=\"bad\" class=\"bclass\">BOLD</b>\n", raw_html: true
1001
+ end
1002
+
1006
1003
  end
1007
1004
  end
1008
1005
  # vim: tw=0
data/test/tree_test.rb CHANGED
@@ -8,26 +8,28 @@ end
8
8
  describe TracWiki::Parser do
9
9
  it 'should work' do
10
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"})
11
+ t.tag_beg(:div, {:class => 'html'})
12
+ t.tag_beg(:div, {id:'JAN', class: nil})
13
+ t.tag(:div, {:class => "ahoj", id: "BHOJ"})
14
14
  t.tag(:br)
15
15
  t.add("bye")
16
16
  t.add_spc
17
17
  t.add("bye ")
18
18
  t.add_spc
19
19
  t.add("bye")
20
- t.tag_end(:body)
21
- t.tag_end(:html)
20
+ t.tag_end(:div)
21
+ t.tag_end(:div)
22
22
  t.add('\bye')
23
23
  t.add_raw('&gt;')
24
24
  t.add_raw('&nbsp;')
25
25
  t.add_raw('&bdquo;')
26
26
 
27
- res = "<html><body hus=\"JAN\"><div ahoj=\"ahoj\" bhoj=\"BHOJ\"/>\n<br/>bye bye bye</body></html>\\bye"
27
+ res = "<div class=\"html\"><div id=\"JAN\"><div class=\"ahoj\" id=\"BHOJ\"></div>\n<br/>bye bye bye</div>\n</div>\n\\bye"
28
28
  res += "&gt;"
29
- res += "\u00a0"
30
- res += "„"
29
+ #res += "\u00a0"
30
+ #res += "„"
31
+ res += '&nbsp;'
32
+ res += '&bdquo;'
31
33
 
32
34
  #print "\n#{t.to_html}\n#{res}"
33
35
  t.to_html.should.equal res
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trac-wiki
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.20
4
+ version: 0.2.21
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-01-06 00:00:00.000000000 Z
12
+ date: 2014-01-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bacon