facwparser 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in facwparser.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 HARUYAMA Seigo
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Facwparser
2
+
3
+ Fuxxing Atlassian Confluence Wiki Parser
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'facwparser'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install facwparser
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ desc "Run Unit Tests"
4
+ task :test do
5
+ $VERBOSE = true
6
+ exec 'ruby', File.dirname(__FILE__) + '/tests/all_tests.rb'
7
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'facwparser/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "facwparser"
8
+ gem.version = Facwparser::VERSION
9
+ gem.authors = ["HARUYAMA Seigo"]
10
+ gem.email = ["haruyama@unixuser.org"]
11
+ gem.description = %q{Fuxxing Atlassian Confluence Wiki Parser}
12
+ gem.summary = %q{Parser of Atlassian Confluence Wiki Markup.}
13
+ gem.homepage = "https://github.com/haruyama/facwparser"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ end
@@ -0,0 +1,317 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'cgi'
4
+
5
+
6
+ module Facwparser
7
+ module Element
8
+ class ElementBase
9
+ attr_reader :source, :children
10
+ def initialize(source)
11
+ @source = source
12
+ @children = nil
13
+ end
14
+ def ==(other)
15
+ self.class == other.class && self.source == other.source
16
+ end
17
+
18
+ def render_html(options)
19
+ raise "TODO: render_html is not implemented: " + self.class.to_s + "\n"
20
+ end
21
+ end
22
+
23
+ class P < ElementBase
24
+ def append(source)
25
+ @source += source
26
+ end
27
+ def render_html(options)
28
+ if source =~ /\A *bq. (.+)/m
29
+ @children ||= Parser.parse_value($1, options)
30
+ "<blockquote>\n" + @children.map { |c| c.render_html(options) }.join("") + "\n</blockquote>\n"
31
+ else
32
+ @children ||= Parser.parse_value(source, options)
33
+ "<p>\n" + @children.map { |c| c.render_html(options) }.join("") + "</p>\n"
34
+ end
35
+ end
36
+ end
37
+ class HorizontalRule < ElementBase
38
+ def render_html(options)
39
+ "<hr>\n"
40
+ end
41
+ end
42
+ class Heading < ElementBase
43
+ attr_reader :level, :value
44
+ def initialize(source, level, value)
45
+ super(source)
46
+ @level = level
47
+ @value = value
48
+ end
49
+ def render_html(options)
50
+ "<h#{level}>#{CGI.escapeHTML value}</h#{level}>\n"
51
+ end
52
+ end
53
+ class List < ElementBase
54
+ attr_reader :type
55
+ def initialize(type)
56
+ super('')
57
+ @type = type
58
+ end
59
+ def push(item)
60
+ @children ||= []
61
+ @children.push(item)
62
+ self
63
+ end
64
+ def render_html(options)
65
+ case @type
66
+ when '#'
67
+ return "<ol>\n" + @children.map{ |c| c.render_html(options) }.join("") + "</ol>\n"
68
+ else
69
+ return "<ul>\n" + @children.map{ |c| c.render_html(options) }.join("") + "</ul>\n"
70
+ end
71
+ end
72
+ end
73
+ class ListItem < ElementBase
74
+ attr_reader :symbols, :level, :value
75
+ def initialize(source, symbols, value)
76
+ super(source)
77
+ @symbols = symbols
78
+ @level = symbols.size
79
+ @value = value
80
+ end
81
+ def render_html(options)
82
+ @children = Parser.parse_value value, options
83
+ "<li>" + @children.map {|c| c.render_html(options) }.join("") + "</li>\n"
84
+ end
85
+ end
86
+ class Table < ElementBase
87
+ def initialize()
88
+ super('')
89
+ end
90
+ def push(item)
91
+ @children ||= []
92
+ @children.push(item)
93
+ self
94
+ end
95
+ def render_html(options)
96
+ "<table><thead>\n" + @children[0].render_html(options) +
97
+ "\n</thead>\n<tbody>\n" +
98
+ @children.drop(1).map{|c| c.render_html(options)}.join("\n") +
99
+ "\n</tbody></table>\n"
100
+ end
101
+ end
102
+ class TableHeaders < ElementBase
103
+ attr_reader :elements
104
+ def initialize(source)
105
+ super(source)
106
+ @elements = source.split('||')[1..-2]
107
+ end
108
+ def render_html(options)
109
+ "<tr>" +
110
+ @elements.map { |e| '<th>' + Parser.parse_value(e, options).map { |c| c.render_html(options) }.join(" ") + '</th>'}.join() +
111
+ "</tr>"
112
+ end
113
+ end
114
+ class TableData < ElementBase
115
+ attr_reader :elements
116
+ def initialize(source)
117
+ super(source)
118
+ @elements = []
119
+ element = ''
120
+ s = StringScanner.new(source[1..-2])
121
+ in_link = false
122
+ while s.rest?
123
+ case
124
+ when s.scan(/[^|\[\]]+/) || s.scan(/\\\[/) || s.scan(/\\\]/) || s.scan(/\\\|/)
125
+ element += s[0]
126
+ when s.scan(/\[/)
127
+ in_link = true
128
+ element += s[0]
129
+ when s.scan(/\]/)
130
+ in_link = false
131
+ element += s[0]
132
+ when s.scan(/\|/)
133
+ if in_link
134
+ element += s[0]
135
+ else
136
+ @elements << element
137
+ element = ''
138
+ end
139
+ else
140
+ element += s.rest
141
+ break
142
+ end
143
+ end
144
+ @elements << element if !element.empty?
145
+ end
146
+ def render_html(options)
147
+ "<tr>" +
148
+ @elements.map { |e| '<td>' + Parser.parse_value(e, options).map { |c| c.render_html(options) }.join(" ") + '</td>'}.join() +
149
+ "</tr>"
150
+ end
151
+ end
152
+
153
+ class MacroBase < ElementBase
154
+ end
155
+ class TocMacro < MacroBase
156
+ def initialize(source, options = nil)
157
+ super(source)
158
+ @options = options
159
+ end
160
+ def render_html(options)
161
+ "TODO: table of contents Macro\n"
162
+ end
163
+ end
164
+ class PagetreeMacro < MacroBase
165
+ def initialize(source, options = nil)
166
+ super(source)
167
+ @options = options
168
+ end
169
+ def render_html(options)
170
+ "TODO: pagetree macro\n"
171
+ end
172
+ end
173
+ class NoformatMacro < MacroBase
174
+ def initialize(source, value)
175
+ super(source)
176
+ @value = value
177
+ end
178
+ def render_html(options)
179
+ "<pre>\n#{CGI.escapeHTML @value}\n</pre>\n"
180
+ end
181
+ end
182
+ class CodeMacro < MacroBase
183
+ def initialize(source, options, value)
184
+ super(source)
185
+ @options = options
186
+ @value = value
187
+ end
188
+ def render_html(options)
189
+ "<code class=\"code_#{CGI.escapeHTML(@options[1..-1])}\"><pre>\n#{CGI.escapeHTML @value}\n</pre></code>\n"
190
+ end
191
+ end
192
+ class QuoteMacro < MacroBase
193
+ def initialize(source, value)
194
+ super(source)
195
+ @value = value
196
+ end
197
+ def render_html(options)
198
+ "<blockquote>\n#{CGI.escapeHTML @value}\n</blockquote>\n"
199
+ end
200
+ end
201
+
202
+ class InlineElementBase < ElementBase
203
+ attr_reader :text
204
+ def initialize(source, text)
205
+ super(source)
206
+ @text = text
207
+ end
208
+ def ==(other)
209
+ super(other) && self.text == other.text
210
+ end
211
+ end
212
+
213
+ class A < InlineElementBase
214
+ def render_html(options)
215
+ if @text =~ /\A(.+)\|((?:https?|ftp|file):.+)\z/
216
+ return '<a href="' + CGI.escapeHTML($2) +'">' + CGI.escapeHTML($1) + '</a>'
217
+ elsif @text =~ /\A(?:https?|ftp|file):.+\z/
218
+ return '<a href="' + CGI.escapeHTML(@text) +'">' + CGI.escapeHTML(@text) + '</a>'
219
+ else
220
+ return '[' + CGI.escapeHTML(@text) + ']'
221
+ end
222
+ end
223
+ end
224
+
225
+ class Bold < InlineElementBase
226
+ def render_html(options)
227
+ "<b>#{CGI.escapeHTML(@text)}</b>"
228
+ end
229
+ end
230
+
231
+ class Italic < InlineElementBase
232
+ def render_html(options)
233
+ "<i>#{CGI.escapeHTML(@text)}</i>"
234
+ end
235
+ end
236
+
237
+ class Strike < InlineElementBase
238
+ def render_html(options)
239
+ "<s>#{CGI.escapeHTML(@text)}</s>"
240
+ end
241
+ end
242
+
243
+ class Under < InlineElementBase
244
+ def render_html(options)
245
+ "<u>#{CGI.escapeHTML(@text)}</u>"
246
+ end
247
+ end
248
+
249
+ class Q < InlineElementBase
250
+ def render_html(options)
251
+ "<q>#{CGI.escapeHTML(@text)}</q>"
252
+ end
253
+ end
254
+
255
+ class SUP < InlineElementBase
256
+ def render_html(options)
257
+ "<sup>#{CGI.escapeHTML(@text)}</sup>"
258
+ end
259
+ end
260
+
261
+ class SUB < InlineElementBase
262
+ def render_html(options)
263
+ "<sub>#{CGI.escapeHTML(@text)}</sub>"
264
+ end
265
+ end
266
+
267
+ class TT < InlineElementBase
268
+ def render_html(options)
269
+ "<tt>#{CGI.escapeHTML(@text)}</tt>"
270
+ end
271
+ end
272
+
273
+ class Image < InlineElementBase
274
+ def render_html(options)
275
+ '<img src="' + CGI.escapeHTML(@text) + '">'
276
+ end
277
+ end
278
+
279
+ class JiraMacro < MacroBase
280
+ attr_reader :options
281
+ def initialize(source, options)
282
+ super(source)
283
+ @options = options
284
+ end
285
+ def render_html(options)
286
+ jira_browse_url = (options && options['jira_browse_url']) || ''
287
+ return '<a href="' + CGI.escapeHTML(jira_browse_url) + CGI.escapeHTML(@options) +'">' + CGI.escapeHTML(@options) + '</a>'
288
+ end
289
+ end
290
+
291
+ class ColorMacroStart < MacroBase
292
+ attr_reader :options
293
+ def initialize(source, options)
294
+ super(source)
295
+ @options = options
296
+ end
297
+ def render_html(options)
298
+ return '<font color="' + CGI.escapeHTML(@options) +'">'
299
+ end
300
+ end
301
+
302
+ class ColorMacroEnd < MacroBase
303
+ def initialize(source)
304
+ super(source)
305
+ end
306
+ def render_html(options)
307
+ return '</font>'
308
+ end
309
+ end
310
+
311
+ class Text < InlineElementBase
312
+ def render_html(options)
313
+ CGI.escapeHTML @source
314
+ end
315
+ end
316
+ end
317
+ end
@@ -0,0 +1,178 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'strscan'
4
+
5
+ require File.dirname(__FILE__) + '/element'
6
+
7
+ module Facwparser
8
+ module Parser
9
+ def self.parse(content, options = {})
10
+ elements = parse1(content, options)
11
+ process_elements(elements, options)
12
+ end
13
+
14
+ def self.process_elements(elements, options)
15
+ # TODO toc
16
+ processed = add_list_elements(elements, options)
17
+ add_table_elements(processed, options)
18
+ end
19
+
20
+ def self.add_list_elements(elements, options)
21
+ processed = []
22
+ list_stack = []
23
+ elements.each { |e|
24
+ case
25
+ when e.class == Element::ListItem
26
+ while list_stack.size > e.level
27
+ list_stack.pop
28
+ end
29
+ while list_stack.size < e.level
30
+ list = Element::List.new(e.symbols[list_stack.size])
31
+ if list_stack.empty?
32
+ processed << list
33
+ else
34
+ list_stack[-1].push list
35
+ end
36
+ list_stack << list
37
+ end
38
+ list_stack[-1].push e
39
+ else
40
+ list_stack.clear if list_stack.size > 0
41
+ processed << e
42
+ end
43
+ }
44
+ processed
45
+ end
46
+
47
+ def self.add_table_elements(elements, options)
48
+ processed = []
49
+ table = nil
50
+ elements.each { |e|
51
+ case
52
+ when e.class == Element::TableHeaders || e.class == Element::TableData
53
+ if !table
54
+ table = Element::Table.new
55
+ processed << table
56
+ end
57
+ table.push e
58
+ else
59
+ table = nil
60
+ processed << e
61
+ end
62
+ }
63
+ processed
64
+ end
65
+
66
+ def self.parse1(content, options)
67
+ s = StringScanner.new(content.gsub("\r", '').gsub(/[\t\f]/, ' ') + "\n")
68
+
69
+ elements = []
70
+
71
+ p = nil
72
+
73
+ while s.rest?
74
+ case
75
+ when s.scan(/h(\d)\. +(.+)\n/)
76
+ p = nil
77
+ elements << Element::Heading.new(s[0], s[1].to_i, s[2])
78
+ when s.scan(/----+\n/)
79
+ p = nil
80
+ elements << Element::HorizontalRule.new(s[0])
81
+ when s.scan(/([*\-#]+) +(.+)\n/)
82
+ p = nil
83
+ elements << Element::ListItem.new(s[0], s[1], s[2])
84
+ when s.scan(/\|\|.+\|\| *\n/)
85
+ p = nil
86
+ elements << Element::TableHeaders.new(s[0])
87
+ when s.scan(/\|.+\| *\n/)
88
+ p = nil
89
+ elements << Element::TableData.new(s[0])
90
+ when s.scan(/\{toc(:.*)?\} *\n/)
91
+ p = nil
92
+ elements << Element::TocMacro.new(s[0], s[1] ? s[1][1,] : nil)
93
+ when s.scan(/\{pagetree(:.*)?\} *\n/)
94
+ p = nil
95
+ elements << Element::PagetreeMacro.new(s[0], s[1] ? s[1][1,] : nil)
96
+ when s.scan(/\{noformat\} *\n(?m)(.+?\n)\{noformat\} *\n/)
97
+ p = nil
98
+ elements << Element::NoformatMacro.new(s[0], s[1])
99
+ when s.scan(/\{code(:.*?)?\} *\n(?m)(.+?\n)\{code\} *\n/)
100
+ p = nil
101
+ elements << Element::CodeMacro.new(s[0], s[1], s[2])
102
+ when s.scan(/\{quote\} *\n(?m)(.+?\n)\{quote\} *\n/)
103
+ p = nil
104
+ elements << Element::QuoteMacro.new(s[0], s[1])
105
+ when s.scan(/ *\n/)
106
+ p = nil
107
+ when s.scan(/(.+)\n/)
108
+ if p
109
+ p.append(s[0])
110
+ else
111
+ p = Element::P.new(s[0])
112
+ elements << p
113
+ end
114
+ else
115
+ raise "Parse Error. line=#{s.rest}"
116
+ end
117
+ end
118
+ elements
119
+ end
120
+
121
+ def self.unescape_text(text)
122
+ text.gsub(/\\([\[\]\*+_?{}!^~-])/) {
123
+ $1
124
+ }
125
+ end
126
+
127
+ def self.parse_value(value, options)
128
+
129
+ #jira
130
+ #img
131
+
132
+ children = []
133
+
134
+ value.split("\n").each { |l|
135
+ s = StringScanner.new(l)
136
+ while s.rest?
137
+ case
138
+ when s.scan(/\[(.+?)(?<!\\)\]/)
139
+ children << Element::A.new(s[0], unescape_text(s[1]))
140
+ when s.scan(/\*(.+?)(?<!\\)\*/)
141
+ children << Element::Bold.new(s[0], unescape_text(s[1]))
142
+ when s.scan(/\_(.+?)(?<!\\)\_/)
143
+ children << Element::Italic.new(s[0], unescape_text(s[1]))
144
+ when s.scan(/\-(.+?)(?<!\\)\-/)
145
+ children << Element::Strike.new(s[0], unescape_text(s[1]))
146
+ when s.scan(/\+(.+?)(?<!\\)\+/)
147
+ children << Element::Under.new(s[0], unescape_text(s[1]))
148
+ when s.scan(/\^(.+?)(?<!\\)\^/)
149
+ children << Element::SUP.new(s[0], unescape_text(s[1]))
150
+ when s.scan(/\~(.+?)(?<!\\)\~/)
151
+ children << Element::SUB.new(s[0], unescape_text(s[1]))
152
+ when s.scan(/\?\?(.+?)(?<!\\)\?\?/)
153
+ children << Element::Q.new(s[0], unescape_text(s[1]))
154
+ when s.scan(/\{\{(.+?)(?<!\\)\}\}/)
155
+ children << Element::TT.new(s[0], unescape_text(s[1]))
156
+ when s.scan(/\!(https?:(?:.+?))(?<!\\)\!/)
157
+ children << Element::Image.new(s[0], unescape_text(s[1]))
158
+ when s.scan(/\{jira:(.+?)(?<!\\)\}/)
159
+ children << Element::JiraMacro.new(s[0], unescape_text(s[1]))
160
+ when s.scan(/\{color:(.+?)(?<!\\)\}/)
161
+ children << Element::ColorMacroStart.new(s[0], unescape_text(s[1]))
162
+ when s.scan(/\{color\}/)
163
+ children << Element::ColorMacroEnd.new(s[0])
164
+ when s.scan(/[^\[^\\*_+{!-]+/)
165
+ children << Element::Text.new(s[0], unescape_text(s[0]))
166
+ when s.scan(/\\[\[\]\*+_?{}!^~-]/)
167
+ children << Element::Text.new(s[0], unescape_text(s[0]))
168
+ else
169
+ children << Element::Text.new(s.rest, unescape_text(s.rest))
170
+ break
171
+ end
172
+ end
173
+ }
174
+
175
+ children
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,15 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require File.dirname(__FILE__) + '/element'
4
+
5
+ module Facwparser
6
+ module Render
7
+ def self.render_html(elements, options = {})
8
+ output = ''
9
+ elements.each { |e|
10
+ output += e.render_html(options)
11
+ }
12
+ output
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ module Facwparser
2
+ VERSION = "0.0.1"
3
+ end
data/lib/facwparser.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'facwparser/version'
2
+ require 'facwparser/parser'
3
+ require 'facwparser/render'
4
+
5
+ module Facwparser
6
+ def self.to_html(source, options = nil)
7
+ Render.render_html(Parser.parse(source, options), options) + "\n"
8
+ end
9
+ end
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- encoding: utf-8 -*-
3
+ require 'facwparser'
4
+
5
+ print <<EOS
6
+ <!DOCTYPE html>
7
+ <html>
8
+ <head>
9
+ <title>sample</title>
10
+ </head>
11
+ <body>
12
+ EOS
13
+ print Facwparser.to_html(ARGF.read)
14
+ print <<EOS
15
+ </body>
16
+ </html>
17
+ EOS
@@ -0,0 +1,3 @@
1
+ Dir.chdir(File.dirname(__FILE__)) do
2
+ Dir.glob('**/test_*.rb') { |test_case| require './' + test_case }
3
+ end
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'test/unit'
3
+ require File.dirname(__FILE__) + '/../../../lib/facwparser/parser'
4
+
5
+
6
+ class TestAddListElements < Test::Unit::TestCase
7
+
8
+ def test_add_list_elements_1
9
+ pre = [
10
+ Facwparser::Element::ListItem.new("* 4\n", '*', '4'),
11
+ Facwparser::Element::ListItem.new("** 5\n", '**', '5'),
12
+ Facwparser::Element::ListItem.new("**# 6\n", '**#', '6'),
13
+ ]
14
+
15
+ assert_equal([
16
+ Facwparser::Element::List.new('*').push(
17
+ Facwparser::Element::ListItem.new("* 4\n", '*', '4')).push(
18
+ Facwparser::Element::List.new('*').push(
19
+ Facwparser::Element::ListItem.new("** 5\n", '**', '5')).push(
20
+ Facwparser::Element::List.new('#').push(
21
+ Facwparser::Element::ListItem.new("**# 6\n", '**#', '6'))
22
+ ))
23
+ ], Facwparser::Parser.add_list_elements(pre, {}))
24
+
25
+ end
26
+
27
+ end
28
+
@@ -0,0 +1,214 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'test/unit'
3
+ require File.dirname(__FILE__) + '/../../../lib/facwparser/parser'
4
+
5
+
6
+ class TestParse1 < Test::Unit::TestCase
7
+
8
+ def test_parse1_p
9
+ source =<<EOS
10
+ ほげ
11
+
12
+ ほげほげ
13
+
14
+ ほげほげげほ
15
+ にゃ
16
+ EOS
17
+ assert_equal(
18
+ [
19
+ Facwparser::Element::P.new("ほげ\n"),
20
+ Facwparser::Element::P.new("ほげほげ\n"),
21
+ Facwparser::Element::P.new("ほげほげげほ\nにゃ\n"),
22
+ ],
23
+ Facwparser::Parser.parse1(source, {}))
24
+
25
+ end
26
+
27
+ def test_parse1_heading
28
+ source =<<EOS
29
+ h1. ほげ
30
+
31
+ ほげほげ
32
+ h3. ほげほげげほ
33
+ にゃ
34
+ EOS
35
+ assert_equal(
36
+ [
37
+ Facwparser::Element::Heading.new("h1. ほげ\n", 1, "ほげ"),
38
+ Facwparser::Element::P.new("ほげほげ\n"),
39
+ Facwparser::Element::Heading.new("h3. ほげほげげほ\n", 3, "ほげほげげほ"),
40
+ Facwparser::Element::P.new("にゃ\n"),
41
+ ],
42
+ Facwparser::Parser.parse1(source, {}))
43
+
44
+ end
45
+
46
+ def test_parse1_horizontal_rule
47
+ source =<<EOS
48
+ 1
49
+ ----
50
+ 2
51
+ ---
52
+ 3
53
+
54
+ -----
55
+ 4
56
+ EOS
57
+ assert_equal(
58
+ [
59
+ Facwparser::Element::P.new("1\n"),
60
+ Facwparser::Element::HorizontalRule.new("----\n"),
61
+ Facwparser::Element::P.new("2\n---\n3\n"),
62
+ Facwparser::Element::HorizontalRule.new("-----\n"),
63
+ Facwparser::Element::P.new("4\n"),
64
+ ],
65
+ Facwparser::Parser.parse1(source, {}))
66
+
67
+ end
68
+
69
+ def test_parse1_list_item
70
+ source =<<EOS
71
+ 1
72
+ - 2
73
+ 3
74
+ ** 4
75
+ ### 5
76
+ #*#* 6
77
+ EOS
78
+ assert_equal(
79
+ [
80
+ Facwparser::Element::P.new("1\n"),
81
+ Facwparser::Element::ListItem.new("- 2\n", '-', '2'),
82
+ Facwparser::Element::P.new("3\n"),
83
+ Facwparser::Element::ListItem.new("** 4\n", '**', '4'),
84
+ Facwparser::Element::ListItem.new("### 5\n", '###', '5'),
85
+ Facwparser::Element::ListItem.new("#*#* 6\n", '#*#*', '6'),
86
+ ],
87
+ Facwparser::Parser.parse1(source, {}))
88
+
89
+ end
90
+
91
+ def test_parse1_table
92
+ source =<<EOS
93
+ 1
94
+ ||2||3||
95
+ |4|5|
96
+ 6
97
+ EOS
98
+ assert_equal(
99
+ [
100
+ Facwparser::Element::P.new("1\n"),
101
+ Facwparser::Element::TableHeaders.new("||2||3||\n"),
102
+ Facwparser::Element::TableData.new("|4|5|\n"),
103
+ Facwparser::Element::P.new("6\n"),
104
+ ],
105
+ Facwparser::Parser.parse1(source, {}))
106
+
107
+ end
108
+
109
+ def test_parse1_toc_1
110
+ source =<<EOS
111
+ 1
112
+ {toc}
113
+ 2
114
+ EOS
115
+ assert_equal(
116
+ [
117
+ Facwparser::Element::P.new("1\n"),
118
+ Facwparser::Element::TocMacro.new("{toc}\n"),
119
+ Facwparser::Element::P.new("2\n"),
120
+ ],
121
+ Facwparser::Parser.parse1(source, {}))
122
+
123
+ end
124
+
125
+ def test_parse1_toc_2
126
+ source =<<EOS
127
+ 1
128
+ {toc:maxLevel=3}
129
+ 2
130
+ EOS
131
+ assert_equal(
132
+ [
133
+ Facwparser::Element::P.new("1\n"),
134
+ Facwparser::Element::TocMacro.new("{toc:maxLevel=3}\n", 'maxLevel=3'),
135
+ Facwparser::Element::P.new("2\n"),
136
+ ],
137
+ Facwparser::Parser.parse1(source, {}))
138
+
139
+ end
140
+
141
+ def test_parse1_pagetree
142
+ source =<<EOS
143
+ 1
144
+ {pagetree:root=@self}
145
+ 2
146
+ EOS
147
+ assert_equal(
148
+ [
149
+ Facwparser::Element::P.new("1\n"),
150
+ Facwparser::Element::PagetreeMacro.new("{pagetree:root=@self}\n", 'root=@self'),
151
+ Facwparser::Element::P.new("2\n"),
152
+ ],
153
+ Facwparser::Parser.parse1(source, {}))
154
+
155
+ end
156
+
157
+ def test_parse1_noformat
158
+ source =<<EOS
159
+ 1
160
+ {noformat}
161
+ 2
162
+ 3
163
+ {noformat}
164
+ 4
165
+ EOS
166
+ assert_equal(
167
+ [
168
+ Facwparser::Element::P.new("1\n"),
169
+ Facwparser::Element::NoformatMacro.new("{noformat}\n2\n3\n{noformat}\n", "2\n3\n"),
170
+ Facwparser::Element::P.new("4\n"),
171
+ ],
172
+ Facwparser::Parser.parse1(source, {}))
173
+
174
+ end
175
+
176
+ def test_parse1_code
177
+ source =<<EOS
178
+ 1
179
+ {code:ruby}
180
+ a = 1 + 2
181
+ 3
182
+ {code}
183
+ 4
184
+ EOS
185
+ assert_equal(
186
+ [
187
+ Facwparser::Element::P.new("1\n"),
188
+ Facwparser::Element::CodeMacro.new("{code:ruby}\na = 1 + 2\n3\n{code}\n", 'ruby', "a = 1 + 2\n3\n"),
189
+ Facwparser::Element::P.new("4\n"),
190
+ ],
191
+ Facwparser::Parser.parse1(source, {}))
192
+
193
+ end
194
+
195
+ def test_parse1_quote
196
+ source =<<EOS
197
+ 1
198
+ {quote}
199
+ 2
200
+ 3
201
+ {quote}
202
+ 4
203
+ EOS
204
+ assert_equal(
205
+ [
206
+ Facwparser::Element::P.new("1\n"),
207
+ Facwparser::Element::QuoteMacro.new("{quote}\n2\n3\n{quote}\n", "2\n3\n"),
208
+ Facwparser::Element::P.new("4\n"),
209
+ ],
210
+ Facwparser::Parser.parse1(source, {}))
211
+
212
+ end
213
+
214
+ end
@@ -0,0 +1,110 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'test/unit'
3
+ require File.dirname(__FILE__) + '/../../../lib/facwparser/parser'
4
+
5
+
6
+ class TestParseValue < Test::Unit::TestCase
7
+
8
+ def test_parse_value_text
9
+ assert_equal([
10
+ Facwparser::Element::Text.new('1', '1')
11
+ ], Facwparser::Parser.parse_value('1', {}))
12
+ assert_equal([
13
+ Facwparser::Element::Text.new('1', '1'),
14
+ Facwparser::Element::Text.new('2', '2')
15
+ ], Facwparser::Parser.parse_value("1\n2", {}))
16
+ end
17
+
18
+ def test_parse_value_a
19
+ assert_equal([
20
+ Facwparser::Element::Text.new('1', '1'),
21
+ Facwparser::Element::A.new('[hoge]', 'hoge'),
22
+ Facwparser::Element::Text.new('2', '2')
23
+ ], Facwparser::Parser.parse_value('1[hoge]2', {}))
24
+ assert_equal([
25
+ Facwparser::Element::Text.new('1', '1'),
26
+ Facwparser::Element::A.new('[hoge\]]', 'hoge]'),
27
+ Facwparser::Element::Text.new('2', '2')
28
+ ], Facwparser::Parser.parse_value('1[hoge\]]2', {}))
29
+ assert_equal([
30
+ Facwparser::Element::A.new('[株式会社ミクシィ|https://mixi.co.jp/]', '株式会社ミクシィ|https://mixi.co.jp/'),
31
+ ], Facwparser::Parser.parse_value('[株式会社ミクシィ|https://mixi.co.jp/]', {}))
32
+ end
33
+
34
+ def test_parse_value_bold
35
+ assert_equal([
36
+ Facwparser::Element::Text.new('1', '1'),
37
+ Facwparser::Element::Bold.new('*hoge*', 'hoge'),
38
+ Facwparser::Element::Text.new('2', '2')
39
+ ], Facwparser::Parser.parse_value('1*hoge*2', {}))
40
+ end
41
+
42
+ def test_parse_value_italic
43
+ assert_equal([
44
+ Facwparser::Element::Text.new('1', '1'),
45
+ Facwparser::Element::Italic.new('_hoge_', 'hoge'),
46
+ Facwparser::Element::Text.new('2', '2')
47
+ ], Facwparser::Parser.parse_value('1_hoge_2', {}))
48
+ end
49
+
50
+ def test_parse_value_strike
51
+ assert_equal([
52
+ Facwparser::Element::Text.new('1', '1'),
53
+ Facwparser::Element::Strike.new('-hoge\-i-', 'hoge-i'),
54
+ Facwparser::Element::Text.new('2', '2')
55
+ ], Facwparser::Parser.parse_value('1-hoge\-i-2', {}))
56
+ end
57
+
58
+ def test_parse_value_under
59
+ assert_equal([
60
+ Facwparser::Element::Text.new('1', '1'),
61
+ Facwparser::Element::Under.new('+hoge+', 'hoge'),
62
+ Facwparser::Element::Text.new('2', '2')
63
+ ], Facwparser::Parser.parse_value('1+hoge+2', {}))
64
+ end
65
+
66
+ def test_parse_value_image
67
+ assert_equal([
68
+ Facwparser::Element::Text.new('1', '1'),
69
+ Facwparser::Element::Image.new('!http://www.unixuser.org/!', 'http://www.unixuser.org/'),
70
+ Facwparser::Element::Text.new('2', '2')
71
+ ], Facwparser::Parser.parse_value('1!http://www.unixuser.org/!2', {}))
72
+ end
73
+
74
+ def test_parse_value_jira_macro
75
+ assert_equal([
76
+ Facwparser::Element::Text.new('1', '1'),
77
+ Facwparser::Element::JiraMacro.new('{jira:SYSTEMRD-1}', 'SYSTEMRD-1'),
78
+ Facwparser::Element::Text.new('2', '2')
79
+ ], Facwparser::Parser.parse_value('1{jira:SYSTEMRD-1}2', {}))
80
+ end
81
+
82
+ def test_parse_value_jira_misc
83
+ assert_equal([
84
+ Facwparser::Element::Text.new('1', '1'),
85
+ Facwparser::Element::Text.new('{jira:SYSTEMRD-1', '{jira:SYSTEMRD-1'),
86
+ ], Facwparser::Parser.parse_value('1{jira:SYSTEMRD-1', {}))
87
+
88
+ assert_equal([
89
+ Facwparser::Element::Text.new('1', '1'),
90
+ Facwparser::Element::Text.new('{jira:SYSTEMRD\-1', '{jira:SYSTEMRD-1'),
91
+ ], Facwparser::Parser.parse_value('1{jira:SYSTEMRD\-1', {}))
92
+
93
+ assert_equal([
94
+ Facwparser::Element::Text.new('1', '1'),
95
+ Facwparser::Element::Text.new('\{', '{'),
96
+ Facwparser::Element::Text.new('jira:SYSTEMRD', 'jira:SYSTEMRD'),
97
+ Facwparser::Element::Text.new('\\-', '-'),
98
+ Facwparser::Element::Text.new('1', '1'),
99
+ ], Facwparser::Parser.parse_value('1\\{jira:SYSTEMRD\\-1', {}))
100
+
101
+ assert_equal([
102
+ Facwparser::Element::Text.new('1', '1'),
103
+ Facwparser::Element::Text.new('\{', '{'),
104
+ Facwparser::Element::JiraMacro.new('{jira:SYSTEMRD\-1}', 'SYSTEMRD-1'),
105
+ ], Facwparser::Parser.parse_value('1\\{{jira:SYSTEMRD\\-1}', {}))
106
+
107
+ end
108
+
109
+ end
110
+
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: facwparser
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - HARUYAMA Seigo
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-08 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Fuxxing Atlassian Confluence Wiki Parser
15
+ email:
16
+ - haruyama@unixuser.org
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - Gemfile
23
+ - LICENSE.txt
24
+ - README.md
25
+ - Rakefile
26
+ - facwparser.gemspec
27
+ - lib/facwparser.rb
28
+ - lib/facwparser/element.rb
29
+ - lib/facwparser/parser.rb
30
+ - lib/facwparser/render.rb
31
+ - lib/facwparser/version.rb
32
+ - sample/confluence2html.rb
33
+ - tests/all_tests.rb
34
+ - tests/units/parse/test_add_list_elements.rb
35
+ - tests/units/parse/test_parse1.rb
36
+ - tests/units/parse/test_parse_value.rb
37
+ homepage: https://github.com/haruyama/facwparser
38
+ licenses: []
39
+ post_install_message:
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ requirements: []
56
+ rubyforge_project:
57
+ rubygems_version: 1.8.24
58
+ signing_key:
59
+ specification_version: 3
60
+ summary: Parser of Atlassian Confluence Wiki Markup.
61
+ test_files: []
62
+ has_rdoc: