wallyqs-org-ruby 0.6.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data/History.txt +41 -11
  2. data/README.rdoc +55 -50
  3. data/bin/org-ruby +11 -5
  4. data/lib/org-ruby.rb +20 -27
  5. data/lib/org-ruby/headline.rb +0 -10
  6. data/lib/org-ruby/html_output_buffer.rb +224 -143
  7. data/lib/org-ruby/html_symbol_replace.rb +359 -340
  8. data/lib/org-ruby/line.rb +91 -30
  9. data/lib/org-ruby/output_buffer.rb +147 -139
  10. data/lib/org-ruby/parser.rb +45 -111
  11. data/lib/org-ruby/regexp_helper.rb +52 -57
  12. data/lib/org-ruby/textile_output_buffer.rb +90 -37
  13. data/lib/org-ruby/textile_symbol_replace.rb +360 -341
  14. metadata +39 -200
  15. data/.bnsignore +0 -18
  16. data/.gitignore +0 -2
  17. data/Gemfile +0 -7
  18. data/Gemfile.lock +0 -36
  19. data/Rakefile +0 -33
  20. data/TAGS +0 -167
  21. data/announcement.txt +0 -24
  22. data/org-ruby.gemspec +0 -40
  23. data/spec/data/freeform-example.org +0 -113
  24. data/spec/data/freeform.org +0 -111
  25. data/spec/data/hyp-planning.org +0 -335
  26. data/spec/data/remember.org +0 -53
  27. data/spec/headline_spec.rb +0 -65
  28. data/spec/html_examples/advanced-code.html +0 -81
  29. data/spec/html_examples/advanced-code.org +0 -106
  30. data/spec/html_examples/advanced-lists.html +0 -31
  31. data/spec/html_examples/advanced-lists.org +0 -31
  32. data/spec/html_examples/block_code.html +0 -28
  33. data/spec/html_examples/block_code.org +0 -35
  34. data/spec/html_examples/blockcomment.html +0 -3
  35. data/spec/html_examples/blockcomment.org +0 -15
  36. data/spec/html_examples/blockquote.html +0 -7
  37. data/spec/html_examples/blockquote.org +0 -13
  38. data/spec/html_examples/center.html +0 -6
  39. data/spec/html_examples/center.org +0 -7
  40. data/spec/html_examples/code-comment.html +0 -18
  41. data/spec/html_examples/code-comment.org +0 -22
  42. data/spec/html_examples/code-syntax.html +0 -98
  43. data/spec/html_examples/code-syntax.org +0 -99
  44. data/spec/html_examples/comment-trees.html +0 -4
  45. data/spec/html_examples/comment-trees.org +0 -13
  46. data/spec/html_examples/custom-seq-todo.html +0 -15
  47. data/spec/html_examples/custom-seq-todo.org +0 -24
  48. data/spec/html_examples/custom-todo.html +0 -15
  49. data/spec/html_examples/custom-todo.org +0 -24
  50. data/spec/html_examples/custom-typ-todo.html +0 -15
  51. data/spec/html_examples/custom-typ-todo.org +0 -24
  52. data/spec/html_examples/deflist.html +0 -6
  53. data/spec/html_examples/deflist.org +0 -6
  54. data/spec/html_examples/entities.html +0 -4
  55. data/spec/html_examples/entities.org +0 -11
  56. data/spec/html_examples/escape-pre.html +0 -6
  57. data/spec/html_examples/escape-pre.org +0 -6
  58. data/spec/html_examples/export-exclude-only.html +0 -13
  59. data/spec/html_examples/export-exclude-only.org +0 -81
  60. data/spec/html_examples/export-keywords.html +0 -4
  61. data/spec/html_examples/export-keywords.org +0 -18
  62. data/spec/html_examples/export-tags.html +0 -8
  63. data/spec/html_examples/export-tags.org +0 -82
  64. data/spec/html_examples/export-title.html +0 -2
  65. data/spec/html_examples/export-title.org +0 -4
  66. data/spec/html_examples/footnotes.html +0 -10
  67. data/spec/html_examples/footnotes.org +0 -7
  68. data/spec/html_examples/html-literal.html +0 -2
  69. data/spec/html_examples/html-literal.org +0 -6
  70. data/spec/html_examples/inline-formatting.html +0 -20
  71. data/spec/html_examples/inline-formatting.org +0 -33
  72. data/spec/html_examples/inline-images.html +0 -10
  73. data/spec/html_examples/inline-images.org +0 -15
  74. data/spec/html_examples/link-features.html +0 -8
  75. data/spec/html_examples/link-features.org +0 -19
  76. data/spec/html_examples/lists.html +0 -23
  77. data/spec/html_examples/lists.org +0 -47
  78. data/spec/html_examples/metadata-comment.html +0 -27
  79. data/spec/html_examples/metadata-comment.org +0 -30
  80. data/spec/html_examples/only-list.html +0 -5
  81. data/spec/html_examples/only-list.org +0 -3
  82. data/spec/html_examples/only-table.html +0 -6
  83. data/spec/html_examples/only-table.org +0 -5
  84. data/spec/html_examples/skip-header.html +0 -3
  85. data/spec/html_examples/skip-header.org +0 -28
  86. data/spec/html_examples/skip-table.html +0 -4
  87. data/spec/html_examples/skip-table.org +0 -19
  88. data/spec/html_examples/subsupscript-nil.html +0 -3
  89. data/spec/html_examples/subsupscript-nil.org +0 -6
  90. data/spec/html_examples/subsupscript.html +0 -3
  91. data/spec/html_examples/subsupscript.org +0 -5
  92. data/spec/html_examples/tables.html +0 -35
  93. data/spec/html_examples/tables.org +0 -50
  94. data/spec/html_examples/text.html +0 -2
  95. data/spec/html_examples/text.org +0 -16
  96. data/spec/line_spec.rb +0 -155
  97. data/spec/output_buffer_spec.rb +0 -19
  98. data/spec/parser_spec.rb +0 -152
  99. data/spec/regexp_helper_spec.rb +0 -57
  100. data/spec/spec_helper.rb +0 -20
  101. data/spec/textile_examples/block_code.org +0 -35
  102. data/spec/textile_examples/block_code.textile +0 -29
  103. data/spec/textile_examples/blockquote.org +0 -13
  104. data/spec/textile_examples/blockquote.textile +0 -11
  105. data/spec/textile_examples/center.org +0 -7
  106. data/spec/textile_examples/center.textile +0 -6
  107. data/spec/textile_examples/footnotes.org +0 -7
  108. data/spec/textile_examples/footnotes.textile +0 -8
  109. data/spec/textile_examples/keywords.org +0 -13
  110. data/spec/textile_examples/keywords.textile +0 -11
  111. data/spec/textile_examples/links.org +0 -11
  112. data/spec/textile_examples/links.textile +0 -10
  113. data/spec/textile_examples/lists.org +0 -36
  114. data/spec/textile_examples/lists.textile +0 -20
  115. data/spec/textile_examples/single-space-plain-list.org +0 -13
  116. data/spec/textile_examples/single-space-plain-list.textile +0 -10
  117. data/spec/textile_examples/tables.org +0 -50
  118. data/spec/textile_examples/tables.textile +0 -40
  119. data/spec/textile_output_buffer_spec.rb +0 -21
  120. data/tasks/test_case.rake +0 -49
  121. data/test/test_orgmode_parser.rb +0 -0
  122. data/util/gen-special-replace.el +0 -37
