wikicloth 0.5.0 → 0.6.0
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/README +1 -1
- data/Rakefile +20 -31
- data/lib/wikicloth/core_ext.rb +22 -17
- data/lib/wikicloth/lexer.rb +105 -0
- data/lib/wikicloth/parser.rb +5 -5
- data/lib/wikicloth/section.rb +2 -0
- data/lib/wikicloth/token.rb +41 -0
- data/lib/wikicloth/wiki_buffer/html_element.rb +21 -1
- data/lib/wikicloth/wiki_buffer/var.rb +103 -27
- data/lib/wikicloth/wiki_buffer.rb +33 -3
- data/lib/wikicloth/wiki_link_handler.rb +9 -5
- data/lib/wikicloth.rb +6 -3
- data/run_tests.rb +2 -2
- data/test/test_helper.rb +4 -0
- data/test/wiki_cloth_test.rb +121 -4
- metadata +36 -9
- data/lib/wikicloth/calc.citrus +0 -133
- data/lib/wikicloth/math.rb +0 -155
- data/lib/wikicloth/wiki_buffer/template.rb +0 -32
data/README
CHANGED
data/Rakefile
CHANGED
@@ -2,18 +2,12 @@ require 'rake'
|
|
2
2
|
require 'rake/testtask'
|
3
3
|
require 'rake/rdoctask'
|
4
4
|
require 'rake/gempackagetask'
|
5
|
-
require 'init'
|
5
|
+
require File.join(File.dirname(__FILE__),'init')
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
require 'bundler'
|
8
|
+
Bundler::GemHelper.install_tasks
|
9
9
|
|
10
|
-
|
11
|
-
Rake::TestTask.new(:test) do |t|
|
12
|
-
t.libs << 'lib'
|
13
|
-
t.libs << 'test'
|
14
|
-
t.pattern = 'test/**/*_test.rb'
|
15
|
-
t.verbose = true
|
16
|
-
end
|
10
|
+
task :default => :test
|
17
11
|
|
18
12
|
desc 'Generate documentation for the wikicloth plugin.'
|
19
13
|
Rake::RDocTask.new(:rdoc) do |rdoc|
|
@@ -24,26 +18,21 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
24
18
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
25
19
|
end
|
26
20
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
s.platform = Gem::Platform::RUBY
|
34
|
-
s.summary = "An implementation of the mediawiki markup in ruby"
|
35
|
-
s.files = FileList["{lib,tasks}/**/*"].to_a +
|
36
|
-
FileList["sample_documents/*.wiki"].to_a +
|
37
|
-
["init.rb","uninstall.rb","Rakefile","install.rb"]
|
38
|
-
s.require_path = "lib"
|
39
|
-
s.description = File.read("README")
|
40
|
-
s.test_files = FileList["{test}/*.rb"].to_a + ["run_tests.rb"]
|
41
|
-
s.has_rdoc = false
|
42
|
-
s.extra_rdoc_files = ["README","MIT-LICENSE"]
|
43
|
-
s.description = %q{mediawiki parser}
|
44
|
-
s.add_dependency 'builder'
|
45
|
-
s.add_dependency 'expression_parser'
|
21
|
+
find_file = lambda do |name|
|
22
|
+
file_name = lambda {|path| File.join(path, "#{name}.rb")}
|
23
|
+
root = $:.detect do |path|
|
24
|
+
File.exist?(file_name[path])
|
25
|
+
end
|
26
|
+
file_name[root] if root
|
46
27
|
end
|
47
|
-
|
48
|
-
|
28
|
+
|
29
|
+
TEST_LOADER = find_file['rake/rake_test_loader']
|
30
|
+
multiruby = lambda do |glob|
|
31
|
+
system 'multiruby', TEST_LOADER, *Dir.glob(glob)
|
32
|
+
end
|
33
|
+
|
34
|
+
Rake::TestTask.new(:test) do |test|
|
35
|
+
test.ruby_opts << "-W"
|
36
|
+
test.pattern = 'test/**/*_test.rb'
|
37
|
+
test.verbose = true
|
49
38
|
end
|
data/lib/wikicloth/core_ext.rb
CHANGED
@@ -1,22 +1,27 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
1
|
+
if RUBY_VERSION < '1.9'
|
2
|
+
READ_MODE = "r"
|
3
|
+
class Object
|
4
|
+
module InstanceExecHelper; end
|
5
|
+
include InstanceExecHelper
|
6
|
+
def instance_exec(*args, &block)
|
7
|
+
begin
|
8
|
+
old_critical, Thread.critical = Thread.critical, true
|
9
|
+
n = 0
|
10
|
+
n += 1 while respond_to?(mname="__instance_exec#{n}")
|
11
|
+
InstanceExecHelper.module_eval{ define_method(mname, &block) }
|
12
|
+
ensure
|
13
|
+
Thread.critical = old_critical
|
14
|
+
end
|
15
|
+
begin
|
16
|
+
ret = send(mname, *args)
|
17
|
+
ensure
|
18
|
+
InstanceExecHelper.module_eval{ remove_method(mname) } rescue nil
|
19
|
+
end
|
20
|
+
ret
|
17
21
|
end
|
18
|
-
ret
|
19
22
|
end
|
23
|
+
else
|
24
|
+
READ_MODE = "r:UTF-8"
|
20
25
|
end
|
21
26
|
|
22
27
|
module Math
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# not actually used by wikicloth atm
|
2
|
+
module WikiCloth
|
3
|
+
|
4
|
+
class Lexer
|
5
|
+
|
6
|
+
def initialize(input)
|
7
|
+
@input = input
|
8
|
+
@return_previous_token = false
|
9
|
+
end
|
10
|
+
|
11
|
+
def get_next_token
|
12
|
+
if @return_previous_token
|
13
|
+
@return_previous_token = false
|
14
|
+
return @previous_token
|
15
|
+
end
|
16
|
+
|
17
|
+
token = Token.new
|
18
|
+
prepend_input = nil
|
19
|
+
|
20
|
+
case @input
|
21
|
+
when /\A\s+/
|
22
|
+
token.kind = Token::Space
|
23
|
+
when /\A:/
|
24
|
+
token.kind = Token::Colon
|
25
|
+
when /\A([']{2,5})/
|
26
|
+
token.kind = Token::BoldItalic
|
27
|
+
when /\A\n([*]{1,})/
|
28
|
+
token.kind = Token::ListItem
|
29
|
+
when /\A~~~~/
|
30
|
+
token.kind = Token::Signature
|
31
|
+
when /\A<!--/
|
32
|
+
token.kind = Token::BeginComment
|
33
|
+
when /\A-->/
|
34
|
+
token.kind = Token::EndComment
|
35
|
+
when /\A[\w\(\)\.\%;\#\-\/,'&\*~]+/
|
36
|
+
# swallowed bold/italic
|
37
|
+
if $&[-2,2] == "''"
|
38
|
+
prepend_input = "''"
|
39
|
+
token.value = $&[0..-3]
|
40
|
+
elsif $&[-3,3] == "'''"
|
41
|
+
prepend_input = "'''"
|
42
|
+
token.value = $&[0..-4]
|
43
|
+
elsif $&[-5,5] == "'''''"
|
44
|
+
prepend_input = "'''''"
|
45
|
+
token.value = $&[0..-6]
|
46
|
+
# accidently swallowed closing comment
|
47
|
+
elsif $&[-2,2] == "--" && $'[0,1] == '>'
|
48
|
+
prepend_input = '--'
|
49
|
+
token.value = $&[0..-3]
|
50
|
+
else
|
51
|
+
token.value = $&
|
52
|
+
end
|
53
|
+
token.kind = Token::Word
|
54
|
+
when /\A\{\|/
|
55
|
+
token.kind = Token::BeginTable
|
56
|
+
when /\A\|\}/
|
57
|
+
token.kind = Token::EndTable
|
58
|
+
when /\A\|/
|
59
|
+
token.kind = Token::Pipe
|
60
|
+
when /\A=/
|
61
|
+
token.kind = Token::Equals
|
62
|
+
when /\A"/
|
63
|
+
token.kind = Token::Quote
|
64
|
+
when /\A\n/
|
65
|
+
token.kind = Token::NewLine
|
66
|
+
when /\A\{\{/
|
67
|
+
token.kind = Token::OpenRes
|
68
|
+
when /\A\}\}/
|
69
|
+
token.kind = Token::CloseRes
|
70
|
+
when /\A\[\[/
|
71
|
+
token.kind = Token::OpenLink
|
72
|
+
token.value = $&
|
73
|
+
when /\A\]\]/
|
74
|
+
token.kind = Token::CloseLink
|
75
|
+
token.value = $&
|
76
|
+
when /\A\[/
|
77
|
+
token.kind = Token::OpenLink
|
78
|
+
token.kind = $&
|
79
|
+
when /\A\]/
|
80
|
+
token.kind = Token::CloseLink
|
81
|
+
token.kind = $&
|
82
|
+
when /\A\<\s*\//
|
83
|
+
token.kind = Token::OpenElement
|
84
|
+
when /\A\</
|
85
|
+
token.kind = Token::OpenElement
|
86
|
+
when /\A\>/
|
87
|
+
token.kind = Token::CloseElement
|
88
|
+
when ''
|
89
|
+
token.kind = Token::End
|
90
|
+
end
|
91
|
+
token.value ||= $&
|
92
|
+
|
93
|
+
raise "Unknown token #{@input}" if token.unknown?
|
94
|
+
@input = "#{prepend_input}#{$'}"
|
95
|
+
|
96
|
+
@previous_token = token
|
97
|
+
token
|
98
|
+
end
|
99
|
+
|
100
|
+
def revert
|
101
|
+
@return_previous_token = true
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
data/lib/wikicloth/parser.rb
CHANGED
@@ -80,21 +80,21 @@ module WikiCloth
|
|
80
80
|
|
81
81
|
# Replace a section, along with any sub-section in the document
|
82
82
|
def put_section(id,data)
|
83
|
-
data = @wikicloth.sections.
|
83
|
+
data = @wikicloth.sections.collect { |s| s.wikitext({ :replace => { id => data.last(1) == "\n" ? data : "#{data}\n" } }) }.join
|
84
84
|
@wikicloth = WikiCloth.new(:data => data, :link_handler => self, :params => @params)
|
85
85
|
end
|
86
86
|
|
87
87
|
# Get the section, along with any sub-section of the document
|
88
88
|
def get_section(id)
|
89
|
-
@wikicloth.sections.
|
89
|
+
@wikicloth.sections.collect { |s| s.get_section(id) }.join
|
90
90
|
end
|
91
91
|
|
92
92
|
def sections
|
93
93
|
@wikicloth.sections
|
94
94
|
end
|
95
95
|
|
96
|
-
def to_html
|
97
|
-
@wikicloth.to_html
|
96
|
+
def to_html(opts = {})
|
97
|
+
@wikicloth.to_html(opts)
|
98
98
|
end
|
99
99
|
|
100
100
|
def to_wiki
|
@@ -102,7 +102,7 @@ module WikiCloth
|
|
102
102
|
end
|
103
103
|
|
104
104
|
def to_wikitext
|
105
|
-
@wikicloth.sections.
|
105
|
+
@wikicloth.sections.collect { |s| s.wikitext() }.join
|
106
106
|
end
|
107
107
|
|
108
108
|
end
|
data/lib/wikicloth/section.rb
CHANGED
@@ -0,0 +1,41 @@
|
|
1
|
+
# not actually used by wikicloth atm
|
2
|
+
module WikiCloth
|
3
|
+
|
4
|
+
class Token
|
5
|
+
OpenRes = 1
|
6
|
+
CloseRes = 2
|
7
|
+
OpenLink = 3
|
8
|
+
CloseLink = 4
|
9
|
+
Heading = 5
|
10
|
+
Word = 6
|
11
|
+
NewLine = 7
|
12
|
+
OpenElement = 8
|
13
|
+
CloseElement = 9
|
14
|
+
Equals = 10
|
15
|
+
Quote = 11
|
16
|
+
BeginComment = 12
|
17
|
+
EndComment = 13
|
18
|
+
BeginTable = 14
|
19
|
+
EndTable = 15
|
20
|
+
Pipe = 16
|
21
|
+
BoldItalic = 17
|
22
|
+
ListItem = 18
|
23
|
+
Signature = 19
|
24
|
+
Space = 20
|
25
|
+
Colon = 21
|
26
|
+
End = 22
|
27
|
+
|
28
|
+
attr_accessor :kind
|
29
|
+
attr_accessor :value
|
30
|
+
|
31
|
+
def initialize
|
32
|
+
@kind = nil
|
33
|
+
@value = nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def unknown?
|
37
|
+
@kind.nil?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -20,7 +20,19 @@ class WikiBuffer::HTMLElement < WikiBuffer
|
|
20
20
|
@in_quotes = false
|
21
21
|
@in_single_quotes = false
|
22
22
|
@start_tag = 1
|
23
|
-
@tag_check = check
|
23
|
+
@tag_check = check
|
24
|
+
end
|
25
|
+
|
26
|
+
def debug
|
27
|
+
case self.element_name
|
28
|
+
when "template"
|
29
|
+
self.get_param("__name")
|
30
|
+
else
|
31
|
+
ret = self.element_name
|
32
|
+
tmp = self.get_param("id")
|
33
|
+
ret += tmp.nil? ? "" : "##{tmp}"
|
34
|
+
ret
|
35
|
+
end
|
24
36
|
end
|
25
37
|
|
26
38
|
def run_globals?
|
@@ -42,6 +54,12 @@ class WikiBuffer::HTMLElement < WikiBuffer
|
|
42
54
|
|
43
55
|
lhandler = @options[:link_handler]
|
44
56
|
case self.element_name
|
57
|
+
when "template"
|
58
|
+
return self.element_content
|
59
|
+
when "noinclude"
|
60
|
+
return self.in_template? ? "" : self.element_content
|
61
|
+
when "includeonly"
|
62
|
+
return self.in_template? ? self.element_content : ""
|
45
63
|
when "ref"
|
46
64
|
self.element_name = "sup"
|
47
65
|
named_ref = self.name_attribute
|
@@ -69,6 +87,8 @@ class WikiBuffer::HTMLElement < WikiBuffer
|
|
69
87
|
}.to_s
|
70
88
|
when "nowiki"
|
71
89
|
return self.element_content
|
90
|
+
when "a"
|
91
|
+
return @options[:link_handler].external_link(self.element_attributes['href'], self.element_content)
|
72
92
|
end
|
73
93
|
|
74
94
|
tmp = elem.tag!(self.element_name, self.element_attributes) { |x| x << self.element_content }
|
@@ -8,10 +8,30 @@ class WikiBuffer::Var < WikiBuffer
|
|
8
8
|
super(data,options)
|
9
9
|
self.buffer_type = "var"
|
10
10
|
@in_quotes = false
|
11
|
+
@tag_start = true
|
12
|
+
@tag_size = 2
|
13
|
+
@close_size = 2
|
14
|
+
@fname = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def tag_size
|
18
|
+
@tag_size
|
19
|
+
end
|
20
|
+
|
21
|
+
def tag_size=(val)
|
22
|
+
@tag_size = val
|
11
23
|
end
|
12
24
|
|
13
25
|
def skip_html?
|
14
|
-
|
26
|
+
false
|
27
|
+
end
|
28
|
+
|
29
|
+
def tag_start
|
30
|
+
@tag_start
|
31
|
+
end
|
32
|
+
|
33
|
+
def tag_start=(val)
|
34
|
+
@tag_start = val
|
15
35
|
end
|
16
36
|
|
17
37
|
def function_name
|
@@ -23,27 +43,35 @@ class WikiBuffer::Var < WikiBuffer
|
|
23
43
|
ret = default_functions(function_name,params.collect { |p| p.strip })
|
24
44
|
ret ||= @options[:link_handler].function(function_name, params.collect { |p| p.strip })
|
25
45
|
ret.to_s
|
46
|
+
elsif self.is_param?
|
47
|
+
ret = nil
|
48
|
+
@options[:buffer].buffers.reverse.each do |b|
|
49
|
+
ret = b.get_param(params[0],params[1]) if b.instance_of?(WikiBuffer::HTMLElement) && b.element_name == "template"
|
50
|
+
end
|
51
|
+
ret.to_s
|
26
52
|
else
|
27
|
-
ret = @options[:link_handler].include_resource("#{params[0]}".strip,params[1..-1])
|
28
|
-
# template params
|
29
|
-
ret = ret.to_s.gsub(/\{\{\{\s*([A-Za-z0-9]+)+(|\|+([^}]+))\s*\}\}\}/) { |match| get_param($1.strip,$3.to_s.strip) }
|
30
53
|
# put template at beginning of buffer
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
54
|
+
template_stack = @options[:buffer].buffers.collect { |b| b.get_param("__name") if b.instance_of?(WikiBuffer::HTMLElement) &&
|
55
|
+
b.element_name == "template" }.compact
|
56
|
+
if template_stack.last == params[0]
|
57
|
+
debug_tree = @options[:buffer].buffers.collect { |b| b.debug }.join("-->")
|
58
|
+
"<span class=\"error\">Template loop detected: {{#{debug_tree}}}</span>"
|
59
|
+
else
|
60
|
+
ret = @options[:link_handler].include_resource("#{params[0]}".strip,params[1..-1]).to_s
|
61
|
+
ret.gsub!(/<!--(.|\s)*?-->/,"")
|
62
|
+
count = 0
|
63
|
+
tag_attr = self.params[1..-1].collect { |p|
|
64
|
+
if p.instance_of?(Hash)
|
65
|
+
"#{p[:name]}=\"#{p[:value]}\""
|
66
|
+
else
|
67
|
+
count += 1
|
68
|
+
"#{count}=\"#{p}\""
|
69
|
+
end
|
70
|
+
}.join(" ")
|
71
|
+
self.data = ret.blank? ? "" : "<template __name=\"#{params[0]}\" #{tag_attr}>#{ret}</template>"
|
72
|
+
""
|
73
|
+
end
|
45
74
|
end
|
46
|
-
ret.nil? ? default : ret
|
47
75
|
end
|
48
76
|
|
49
77
|
def default_functions(name,params)
|
@@ -51,11 +79,19 @@ class WikiBuffer::Var < WikiBuffer
|
|
51
79
|
when "#if"
|
52
80
|
params.first.blank? ? params[2] : params[1]
|
53
81
|
when "#switch"
|
54
|
-
params.
|
55
|
-
|
56
|
-
|
82
|
+
match = params.first
|
83
|
+
default = nil
|
84
|
+
for p in params[1..-1]
|
85
|
+
temp = p.split("=")
|
86
|
+
if temp.length == 1 && p == params.last
|
87
|
+
return p
|
88
|
+
elsif temp.instance_of?(Array) && temp.length > 1
|
89
|
+
test = temp.first.strip
|
90
|
+
default = temp[1].strip if test == "#default"
|
91
|
+
return temp[1].strip if test == match
|
92
|
+
end
|
57
93
|
end
|
58
|
-
|
94
|
+
default.nil? ? "" : default
|
59
95
|
when "#expr"
|
60
96
|
begin
|
61
97
|
ExpressionParser::Parser.new.parse(params.first)
|
@@ -96,9 +132,32 @@ class WikiBuffer::Var < WikiBuffer
|
|
96
132
|
params.first[0,1].downcase + params.first[1,-1]
|
97
133
|
when "plural"
|
98
134
|
params.first.to_i > 1 ? params[1] : params[2]
|
135
|
+
when "debug"
|
136
|
+
ret = nil
|
137
|
+
case params.first
|
138
|
+
when "param"
|
139
|
+
@options[:buffer].buffers.reverse.each do |b|
|
140
|
+
if b.instance_of?(WikiBuffer::HTMLElement) && b.element_name == "template"
|
141
|
+
ret = b.get_param(params[1])
|
142
|
+
end
|
143
|
+
end
|
144
|
+
ret
|
145
|
+
when "buffer"
|
146
|
+
ret = "<pre>"
|
147
|
+
buffer = @options[:buffer].buffers
|
148
|
+
buffer.each do |b|
|
149
|
+
ret += " --- #{b.class}"
|
150
|
+
ret += b.instance_of?(WikiBuffer::HTMLElement) ? " -- #{b.element_name}\n" : " -- #{b.data}\n"
|
151
|
+
end
|
152
|
+
"#{ret}</pre>"
|
153
|
+
end
|
99
154
|
end
|
100
155
|
end
|
101
156
|
|
157
|
+
def is_param?
|
158
|
+
@tag_size == 3 ? true : false
|
159
|
+
end
|
160
|
+
|
102
161
|
def is_function?
|
103
162
|
self.function_name.nil? || self.function_name.blank? ? false : true
|
104
163
|
end
|
@@ -129,13 +188,30 @@ class WikiBuffer::Var < WikiBuffer
|
|
129
188
|
|
130
189
|
# End of a template, variable, or function
|
131
190
|
when current_char == '}' && previous_char == '}'
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
191
|
+
if @close_size == @tag_size
|
192
|
+
self.data.chop!
|
193
|
+
self.current_param = self.data
|
194
|
+
self.data = ""
|
195
|
+
return false
|
196
|
+
else
|
197
|
+
@close_size += 1
|
198
|
+
end
|
136
199
|
|
137
200
|
else
|
138
201
|
self.data += current_char
|
202
|
+
if @tag_start
|
203
|
+
# FIXME: template params and templates colliding
|
204
|
+
if @tag_size > 3
|
205
|
+
if @tag_size == 5
|
206
|
+
@options[:buffer].buffers << WikiBuffer::Var.new(self.data,@options)
|
207
|
+
@options[:buffer].buffers[-1].tag_start = false
|
208
|
+
self.data = ""
|
209
|
+
@tag_size = 3
|
210
|
+
return true
|
211
|
+
end
|
212
|
+
end
|
213
|
+
@tag_start = false
|
214
|
+
end
|
139
215
|
end
|
140
216
|
|
141
217
|
return true
|
@@ -3,18 +3,29 @@ class WikiBuffer
|
|
3
3
|
|
4
4
|
def initialize(data="",options={})
|
5
5
|
@options = options
|
6
|
+
@options[:buffer] ||= self
|
6
7
|
self.data = data
|
7
8
|
self.buffer_type = nil
|
8
9
|
@section_count = 0
|
9
10
|
@buffers ||= [ ]
|
10
11
|
@buffers << self
|
11
12
|
@list_data = []
|
13
|
+
@check_new_tag = false
|
14
|
+
@indent = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def debug
|
18
|
+
self.params[0]
|
12
19
|
end
|
13
20
|
|
14
21
|
def run_globals?
|
15
22
|
true
|
16
23
|
end
|
17
24
|
|
25
|
+
def buffers
|
26
|
+
@buffers
|
27
|
+
end
|
28
|
+
|
18
29
|
def skip_html?
|
19
30
|
false
|
20
31
|
end
|
@@ -27,6 +38,21 @@ class WikiBuffer
|
|
27
38
|
@params ||= [ "" ]
|
28
39
|
end
|
29
40
|
|
41
|
+
def get_param(name,default=nil)
|
42
|
+
ret = nil
|
43
|
+
self.params.each do |param|
|
44
|
+
ret = param[:value] if param.instance_of?(Hash) && param[:name] == name
|
45
|
+
end
|
46
|
+
ret.nil? ? default : ret
|
47
|
+
end
|
48
|
+
|
49
|
+
def in_template?
|
50
|
+
@options[:buffer].buffers.each do |b|
|
51
|
+
return true if b.instance_of?(WikiBuffer::HTMLElement) && b.element_name == "template"
|
52
|
+
end
|
53
|
+
false
|
54
|
+
end
|
55
|
+
|
30
56
|
def buffer_type
|
31
57
|
@buffer_type
|
32
58
|
end
|
@@ -68,8 +94,12 @@ class WikiBuffer
|
|
68
94
|
case
|
69
95
|
# start variable
|
70
96
|
when previous_char == '{' && current_char == '{'
|
71
|
-
@buffers[-1].
|
72
|
-
|
97
|
+
if @buffers[-1].instance_of?(WikiBuffer::Var) && @buffers[-1].tag_start == true
|
98
|
+
@buffers[-1].tag_size += 1
|
99
|
+
else
|
100
|
+
@buffers[-1].data.chop!
|
101
|
+
@buffers << WikiBuffer::Var.new("",@options)
|
102
|
+
end
|
73
103
|
return true
|
74
104
|
|
75
105
|
# start link
|
@@ -102,7 +132,7 @@ class WikiBuffer
|
|
102
132
|
@buffers[-1].data += tmp.to_s
|
103
133
|
# any data left in the buffer we feed into the parent
|
104
134
|
unless tmp.data.blank?
|
105
|
-
tmp.data.each_char { |
|
135
|
+
tmp.data.each_char { |x| self.add_char(x) }
|
106
136
|
end
|
107
137
|
end
|
108
138
|
end
|
@@ -45,6 +45,10 @@ class WikiLinkHandler
|
|
45
45
|
@external_links ||= []
|
46
46
|
end
|
47
47
|
|
48
|
+
def internal_links
|
49
|
+
@internal_links ||= []
|
50
|
+
end
|
51
|
+
|
48
52
|
def find_reference_by_name(n)
|
49
53
|
references.each { |r| return r if !r[:name].nil? && r[:name].strip == n }
|
50
54
|
return nil
|
@@ -72,6 +76,10 @@ class WikiLinkHandler
|
|
72
76
|
@external_links = val
|
73
77
|
end
|
74
78
|
|
79
|
+
def internal_links=(val)
|
80
|
+
@internal_links = val
|
81
|
+
end
|
82
|
+
|
75
83
|
def url_for(page)
|
76
84
|
"javascript:void(0)"
|
77
85
|
end
|
@@ -81,6 +89,7 @@ class WikiLinkHandler
|
|
81
89
|
end
|
82
90
|
|
83
91
|
def link_for(page, text)
|
92
|
+
self.internal_links << page
|
84
93
|
ltitle = !text.nil? && text.blank? ? self.pipe_trick(page) : text
|
85
94
|
ltitle = page if text.nil?
|
86
95
|
elem.a(link_attributes_for(page)) { |x| x << ltitle.strip }
|
@@ -90,11 +99,6 @@ class WikiLinkHandler
|
|
90
99
|
if self.params.has_key?(resource)
|
91
100
|
self.params[resource]
|
92
101
|
else
|
93
|
-
# FIXME: hack to keep template loops from raising havoc
|
94
|
-
@include_count ||= 0
|
95
|
-
@include_count += 1
|
96
|
-
raise "Page reached maximum number of includes [1000] (possible template loop?)" if @include_count > 100
|
97
|
-
|
98
102
|
ret = template(resource)
|
99
103
|
unless ret.nil?
|
100
104
|
@included_templates ||= {}
|
data/lib/wikicloth.rb
CHANGED
@@ -4,17 +4,19 @@ require File.join(File.expand_path(File.dirname(__FILE__)), "wikicloth", "wiki_b
|
|
4
4
|
require File.join(File.expand_path(File.dirname(__FILE__)), "wikicloth", "wiki_link_handler")
|
5
5
|
require File.join(File.expand_path(File.dirname(__FILE__)), "wikicloth", "parser")
|
6
6
|
require File.join(File.expand_path(File.dirname(__FILE__)), "wikicloth", "section")
|
7
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "wikicloth", "token")
|
8
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "wikicloth", "lexer")
|
7
9
|
String.send(:include, ExtendedString)
|
8
10
|
|
9
11
|
module WikiCloth
|
10
12
|
|
11
|
-
VERSION = "0.
|
13
|
+
VERSION = "0.6.0"
|
12
14
|
|
13
15
|
class WikiCloth
|
14
16
|
|
15
17
|
def initialize(opt={})
|
16
18
|
self.options[:link_handler] = opt[:link_handler] unless opt[:link_handler].nil?
|
17
|
-
self.load(opt[:data],opt[:params]) unless opt[:data].nil?
|
19
|
+
self.load(opt[:data],opt[:params]) unless opt[:data].nil?
|
18
20
|
end
|
19
21
|
|
20
22
|
def load(data,p={})
|
@@ -55,8 +57,9 @@ module WikiCloth
|
|
55
57
|
self.params.merge!({ 'WIKI_VERSION' => ::WikiCloth::VERSION })
|
56
58
|
self.options = { :output => :html, :link_handler => self.link_handler, :params => self.params, :sections => self.sections }.merge(opt)
|
57
59
|
self.options[:link_handler].params = options[:params]
|
58
|
-
data = self.sections.
|
60
|
+
data = self.sections.collect { |s| s.render(self.options) }.join
|
59
61
|
data.gsub!(/<!--(.|\s)*?-->/,"")
|
62
|
+
data << "\n" if data.last(1) != "\n"
|
60
63
|
buffer = WikiBuffer.new("",options)
|
61
64
|
data.each_char { |c| buffer.add_char(c) }
|
62
65
|
buffer.to_s
|
data/run_tests.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'init'
|
1
|
+
require File.join(File.dirname(__FILE__),'init')
|
2
2
|
include WikiCloth
|
3
3
|
|
4
4
|
class WikiParser < WikiCloth::Parser
|
@@ -37,7 +37,7 @@ Dir.glob("sample_documents/*.wiki").each do |x|
|
|
37
37
|
|
38
38
|
start_time = Time.now
|
39
39
|
out_name = "#{x}.html"
|
40
|
-
data = File.open(x) { |x| x.read }
|
40
|
+
data = File.open(x, READ_MODE) { |x| x.read }
|
41
41
|
|
42
42
|
tmp = WikiCloth::Parser.new({
|
43
43
|
:data => data,
|
data/test/test_helper.rb
CHANGED
data/test/wiki_cloth_test.rb
CHANGED
@@ -1,8 +1,125 @@
|
|
1
|
-
require 'test_helper'
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'test_helper'))
|
2
|
+
|
3
|
+
class WikiParser < WikiCloth::Parser
|
4
|
+
template do |template|
|
5
|
+
case template
|
6
|
+
when "noinclude"
|
7
|
+
"<noinclude>hello world</noinclude><includeonly>testing</includeonly>"
|
8
|
+
when "test"
|
9
|
+
"busted"
|
10
|
+
when "nowiki"
|
11
|
+
"hello world"
|
12
|
+
when "testparams"
|
13
|
+
"{{{def|hello world}}} {{{1}}} {{{test}}} {{{nested|{{{2}}}}}}"
|
14
|
+
when "moreparamtest"
|
15
|
+
"{{{{{test|bla}}|wtf}}}"
|
16
|
+
when "loop"
|
17
|
+
"{{loop}}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
external_link do |url,text|
|
21
|
+
"<a href=\"#{url}\" target=\"_blank\" class=\"exlink\">#{text.blank? ? url : text}</a>"
|
22
|
+
end
|
23
|
+
end
|
2
24
|
|
3
25
|
class WikiClothTest < ActiveSupport::TestCase
|
4
|
-
|
5
|
-
test "
|
6
|
-
|
26
|
+
|
27
|
+
test "links and references" do
|
28
|
+
wiki = WikiCloth::Parser.new(:data => File.open(File.join(File.dirname(__FILE__), '../sample_documents/george_washington.wiki'), READ_MODE) { |f| f.read })
|
29
|
+
data = wiki.to_html
|
30
|
+
assert wiki.external_links.size == 62
|
31
|
+
assert wiki.references.size == 76
|
32
|
+
assert wiki.internal_links.size == 560
|
33
|
+
end
|
34
|
+
|
35
|
+
test "template params" do
|
36
|
+
wiki = WikiParser.new(:data => "{{testparams|test|test=bla|it worked|bla=whoo}}\n")
|
37
|
+
data = wiki.to_html
|
38
|
+
assert data =~ /hello world/
|
39
|
+
assert data =~ /test/
|
40
|
+
assert data =~ /bla/
|
41
|
+
assert data =~ /it worked/ # nested default param
|
42
|
+
|
43
|
+
wiki = WikiParser.new(:data => "{{moreparamtest|p=othervar}}")
|
44
|
+
data = wiki.to_html
|
45
|
+
assert data =~ /wtf/
|
46
|
+
|
47
|
+
wiki = WikiParser.new(:data => "{{moreparamtest|p=othervar|busted=whoo}}")
|
48
|
+
data = wiki.to_html
|
49
|
+
assert data =~ /whoo/
|
50
|
+
end
|
51
|
+
|
52
|
+
test "horizontal rule" do
|
53
|
+
wiki = WikiParser.new(:data => "----\n")
|
54
|
+
data = wiki.to_html
|
55
|
+
assert data =~ /hr/
|
56
|
+
end
|
57
|
+
|
58
|
+
test "template loops" do
|
59
|
+
wiki = WikiParser.new(:data => "{{#iferror:{{loop}}|loop detected|wtf}}")
|
60
|
+
data = wiki.to_html
|
61
|
+
assert data =~ /loop detected/
|
62
|
+
end
|
63
|
+
|
64
|
+
test "input with no newline" do
|
65
|
+
wiki = WikiParser.new(:data => "{{test}}")
|
66
|
+
data = wiki.to_html
|
67
|
+
assert data =~ /busted/
|
7
68
|
end
|
69
|
+
|
70
|
+
test "lists" do
|
71
|
+
wiki = WikiParser.new(:data => "* item 1\n* item 2\n* item 3\n")
|
72
|
+
data = wiki.to_html
|
73
|
+
assert data =~ /ul/
|
74
|
+
count = 0
|
75
|
+
# should == 6.. 3 <li>'s and 3 </li>'s
|
76
|
+
data.gsub(/li/) { |ret|
|
77
|
+
count += 1
|
78
|
+
ret
|
79
|
+
}
|
80
|
+
assert count == 6
|
81
|
+
end
|
82
|
+
|
83
|
+
test "noinclude and includeonly tags" do
|
84
|
+
wiki = WikiParser.new(:data => "<noinclude>main page</noinclude><includeonly>never seen</includeonly>{{noinclude}}\n")
|
85
|
+
data = wiki.to_html
|
86
|
+
assert data =~ /testing/
|
87
|
+
assert data =~ /main page/
|
88
|
+
assert !(data =~ /never seen/)
|
89
|
+
assert !(data =~ /hello world/)
|
90
|
+
end
|
91
|
+
|
92
|
+
test "bold/italics" do
|
93
|
+
wiki = WikiParser.new(:data => "test ''testing'' '''123''' '''''echo'''''\n")
|
94
|
+
data = wiki.to_html
|
95
|
+
assert data =~ /<i>testing<\/i>/
|
96
|
+
assert data =~ /<b>123<\/b>/
|
97
|
+
assert data =~ /<b><i>echo<\/i><\/b>/
|
98
|
+
end
|
99
|
+
|
100
|
+
test "sanitize html" do
|
101
|
+
wiki = WikiParser.new(:data => "<script type=\"text/javascript\" src=\"bla.js\"></script>\n<a href=\"test.html\" onmouseover=\"alert('hello world');\">test</a>\n")
|
102
|
+
data = wiki.to_html
|
103
|
+
assert !(data =~ /<script/)
|
104
|
+
assert !(data =~ /onmouseover/)
|
105
|
+
assert data =~ /exlink/
|
106
|
+
end
|
107
|
+
|
108
|
+
test "nowiki and code tags" do
|
109
|
+
wiki = WikiParser.new(:data => "<nowiki>{{test}}</nowiki><code>{{test}}</code>{{nowiki}}\n")
|
110
|
+
data = wiki.to_html
|
111
|
+
assert !(data =~ /busted/)
|
112
|
+
assert data =~ /hello world/
|
113
|
+
end
|
114
|
+
|
115
|
+
test "disable edit stuff" do
|
116
|
+
wiki = WikiParser.new(:data => "= Hallo =")
|
117
|
+
data = wiki.to_html
|
118
|
+
assert_equal data, "<p>\n<h1><span class=\"editsection\">[<a href=\"?section=Hallo\" target=\"_blank\" class=\"exlink\">edit</a>]</span> <span class=\"mw-headline\" id=\"Hallo\">Hallo</span></h1>\n</p>"
|
119
|
+
|
120
|
+
data = wiki.to_html(:noedit => true)
|
121
|
+
assert_equal data, "<p>\n<h1> <span class=\"mw-headline\" id=\"Hallo\">Hallo</span></h1>\n</p>"
|
122
|
+
|
123
|
+
end
|
124
|
+
|
8
125
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wikicloth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 7
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 6
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.6.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- David Ricciardi
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-12-23 00:00:00 +00:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -46,6 +46,34 @@ dependencies:
|
|
46
46
|
version: "0"
|
47
47
|
type: :runtime
|
48
48
|
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: test-unit
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
type: :development
|
62
|
+
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: activesupport
|
65
|
+
prerelease: false
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 3
|
72
|
+
segments:
|
73
|
+
- 0
|
74
|
+
version: "0"
|
75
|
+
type: :development
|
76
|
+
version_requirements: *id004
|
49
77
|
description: mediawiki parser
|
50
78
|
email: nricciar@gmail.com
|
51
79
|
executables: []
|
@@ -57,14 +85,13 @@ extra_rdoc_files:
|
|
57
85
|
- MIT-LICENSE
|
58
86
|
files:
|
59
87
|
- lib/wikicloth.rb
|
60
|
-
- lib/wikicloth/calc.citrus
|
61
|
-
- lib/wikicloth/math.rb
|
62
88
|
- lib/wikicloth/core_ext.rb
|
63
89
|
- lib/wikicloth/wiki_buffer/html_element.rb
|
64
90
|
- lib/wikicloth/wiki_buffer/var.rb
|
65
91
|
- lib/wikicloth/wiki_buffer/table.rb
|
66
|
-
- lib/wikicloth/wiki_buffer/template.rb
|
67
92
|
- lib/wikicloth/wiki_buffer/link.rb
|
93
|
+
- lib/wikicloth/token.rb
|
94
|
+
- lib/wikicloth/lexer.rb
|
68
95
|
- lib/wikicloth/parser.rb
|
69
96
|
- lib/wikicloth/section.rb
|
70
97
|
- lib/wikicloth/wiki_link_handler.rb
|
@@ -84,11 +111,11 @@ files:
|
|
84
111
|
- uninstall.rb
|
85
112
|
- Rakefile
|
86
113
|
- install.rb
|
114
|
+
- README
|
115
|
+
- MIT-LICENSE
|
87
116
|
- test/wiki_cloth_test.rb
|
88
117
|
- test/test_helper.rb
|
89
118
|
- run_tests.rb
|
90
|
-
- README
|
91
|
-
- MIT-LICENSE
|
92
119
|
has_rdoc: true
|
93
120
|
homepage: http://github.com/nricciar/wikicloth
|
94
121
|
licenses: []
|
data/lib/wikicloth/calc.citrus
DELETED
@@ -1,133 +0,0 @@
|
|
1
|
-
# A grammar for mathematical formulas that apply basic mathematical operations
|
2
|
-
# to all numbers, respecting operator precedence and grouping of expressions
|
3
|
-
# while ignoring whitespace.
|
4
|
-
#
|
5
|
-
# An identical grammar that is written using pure Ruby can be found in calc.rb.
|
6
|
-
grammar Calc
|
7
|
-
|
8
|
-
## Hierarchy
|
9
|
-
|
10
|
-
rule term
|
11
|
-
additive | factor
|
12
|
-
end
|
13
|
-
|
14
|
-
rule additive
|
15
|
-
(factor additive_operator term) {
|
16
|
-
def value
|
17
|
-
additive_operator.apply(factor.value, term.value)
|
18
|
-
end
|
19
|
-
}
|
20
|
-
end
|
21
|
-
|
22
|
-
rule factor
|
23
|
-
multiplicative | prefix
|
24
|
-
end
|
25
|
-
|
26
|
-
rule multiplicative
|
27
|
-
(prefix multiplicative_operator factor) {
|
28
|
-
def value
|
29
|
-
multiplicative_operator.apply(prefix.value, factor.value)
|
30
|
-
end
|
31
|
-
}
|
32
|
-
end
|
33
|
-
|
34
|
-
rule prefix
|
35
|
-
prefixed | exponent
|
36
|
-
end
|
37
|
-
|
38
|
-
rule prefixed
|
39
|
-
(unary_operator prefix) {
|
40
|
-
def value
|
41
|
-
unary_operator.apply(prefix.value)
|
42
|
-
end
|
43
|
-
}
|
44
|
-
end
|
45
|
-
|
46
|
-
rule exponent
|
47
|
-
exponential | primary
|
48
|
-
end
|
49
|
-
|
50
|
-
rule exponential
|
51
|
-
(primary exponential_operator exponent) {
|
52
|
-
def value
|
53
|
-
exponential_operator.apply(primary.value, exponent.value)
|
54
|
-
end
|
55
|
-
}
|
56
|
-
end
|
57
|
-
|
58
|
-
rule primary
|
59
|
-
group | number
|
60
|
-
end
|
61
|
-
|
62
|
-
rule group
|
63
|
-
(lparen term rparen) {
|
64
|
-
def value
|
65
|
-
term.value
|
66
|
-
end
|
67
|
-
}
|
68
|
-
end
|
69
|
-
|
70
|
-
## Syntax
|
71
|
-
|
72
|
-
rule number
|
73
|
-
float | integer
|
74
|
-
end
|
75
|
-
|
76
|
-
rule float
|
77
|
-
(digits '.' digits space) {
|
78
|
-
def value
|
79
|
-
text.strip.to_f
|
80
|
-
end
|
81
|
-
}
|
82
|
-
end
|
83
|
-
|
84
|
-
rule integer
|
85
|
-
(digits space) {
|
86
|
-
def value
|
87
|
-
text.strip.to_i
|
88
|
-
end
|
89
|
-
}
|
90
|
-
end
|
91
|
-
|
92
|
-
rule digits
|
93
|
-
[0-9]+ ('_' [0-9]+)*
|
94
|
-
end
|
95
|
-
|
96
|
-
rule additive_operator
|
97
|
-
(('+' | '-') space) {
|
98
|
-
def apply(n1, n2)
|
99
|
-
n1.send(text.strip, n2)
|
100
|
-
end
|
101
|
-
}
|
102
|
-
end
|
103
|
-
|
104
|
-
rule multiplicative_operator
|
105
|
-
(('*' | '/' | '%') space) {
|
106
|
-
def apply(n1, n2)
|
107
|
-
n1.send(text.strip, n2)
|
108
|
-
end
|
109
|
-
}
|
110
|
-
end
|
111
|
-
|
112
|
-
rule exponential_operator
|
113
|
-
('**' space) {
|
114
|
-
def apply(n1, n2)
|
115
|
-
n1 ** n2
|
116
|
-
end
|
117
|
-
}
|
118
|
-
end
|
119
|
-
|
120
|
-
rule unary_operator
|
121
|
-
(('~' | '+' | '-') space) {
|
122
|
-
def apply(n)
|
123
|
-
op = text.strip
|
124
|
-
# Unary + and - require an @.
|
125
|
-
n.send(op == '~' ? op : '%s@' % op)
|
126
|
-
end
|
127
|
-
}
|
128
|
-
end
|
129
|
-
|
130
|
-
rule lparen '(' space end
|
131
|
-
rule rparen ')' space end
|
132
|
-
rule space [ \t\n\r]* end
|
133
|
-
end
|
data/lib/wikicloth/math.rb
DELETED
@@ -1,155 +0,0 @@
|
|
1
|
-
# The following code taken from http://lukaszwrobel.pl/blog/math-parser-part-3-implementation
|
2
|
-
module WikiCloth
|
3
|
-
|
4
|
-
class Token
|
5
|
-
Plus = 0
|
6
|
-
Minus = 1
|
7
|
-
Multiply = 2
|
8
|
-
Divide = 3
|
9
|
-
|
10
|
-
Number = 4
|
11
|
-
|
12
|
-
LParen = 5
|
13
|
-
RParen = 6
|
14
|
-
|
15
|
-
End = 7
|
16
|
-
|
17
|
-
attr_accessor :kind
|
18
|
-
attr_accessor :value
|
19
|
-
|
20
|
-
def initialize
|
21
|
-
@kind = nil
|
22
|
-
@value = nil
|
23
|
-
end
|
24
|
-
|
25
|
-
def unknown?
|
26
|
-
@kind.nil?
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
class Lexer
|
31
|
-
def initialize(input)
|
32
|
-
@input = input
|
33
|
-
@return_previous_token = false
|
34
|
-
end
|
35
|
-
|
36
|
-
def get_next_token
|
37
|
-
if @return_previous_token
|
38
|
-
@return_previous_token = false
|
39
|
-
return @previous_token
|
40
|
-
end
|
41
|
-
|
42
|
-
token = Token.new
|
43
|
-
|
44
|
-
@input.lstrip!
|
45
|
-
|
46
|
-
case @input
|
47
|
-
when /\A\+/ then
|
48
|
-
token.kind = Token::Plus
|
49
|
-
when /\A-/ then
|
50
|
-
token.kind = Token::Minus
|
51
|
-
when /\A\*/ then
|
52
|
-
token.kind = Token::Multiply
|
53
|
-
when /\A\// then
|
54
|
-
token.kind = Token::Divide
|
55
|
-
when /\A\d+(\.\d+)?/
|
56
|
-
token.kind = Token::Number
|
57
|
-
token.value = $&.to_f
|
58
|
-
when /\A\(/
|
59
|
-
token.kind = Token::LParen
|
60
|
-
when /\A\)/
|
61
|
-
token.kind = Token::RParen
|
62
|
-
when ''
|
63
|
-
token.kind = Token::End
|
64
|
-
end
|
65
|
-
|
66
|
-
raise 'Unknown token' if token.unknown?
|
67
|
-
@input = $'
|
68
|
-
|
69
|
-
@previous_token = token
|
70
|
-
token
|
71
|
-
end
|
72
|
-
|
73
|
-
def revert
|
74
|
-
@return_previous_token = true
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
class MathParser
|
79
|
-
def parse(input)
|
80
|
-
@lexer = Lexer.new(input)
|
81
|
-
|
82
|
-
expression_value = expression
|
83
|
-
|
84
|
-
token = @lexer.get_next_token
|
85
|
-
if token.kind == Token::End
|
86
|
-
expression_value
|
87
|
-
else
|
88
|
-
raise 'End expected'
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
protected
|
93
|
-
def expression
|
94
|
-
component1 = factor
|
95
|
-
|
96
|
-
additive_operators = [Token::Plus, Token::Minus]
|
97
|
-
|
98
|
-
token = @lexer.get_next_token
|
99
|
-
while additive_operators.include?(token.kind)
|
100
|
-
component2 = factor
|
101
|
-
|
102
|
-
if token.kind == Token::Plus
|
103
|
-
component1 += component2
|
104
|
-
else
|
105
|
-
component1 -= component2
|
106
|
-
end
|
107
|
-
|
108
|
-
token = @lexer.get_next_token
|
109
|
-
end
|
110
|
-
@lexer.revert
|
111
|
-
|
112
|
-
component1
|
113
|
-
end
|
114
|
-
|
115
|
-
def factor
|
116
|
-
factor1 = number
|
117
|
-
|
118
|
-
multiplicative_operators = [Token::Multiply, Token::Divide]
|
119
|
-
|
120
|
-
token = @lexer.get_next_token
|
121
|
-
while multiplicative_operators.include?(token.kind)
|
122
|
-
factor2 = number
|
123
|
-
|
124
|
-
if token.kind == Token::Multiply
|
125
|
-
factor1 *= factor2
|
126
|
-
else
|
127
|
-
factor1 /= factor2
|
128
|
-
end
|
129
|
-
|
130
|
-
token = @lexer.get_next_token
|
131
|
-
end
|
132
|
-
@lexer.revert
|
133
|
-
|
134
|
-
factor1
|
135
|
-
end
|
136
|
-
|
137
|
-
def number
|
138
|
-
token = @lexer.get_next_token
|
139
|
-
|
140
|
-
if token.kind == Token::LParen
|
141
|
-
value = expression
|
142
|
-
|
143
|
-
expected_rparen = @lexer.get_next_token
|
144
|
-
raise 'Unbalanced parenthesis' unless expected_rparen.kind == Token::RParen
|
145
|
-
elsif token.kind == Token::Number
|
146
|
-
value = token.value
|
147
|
-
else
|
148
|
-
raise 'Not a number'
|
149
|
-
end
|
150
|
-
|
151
|
-
value
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
module WikiCloth
|
2
|
-
|
3
|
-
class WikiBuffer::Template < WikiBuffer
|
4
|
-
|
5
|
-
def initialize(data="",options={})
|
6
|
-
super(data,options)
|
7
|
-
@in_quotes = false
|
8
|
-
end
|
9
|
-
|
10
|
-
def to_s
|
11
|
-
"WICKED COOL"
|
12
|
-
end
|
13
|
-
|
14
|
-
protected
|
15
|
-
def new_char()
|
16
|
-
case
|
17
|
-
# End of a template, variable, or function
|
18
|
-
when current_char == '}' && previous_char == '}'
|
19
|
-
puts "TEMP: #{self.data} ----"
|
20
|
-
self.data = ""
|
21
|
-
return false
|
22
|
-
|
23
|
-
else
|
24
|
-
self.data += current_char
|
25
|
-
end
|
26
|
-
|
27
|
-
return true
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
end
|