trac-wiki 0.2.20 → 0.2.21
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/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
|