@@ -1,4 +1,3 @@
1
- require 'rubygems'
2
1
  require 'rubypants'
3
2
 
4
3
  module Orgmode
@@ -100,74 +99,48 @@ module Orgmode
100
99
  mode = :normal
101
100
  previous_line = nil
102
101
  table_header_set = false
103
- @lines.each do |line|
104
- case mode
105
- when :normal
102
+ @lines.each do |text|
103
+ line = Line.new text, self
104
+ mode = :normal if line.end_block? and mode == line.paragraph_type
105
+ mode = :normal if line.property_drawer_end_block? and mode == :property_drawer
106
106
 
107
- if (Headline.headline? line) then
108
- @current_headline = Headline.new line, self, offset
109
- @headlines << @current_headline
110
- else
111
- line = Line.new line, self
112
- # If there is a setting on this line, remember it.
113
- line.in_buffer_setting? do |key, value|
114
- store_in_buffer_setting key, value
115
- end
116
- if line.table_separator? then
117
- if previous_line and previous_line.paragraph_type == :table_row and !table_header_set
118
- previous_line.assigned_paragraph_type = :table_header
119
- table_header_set = true
120
- end
121
- end
122
- table_header_set = false if !line.table?
123
- mode = :code if line.begin_block? and line.block_type == "EXAMPLE"
124
- mode = :block_comment if line.begin_block? and line.block_type == "COMMENT"
125
- mode = :property_drawer if line.property_drawer_begin_block?
126
- if (@current_headline) then
127
- @current_headline.body_lines << line
128
- else
129
- @header_lines << line
107
+ case mode
108
+ when :normal, :quote, :center
109
+ if Headline.headline? line.line
110
+ line = Headline.new line.line, self, offset
111
+ elsif line.table_separator?
112
+ if previous_line and previous_line.paragraph_type == :table_row and !table_header_set
113
+ previous_line.assigned_paragraph_type = :table_header
114
+ table_header_set = true
130
115
  end
