diff --git a/lib/org-ruby/html_output_buffer.rb b/lib/org-ruby/html_output_buffer.rb index 0c6b47e..d7670c9 100644 --- a/lib/org-ruby/html_output_buffer.rb +++ b/lib/org-ruby/html_output_buffer.rb @@ -130,7 +130,7 @@ def flush! # Whitespace is significant in :code mode. Always output the buffer # and do not do any additional translation. @logger.debug "FLUSH CODE ==========> #{@buffer.inspect}" - @output << @buffer << "\n" + @output << @buffer else escape_buffer! if @buffer.length > 0 and @output_type == :horizontal_rule then @@ -177,7 +177,7 @@ def flush! def output_footnotes! return false unless @options[:export_footnotes] and not @footnotes.empty? - @output << "
\n

Footnotes:

\n
\n" + @output << "
\n

Footnotes:\n

\n
\n" @footnotes.each do |name, defi| @output << "

#{name}" \ diff --git a/lib/org-ruby/line.rb b/lib/org-ruby/line.rb index 34ff634..8dca0d7 100644 --- a/lib/org-ruby/line.rb +++ b/lib/org-ruby/line.rb @@ -14,9 +14,12 @@ class Line # Backpointer to the parser that owns this line. attr_reader :parser - # Paragraph type determined for the line + # Paragraph type determined for the line. attr_reader :paragraph_type + # Major modes assosiate paragraphs with a table, list and so on. + attr_reader :major_mode + # A line can have its type assigned instead of inferred from its # content. For example, something that parses as a "table" on its # own ("| one | two|\n") may just be a paragraph if it's inside @@ -30,6 +33,7 @@ def initialize(line, parser = nil) @indent = 0 @line =~ /\s*/ determine_paragraph_type + determine_major_mode @assigned_paragraph_type = nil @indent = $&.length unless blank? end @@ -245,11 +249,26 @@ def determine_paragraph_type end end - def major_mode - return :definition_list if definition_list? # order is important! A definition_list is also an unordered_list! - return :ordered_list if ordered_list? - return :unordered_list if unordered_list? - return :table if table? + def determine_major_mode + @major_mode = \ + case + when definition_list? # order is important! A definition_list is also an unordered_list! + :definition_list + when ordered_list? + :ordered_list + when unordered_list? + :unordered_list + when table? + :table + when (begin_block? and block_type.casecmp("QUOTE") == 0) + :blockquote + when (begin_block? and block_type.casecmp("CENTER") == 0) + :center + when (begin_block? and block_type.casecmp("EXAMPLE") == 0) + :example + when (begin_block? and block_type.casecmp("SRC") == 0) + :src + end end ###################################################################### diff --git a/lib/org-ruby/output_buffer.rb b/lib/org-ruby/output_buffer.rb index e614312..b543383 100644 --- a/lib/org-ruby/output_buffer.rb +++ b/lib/org-ruby/output_buffer.rb @@ -54,6 +54,7 @@ def initialize(output) end HeadingModes = [:heading1, :heading2, :heading3, :heading4, :heading5, :heading6] + BlockModes = [:blockquote, :center, :example, :src] def current_mode @mode_stack.last @@ -77,12 +78,13 @@ def pop_mode(mode = nil) # As a side effect, this may flush the current accumulated text. def prepare(line) @logger.debug "Looking at #{line.paragraph_type}(#{current_mode}) : #{line.to_s}" - if line.begin_block? and line.code_block? - flush! + if mode_is_code(current_mode) + if line.end_block? + flush! + maintain_mode_stack(line) + end # We try to get the lang from #+BEGIN_SRC blocks - @block_lang = line.block_lang - elsif current_mode == :example and line.end_block? - flush! + @block_lang = line.block_lang if line.code_block? elsif not should_accumulate_output?(line) flush! maintain_mode_stack(line) @@ -167,9 +169,15 @@ def maintain_mode_stack(line) @output_type == :blank) # Close previous tags on demand. Two blank lines close all tags. while ((not @list_indent_stack.empty?) and - @list_indent_stack.last >= line.indent) - unless (@list_indent_stack.last == line.indent and - current_mode == line.major_mode) + @list_indent_stack.last > line.indent) + pop_mode + end + while ((not @list_indent_stack.empty?) and + @list_indent_stack.last == line.indent) + if BlockModes.include?(current_mode) + # Special case: Only end-block line closes the block + pop_mode if line.end_block? + elsif current_mode != line.major_mode # item can't close its major mode pop_mode else break @@ -183,10 +191,10 @@ def maintain_mode_stack(line) @output << "\n" end end - # Open tag preceding text, including list item. + # Open tag that precedes text immediately if (@list_indent_stack.empty? or @list_indent_stack.last <= line.indent) - push_mode(line.paragraph_type, line) + push_mode(line.paragraph_type, line) unless line.begin_block? end else # If blank line, close preceding paragraph pop_mode if current_mode == :paragraph @@ -213,14 +221,14 @@ def should_accumulate_output?(line) # Special case: Blank line at least splits paragraphs return false if @output_type == :blank - if line.paragraph_type == :paragraph + if line.paragraph_type == :paragraph and current_mode != :comment # Paragraph gets accumulated only if its indent level is # greater than the indent level of the previous modes. @list_indent_stack[0..-2].each do |indent| return false if line.indent <= indent end # Special case: Multiple "paragraphs" get accumulated. - return true unless current_mode == :comment + return true end false diff --git a/lib/org-ruby/parser.rb b/lib/org-ruby/parser.rb index 9db2ac4..f11b293 100644 --- a/lib/org-ruby/parser.rb +++ b/lib/org-ruby/parser.rb @@ -258,21 +258,11 @@ def self.translate(lines, output_buffer) case line.paragraph_type when :metadata, :table_separator, :blank, :comment, :property_drawer_item, :property_drawer_begin_block, :property_drawer_end_block - output_buffer << line.line if output_buffer.preserve_whitespace? + output_buffer << line.line << "\n" if output_buffer.preserve_whitespace? - when :begin_block + when :begin_block, :end_block - output_buffer.push_mode(:blockquote, line) if line.block_type.casecmp("QUOTE") == 0 - output_buffer.push_mode(:src, line) if line.block_type.casecmp("SRC") == 0 - output_buffer.push_mode(:example, line) if line.block_type.casecmp("EXAMPLE") == 0 - output_buffer.push_mode(:center, line) if line.block_type.casecmp("CENTER") == 0 - - when :end_block - - output_buffer.pop_mode(:blockquote) if line.block_type.casecmp("QUOTE") == 0 - output_buffer.pop_mode(:src) if line.block_type.casecmp("SRC") == 0 - output_buffer.pop_mode(:example) if line.block_type.casecmp("EXAMPLE") == 0 - output_buffer.pop_mode(:center) if line.block_type.casecmp("CENTER") == 0 + # Nothing when :table_row, :table_header @@ -288,7 +278,7 @@ def self.translate(lines, output_buffer) else if output_buffer.preserve_whitespace? then - output_buffer << line.output_text + output_buffer << line.output_text << "\n" else output_buffer << line.output_text.strip << "\n" end