Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

New pretty indentation of HTML output done, code essentially simplifi…

…ed. Currently, supports ordered and unordered lists, can broke Textile output.
  • Loading branch information...
commit 8482368b7f78ca5add55edce9cd3da754ef27564 1 parent af069b6
Vladimir Ivanov authored
105 lib/org-ruby/html_output_buffer.rb
View
@@ -15,12 +15,20 @@ class HtmlOutputBuffer < OutputBuffer
HtmlBlockTag = {
:paragraph => "p",
- :ordered_list => "li",
- :unordered_list => "li",
+ :unordered_list => "ul",
+ :ordered_list => "ol",
+ :list_item => "li",
+ :definition_list => "dl",
:definition_term => "dt",
:definition_descr => "dd",
+ :table => "table",
:table_row => "tr",
:table_header => "tr",
+ :blockquote => "blockquote",
+ :example => "pre",
+ :src => "pre",
+ :inline_example => "pre",
+ :center => "div",
:heading1 => "h1",
:heading2 => "h2",
:heading3 => "h3",
@@ -29,18 +37,6 @@ class HtmlOutputBuffer < OutputBuffer
:heading6 => "h6"
}
- ModeTag = {
- :unordered_list => "ul",
- :ordered_list => "ol",
- :definition_list => "dl",
- :table => "table",
- :blockquote => "blockquote",
- :example => "pre",
- :src => "pre",
- :inline_example => "pre",
- :center => "div"
- }
-
attr_reader :options
def initialize(output, opts = {})
@@ -57,12 +53,13 @@ def initialize(output, opts = {})
end
# Output buffer is entering a new mode. Use this opportunity to
- # write out one of the block tags in the ModeTag constant to put
- # this information in the HTML stream.
- def push_mode(mode)
- if ModeTag[mode] then
+ # write out one of the block tags in the HtmlBlockTag constant to
+ # put this information in the HTML stream.
+ def push_mode(mode, line)
+ @list_indent_stack.push(line.indent)
+ if HtmlBlockTag[mode] then
output_indentation
- css_class = ""
+ css_class = @title_decoration
css_class = " class=\"src\"" if mode == :src and @block_lang.empty?
css_class = " class=\"src src-#{@block_lang}\"" if mode == :src and not @block_lang.empty?
css_class = " class=\"example\"" if (mode == :example || mode == :inline_example)
@@ -70,8 +67,8 @@ def push_mode(mode)
unless ((mode == :table and skip_tables?) or
(mode == :src and defined? Pygments))
- @logger.debug "#{mode}: <#{ModeTag[mode]}#{css_class}>\n"
- @output << "<#{ModeTag[mode]}#{css_class}>\n"
+ @logger.debug "#{mode}: <#{HtmlBlockTag[mode]}#{css_class}>\n"
+ @output << "<#{HtmlBlockTag[mode]}#{css_class}>"
end
# Entering a new mode obliterates the title decoration
@title_decoration = ""
@@ -83,29 +80,18 @@ def push_mode(mode)
# entering this mode.
def pop_mode(mode = nil)
m = super(mode)
- if ModeTag[m] then
+ if HtmlBlockTag[m] then
output_indentation
- # Need to close the floating li elements before closing the list
- if (m == :unordered_list or
- m == :ordered_list or
- m == :definition_list) and
- (not @unclosed_tags.empty?)
- close_floating_li_tags
- end
-
unless ((mode == :table and skip_tables?) or
(mode == :src and defined? Pygments))
- @logger.debug "</#{ModeTag[m]}>\n"
- @output << "</#{ModeTag[m]}>\n"
+ @logger.debug "</#{HtmlBlockTag[m]}>\n"
+ @output << "</#{HtmlBlockTag[m]}>\n"
end
-
- # In case it was a sublist, close it here
- close_last_li_tag_maybe
end
+ @list_indent_stack.pop
end
def flush!
- @buffer = @buffer.rstrip
if buffer_mode_is_src_block?
# Only try to colorize #+BEGIN_SRC blocks with a specified language,
@@ -166,13 +152,6 @@ def flush!
elsif @buffer.length > 0 then
unless buffer_mode_is_table? and skip_tables?
@logger.debug "FLUSH ==========> #{@buffer_mode}"
- output_indentation
- if ((@buffered_lines[0].plain_list?) and
- (@unclosed_tags.count == @list_indent_stack.count))
- @output << @unclosed_tags.pop
- output_indentation
- end
- @output << "<#{HtmlBlockTag[@output_type]}#{@title_decoration}>"
if (@buffered_lines[0].kind_of?(Headline)) then
headline = @buffered_lines[0]
raise "Cannot be more than one headline!" if @buffered_lines.length > 1
@@ -187,19 +166,6 @@ def flush!
end
end
@output << inline_formatting(@buffer)
-
- # Only close the list when it is the last element from that list,
- # or when starting another list
- if (@output_type == :unordered_list or
- @output_type == :ordered_list or
- @output_type == :definition_list) and
- (not @list_indent_stack.empty?)
- @unclosed_tags.push("</#{HtmlBlockTag[@output_type]}>\n")
- @output << "\n"
- else
- @output << "</#{HtmlBlockTag[@output_type]}>\n"
- end
- @title_decoration = ""
else
@logger.debug "SKIP ==========> #{@buffer_mode}"
end
@@ -248,7 +214,7 @@ def escape_buffer!
end
def output_indentation
- indent = " " * (@mode_stack.length - 1)
+ indent = " " * (@list_indent_stack.length - 1)
@output << indent
end
@@ -264,7 +230,6 @@ def output_indentation
# Applies inline formatting rules to a string.
def inline_formatting(str)
- str.rstrip!
str = @re_help.rewrite_emphasis(str) do |marker, s|
"#{Tags[marker][:open]}#{s}#{Tags[marker][:close]}"
end
@@ -320,30 +285,6 @@ def inline_formatting(str)
str
end
- def close_floating_li_tags
- unless @final_list_node
- unless @unclosed_tags.empty?
- @output << " " << @unclosed_tags.pop
- output_indentation
- end
- end
-
- @final_list_node = false
- end
-
- def close_last_li_tag_maybe
- if (@list_indent_stack.count < @unclosed_tags.count) and not
- (@list_indent_stack.empty? and @unclosed_tags.empty?)
- output_indentation
- @output << @unclosed_tags.pop
- if (@list_indent_stack.count == @unclosed_tags.count) and not
- (@list_indent_stack.empty? and @unclosed_tags.empty?)
- @final_list_node = true
- pop_mode
- end
- end
- end
-
def normalize_lang(lang)
case lang
when 'emacs-lisp', 'common-lisp', 'lisp'
116 lib/org-ruby/output_buffer.rb
View
@@ -51,10 +51,9 @@ def initialize(output)
end
@re_help = RegexpHelper.new
- push_mode(:normal)
end
- Modes = [:normal, :ordered_list, :unordered_list, :definition_list, :blockquote, :src, :example, :table, :inline_example, :center, :property_drawer]
+ HeadingModes = [:heading1, :heading2, :heading3, :heading4, :heading5, :heading6]
def current_mode
@mode_stack.last
@@ -65,7 +64,6 @@ def current_mode_list?
end
def push_mode(mode)
- raise "Not a recognized mode: #{mode}" unless Modes.include?(mode)
@mode_stack.push(mode)
end
@@ -83,20 +81,18 @@ def prepare(line)
flush!
# We try to get the lang from #+BEGIN_SRC blocks
@block_lang = line.block_lang
- @output_type = line.paragraph_type
elsif current_mode == :example and line.end_block?
flush!
- @output_type = line.paragraph_type
elsif not should_accumulate_output?(line)
flush!
- maintain_list_indent_stack(line)
- @output_type = line.paragraph_type
+ maintain_mode_stack(line)
end
- push_mode(:inline_example) if line.inline_example? and current_mode != :inline_example and not line.property_drawer?
+ @output_type = line.paragraph_type
+ push_mode(:inline_example, line) if line.inline_example? and current_mode != :inline_example and not line.property_drawer?
pop_mode(:inline_example) if current_mode == :inline_example and !line.inline_example?
- push_mode(:property_drawer) if line.property_drawer? and current_mode != :property_drawer
+ push_mode(:property_drawer, line) if line.property_drawer? and current_mode != :property_drawer
pop_mode(:property_drawer) if current_mode == :property_drawer and line.property_drawer_end_block?
- push_mode(:table) if enter_table?
+ push_mode(:table, line) if enter_table?
pop_mode(:table) if exit_table?
@buffered_lines.push(line)
end
@@ -171,36 +167,43 @@ def mode_is_code(mode)
end
end
- def maintain_list_indent_stack(line)
- if (line.plain_list?) then
- while (not @list_indent_stack.empty? \
- and (@list_indent_stack.last > line.indent))
- @list_indent_stack.pop
- pop_mode
+ def maintain_mode_stack(line)
+ # Always close heading line
+ pop_mode if HeadingModes.include?(current_mode)
+
+ if ((not line.paragraph_type == :blank) or
+ @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 (line.plain_list? and
+ current_mode == line.paragraph_type and
+ @list_indent_stack.last == line.indent)
+ pop_mode
+ else
+ break
+ end
end
- if (@list_indent_stack.empty? \
- or @list_indent_stack.last < line.indent)
- @list_indent_stack.push(line.indent)
- push_mode line.paragraph_type
+ # Open plain list.
+ if line.plain_list?
+ if (@list_indent_stack.empty? or
+ @list_indent_stack.last < line.indent)
+ push_mode(line.paragraph_type, line)
+ @output << "\n"
+ end
end
- elsif line.blank? then
-
- # Nothing
-
- elsif ((not line.plain_list?) and
- (not @list_indent_stack.empty?) and
- (line.indent > @list_indent_stack.last))
-
- # Nothing -- output this paragraph inside
- # the list block (ul/ol)
-
- else
- @list_indent_stack = []
- while ((current_mode == :ordered_list) or
- (current_mode == :definition_list) or
- (current_mode == :unordered_list))
- pop_mode
+ # Open tag preceding text, including list item.
+ if (@list_indent_stack.empty? or
+ @list_indent_stack.last <= line.indent)
+ if (line.paragraph_type == :ordered_list or
+ line.paragraph_type == :unordered_list)
+ push_mode(:list_item, line)
+ elsif not line.paragraph_type == :blank
+ push_mode(line.paragraph_type, line)
+ end
end
+ else # If blank line, close preceding paragraph
+ pop_mode if current_mode == :paragraph
end
end
@@ -209,39 +212,26 @@ def output_footnotes!
end
# Tests if the current line should be accumulated in the current
- # output buffer. (Extraneous line breaks in the orgmode buffer
- # are removed by accumulating lines in the output buffer without
- # line breaks.)
+ # output buffer.
def should_accumulate_output?(line)
+ # Special case: Assing mode if not yet done.
+ return false if not current_mode
# Special case: We are accumulating source code block content for colorizing
return true if line.paragraph_type == :src and @output_type == :src
- # Special case: Preserve line breaks in block code mode.
- return false if preserve_whitespace?
+ # Special case: Multiple "paragraphs" get accumulated.
+ return true if (line.paragraph_type == :paragraph and
+ current_mode == :paragraph)
- # Special case: Multiple blank lines get accumulated.
- return true if line.paragraph_type == :blank and @output_type == :blank
-
- # Currently only "paragraphs" get accumulated with previous output.
- return false unless line.paragraph_type == :paragraph
- if ((@output_type == :ordered_list) or
- (@output_type == :definition_list) or
- (@output_type == :unordered_list)) then
-
- # If the previous output type was a list item, then we only put a paragraph in it
- # if its indent level is greater than the list indent level.
-
- return false unless line.indent > @list_indent_stack.last
- end
+ # If the current mode is not paragraph, then we only put a
+ # paragraph in it if its indent level is greater than the indent
+ # level of the current mode and no blank lines before.
+ return true if (line.paragraph_type == :paragraph and
+ (not @output_type == :blank) and
+ line.indent > @list_indent_stack.last)
- # Only accumulate paragraphs with lists & paragraphs.
- return false unless
- ((@output_type == :paragraph) or
- (@output_type == :ordered_list) or
- (@output_type == :definition_list) or
- (@output_type == :unordered_list))
- true
+ false
end
end # class OutputBuffer
end # module Orgmode
10 lib/org-ruby/parser.rb
View
@@ -262,10 +262,10 @@ def self.translate(lines, output_buffer)
when :begin_block
- output_buffer.push_mode(:blockquote) if line.block_type.casecmp("QUOTE") == 0
- output_buffer.push_mode(:src) if line.block_type.casecmp("SRC") == 0
- output_buffer.push_mode(:example) if line.block_type.casecmp("EXAMPLE") == 0
- output_buffer.push_mode(:center) if line.block_type.casecmp("CENTER") == 0
+ 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
@@ -295,7 +295,7 @@ def self.translate(lines, output_buffer)
end
end
output_buffer.flush!
- output_buffer.pop_mode until output_buffer.current_mode == :normal
+ output_buffer.pop_mode while output_buffer.current_mode
output_buffer.output_footnotes!
output_buffer.output
end
Please sign in to comment.
Something went wrong with that request. Please try again.