131
116
  end
117
+ table_header_set = false if !line.table?
132
118
 
133
- when :block_comment
134
- line = Line.new line, self
135
- if line.end_block? and line.block_type == "COMMENT"
136
- mode = :normal
137
- else
138
- line.assigned_paragraph_type = :comment
139
- end
140
-
141
- when :code
142
-
143
- # As long as we stay in code mode, force lines to be either blank or paragraphs.
119
+ when :example, :html, :src
120
+ # As long as we stay in code mode, force lines to be code.
144
121
  # Don't try to interpret structural items, like headings and tables.
145
- line = Line.new line, self
146
- if line.end_block? and line.block_type == "EXAMPLE"
147
- mode = :normal
148
- else
149
- line.assigned_paragraph_type = :paragraph unless line.blank?
150
- end
151
- if (@current_headline) then
152
- @current_headline.body_lines << line
153
- else
154
- @header_lines << line
122
+ line.assigned_paragraph_type = :code
123
+ end
124
+
125
+ if mode == :normal
126
+ @headlines << @current_headline = line if Headline.headline? line.line
127
+ # If there is a setting on this line, remember it.
128
+ line.in_buffer_setting? do |key, value|
129
+ store_in_buffer_setting key.upcase, value
155
130
  end
156
131
 
157
- when :property_drawer
132
+ mode = line.paragraph_type if line.begin_block?
133
+ mode = :property_drawer if line.property_drawer_begin_block?
134
+ end
158
135
 
159
- line = Line.new line, self
160
- if line.property_drawer_end_block?
161
- mode = :normal
162
- else
163
- line.assigned_paragraph_type = :property_drawer unless line.blank?
164
- end
165
- if (@current_headline) then
136
+ unless mode == :comment
137
+ if @current_headline
166
138
  @current_headline.body_lines << line
167
139
  else
168
140
  @header_lines << line
169
141
  end
170
- end # case
142
+ end
143
+
171
144
  previous_line = line
172
145
  end # @lines.each
173
146
  end # initialize
@@ -181,9 +154,11 @@ module Orgmode
181
154
  # Saves the loaded orgmode file as a textile file.
182
155
  def to_textile
183
156
  output = ""
