org-ruby 0.3.0 → 0.4.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/.bnsignore +18 -0
- data/History.txt +40 -32
- data/README.txt +66 -66
- data/Rakefile +27 -26
- data/bin/org-ruby +40 -40
- data/lib/org-ruby.rb +50 -50
- data/lib/org-ruby/headline.rb +80 -75
- data/lib/org-ruby/html_output_buffer.rb +105 -81
- data/lib/org-ruby/line.rb +173 -173
- data/lib/org-ruby/output_buffer.rb +172 -154
- data/lib/org-ruby/parser.rb +80 -76
- data/lib/org-ruby/regexp_helper.rb +156 -156
- data/lib/org-ruby/textile_output_buffer.rb +67 -67
- data/spec/data/freeform.org +111 -111
- data/spec/data/hyp-planning.org +335 -335
- data/spec/data/remember.org +53 -53
- data/spec/headline_spec.rb +55 -55
- data/spec/html_examples/advanced-lists.html +31 -0
- data/spec/html_examples/advanced-lists.org +31 -0
- data/spec/html_examples/block_code.html +30 -30
- data/spec/html_examples/block_code.org +35 -35
- data/spec/html_examples/blockquote.html +7 -7
- data/spec/html_examples/blockquote.org +13 -13
- data/spec/html_examples/escape-pre.html +7 -7
- data/spec/html_examples/escape-pre.org +6 -6
- data/spec/html_examples/inline-formatting.html +10 -10
- data/spec/html_examples/inline-formatting.org +17 -17
- data/spec/html_examples/lists.html +19 -19
- data/spec/html_examples/lists.org +36 -36
- data/spec/html_examples/only-list.html +5 -5
- data/spec/html_examples/only-list.org +3 -3
- data/spec/html_examples/only-table.html +6 -6
- data/spec/html_examples/only-table.org +5 -5
- data/spec/html_examples/tables.html +20 -20
- data/spec/html_examples/tables.org +26 -26
- data/spec/html_examples/text.html +2 -2
- data/spec/html_examples/text.org +16 -16
- data/spec/line_spec.rb +89 -89
- data/spec/parser_spec.rb +86 -86
- data/spec/regexp_helper_spec.rb +57 -57
- data/spec/spec_helper.rb +20 -20
- data/spec/textile_examples/block_code.org +35 -35
- data/spec/textile_examples/block_code.textile +29 -29
- data/spec/textile_examples/blockquote.org +13 -13
- data/spec/textile_examples/blockquote.textile +11 -11
- data/spec/textile_examples/keywords.org +13 -13
- data/spec/textile_examples/keywords.textile +11 -11
- data/spec/textile_examples/links.org +11 -11
- data/spec/textile_examples/links.textile +10 -10
- data/spec/textile_examples/lists.org +36 -36
- data/spec/textile_examples/lists.textile +20 -20
- data/spec/textile_examples/single-space-plain-list.org +13 -13
- data/spec/textile_examples/single-space-plain-list.textile +10 -10
- data/spec/textile_examples/tables.org +26 -26
- data/spec/textile_examples/tables.textile +23 -23
- data/spec/textile_output_buffer_spec.rb +21 -21
- data/tasks/test_case.rake +49 -49
- metadata +5 -2
data/lib/org-ruby/headline.rb
CHANGED
@@ -1,75 +1,80 @@
|
|
1
|
-
require OrgRuby.libpath(*%w[org-ruby line])
|
2
|
-
|
3
|
-
module Orgmode
|
4
|
-
|
5
|
-
# Represents a headline in an orgmode file.
|
6
|
-
class Headline < Line
|
7
|
-
|
8
|
-
# This is the "level" of the headline
|
9
|
-
attr_reader :level
|
10
|
-
|
11
|
-
# This is the headline text -- the part of the headline minus the leading
|
12
|
-
# asterisks, the keywords, and the tags.
|
13
|
-
attr_reader :headline_text
|
14
|
-
|
15
|
-
# This contains the lines that "belong" to the headline.
|
16
|
-
attr_reader :body_lines
|
17
|
-
|
18
|
-
# These are the headline tags
|
19
|
-
attr_reader :tags
|
20
|
-
|
21
|
-
# Optional keyword found at the beginning of the headline.
|
22
|
-
attr_reader :keyword
|
23
|
-
|
24
|
-
# This is the regex that matches a line
|
25
|
-
LineRegexp = /^\*+\s+/
|
26
|
-
|
27
|
-
# This matches the tags on a headline
|
28
|
-
TagsRegexp = /\s*:[\w:]*:\s*$/
|
29
|
-
|
30
|
-
# Special keywords allowed at the start of a line.
|
31
|
-
Keywords = %w[TODO DONE]
|
32
|
-
|
33
|
-
KeywordsRegexp = Regexp.new("\\s*(#{Keywords.join('|')})\\s*")
|
34
|
-
|
35
|
-
def initialize(line)
|
36
|
-
super(line)
|
37
|
-
@body_lines = []
|
38
|
-
@tags = []
|
39
|
-
if (@line =~ LineRegexp) then
|
40
|
-
@level = $&.strip.length
|
41
|
-
@headline_text = $'.strip
|
42
|
-
if (@headline_text =~ TagsRegexp) then
|
43
|
-
@tags = $&.split(/:/) # split tag text on semicolon
|
44
|
-
@tags.delete_at(0) # the first item will be empty; discard
|
45
|
-
@headline_text.gsub!(TagsRegexp, "") # Removes the tags from the headline
|
46
|
-
end
|
47
|
-
if (@headline_text =~ KeywordsRegexp) then
|
48
|
-
@headline_text = $'
|
49
|
-
@keyword = $1
|
50
|
-
end
|
51
|
-
else
|
52
|
-
raise "'#{line}' is not a valid headline"
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
# Determines if a line is an orgmode "headline":
|
57
|
-
# A headline begins with one or more asterisks.
|
58
|
-
def self.headline?(line)
|
59
|
-
line =~ LineRegexp
|
60
|
-
end
|
61
|
-
|
62
|
-
# Converts this headline and its body to textile.
|
63
|
-
def to_textile
|
64
|
-
output = "h#{@level}. #{@headline_text}\n"
|
65
|
-
output << Line.to_textile(@body_lines)
|
66
|
-
output
|
67
|
-
end
|
68
|
-
|
69
|
-
def to_html
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
1
|
+
require OrgRuby.libpath(*%w[org-ruby line])
|
2
|
+
|
3
|
+
module Orgmode
|
4
|
+
|
5
|
+
# Represents a headline in an orgmode file.
|
6
|
+
class Headline < Line
|
7
|
+
|
8
|
+
# This is the "level" of the headline
|
9
|
+
attr_reader :level
|
10
|
+
|
11
|
+
# This is the headline text -- the part of the headline minus the leading
|
12
|
+
# asterisks, the keywords, and the tags.
|
13
|
+
attr_reader :headline_text
|
14
|
+
|
15
|
+
# This contains the lines that "belong" to the headline.
|
16
|
+
attr_reader :body_lines
|
17
|
+
|
18
|
+
# These are the headline tags
|
19
|
+
attr_reader :tags
|
20
|
+
|
21
|
+
# Optional keyword found at the beginning of the headline.
|
22
|
+
attr_reader :keyword
|
23
|
+
|
24
|
+
# This is the regex that matches a line
|
25
|
+
LineRegexp = /^\*+\s+/
|
26
|
+
|
27
|
+
# This matches the tags on a headline
|
28
|
+
TagsRegexp = /\s*:[\w:]*:\s*$/
|
29
|
+
|
30
|
+
# Special keywords allowed at the start of a line.
|
31
|
+
Keywords = %w[TODO DONE]
|
32
|
+
|
33
|
+
KeywordsRegexp = Regexp.new("\\s*(#{Keywords.join('|')})\\s*")
|
34
|
+
|
35
|
+
def initialize(line)
|
36
|
+
super(line)
|
37
|
+
@body_lines = []
|
38
|
+
@tags = []
|
39
|
+
if (@line =~ LineRegexp) then
|
40
|
+
@level = $&.strip.length
|
41
|
+
@headline_text = $'.strip
|
42
|
+
if (@headline_text =~ TagsRegexp) then
|
43
|
+
@tags = $&.split(/:/) # split tag text on semicolon
|
44
|
+
@tags.delete_at(0) # the first item will be empty; discard
|
45
|
+
@headline_text.gsub!(TagsRegexp, "") # Removes the tags from the headline
|
46
|
+
end
|
47
|
+
if (@headline_text =~ KeywordsRegexp) then
|
48
|
+
@headline_text = $'
|
49
|
+
@keyword = $1
|
50
|
+
end
|
51
|
+
else
|
52
|
+
raise "'#{line}' is not a valid headline"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Determines if a line is an orgmode "headline":
|
57
|
+
# A headline begins with one or more asterisks.
|
58
|
+
def self.headline?(line)
|
59
|
+
line =~ LineRegexp
|
60
|
+
end
|
61
|
+
|
62
|
+
# Converts this headline and its body to textile.
|
63
|
+
def to_textile
|
64
|
+
output = "h#{@level}. #{@headline_text}\n"
|
65
|
+
output << Line.to_textile(@body_lines)
|
66
|
+
output
|
67
|
+
end
|
68
|
+
|
69
|
+
def to_html(opts = {})
|
70
|
+
if opts[:decorate_title]
|
71
|
+
decoration = " class=\"title\""
|
72
|
+
else
|
73
|
+
decoration = ""
|
74
|
+
end
|
75
|
+
output = "<h#{@level}#{decoration}>#{@headline_text}</h#{@level}>\n"
|
76
|
+
output << Line.to_html(@body_lines)
|
77
|
+
output
|
78
|
+
end
|
79
|
+
end # class Headline
|
80
|
+
end # class Orgmode
|
@@ -1,81 +1,105 @@
|
|
1
|
-
require OrgRuby.libpath(*%w[org-ruby output_buffer])
|
2
|
-
require 'cgi'
|
3
|
-
|
4
|
-
module Orgmode
|
5
|
-
|
6
|
-
class HtmlOutputBuffer < OutputBuffer
|
7
|
-
|
8
|
-
HtmlBlockTag = {
|
9
|
-
:paragraph => "p",
|
10
|
-
:ordered_list => "li",
|
11
|
-
:unordered_list => "li",
|
12
|
-
:table_row => "tr"
|
13
|
-
}
|
14
|
-
|
15
|
-
ModeTag = {
|
16
|
-
:unordered_list => "ul",
|
17
|
-
:ordered_list => "ol",
|
18
|
-
:table => "table",
|
19
|
-
:blockquote => "blockquote",
|
20
|
-
:code => "pre"
|
21
|
-
}
|
22
|
-
|
23
|
-
def
|
24
|
-
super(
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
#
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
1
|
+
require OrgRuby.libpath(*%w[org-ruby output_buffer])
|
2
|
+
require 'cgi'
|
3
|
+
|
4
|
+
module Orgmode
|
5
|
+
|
6
|
+
class HtmlOutputBuffer < OutputBuffer
|
7
|
+
|
8
|
+
HtmlBlockTag = {
|
9
|
+
:paragraph => "p",
|
10
|
+
:ordered_list => "li",
|
11
|
+
:unordered_list => "li",
|
12
|
+
:table_row => "tr"
|
13
|
+
}
|
14
|
+
|
15
|
+
ModeTag = {
|
16
|
+
:unordered_list => "ul",
|
17
|
+
:ordered_list => "ol",
|
18
|
+
:table => "table",
|
19
|
+
:blockquote => "blockquote",
|
20
|
+
:code => "pre"
|
21
|
+
}
|
22
|
+
|
23
|
+
def initialize(output, opts = {})
|
24
|
+
super(output)
|
25
|
+
if opts[:decorate_title] then
|
26
|
+
@title_decoration = " class=\"title\""
|
27
|
+
else
|
28
|
+
@title_decoration = ""
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def push_mode(mode)
|
33
|
+
if ModeTag[mode] then
|
34
|
+
output_indentation
|
35
|
+
@output << "<#{ModeTag[mode]}>\n"
|
36
|
+
# Entering a new mode obliterates the title decoration
|
37
|
+
@title_decoration = ""
|
38
|
+
end
|
39
|
+
super(mode)
|
40
|
+
end
|
41
|
+
|
42
|
+
def pop_mode(mode = nil)
|
43
|
+
m = super(mode)
|
44
|
+
if ModeTag[m] then
|
45
|
+
output_indentation
|
46
|
+
@output << "</#{ModeTag[m]}>\n"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def flush!
|
51
|
+
@logger.debug "FLUSH ==========> #{@output_type}"
|
52
|
+
if current_mode == :code then
|
53
|
+
# Whitespace is significant in :code mode. Always output the buffer
|
54
|
+
# and do not do any additional translation.
|
55
|
+
@output << CGI.escapeHTML(@buffer) << "\n"
|
56
|
+
else
|
57
|
+
if (@buffer.length > 0) then
|
58
|
+
output_indentation
|
59
|
+
@output << "<#{HtmlBlockTag[@output_type]}#{@title_decoration}>" \
|
60
|
+
<< inline_formatting(@buffer) \
|
61
|
+
<< "</#{HtmlBlockTag[@output_type]}>\n"
|
62
|
+
@title_decoration = ""
|
63
|
+
end
|
64
|
+
end
|
65
|
+
@buffer = ""
|
66
|
+
end
|
67
|
+
|
68
|
+
######################################################################
|
69
|
+
private
|
70
|
+
|
71
|
+
def output_indentation
|
72
|
+
indent = " " * (@mode_stack.length - 1)
|
73
|
+
@output << indent
|
74
|
+
end
|
75
|
+
|
76
|
+
Tags = {
|
77
|
+
"*" => { :open => "<b>", :close => "</b>" },
|
78
|
+
"/" => { :open => "<i>", :close => "</i>" },
|
79
|
+
"_" => { :open => "<span style=\"text-decoration:underline;\">",
|
80
|
+
:close => "</span>" },
|
81
|
+
"=" => { :open => "<code>", :close => "</code>" },
|
82
|
+
"~" => { :open => "<code>", :close => "</code>" },
|
83
|
+
"+" => { :open => "<del>", :close => "</del>" }
|
84
|
+
}
|
85
|
+
|
86
|
+
# Applies inline formatting rules to a string.
|
87
|
+
def inline_formatting(str)
|
88
|
+
str.rstrip!
|
89
|
+
str = @re_help.rewrite_emphasis(str) do |marker, s|
|
90
|
+
"#{Tags[marker][:open]}#{s}#{Tags[marker][:close]}"
|
91
|
+
end
|
92
|
+
str = @re_help.rewrite_links(str) do |link, text|
|
93
|
+
text ||= link
|
94
|
+
"<a href=\"#{link}\">#{text}</a>"
|
95
|
+
end
|
96
|
+
if (@output_type == :table_row) then
|
97
|
+
str.gsub!(/^\|\s*/, "<td>")
|
98
|
+
str.gsub!(/\s*\|$/, "</td>")
|
99
|
+
str.gsub!(/\s*\|\s*/, "</td><td>")
|
100
|
+
end
|
101
|
+
str
|
102
|
+
end
|
103
|
+
|
104
|
+
end # class HtmlOutputBuffer
|
105
|
+
end # module Orgmode
|
data/lib/org-ruby/line.rb
CHANGED
@@ -1,173 +1,173 @@
|
|
1
|
-
module Orgmode
|
2
|
-
|
3
|
-
# Represents a single line of an orgmode file.
|
4
|
-
class Line
|
5
|
-
|
6
|
-
# This is the line itself.
|
7
|
-
attr_reader :line
|
8
|
-
|
9
|
-
# The indent level of this line. this is important to properly translate
|
10
|
-
# nested lists from orgmode to textile.
|
11
|
-
# TODO 2009-12-20 bdewey: Handle tabs
|
12
|
-
attr_reader :indent
|
13
|
-
|
14
|
-
def initialize(line)
|
15
|
-
@line = line
|
16
|
-
@indent = 0
|
17
|
-
@line =~ /\s*/
|
18
|
-
@indent = $&.length unless blank?
|
19
|
-
end
|
20
|
-
|
21
|
-
def to_s
|
22
|
-
return @line
|
23
|
-
end
|
24
|
-
|
25
|
-
# Tests if a line is a comment.
|
26
|
-
def comment?
|
27
|
-
@line =~ /^\s*#/
|
28
|
-
end
|
29
|
-
|
30
|
-
# Tests if a line contains metadata instead of actual content.
|
31
|
-
def metadata?
|
32
|
-
@line =~ /^\s*(CLOCK|DEADLINE|START|CLOSED|SCHEDULED):/
|
33
|
-
end
|
34
|
-
|
35
|
-
def nonprinting?
|
36
|
-
comment? || metadata?
|
37
|
-
end
|
38
|
-
|
39
|
-
def blank?
|
40
|
-
@line =~ /^\s*$/
|
41
|
-
end
|
42
|
-
|
43
|
-
def plain_list?
|
44
|
-
ordered_list? or unordered_list?
|
45
|
-
end
|
46
|
-
|
47
|
-
UnorderedListRegexp = /^\s*(-|\+)\s*/
|
48
|
-
|
49
|
-
def unordered_list?
|
50
|
-
@line =~ UnorderedListRegexp
|
51
|
-
end
|
52
|
-
|
53
|
-
def strip_unordered_list_tag
|
54
|
-
@line.sub(UnorderedListRegexp, "")
|
55
|
-
end
|
56
|
-
|
57
|
-
OrderedListRegexp = /^\s*\d+(\.|\))\s*/
|
58
|
-
|
59
|
-
def ordered_list?
|
60
|
-
@line =~ OrderedListRegexp
|
61
|
-
end
|
62
|
-
|
63
|
-
def strip_ordered_list_tag
|
64
|
-
@line.sub(OrderedListRegexp, "")
|
65
|
-
end
|
66
|
-
|
67
|
-
def plain_text?
|
68
|
-
not metadata? and not blank? and not plain_list?
|
69
|
-
end
|
70
|
-
|
71
|
-
def table_row?
|
72
|
-
# for an org-mode table, the first non-whitespace character is a
|
73
|
-
# | (pipe).
|
74
|
-
@line =~ /^\s*\|/
|
75
|
-
end
|
76
|
-
|
77
|
-
def table_separator?
|
78
|
-
# an org-mode table separator has the first non-whitespace
|
79
|
-
# character as a | (pipe), then consists of nothing else other
|
80
|
-
# than pipes, hyphens, and pluses.
|
81
|
-
|
82
|
-
@line =~ /^\s*\|[-\|\+]*\s*$/
|
83
|
-
end
|
84
|
-
|
85
|
-
def table?
|
86
|
-
table_row? or table_separator?
|
87
|
-
end
|
88
|
-
|
89
|
-
BlockRegexp = /^\s*#\+(BEGIN|END)_(\w*)/
|
90
|
-
|
91
|
-
def begin_block?
|
92
|
-
@line =~ BlockRegexp && $1 == "BEGIN"
|
93
|
-
end
|
94
|
-
|
95
|
-
def end_block?
|
96
|
-
@line =~ BlockRegexp && $1 == "END"
|
97
|
-
end
|
98
|
-
|
99
|
-
def block_type
|
100
|
-
$2 if @line =~ BlockRegexp
|
101
|
-
end
|
102
|
-
|
103
|
-
# Determines the paragraph type of the current line.
|
104
|
-
def paragraph_type
|
105
|
-
return :blank if blank?
|
106
|
-
return :ordered_list if ordered_list?
|
107
|
-
return :unordered_list if unordered_list?
|
108
|
-
return :metadata if metadata?
|
109
|
-
return :comment if comment?
|
110
|
-
return :table_separator if table_separator?
|
111
|
-
return :table_row if table_row?
|
112
|
-
return :paragraph
|
113
|
-
end
|
114
|
-
|
115
|
-
def self.to_textile(lines)
|
116
|
-
output = ""
|
117
|
-
output_buffer = TextileOutputBuffer.new(output)
|
118
|
-
translate(lines, output_buffer)
|
119
|
-
end
|
120
|
-
|
121
|
-
def self.to_html(lines)
|
122
|
-
output = ""
|
123
|
-
output_buffer = HtmlOutputBuffer.new(output)
|
124
|
-
translate(lines, output_buffer)
|
125
|
-
end
|
126
|
-
|
127
|
-
# Converts an array of lines to textile format.
|
128
|
-
def self.translate(lines, output_buffer)
|
129
|
-
lines.each do |line|
|
130
|
-
|
131
|
-
# See if we're carrying paragraph payload, and output
|
132
|
-
# it if we're about to switch to some other output type.
|
133
|
-
output_buffer.prepare(line)
|
134
|
-
|
135
|
-
case line.paragraph_type
|
136
|
-
when :metadata, :table_separator, :blank
|
137
|
-
|
138
|
-
# IGNORE
|
139
|
-
|
140
|
-
when :comment
|
141
|
-
|
142
|
-
output_buffer.push_mode(:blockquote) if line.begin_block? and line.block_type == "QUOTE"
|
143
|
-
output_buffer.push_mode(:code) if line.begin_block? and line.block_type == "EXAMPLE"
|
144
|
-
output_buffer.pop_mode(:blockquote) if line.end_block? and line.block_type == "QUOTE"
|
145
|
-
output_buffer.pop_mode(:code) if line.end_block? and line.block_type == "EXAMPLE"
|
146
|
-
|
147
|
-
when :table_row
|
148
|
-
|
149
|
-
output_buffer << line.line.lstrip
|
150
|
-
|
151
|
-
when :ordered_list
|
152
|
-
|
153
|
-
output_buffer << line.strip_ordered_list_tag << " "
|
154
|
-
|
155
|
-
when :unordered_list
|
156
|
-
|
157
|
-
output_buffer << line.strip_unordered_list_tag << " "
|
158
|
-
|
159
|
-
when :paragraph
|
160
|
-
|
161
|
-
if output_buffer.preserve_whitespace? then
|
162
|
-
output_buffer << line.line
|
163
|
-
else
|
164
|
-
output_buffer << line.line.strip << " "
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
output_buffer.flush!
|
169
|
-
output_buffer.pop_mode until output_buffer.current_mode == :normal
|
170
|
-
output_buffer.output
|
171
|
-
end
|
172
|
-
end # class Line
|
173
|
-
end # module Orgmode
|
1
|
+
module Orgmode
|
2
|
+
|
3
|
+
# Represents a single line of an orgmode file.
|
4
|
+
class Line
|
5
|
+
|
6
|
+
# This is the line itself.
|
7
|
+
attr_reader :line
|
8
|
+
|
9
|
+
# The indent level of this line. this is important to properly translate
|
10
|
+
# nested lists from orgmode to textile.
|
11
|
+
# TODO 2009-12-20 bdewey: Handle tabs
|
12
|
+
attr_reader :indent
|
13
|
+
|
14
|
+
def initialize(line)
|
15
|
+
@line = line
|
16
|
+
@indent = 0
|
17
|
+
@line =~ /\s*/
|
18
|
+
@indent = $&.length unless blank?
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
return @line
|
23
|
+
end
|
24
|
+
|
25
|
+
# Tests if a line is a comment.
|
26
|
+
def comment?
|
27
|
+
@line =~ /^\s*#/
|
28
|
+
end
|
29
|
+
|
30
|
+
# Tests if a line contains metadata instead of actual content.
|
31
|
+
def metadata?
|
32
|
+
@line =~ /^\s*(CLOCK|DEADLINE|START|CLOSED|SCHEDULED):/
|
33
|
+
end
|
34
|
+
|
35
|
+
def nonprinting?
|
36
|
+
comment? || metadata?
|
37
|
+
end
|
38
|
+
|
39
|
+
def blank?
|
40
|
+
@line =~ /^\s*$/
|
41
|
+
end
|
42
|
+
|
43
|
+
def plain_list?
|
44
|
+
ordered_list? or unordered_list?
|
45
|
+
end
|
46
|
+
|
47
|
+
UnorderedListRegexp = /^\s*(-|\+)\s*/
|
48
|
+
|
49
|
+
def unordered_list?
|
50
|
+
@line =~ UnorderedListRegexp
|
51
|
+
end
|
52
|
+
|
53
|
+
def strip_unordered_list_tag
|
54
|
+
@line.sub(UnorderedListRegexp, "")
|
55
|
+
end
|
56
|
+
|
57
|
+
OrderedListRegexp = /^\s*\d+(\.|\))\s*/
|
58
|
+
|
59
|
+
def ordered_list?
|
60
|
+
@line =~ OrderedListRegexp
|
61
|
+
end
|
62
|
+
|
63
|
+
def strip_ordered_list_tag
|
64
|
+
@line.sub(OrderedListRegexp, "")
|
65
|
+
end
|
66
|
+
|
67
|
+
def plain_text?
|
68
|
+
not metadata? and not blank? and not plain_list?
|
69
|
+
end
|
70
|
+
|
71
|
+
def table_row?
|
72
|
+
# for an org-mode table, the first non-whitespace character is a
|
73
|
+
# | (pipe).
|
74
|
+
@line =~ /^\s*\|/
|
75
|
+
end
|
76
|
+
|
77
|
+
def table_separator?
|
78
|
+
# an org-mode table separator has the first non-whitespace
|
79
|
+
# character as a | (pipe), then consists of nothing else other
|
80
|
+
# than pipes, hyphens, and pluses.
|
81
|
+
|
82
|
+
@line =~ /^\s*\|[-\|\+]*\s*$/
|
83
|
+
end
|
84
|
+
|
85
|
+
def table?
|
86
|
+
table_row? or table_separator?
|
87
|
+
end
|
88
|
+
|
89
|
+
BlockRegexp = /^\s*#\+(BEGIN|END)_(\w*)/
|
90
|
+
|
91
|
+
def begin_block?
|
92
|
+
@line =~ BlockRegexp && $1 == "BEGIN"
|
93
|
+
end
|
94
|
+
|
95
|
+
def end_block?
|
96
|
+
@line =~ BlockRegexp && $1 == "END"
|
97
|
+
end
|
98
|
+
|
99
|
+
def block_type
|
100
|
+
$2 if @line =~ BlockRegexp
|
101
|
+
end
|
102
|
+
|
103
|
+
# Determines the paragraph type of the current line.
|
104
|
+
def paragraph_type
|
105
|
+
return :blank if blank?
|
106
|
+
return :ordered_list if ordered_list?
|
107
|
+
return :unordered_list if unordered_list?
|
108
|
+
return :metadata if metadata?
|
109
|
+
return :comment if comment?
|
110
|
+
return :table_separator if table_separator?
|
111
|
+
return :table_row if table_row?
|
112
|
+
return :paragraph
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.to_textile(lines)
|
116
|
+
output = ""
|
117
|
+
output_buffer = TextileOutputBuffer.new(output)
|
118
|
+
translate(lines, output_buffer)
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.to_html(lines, opts = { })
|
122
|
+
output = ""
|
123
|
+
output_buffer = HtmlOutputBuffer.new(output, opts)
|
124
|
+
translate(lines, output_buffer)
|
125
|
+
end
|
126
|
+
|
127
|
+
# Converts an array of lines to textile format.
|
128
|
+
def self.translate(lines, output_buffer)
|
129
|
+
lines.each do |line|
|
130
|
+
|
131
|
+
# See if we're carrying paragraph payload, and output
|
132
|
+
# it if we're about to switch to some other output type.
|
133
|
+
output_buffer.prepare(line)
|
134
|
+
|
135
|
+
case line.paragraph_type
|
136
|
+
when :metadata, :table_separator, :blank
|
137
|
+
|
138
|
+
# IGNORE
|
139
|
+
|
140
|
+
when :comment
|
141
|
+
|
142
|
+
output_buffer.push_mode(:blockquote) if line.begin_block? and line.block_type == "QUOTE"
|
143
|
+
output_buffer.push_mode(:code) if line.begin_block? and line.block_type == "EXAMPLE"
|
144
|
+
output_buffer.pop_mode(:blockquote) if line.end_block? and line.block_type == "QUOTE"
|
145
|
+
output_buffer.pop_mode(:code) if line.end_block? and line.block_type == "EXAMPLE"
|
146
|
+
|
147
|
+
when :table_row
|
148
|
+
|
149
|
+
output_buffer << line.line.lstrip
|
150
|
+
|
151
|
+
when :ordered_list
|
152
|
+
|
153
|
+
output_buffer << line.strip_ordered_list_tag << " "
|
154
|
+
|
155
|
+
when :unordered_list
|
156
|
+
|
157
|
+
output_buffer << line.strip_unordered_list_tag << " "
|
158
|
+
|
159
|
+
when :paragraph
|
160
|
+
|
161
|
+
if output_buffer.preserve_whitespace? then
|
162
|
+
output_buffer << line.line
|
163
|
+
else
|
164
|
+
output_buffer << line.line.strip << " "
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
output_buffer.flush!
|
169
|
+
output_buffer.pop_mode until output_buffer.current_mode == :normal
|
170
|
+
output_buffer.output
|
171
|
+
end
|
172
|
+
end # class Line
|
173
|
+
end # module Orgmode
|