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.
- data/lib/trac-wiki/parser.rb +31 -11
- data/lib/trac-wiki/tree.rb +87 -28
- data/lib/trac-wiki/version.rb +1 -1
- data/test/parser_test.rb +33 -36
- data/test/tree_test.rb +10 -8
- metadata +2 -2
data/lib/trac-wiki/parser.rb
CHANGED
@@ -65,9 +65,8 @@ module TracWiki
|
|
65
65
|
attr_writer :math
|
66
66
|
def math?; @math; end
|
67
67
|
|
68
|
-
# allow
|
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\
|
465
|
-
|
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
|
662
|
-
|
663
|
-
|
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)
|
data/lib/trac-wiki/tree.rb
CHANGED
@@ -55,12 +55,24 @@ module TracWiki
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def tag_end(tag_name)
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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(
|
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
|
-
|
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
|
116
|
-
|
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 =
|
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
|
|
data/lib/trac-wiki/version.rb
CHANGED
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 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 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
|
-
|
943
|
-
tc
|
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><b></b></p>\n", "<b></b>\n"
|
943
|
+
tc "<p><div><script>alert(666)</script></div></p>\n", "<div><script>alert(666)</script></div>\n"
|
948
944
|
end
|
949
945
|
it 'should entity' do
|
950
|
-
tc "<p>\u00a0</p>\n", " "
|
951
|
-
tc "<p>„text“</p>\n", "„text“"
|
946
|
+
#tc "<p>\u00a0</p>\n", " "
|
947
|
+
#tc "<p>„text“</p>\n", "„text“"
|
948
|
+
tc "<p> </p>\n", " "
|
949
|
+
tc "<p>„text“</p>\n", "„text“"
|
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
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
tc "<p>
|
988
|
-
tc "<p
|
989
|
-
tc "<
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
tc "
|
994
|
-
tc "<p
|
995
|
-
tc "<
|
996
|
-
|
997
|
-
tc "<
|
998
|
-
tc "<
|
999
|
-
tc "<p
|
1000
|
-
tc "<p
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
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(:
|
13
|
-
t.tag(:div, {
|
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(:
|
21
|
-
t.tag_end(:
|
20
|
+
t.tag_end(:div)
|
21
|
+
t.tag_end(:div)
|
22
22
|
t.add('\bye')
|
23
23
|
t.add_raw('>')
|
24
24
|
t.add_raw(' ')
|
25
25
|
t.add_raw('„')
|
26
26
|
|
27
|
-
res = "<html><
|
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 += ">"
|
29
|
-
res += "\u00a0"
|
30
|
-
res += "„"
|
29
|
+
#res += "\u00a0"
|
30
|
+
#res += "„"
|
31
|
+
res += ' '
|
32
|
+
res += '„'
|
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.
|
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-
|
12
|
+
date: 2014-01-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bacon
|