184
- output << Line.to_textile(@header_lines)
157
+ output_buffer = TextileOutputBuffer.new(output)
158
+
159
+ translate(@header_lines, output_buffer)
185
160
  @headlines.each do |headline|
186
- output << headline.to_textile
161
+ translate(headline.body_lines, output_buffer)
187
162
  end
188
163
  output
189
164
  end
@@ -192,7 +167,7 @@ module Orgmode
192
167
  def to_html
193
168
  mark_trees_for_export
194
169
  export_options = {
195
- :decorate_title => true,
170
+ :decorate_title => @in_buffer_settings["TITLE"],
196
171
  :export_heading_number => export_heading_number?,
197
172
  :export_todo => export_todo?,
198
173
  :use_sub_superscripts => use_sub_superscripts?,
@@ -207,9 +182,9 @@ module Orgmode
207
182
  # If we're given a new title, then just create a new line
208
183
  # for that title.
209
184
  title = Line.new(@in_buffer_settings["TITLE"], self)
210
- Parser.translate([title], output_buffer)
185
+ translate([title], output_buffer)
211
186
  end
212
- Parser.translate(@header_lines, output_buffer) unless skip_header_lines?
187
+ translate(@header_lines, output_buffer) unless skip_header_lines?
213
188
 
214
189
  # If we've output anything at all, remove the :decorate_title option.
215
190
  export_options.delete(:decorate_title) if (output.length > 0)
@@ -219,11 +194,13 @@ module Orgmode
219
194
  when :exclude
220
195
  # NOTHING
221
196
  when :headline_only
222
- Parser.translate(headline.body_lines[0, 1], output_buffer)
197
+ translate(headline.body_lines[0, 1], output_buffer)
223
198
  when :all
224
- Parser.translate(headline.body_lines, output_buffer)
199
+ translate(headline.body_lines, output_buffer)
225
200
  end
226
201
  end
202
+ output << "\n"
203
+
227
204
  rp = RubyPants.new(output)
228
205
  rp.to_html
229
206
  end
@@ -233,54 +210,11 @@ module Orgmode
233
210
 
234
211
  # Converts an array of lines to the appropriate format.
235
212
  # Writes the output to +output_buffer+.
236
- def self.translate(lines, output_buffer)
237
- lines.each do |line|
238
-
239
- # See if we're carrying paragraph payload, and output
240
- # it if we're about to switch to some other output type.
241
- output_buffer.prepare(line)
242
- case line.paragraph_type
243
- when :metadata, :table_separator, :blank, :comment, :property_drawer_item, :property_drawer_begin_block, :property_drawer_end_block
244
-
245
- output_buffer << line.line if output_buffer.preserve_whitespace?
246
-
247
- when :begin_block
248
-
249
- output_buffer.push_mode(:blockquote) if line.block_type.casecmp("QUOTE") == 0
250
- output_buffer.push_mode(:src) if line.block_type.casecmp("SRC") == 0
251
- output_buffer.push_mode(:example) if line.block_type.casecmp("EXAMPLE") == 0
252
- output_buffer.push_mode(:center) if line.block_type.casecmp("CENTER") == 0
253
-
254
- when :end_block
255
-
256
- output_buffer.pop_mode(:blockquote) if line.block_type.casecmp("QUOTE") == 0
257
- output_buffer.pop_mode(:src) if line.block_type.casecmp("SRC") == 0
258
- output_buffer.pop_mode(:example) if line.block_type.casecmp("EXAMPLE") == 0
259
- output_buffer.pop_mode(:center) if line.block_type.casecmp("CENTER") == 0
260
-
261
- when :table_row, :table_header
262
-
263
- output_buffer << line.line.lstrip
264
-
265
- when :unordered_list, :ordered_list, :definition_list
266
-
267
- output_buffer << line.output_text << " "
268
-
269
- when :inline_example
270
-
271
- output_buffer << line.output_text
272
-
273
- else
274
-
275
- if output_buffer.preserve_whitespace? then
276
- output_buffer << line.output_text
277
- else
278
- output_buffer << line.output_text.strip << " "
279
- end
280
- end
281
- end
213
+ def translate(lines, output_buffer)
214
+ output_buffer.output_type = :start
215
+ lines.each { |line| output_buffer.insert(line) }
282
216
  output_buffer.flush!
283
- output_buffer.pop_mode until output_buffer.current_mode == :normal
217
+ output_buffer.pop_mode while output_buffer.current_mode
284
218
  output_buffer.output_footnotes!
285
219
  output_buffer.output
286
220
  end
@@ -3,7 +3,7 @@ require 'logger'
3
3
  module Orgmode
4
4
 
5
5
  # = Summary
6
- #
6
+ #
7
7
  # This class contains helper routines to deal with the Regexp "black
8
8
  # magic" you need to properly parse org-mode files.
9
9
  #
@@ -39,24 +39,20 @@ module Orgmode
39
39
  # body-regexp A regexp like \".\" to match a body character. Don't use
40
40
  # non-shy groups here, and don't allow newline here.
41
41
  # newline The maximum number of newlines allowed in an emphasis exp.
42
- #
43
- # I currently don't use +newline+ because I've thrown this information
44
- # away by this point in the code. TODO -- revisit?
45
- attr_reader :pre_emphasis
46
- attr_reader :post_emphasis
47
- attr_reader :border_forbidden
48
- attr_reader :body_regexp
49
- attr_reader :markers
50
42
 
51
- attr_reader :org_emphasis_regexp
43
+ attr_reader :org_image_file_regexp
52
44
 
53
45
  def initialize
54
46
  # Set up the emphasis regular expression.
55
- @pre_emphasis = " \t\\('\""
56
- @post_emphasis = "- \t.,:!?;'\"\\)"
57
- @border_forbidden = " \t\r\n,\"'"
58
- @body_regexp = ".*?"
59
- @markers = "*/_=~+"
47
+ @pre_emphasis = ' \t\(\'"\{'
48
+ @post_emphasis = '- \t\.,:!\?;\'"\)\}\\\\'
49
+ @border_forbidden = '\s,"\''
50
+ @body_regexp = '.*?'
51
+ @max_newlines = 1
52
+ @body_regexp = "#{@body_regexp}" +
53
+ "(?:\\n#{@body_regexp}){0,#{@max_newlines}}" if @max_newlines > 0
54
+ @markers = '\*\/_=~\+'
55
+ @code_snippet_stack = []
60
56
  @logger = Logger.new(STDERR)
61
57
  @logger.level = Logger::WARN
62
58
  build_org_emphasis_regexp
@@ -94,23 +90,32 @@ module Orgmode
94
90
  # replace "*bold*", "/italic/", and "=code=",
95
91
  # respectively. (Clearly this sample string will use HTML-like
96
92
  # syntax, assuming +map+ is defined appropriately.)
97
- def rewrite_emphasis(str)
98
- str.gsub(@org_emphasis_regexp) do |match|
99
- inner = yield $2, $3
100
- "#{$1}#{inner}#{$4}"
93
+ def rewrite_emphasis str
94
+ # escape the percent signs for safe restoring code snippets
95
+ str.gsub!(/%/, "%%")
96
+ format_str = "%s"
97
+ str.gsub! @org_emphasis_regexp do |match|
98
+ # preserve the code snippet from further formatting
99
+ inner = if $2 == "=" or $2 == "~"
100
+ @code_snippet_stack.push $3
101
+ yield $2, format_str
102
+ else
103
+ yield $2, $3
104
+ end
105
+ "#{$1}#{inner}"
101
106
  end
102
107
  end
103
108
 
104
109
  # rewrite subscript and superscript (_{foo} and ^{bar})
105
- def rewrite_subp(str) # :yields: type ("_" for subscript and "^" for superscript), text
106
- str.gsub(@org_subp_regexp) do |match|
110
+ def rewrite_subp str # :yields: type ("_" for subscript and "^" for superscript), text
111
+ str.gsub! @org_subp_regexp do |match|
107
112
  yield $1, $2
108
113
  end
109
114
  end
110
115
 
111
116
  # rewrite footnotes
112
- def rewrite_footnote(str) # :yields: name, definition or nil
113
- str.gsub(@org_footnote_regexp) do |match|
117
+ def rewrite_footnote str # :yields: name, definition or nil
118
+ str.gsub! @org_footnote_regexp do |match|
114
119
  yield $1, $3
115
120
  end
116
121
  end
@@ -121,7 +126,7 @@ module Orgmode
121
126
  # output format.
122
127
  #
123
128
  # = Usage
124
- #
129
+ #
125
130
  # Give this a block that expect the link and optional friendly
126
131
  # text. Return how that link should get formatted.
127
132
  #
@@ -140,53 +145,43 @@ module Orgmode
140
145
  # +http://www.hotmail.com+. In both cases, the block returns an
141
146
  # HTML-style link, and that is how things will get recorded in
142
147
  # +result+.
143
- def rewrite_links(str) # :yields: link, text
144
- i = str.gsub(@org_link_regexp) do |match|
145
- yield $1, nil
148
+ def rewrite_links str # :yields: link, text
149
+ str.gsub! @org_link_regexp do |match|
150
+ yield $1, $3
146
151
  end
147
- if str =~ @org_angle_link_text_regexp
148
- i.gsub(@org_angle_link_text_regexp) do |match|
149
- yield "#{$2}:#{$3}", nil
150
- end
151
- else
152
- i.gsub(@org_link_text_regexp) do |match|
153
- yield $1, $2
154
- end
152
+ str.gsub! @org_angle_link_text_regexp do |match|
153
+ yield $1, nil
155
154
  end
155
+
156
+ str # for testing
156
157
  end
157
158
 
158
- # Rewrites all of the inline image tags.
159
- def rewrite_images(str) # :yields: image_link
160
- str.gsub(@org_img_regexp) do |match|
161
- yield $1
162
- end
159
+ def restore_code_snippets str
160
+ str = str % @code_snippet_stack
161
+ @code_snippet_stack = []
162
+ str
163
163
  end
164
164
 
165
165
  private
166
166
 
167
167
  def build_org_emphasis_regexp
168
- @org_emphasis_regexp = Regexp.new("([#{@pre_emphasis}]|^)\n" +
169
- "( [#{@markers}] )\n" +
170
- "( [^#{@border_forbidden}] | " +
171
- " [^#{@border_forbidden}]#{@body_regexp}[^#{@border_forbidden}] )\n" +
172
- "\\2\n" +
173
- "([#{@post_emphasis}]|$)\n", Regexp::EXTENDED)
168
+ @org_emphasis_regexp = Regexp.new("([#{@pre_emphasis}]|^)" +
169
+ "([#{@markers}])(?!\\2)" +
170
+ "([^#{@border_forbidden}]|" +
171
+ "[^#{@border_forbidden}]#{@body_regexp}" +
172
+ "[^#{@border_forbidden}])\\2" +
173
+ "(?=[#{@post_emphasis}]|$)")
174
174
  @logger.debug "Just created regexp: #{@org_emphasis_regexp}"
175
175
  end
176
176
 
177
177
  def build_org_link_regexp
178
178
  @org_link_regexp = /\[\[
179
- ([^\]]*) # This is the URL
180
- \]\]/x
181
- @org_img_regexp = /\[\[
182
- ([^\]]*\.(jpg|jpeg|gif|png)) # Like a normal URL, but must end with a specified extension
183
- \]\]/xi
184
- @org_link_text_regexp = /\[\[
185
- ([^\]]*) # This is the URL
186
- \]\[
187
- ([^\]]*) # This is the friendly text
188
- \]\]/x
189
- @org_angle_link_text_regexp = /(<|&lt;)(\w+):([^\]\t\n\r<> ][^\]\t\n\r<> ]*)(>|&gt;)/x
179
+ ([^\]\[]+) # This is the URL
180
+ \](\[
181
+ ([^\]\[]+) # This is the friendly text
182
+ \])?\]/x
183
+ @org_angle_link_text_regexp = /<(\w+:[^\]\s<>]+)>/
184
+ @org_image_file_regexp = /\.(gif|jpe?g|p(?:bm|gm|n[gm]|pm)|svg|tiff?|x[bp]m)/i
190
185
  end
