trac-wiki 0.2.16 → 0.2.20
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/trac-wiki.rb +1 -0
- data/lib/trac-wiki/env.rb +256 -0
- data/lib/trac-wiki/parser.rb +80 -95
- data/lib/trac-wiki/tree.rb +3 -1
- data/lib/trac-wiki/version.rb +1 -1
- data/test/parser_test.rb +89 -11
- metadata +3 -2
data/lib/trac-wiki.rb
CHANGED
@@ -0,0 +1,256 @@
|
|
1
|
+
module TracWiki
|
2
|
+
|
3
|
+
class Env
|
4
|
+
def initialize(parser, env = {})
|
5
|
+
@parser = parser
|
6
|
+
@env = env
|
7
|
+
end
|
8
|
+
|
9
|
+
def parse_macro_all(macro_name, str)
|
10
|
+
#print "macro_all: #{macro_name}, str:#{str}.\n"
|
11
|
+
if macro_name =~ /\A!/
|
12
|
+
# {{!cmd}}
|
13
|
+
mac_out, rest, lines = parse_macro_cmd(macro_name, str)
|
14
|
+
else
|
15
|
+
# {{$cmd}}, {{template}}, ...
|
16
|
+
mac_out, rest, lines = parse_macro_vartempl(macro_name, str)
|
17
|
+
end
|
18
|
+
return mac_out || '', rest, lines
|
19
|
+
end
|
20
|
+
|
21
|
+
# read to args to }} (while balancing {{ and }})
|
22
|
+
# ret: (arg, rest, lines)
|
23
|
+
# mac_out -- string to }} (macros inside expanded)
|
24
|
+
# rest -- str aftrer }}
|
25
|
+
# lines -- howmany \n eaten from str (from begining to }})
|
26
|
+
def parse_macro_vartempl(macro_name, str)
|
27
|
+
str_orig = str
|
28
|
+
lines = 0
|
29
|
+
arg = ''
|
30
|
+
# FIXME: MACRO_REX
|
31
|
+
# prefix }}... {{macro_name
|
32
|
+
while str =~ TracWiki::Parser::MACRO_END_REX
|
33
|
+
prefix, bracket, sub_macro_name, str = $1, $2, $3, $'
|
34
|
+
arg << prefix
|
35
|
+
lines += prefix.count("\n")
|
36
|
+
if bracket == '}}'
|
37
|
+
#print "prefix: #{prefix}\n"
|
38
|
+
return do_macro_var($1, arg), str, lines if macro_name =~ /^\$(.*)/
|
39
|
+
return do_macro_templ(macro_name, arg), str, lines
|
40
|
+
end
|
41
|
+
|
42
|
+
# we need to go deeper!
|
43
|
+
mac_out, str, l = parse_macro_all(sub_macro_name, str)
|
44
|
+
arg << mac_out
|
45
|
+
lines += l
|
46
|
+
end
|
47
|
+
print "Error parsing macro(#{macro_name}) near '#{str}'(#{str_orig}) (arg:#{arg}, lines=#{lines})\n"
|
48
|
+
raise "Error parsing macro near '#{str}' (arg:#{arg}, lines=#{lines})"
|
49
|
+
end
|
50
|
+
|
51
|
+
# parse to next }} (with balanced {{..}})
|
52
|
+
# like parse_macro_vartempl but not expand content
|
53
|
+
# r: [expansion, rest_of_str, count_of_consumed_lines]
|
54
|
+
def parse_macro_cmd(macro_name, str)
|
55
|
+
str.sub!(/\A\s*\|?/, '')
|
56
|
+
return do_macro_cmd(macro_name, []), $', 0 if str =~ /\A}}/
|
57
|
+
#print "parse_macro_cmd: #{macro_name}, str#{str}\n"
|
58
|
+
dep = 0
|
59
|
+
lines = 0
|
60
|
+
args = ['']
|
61
|
+
while str =~ /{{|}}|\|/
|
62
|
+
prefix, match, str = $`, $&, $'
|
63
|
+
args[-1] += prefix
|
64
|
+
lines += prefix.count("\n")
|
65
|
+
if match == '{{'
|
66
|
+
dep += 1
|
67
|
+
args[-1] += $&
|
68
|
+
elsif match == '}}'
|
69
|
+
dep -= 1
|
70
|
+
return do_macro_cmd(macro_name, args), str, lines if dep < 0
|
71
|
+
args[-1] += $&
|
72
|
+
elsif match == '|' && dep == 0
|
73
|
+
args.push('')
|
74
|
+
else
|
75
|
+
args[-1] += $&
|
76
|
+
end
|
77
|
+
end
|
78
|
+
raise "eol in parsing macro params"
|
79
|
+
end
|
80
|
+
|
81
|
+
# calls {{!cmd}} (if exists
|
82
|
+
# r: result of {{!cmd}}
|
83
|
+
def do_macro_cmd(macro_name, args)
|
84
|
+
return '|' if macro_name == '!'
|
85
|
+
if @parser.plugins.key?(macro_name)
|
86
|
+
@env['args'] = args
|
87
|
+
@env['arg0'] = macro_name
|
88
|
+
#print "mac: #{macro_name} env:" ; pp (@env)
|
89
|
+
ret = @parser.plugins[macro_name].call(self)
|
90
|
+
return ret
|
91
|
+
end
|
92
|
+
"UCMD(#{macro_name}|#{@env['arg']})"
|
93
|
+
end
|
94
|
+
def arg(idx)
|
95
|
+
@env['args'][idx] || ''
|
96
|
+
end
|
97
|
+
|
98
|
+
def prepare_y
|
99
|
+
#print "prepare_y\n"
|
100
|
+
return if @env.key? 'y'
|
101
|
+
arg = @env['arg']
|
102
|
+
return if arg.nil?
|
103
|
+
begin
|
104
|
+
@env['y'] = YAML.load(arg)
|
105
|
+
#print "y"
|
106
|
+
#pp @env['y']
|
107
|
+
rescue
|
108
|
+
@env['y'] = nil
|
109
|
+
#print "y:nil\n"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def at(key, default = nil, to_str = true)
|
114
|
+
#print "at(#{key}), env:"
|
115
|
+
#pp @env
|
116
|
+
return @env[key] || default if key.is_a? Symbol
|
117
|
+
prepare_y if key =~ /^y\./
|
118
|
+
cur = @env
|
119
|
+
key.split(/\./).each do |subkey|
|
120
|
+
subkey = at($1, '') if subkey =~ /\A\$(.*)/
|
121
|
+
#print "at:subkey: #{subkey}\n"
|
122
|
+
if cur.is_a? Hash
|
123
|
+
cur = cur[subkey]
|
124
|
+
elsif cur.is_a? Array
|
125
|
+
cur = cur[subkey.to_i]
|
126
|
+
else
|
127
|
+
#print "at(#{key})->: default"
|
128
|
+
return default
|
129
|
+
end
|
130
|
+
#print "at(#{key}) -> default\n" if cur.nil?
|
131
|
+
return default if cur.nil?
|
132
|
+
end
|
133
|
+
#print "at(#{key})->#{cur}\n"
|
134
|
+
to_str ? cur.to_s : cur
|
135
|
+
end
|
136
|
+
def atput(key, val = nil)
|
137
|
+
#print "atput: #{key}, #{val} env:"
|
138
|
+
#pp @env
|
139
|
+
cur = @env
|
140
|
+
if val.is_a? Symbol
|
141
|
+
@env[key] = val
|
142
|
+
return
|
143
|
+
end
|
144
|
+
keys = key.split(/\./)
|
145
|
+
lastkey = keys.pop
|
146
|
+
keys.each do |subkey|
|
147
|
+
if cur.is_a? Hash
|
148
|
+
cur = cur[subkey]
|
149
|
+
elsif cur.is_a? Array
|
150
|
+
cur = cur[subkey.to_i]
|
151
|
+
else
|
152
|
+
return
|
153
|
+
end
|
154
|
+
end
|
155
|
+
if cur.is_a? Hash
|
156
|
+
cur[lastkey] = val
|
157
|
+
elsif cur.is_a? Array
|
158
|
+
cur[lastkey.to_i] = val
|
159
|
+
end
|
160
|
+
#print "atput:env:"
|
161
|
+
#pp @env
|
162
|
+
end
|
163
|
+
|
164
|
+
def [](key)
|
165
|
+
at(key)
|
166
|
+
end
|
167
|
+
|
168
|
+
def []=(key,val)
|
169
|
+
#print "set #{key} to #{val}\n"
|
170
|
+
atput(key,val)
|
171
|
+
end
|
172
|
+
|
173
|
+
# expand macro `macro_name` with `args`
|
174
|
+
# afer expansion all {{macros}} will be expanded recursively
|
175
|
+
# r: expanded string
|
176
|
+
def do_macro_templ(macro_name, arg)
|
177
|
+
return "!{{toc}}" if macro_name == 'toc'
|
178
|
+
return arg.strip if macro_name == '#echo'
|
179
|
+
return '' if macro_name == '#'
|
180
|
+
|
181
|
+
env = do_macro_arg_to_env(arg, @env[:depth])
|
182
|
+
|
183
|
+
#print "templ:#{macro_name}env:"
|
184
|
+
#pp(env)
|
185
|
+
|
186
|
+
if ! @parser.template_handler.nil?
|
187
|
+
str = @parser.template_handler.call(macro_name, env)
|
188
|
+
if !str.nil?
|
189
|
+
#print "dep:#{env[:depth]}(#{macro_name}, #{str})\n"
|
190
|
+
if env[:depth] > 32
|
191
|
+
return "TOO_DEEP_RECURSION(`#{str}`)\n"
|
192
|
+
#return "TOO_DEEP_RECURSION"
|
193
|
+
end
|
194
|
+
# FIXME: melo by nahlasit jestli to chce expandovat | wiki expadnovat |raw html
|
195
|
+
#print "temp(#{macro_name}) --> : #{str}\n"
|
196
|
+
#print "bf ex: [#{str}]\n"
|
197
|
+
str = env.expand(str)
|
198
|
+
#print "af ex: [#{str}]\n"
|
199
|
+
return str
|
200
|
+
end
|
201
|
+
end
|
202
|
+
#print "UMACRO(#{macro_name}|#{arg})\n"
|
203
|
+
"UMACRO(#{macro_name}|#{arg})"
|
204
|
+
end
|
205
|
+
|
206
|
+
def do_macro_arg_to_env(arg, depth)
|
207
|
+
arg.sub!(/\A\s*\|?/, '')
|
208
|
+
env = { 'arg' => arg , depth: (depth||0) + 1 }
|
209
|
+
idx = 1
|
210
|
+
arg.split(/\|/).each do |val|
|
211
|
+
if val =~ /\A\s*(\w+)\s*=\s*(.*)/s
|
212
|
+
env[$1] = $2
|
213
|
+
else
|
214
|
+
env[idx.to_s] = val
|
215
|
+
idx+=1
|
216
|
+
end
|
217
|
+
end
|
218
|
+
return Env.new(@parser, env)
|
219
|
+
end
|
220
|
+
|
221
|
+
def do_macro_var(var_name, arg)
|
222
|
+
#print "var(#{var_name})env:"
|
223
|
+
#pp(@env)
|
224
|
+
ret = at(var_name, nil)
|
225
|
+
return ret if !ret.nil?
|
226
|
+
return arg.sub(/\A\s*\|?/, '') if arg
|
227
|
+
"UVAR(#{macro_name}|#{@env['arg']})"
|
228
|
+
end
|
229
|
+
|
230
|
+
# template expand
|
231
|
+
def expand_arg(idx)
|
232
|
+
expand(@env['args'][idx])
|
233
|
+
end
|
234
|
+
|
235
|
+
def pp_env
|
236
|
+
pp(@env)
|
237
|
+
end
|
238
|
+
def expand(str)
|
239
|
+
ret = ''
|
240
|
+
return '' if str.nil?
|
241
|
+
while str =~ TracWiki::Parser::MACRO_BEG_INSIDE_REX
|
242
|
+
prefix, macro_name2, str = $1, $2, $'
|
243
|
+
ret << prefix
|
244
|
+
# FIXME if macro_name2 =~ /^!/
|
245
|
+
mac_out, str, lines = parse_macro_all(macro_name2, str)
|
246
|
+
ret << mac_out
|
247
|
+
#print "Too long macro expadion" if ret.size > 1_000_000
|
248
|
+
raise TooLongException if ret.size > 1_000_000
|
249
|
+
end
|
250
|
+
#print "text: #{text.nil?}\n"
|
251
|
+
#print "ret: #{ret.nil?}\n"
|
252
|
+
return ret + str
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
end
|
data/lib/trac-wiki/parser.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'cgi'
|
2
2
|
require 'uri'
|
3
3
|
require 'iconv'
|
4
|
+
require 'yaml'
|
4
5
|
|
5
6
|
# :main: TracWiki
|
6
7
|
|
@@ -38,6 +39,9 @@ require 'iconv'
|
|
38
39
|
# Inherit this to provide custom handling of links. The overrideable
|
39
40
|
# methods are: make_local_link
|
40
41
|
module TracWiki
|
42
|
+
class TooLongException < Exception
|
43
|
+
end
|
44
|
+
|
41
45
|
class Parser
|
42
46
|
|
43
47
|
# Allowed url schemes
|
@@ -85,18 +89,23 @@ module TracWiki
|
|
85
89
|
|
86
90
|
# when id_from_heading, non ascii char are transliterated to ascii
|
87
91
|
attr_writer :id_translit
|
92
|
+
attr_accessor :plugins
|
93
|
+
@plugins = {}
|
88
94
|
|
89
95
|
# string begins with macro
|
90
|
-
MACRO_BEG_REX = /\A\{\{ ( [
|
91
|
-
MACRO_BEG_INSIDE_REX =
|
96
|
+
MACRO_BEG_REX = /\A\{\{ ( \$[\$\.\w]+ | [\#!]\w* |\w+ ) /x
|
97
|
+
MACRO_BEG_INSIDE_REX = /\A(.*?)(?<!\{)\{\{ ( \$[\$\.\w]+ | [\#!]\w* | \w+ ) /xm
|
92
98
|
# find end of marcro or begin of inner macro
|
93
|
-
MACRO_END_REX = /\A(.*?) ( \}\} | \{\{ (
|
99
|
+
MACRO_END_REX = /\A(.*?) ( \}\} | \{\{ ( \$[\$\.\w]+ | [\#!]\w* | \w+) )/mx
|
94
100
|
def id_translit?; @id_translit; end
|
95
101
|
|
96
102
|
# Create a new Parser instance.
|
97
103
|
def initialize(text, options = {})
|
104
|
+
init_plugins
|
98
105
|
@allowed_schemes = %w(http https ftp ftps)
|
99
106
|
@anames = {}
|
107
|
+
plugins = options.delete :plugins
|
108
|
+
@plugins.merge! plugins if ! plugins.nil?
|
100
109
|
@text = text
|
101
110
|
@no_escape = nil
|
102
111
|
@base = ''
|
@@ -104,8 +113,47 @@ module TracWiki
|
|
104
113
|
@base += '/' if !@base.empty? && @base[-1] != '/'
|
105
114
|
end
|
106
115
|
|
116
|
+
def init_plugins
|
117
|
+
@plugins = {
|
118
|
+
'!ifeq' => proc { |env| env.expand_arg(0) == env.expand_arg(1) ? env.expand_arg(2) : env.expand_arg(3) },
|
119
|
+
'!ifdef' => proc { |env| env.at(env.expand_arg(0), nil, false).nil? ? env.expand_arg(2) : env.expand_arg(1) },
|
120
|
+
'!set' => proc { |env| env[env.expand_arg(0)] = env.expand_arg(1); '' },
|
121
|
+
'!yset' => proc { |env| env[env.expand_arg(0)] = YAML.load(env.arg(1)); '' },
|
122
|
+
|
123
|
+
'!html' => proc { |env| "\n{{{!\n#{env.arg(0)}\n}}}\n" },
|
124
|
+
'!sub' => proc { |env| pat = env.expand_arg(1)
|
125
|
+
pat = Regexp.new(pat[1..-2]) if pat =~ /\A\/.*\/\Z/
|
126
|
+
env.expand_arg(0).gsub(pat, env.expand_arg(2))
|
127
|
+
},
|
128
|
+
'!for' => proc { |env| i_name = env.arg(0)
|
129
|
+
top = env.arg(1)
|
130
|
+
tmpl = env.arg(2)
|
131
|
+
#print "top#{top}\n"
|
132
|
+
if top =~ /^\d+/
|
133
|
+
set = (0..(top.to_i-1))
|
134
|
+
else
|
135
|
+
set = env.at(top, nil, false)
|
136
|
+
if set.is_a?(Hash)
|
137
|
+
set = set.keys.sort
|
138
|
+
elsif set.is_a?(Array)
|
139
|
+
set = (0 .. set.size-1)
|
140
|
+
else
|
141
|
+
print "error top(#{top}), set#{set} #{set.class}\n"
|
142
|
+
env.pp_env
|
143
|
+
raise "Error in {{!for #{i_name}|#{top}|#{tmpl}}}"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
set.map do |i|
|
147
|
+
env[i_name] = i.to_s
|
148
|
+
env.expand(tmpl)
|
149
|
+
end.join('')
|
150
|
+
},
|
151
|
+
}
|
152
|
+
|
153
|
+
end
|
154
|
+
|
107
155
|
# th(macroname) -> template_text
|
108
|
-
|
156
|
+
attr_accessor :template_handler
|
109
157
|
|
110
158
|
@was_math = false
|
111
159
|
def was_math?; @was_math; end
|
@@ -138,6 +186,12 @@ module TracWiki
|
|
138
186
|
@tree.to_html
|
139
187
|
end
|
140
188
|
|
189
|
+
def add_plugin(name, &block)
|
190
|
+
@plugins[name] = block
|
191
|
+
end
|
192
|
+
|
193
|
+
|
194
|
+
|
141
195
|
protected
|
142
196
|
|
143
197
|
# Escape any characters with special meaning in HTML using HTML
|
@@ -407,11 +461,13 @@ module TracWiki
|
|
407
461
|
|
408
462
|
def parse_inline_tag(str)
|
409
463
|
case
|
410
|
-
when str =~ /\A\{\{\{(.*?\}*)\}\}\}/ # inline
|
464
|
+
when raw_html? && str =~ /\A\{\{\{!(.*?\}*)\}\}\}/ # inline {{{! raw html }}}
|
465
|
+
do_raw_html($1, true)
|
466
|
+
when str =~ /\A\{\{\{(.*?\}*)\}\}\}/ # inline {{{ }}} pre (tt)
|
411
467
|
@tree.tag(:tt, $1)
|
412
468
|
when str =~ MACRO_BEG_REX # macro {{
|
413
469
|
str, lines = parse_macro($1, $')
|
414
|
-
#print "MACRO.inline(#{$1})"
|
470
|
+
#print "MACRO.inline(#{$1}), next:#{str}"
|
415
471
|
return str
|
416
472
|
when str =~ /\A`(.*?)`/ # inline pre (tt)
|
417
473
|
@tree.tag(:tt, $1)
|
@@ -421,7 +477,7 @@ module TracWiki
|
|
421
477
|
#@tree.tag(:span, {class:'math'}, $1)
|
422
478
|
@was_math = true
|
423
479
|
when str =~ /\A(\&\w*;)/ # html entity
|
424
|
-
print "add html ent: #{$1}\n"
|
480
|
+
#print "add html ent: #{$1}\n"
|
425
481
|
@tree.add_raw($1)
|
426
482
|
when str =~ /\A([:alpha:]|[:digit:])+/
|
427
483
|
@tree.add($&) # word
|
@@ -455,103 +511,31 @@ module TracWiki
|
|
455
511
|
return $'
|
456
512
|
end
|
457
513
|
|
514
|
+
#################################################################
|
515
|
+
# macro {{ }}
|
516
|
+
# convetntion {{!cmd}} {{template}} {{$var}} {{# comment}} {{!}} (pipe)
|
517
|
+
|
458
518
|
# r: expanded macro + rest of str, count lines taken from str
|
459
519
|
# sideefect: parse result of macro
|
460
520
|
def parse_macro(macro_name, str)
|
521
|
+
@env = Env.new(self) if @env.nil?
|
461
522
|
begin
|
462
|
-
mac_out, rest, lines =
|
463
|
-
#
|
464
|
-
#@tree.add(mac)
|
465
|
-
#print "MACOUT:'#{mac_out}'\n"
|
523
|
+
mac_out, rest, lines = @env.parse_macro_all(macro_name, str)
|
524
|
+
#print "mac: '#{mac_out}' rest: '#{rest}'\n"
|
466
525
|
return mac_out + rest, lines
|
467
|
-
rescue
|
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
|
526
|
+
rescue TooLongException => e
|
527
|
+
return "TOO_LONG_EXPANSION_OF_MACRO(#{macro_name})QUIT", 0
|
497
528
|
end
|
498
|
-
raise "Error parsing macro near '#{str}' (arg:#{arg}, lines=#{lines})"
|
499
529
|
end
|
500
530
|
|
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
531
|
|
509
|
-
return do_macro_var(macro_name, env) if macro_name =~ /^\$/
|
510
532
|
|
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
|
533
|
+
#################################################################
|
551
534
|
|
552
535
|
|
553
536
|
def parse_table_row(str)
|
554
537
|
start_tag('tr') if !@stack.include?('tr')
|
538
|
+
str.sub!(/\r/, '')
|
555
539
|
colspan = 1
|
556
540
|
print_tr = true
|
557
541
|
last_tail = ''
|
@@ -674,8 +658,8 @@ module TracWiki
|
|
674
658
|
@tree.tag(:pre, nowikiblock)
|
675
659
|
end
|
676
660
|
|
677
|
-
def do_raw_html(text)
|
678
|
-
end_paragraph
|
661
|
+
def do_raw_html(text, inline=false)
|
662
|
+
end_paragraph if !inline
|
679
663
|
@tree.add_raw(text)
|
680
664
|
end
|
681
665
|
|
@@ -741,7 +725,8 @@ module TracWiki
|
|
741
725
|
# macro
|
742
726
|
when str =~ MACRO_BEG_REX
|
743
727
|
str, lines = parse_macro($1, $')
|
744
|
-
#print "MACRO.block(#{$1})\n"
|
728
|
+
#print "MACRO.block(#{$1})next:#{str}\n"
|
729
|
+
@line_no += lines
|
745
730
|
next
|
746
731
|
# display math $$
|
747
732
|
when math? && str =~ /\A\$\$(.*?)\$\$/m
|
@@ -778,7 +763,7 @@ module TracWiki
|
|
778
763
|
do_citation($1.count('>'), $2)
|
779
764
|
# ordinary line
|
780
765
|
when str =~ /\A(\s*)(\S+.*?)$(\r?\n)?/
|
781
|
-
do_ord_line($1.size, $2)
|
766
|
+
do_ord_line($1.size, $2)
|
782
767
|
else # case str
|
783
768
|
raise "Parse error at #{str[0,30].inspect}"
|
784
769
|
end
|
@@ -786,7 +771,7 @@ module TracWiki
|
|
786
771
|
str = $'
|
787
772
|
end
|
788
773
|
end_paragraph
|
789
|
-
@headings.last[:eline] = @line_no - 1
|
774
|
+
@headings.last[:eline] = @line_no - 1
|
790
775
|
end
|
791
776
|
|
792
777
|
def aname_nice(aname, title)
|
data/lib/trac-wiki/tree.rb
CHANGED
@@ -145,9 +145,11 @@ module TracWiki
|
|
145
145
|
|
146
146
|
def san_conf
|
147
147
|
return @san_conf if @san_conf
|
148
|
-
conf = { elements: ['form', 'input'],
|
148
|
+
conf = { elements: ['form', 'input', 'span', 'div'],
|
149
149
|
attributes: { 'form' => ['action', 'meth'],
|
150
150
|
'input' => ['type', 'value'],
|
151
|
+
'span' => ['class'],
|
152
|
+
'div' => ['class'],
|
151
153
|
},
|
152
154
|
}
|
153
155
|
|
data/lib/trac-wiki/version.rb
CHANGED
data/test/parser_test.rb
CHANGED
@@ -5,13 +5,26 @@ require 'pp'
|
|
5
5
|
|
6
6
|
class Bacon::Context
|
7
7
|
def tc(html, wiki, options = {})
|
8
|
-
|
8
|
+
options[:plugins] = { '!print' => proc { |env| env.arg(0) + '! ' },
|
9
|
+
}
|
9
10
|
options[:template_handler] = self.method(:template_handler)
|
10
|
-
|
11
|
+
|
12
|
+
parser = TracWiki.parser(wiki, options)
|
13
|
+
parser.to_html.should.equal html
|
11
14
|
end
|
12
15
|
|
13
16
|
def template_handler(tname, env)
|
14
17
|
case tname
|
18
|
+
when 'ifeqtest'
|
19
|
+
"{{!ifeq {{$1}}|{{$2}}|TRUE|FALSE}}"
|
20
|
+
when 'vartest2'
|
21
|
+
"{{vartest {{$1}}|{{$dva}}|p={{$p}}|{{$3 |tridef}}}}"
|
22
|
+
when 'ytest'
|
23
|
+
"{{$y.ahoj}},{{$y.bhoj.1}}"
|
24
|
+
when 'ytest2'
|
25
|
+
"{{!set i|ahoj}}{{$y.$i}},{{$y.bhoj.1}}"
|
26
|
+
when 'vartest'
|
27
|
+
"jedna:{{$1}},dve:{{$2}},p:{{$p}},arg:{{$arg}}"
|
15
28
|
when 'test'
|
16
29
|
"{{west}}"
|
17
30
|
when 'west'
|
@@ -20,6 +33,8 @@ class Bacon::Context
|
|
20
33
|
"{{deep}}"
|
21
34
|
when 'wide'
|
22
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}}"
|
23
38
|
else
|
24
39
|
nil
|
25
40
|
#"UNK_TEMPL(#{tname})"
|
@@ -574,6 +589,8 @@ describe TracWiki::Parser do
|
|
574
589
|
|
575
590
|
it 'should parse table' do
|
576
591
|
tc "<table><tr><td>Hello</td><td>World!</td></tr></table>", "||Hello||World!||"
|
592
|
+
tc "<table><tr><td>Hello</td><td>World!</td></tr><tr><td>Hello</td><td>World!</td></tr></table>", "||Hello||World!||\n||Hello||World!||\n\n"
|
593
|
+
tc "<table><tr><td>Hello</td><td>World!</td></tr><tr><td>Hello</td><td>World!</td></tr></table>", "||Hello||World!||\r\n||Hello||World!||\r\n\n"
|
577
594
|
tc "<table><tr><td>Hello</td><td>World!</td></tr></table>", "||Hello||\\\n||World!||"
|
578
595
|
tc "<table><tr><td>He</td><td>llo</td><td>World!</td></tr></table>", "||He||llo||\\\n||World!||"
|
579
596
|
tc "<table><tr><td>Hello</td><td colspan=\"2\">World!</td></tr></table>", "||Hello||||World!||"
|
@@ -893,12 +910,12 @@ eos
|
|
893
910
|
|
894
911
|
tc "<h1>h1</h1>" , "{{# co{{HUU}}mment }}\n\n\n= h1 =\n{{# Comment2}}\n"
|
895
912
|
|
896
|
-
tc "<p>UMACRO(macr
|
897
|
-
tc "<p>ahoj UMACRO(
|
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(
|
901
|
-
tc "<p>ahoj
|
913
|
+
tc "<p>UMACRO(macr|ahoj )</p>\n" , "{{macr\nahoj\n}}"
|
914
|
+
tc "<p>ahoj UMACRO(macr|UMACRO(o|))</p>\n" , "ahoj {{macr{{o}}}}"
|
915
|
+
tc "<p>ahoj UMACRO(macro|)</p>\n" , "ahoj {{macro}}"
|
916
|
+
tc "<p>ahoj {{%macrUMACRO(o|)}}</p>\n" , "ahoj {{%macr{{o}}}}"
|
917
|
+
tc "<p>ahoj UMACRO(macr|UMACRO(mac|<strong>o</strong>))</p>\n" , "ahoj {{macr{{mac **o**}}}}"
|
918
|
+
tc "<p>ahoj ahoj</p>\n" , "ahoj {{$mac|ahoj}}"
|
902
919
|
end
|
903
920
|
|
904
921
|
it 'should do temlate' do
|
@@ -908,23 +925,84 @@ eos
|
|
908
925
|
# macro errors:
|
909
926
|
tc "<p>TOO_DEEP_RECURSION(<tt>{{deep}}</tt>) 3</p>\n", "{{deep}}3"
|
910
927
|
tc "<p>TOO_LONG_EXPANSION_OF_MACRO(wide)QUIT</p>\n", "{{wide}}3"
|
911
|
-
tc "<p>UMACRO(unknown)3</p>\n", "{{unknown}}3"
|
928
|
+
tc "<p>UMACRO(unknown|)3</p>\n", "{{unknown}}3"
|
929
|
+
end
|
930
|
+
it 'should do temlate with args' do
|
931
|
+
tc "<p>jedna:VARTESTPARAM,dve:,p:DVE,arg:VARTESTPARAM|p=DVE</p>\n", "{{vartest VARTESTPARAM|p=DVE}}"
|
932
|
+
tc "<p>jedna:VARTESTPARAM,dve:TRI,p:DVE,arg:VARTESTPARAM|p=DVE|TRI</p>\n", "{{vartest VARTESTPARAM|p=DVE|TRI}}"
|
933
|
+
tc "<p>jedna:VARTESTPARAM,dve:TRI,p:DVE,arg:VARTESTPARAM|TRI|p=DVE|tridef</p>\n", "{{vartest2 VARTESTPARAM|p=DVE|dva=TRI}}"
|
934
|
+
tc "<p>ahoj |</p>\n", "ahoj {{!}}"
|
935
|
+
#FIXME: should be: '... jedna:be||no to be,dve: ..'
|
936
|
+
tc "<p>jedna:be,dve:,p:,arg:be||not to be</p>\n", "{{vartest be{{!}}{{!}}not to be}}"
|
912
937
|
end
|
913
938
|
it 'should support options' do
|
914
939
|
tc "<h3>h1<a class=\"editheading\" href=\"?edit=1\">edit</a></h3>", "=== h1 ==", edit_heading: true
|
915
940
|
end
|
916
941
|
it 'should not html' do
|
917
|
-
tc "<p>{{{! <a></a> }}}</p>\n", "{{{!\n<a></a>\n}}}\n"
|
942
|
+
#tc "<p>{{{! <a></a> }}}</p>\n", "{{{!\n<a></a>\n}}}\n"
|
918
943
|
tc '<a></a>', "{{{!\n<a></a>\n}}}\n", raw_html: true
|
919
944
|
tc '<a></a>', "{{{!\n<a></a>\n}}}\n", raw_html: true
|
920
945
|
tc "<form meth=\"POST\" action=\"http://www.example.com\"><input type=\"hidden\" value=\"VAL\"></form>",
|
921
946
|
"{{{!\n<form meth=\"POST\" action=\"http://www.example.com\"><input type=\"hidden\" value=\"VAL\"/></form>\n}}}\n", raw_html: true
|
922
947
|
tc 'alert(444);', "{{{!\n<script>alert(444);</script>\n}}}\n", raw_html: true
|
923
948
|
end
|
924
|
-
it 'should
|
949
|
+
it 'should entity' do
|
925
950
|
tc "<p>\u00a0</p>\n", " "
|
926
951
|
tc "<p>„text“</p>\n", "„text“"
|
927
952
|
end
|
953
|
+
it 'should plugin' do
|
954
|
+
tc "<p>AHOJTE!</p>\n", "{{!print AHOJTE}}"
|
955
|
+
tc "<p>test:AHOJTE! AHOJTE! </p>\n", "test:{{!print AHOJTE}}{{!print AHOJTE}}"
|
956
|
+
tc "<p>FALSE</p>\n", "{{ifeqtest JEDNA|DVE}}"
|
957
|
+
tc "<p>TRUE</p>\n", "{{ifeqtest JEDNA|JEDNA}}"
|
958
|
+
tc "<p>AHOJ</p>\n", "{{!set ahoj|AHOJ}}{{$ahoj}}"
|
959
|
+
tc "<p>BHOJ</p>\n", "{{!ifeq a|b|{{!set ahoj|AHOJ}}|{{!set ahoj|BHOJ}}}}{{$ahoj}}"
|
960
|
+
tc "<p>AHOJ</p>\n", "{{!ifeq a|a|{{!set ahoj|AHOJ}}|{{!set ahoj|BHOJ}}}}{{$ahoj}}"
|
961
|
+
tc "<p>TRUE</p>\n", "{{!set a|a}}{{!ifeq {{$a}}|a|TRUE|FALSE}}"
|
962
|
+
tc "<p>FALSE</p>\n", "{{!set a|a}}{{!ifeq {{$a}}|b|TRUE|FALSE}}"
|
963
|
+
tc "<p>,AHOJ! ,FALSE</p>\n", "{{!set a|a}},{{!print AHOJ}},{{!ifeq {{$a}}|b|TRUE|FALSE}}"
|
964
|
+
tc "", "{{!ifeq a|b|TRUE}}"
|
965
|
+
tc "<p>AHOJ,dve</p>\n", "{{ytest \nahoj: AHOJ\nbhoj: [ jedna, dve ]\n}}"
|
966
|
+
tc "<p>,malo</p>\n", "{{!yset ahoj|data: [1,2]\ndesc: malo}},{{$ahoj.desc}}"
|
967
|
+
tc "<p>,BETA</p>\n", "{{!yset ahoj|data: [ALFA,BETA]\ndesc: malo}},{{$ahoj.data.1}}"
|
968
|
+
tc "<p>,GAMA</p>\n", "{{!yset ahoj|data: [ALFA,BETA]\ndesc: malo}},{{!set ahoj.data.3|GAMA}}{{$ahoj.data.3}}"
|
969
|
+
tc "<p>,2</p>\n", "{{!yset ahoj|data: [1,2]\ndesc: malo}},{{$ahoj.data.1}}"
|
970
|
+
tc "<p>AHOJ,dve</p>\n", "{{ytest2 \nahoj: AHOJ\nbhoj: [ jedna, dve ]\n}}"
|
971
|
+
tc "<p>,,BHOJ</p>\n", "{{!set ahoj|AHOJ}},{{!set AHOJ|BHOJ}},{{$$ahoj}}"
|
972
|
+
tc "<p>(0),(1),(2),</p>\n", "{{!for i|3|({{$i}}),}}", raw_html: true
|
973
|
+
tc "<p>(0),(1),(2),(3),</p>\n", "{{!for i|4|({{$i}}),}}", raw_html: true
|
974
|
+
tc "<p>,(ALFA),(BETA),</p>\n", "{{!yset data|[ALFA,BETA]}},{{!for i|data|({{$data.$i}}),}}"
|
975
|
+
tc "<p>,(1),(2),</p>\n", "{{!yset data|[1,2]}},{{!for i|data|({{$data.$i}}),}}"
|
976
|
+
tc "<p>,(alfa:ALFA),(beta:BETA),</p>\n", "{{!yset data|beta: BETA\nalfa: ALFA\n}},{{!for i|data|({{$i}}:{{$data.$i}}),}}"
|
977
|
+
|
978
|
+
tc "<p>,FALSE</p>\n", "{{!yset data|[1,2]}},{{!ifdef data.55|TRUE|FALSE}}"
|
979
|
+
tc "<p>,TRUE</p>\n", "{{!yset data|[1,2]}},{{!ifdef data.1|TRUE|FALSE}}"
|
980
|
+
tc "<p>,TRUE</p>\n", "{{!yset data|{a: 1, b: 2} }},{{!ifdef data.a|TRUE|FALSE}}"
|
981
|
+
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
|
928
1006
|
end
|
929
1007
|
end
|
930
1008
|
# vim: tw=0
|
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.20
|
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:
|
12
|
+
date: 2014-01-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bacon
|
@@ -60,6 +60,7 @@ files:
|
|
60
60
|
- Rakefile
|
61
61
|
- bin/trac-wiki.rb
|
62
62
|
- lib/trac-wiki.rb
|
63
|
+
- lib/trac-wiki/env.rb
|
63
64
|
- lib/trac-wiki/parser.rb
|
64
65
|
- lib/trac-wiki/tree.rb
|
65
66
|
- lib/trac-wiki/version.rb
|