wallyqs-org-ruby 0.6.1 → 0.8.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.
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