191
186
  end # class Emphasis
192
187
  end # module Orgmode
@@ -6,21 +6,28 @@ module Orgmode
6
6
 
7
7
  def initialize(output)
8
8
  super(output)
9
- @add_paragraph = false
9
+ @add_paragraph = true
10
10
  @support_definition_list = true # TODO this should be an option
11
- @footnotes = {}
11
+ @footnotes = []
12
12
  end
13
13
 
14
- def push_mode(mode)
14
+ def push_mode(mode, indent)
15
+ @list_indent_stack.push(indent)
15
16
  super(mode)
16
- @output << "bc.. " if mode_is_code(mode)
17
- @output << "\np=. " if mode == :center
17
+ @output << "bc. " if mode_is_code? mode
18
+ if mode == :center or mode == :quote
19
+ @add_paragraph = false
20
+ @output << "\n"
21
+ end
18
22
  end
19
23
 
20
24
  def pop_mode(mode = nil)
21
25
  m = super(mode)
22
- @add_paragraph = (mode_is_code(m))
23
- @output << "\n" if mode == :center
26
+ @list_indent_stack.pop
27
+ if m == :center or m == :quote
28
+ @add_paragraph = true
29
+ @output << "\n"
30
+ end
24
31
  m
25
32
  end
26
33
 
