Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
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
@vonavi authored
View
105 lib/org-ruby/html_output_buffer.rb
@@ -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'
View
116 lib/org-ruby/output_buffer.rb
@@ -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
View
10 lib/org-ruby/parser.rb
@@ -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.