@@ -36,37 +43,68 @@ module Orgmode
36
43
 
37
44
  # Handles inline formatting for textile.
38
45
  def inline_formatting(input)
39
- input = @re_help.rewrite_emphasis(input) do |marker, body|
46
+ @re_help.rewrite_emphasis input do |marker, body|
40
47
  m = TextileMap[marker]
41
48
  "#{m}#{body}#{m}"
42
49
  end
43
- input = @re_help.rewrite_subp(input) do |type, text|
50
+ @re_help.rewrite_subp input do |type, text|
44
51
  if type == "_" then
45
52
  "~#{text}~"
46
53
  elsif type == "^" then
47
54
  "^#{text}^"
48
55
  end
49
56
  end
50
- input = @re_help.rewrite_links(input) do |link, text|
51
- text ||= link
52
- link = link.gsub(/ /, "%20")
53
- "\"#{text}\":#{link}"
57
+ @re_help.rewrite_links input do |link, defi|
58
+ [link, defi].compact.each do |text|
59
+ # We don't support search links right now. Get rid of it.
60
+ text.sub!(/\A(file:[^\s]+)::[^\s]*?\Z/, "\\1")
61
+ text.sub!(/\A(file:[^\s]+)\.org\Z/i, "\\1.textile")
62
+ text.sub!(/\Afile:(?=[^\s]+\Z)/, "")
63
+ end
64
+
65
+ # We don't add a description for images in links, because its
66
+ # empty value forces the image to be inlined.
67
+ defi ||= link unless link =~ @re_help.org_image_file_regexp
68
+ link = link.gsub(/ /, "%%20")
69
+
70
+ if defi =~ @re_help.org_image_file_regexp
71
+ defi = "!#{defi}(#{defi})!"
72
+ elsif defi
73
+ defi = "\"#{defi}\""
74
+ end
75
+
76
+ if defi
77
+ "#{defi}:#{link}"
78
+ else
79
+ "!#{link}(#{link})!"
80
+ end
54
81
  end
55
- input = @re_help.rewrite_footnote(input) do |name, defi|
56
- # textile only support numerical names! Use hash as a workarround
57
- name = name.hash.to_s unless name.to_i.to_s == name # check if number
58
- @footnotes[name] = defi if defi
59
- "[#{name}]"
82
+ @re_help.rewrite_footnote input do |name, definition|
83
+ # textile only support numerical names, so we need to do some conversion
84
+ # Try to find the footnote and use its index
85
+ footnote = @footnotes.select {|f| f[:name] == name }.first
86
+ if footnote
87
+ # The latest definition overrides other ones
88
+ footnote[:definition] = definition if definition and not footnote[:definition]
89
+ else
90
+ # There is no footnote with the current name so we add it
91
+ footnote = { :name => name, :definition => definition }
92
+ @footnotes << footnote
93
+ end
94
+
95
+ "[#{@footnotes.index(footnote)}]"
60
96
  end
61
97
  Orgmode.special_symbols_to_textile(input)
98
+ input = @re_help.restore_code_snippets input
62
99
  input
63
100
  end
64
101
 
65
102
  def output_footnotes!
66
103
  return false if @footnotes.empty?
67
104
 
68
- @footnotes.each do |name, defi|
69
- @output << "\nfn#{name}. #{defi}\n"
105
+ @footnotes.each do |footnote|
106
+ index = @footnotes.index(footnote)
107
+ @output << "\nfn#{index}. #{footnote[:definition] || 'DEFINITION NOT FOUND' }\n"
70
108
  end
71
109
 
72
110
  return true
@@ -74,29 +112,44 @@ module Orgmode
74
112
 
75
113
  # Flushes the current buffer
76
114
  def flush!
115
+ return false if @buffer.empty? and @output_type != :blank
77
116
  @logger.debug "FLUSH ==========> #{@output_type}"
78
- if (@output_type == :blank) then
117
+ @buffer.gsub!(/\A\n*/, "")
118
+
119
+ case
120
+ when preserve_whitespace?
121
+ @output << @buffer << "\n"
122
+
123
+ when @output_type == :blank
79
124
  @output << "\n"
80
- elsif (@buffer.length > 0) then
81
- if @add_paragraph then
82
- @output << "p. " if @output_type == :paragraph
83
- @add_paragraph = false
84
- end
85
- @output << "bq. " if current_mode == :blockquote
86
- if @output_type == :definition_list and @support_definition_list then
87
- @output << "-" * @list_indent_stack.length << " "
88
- @buffer.sub!("::", ":=")
89
- elsif @output_type == :ordered_list then
90
- @output << "#" * @list_indent_stack.length << " "
91
- elsif @output_type == :unordered_list or \
92
- (@output_type == :definition_list and not @support_definition_list) then
93
- @output << "*" * @list_indent_stack.length << " "
125
+
126
+ else
127
+ case current_mode
128
+ when :paragraph
129
+ @output << "p. " if @add_paragraph
130
+ @output << "p=. " if @mode_stack[0] == :center
131
+ @output << "bq. " if @mode_stack[0] == :quote
132
+
133
+ when :list_item
134
+ if @mode_stack[-2] == :ordered_list
135
+ @output << "#" * @mode_stack.count(:list_item) << " "
136
+ else # corresponds to unordered list
137
+ @output << "*" * @mode_stack.count(:list_item) << " "
138
+ end
139
+
140
+ when :definition_term
141
+ if @support_definition_list
142
+ @output << "-" * @mode_stack.count(:definition_term) << " "
143
+ @buffer.sub!("::", ":=")
144
+ end
94
145
  end
95
146
  @output << inline_formatting(@buffer) << "\n"
96
147
  end
97
- clear_accumulation_buffer!
148
+ @buffer = ""
98
149
  end
99
150
 
100
-
151
+ def add_line_attributes headline
152
+ @output << "h#{headline.level}. "
153
+ end
101
154
  end # class TextileOutputBuffer
102
155
  end # module Orgmode