diff --git a/lib/rdoc/markup/simple_markup.rb b/lib/rdoc/markup/simple_markup.rb index 8193ca02d4..ed3b4d3270 100644 --- a/lib/rdoc/markup/simple_markup.rb +++ b/lib/rdoc/markup/simple_markup.rb @@ -1,5 +1,7 @@ -# = Introduction -# +require 'rdoc/markup/simple_markup/fragments' +require 'rdoc/markup/simple_markup/lines.rb' + +## # SimpleMarkup parses plain text documents and attempts to decompose # them into their constituent parts. Some of these parts are high-level: # paragraphs, chunks of verbatim text, list entries and the like. Other @@ -65,7 +67,7 @@ # # ant:: a little insect that is known # to enjoy picnics -# +# # This latter style guarantees that the list bodies' left margins are # aligned: think of them as a two column table. # @@ -107,19 +109,13 @@ # # = Using SimpleMarkup # -# For information on using SimpleMarkup programatically, -# see SM::SimpleMarkup. -# +# For information on using SimpleMarkup programatically, see SM::SimpleMarkup. +#-- # Author:: Dave Thomas, dave@pragmaticprogrammer.com # Version:: 0.0 # License:: Ruby license - - -require 'rdoc/markup/simple_markup/fragments' -require 'rdoc/markup/simple_markup/lines.rb' - -module SM #:nodoc: +module SM # == Synopsis # @@ -162,25 +158,18 @@ module SM #:nodoc: # h.add_tag(:STRIKE, "", "") # # puts "" + p.convert(ARGF.read, h) + "" - # - # == Output Formatters - # - # _missing_ - # - # class SimpleMarkup SPACE = ?\s # List entries look like: - # * text - # 1. text - # [label] text - # label:: text + # * text + # 1. text + # [label] text + # label:: text # - # Flag it as a list entry, and - # work out the indent for subsequent lines + # Flag it as a list entry, and work out the indent for subsequent lines SIMPLE_LIST_RE = /^( ( \* (?# bullet) @@ -197,12 +186,10 @@ module SM #:nodoc: )(?:\s+|$) )/x - ## - # take a block of text and use various heuristics to determine - # it's structure (paragraphs, lists, and so on). Invoke an - # event handler as we identify significant chunks. - # + # Take a block of text and use various heuristics to determine it's + # structure (paragraphs, lists, and so on). Invoke an event handler as we + # identify significant chunks. def initialize @am = AttributeManager.new @@ -210,41 +197,39 @@ module SM #:nodoc: end ## - # Add to the sequences used to add formatting to an individual word - # (such as *bold*). Matching entries will generate attibutes - # that the output formatters can recognize by their +name+ + # Add to the sequences used to add formatting to an individual word (such + # as *bold*). Matching entries will generate attibutes that the output + # formatters can recognize by their +name+. def add_word_pair(start, stop, name) @am.add_word_pair(start, stop, name) end ## - # Add to the sequences recognized as general markup - # + # Add to the sequences recognized as general markup. def add_html(tag, name) @am.add_html(tag, name) end ## - # Add to other inline sequences. For example, we could add - # WikiWords using something like: + # Add to other inline sequences. For example, we could add WikiWords using + # something like: # # parser.add_special(/\b([A-Z][a-z]+[A-Z]\w+)/, :WIKIWORD) # - # Each wiki word will be presented to the output formatter - # via the accept_special method - # + # Each wiki word will be presented to the output formatter via the + # accept_special method. def add_special(pattern, name) @am.add_special(pattern, name) end - - # We take a string, split it into lines, work out the type of - # each line, and from there deduce groups of lines (for example - # all lines in a paragraph). We then invoke the output formatter - # using a Visitor to display the result + ## + # We take a string, split it into lines, work out the type of each line, + # and from there deduce groups of lines (for example all lines in a + # paragraph). We then invoke the output formatter using a Visitor to + # display the result. def convert(str, op) @lines = Lines.new(str.split(/\r?\n/).collect { |aLine| @@ -258,16 +243,11 @@ module SM #:nodoc: group.accept(@am, op) end - - ####### private - ####### - ## # Look through the text at line indentation. We flag each line as being - # Blank, a paragraph, a list element, or verbatim text - # + # Blank, a paragraph, a list element, or verbatim text. def assign_types_to_lines(margin = 0, level = 0) @@ -362,23 +342,24 @@ module SM #:nodoc: end end - # Handle labeled list entries, We have a special case - # to deal with. Because the labels can be long, they force - # the remaining block of text over the to right: + ## + # Handle labeled list entries, We have a special case to deal with. + # Because the labels can be long, they force the remaining block of text + # over the to right: # - # this is a long label that I wrote:: and here is the - # block of text with - # a silly margin + # this is a long label that I wrote:: and here is the + # block of text with + # a silly margin # - # So we allow the special case. If the label is followed - # by nothing, and if the following line is indented, then - # we take the indent of that line as the new margin + # So we allow the special case. If the label is followed by nothing, and + # if the following line is indented, then we take the indent of that line + # as the new margin. # - # this is a long label that I wrote:: - # here is a more reasonably indented block which - # will ab attached to the label. + # this is a long label that I wrote:: + # here is a more reasonably indented block which + # will be attached to the label. # - + def handled_labeled_list(line, level, margin, offset, prefix) prefix_length = prefix.length text = line.text @@ -425,12 +406,12 @@ module SM #:nodoc: return true end - # Return a block consisting of fragments which are - # paragraphs, list entries or verbatim text. We merge consecutive - # lines of the same type and level together. We are also slightly - # tricky with lists: the lines following a list introduction - # look like paragraph lines at the next level, and we remap them - # into list entries instead + ## + # Return a block consisting of fragments which are paragraphs, list + # entries or verbatim text. We merge consecutive lines of the same type + # and level together. We are also slightly tricky with lists: the lines + # following a list introduction look like paragraph lines at the next + # level, and we remap them into list entries instead. def group_lines @lines.rewind @@ -460,17 +441,23 @@ module SM #:nodoc: block end - ## for debugging, we allow access to our line contents as text + ## + # For debugging, we allow access to our line contents as text. + def content @lines.as_text end public :content - ## for debugging, return the list of line types + ## + # For debugging, return the list of line types. + def get_line_types @lines.line_types end public :get_line_types + end end + diff --git a/lib/rdoc/markup/simple_markup/fragments.rb b/lib/rdoc/markup/simple_markup/fragments.rb index 6ca06382ab..bd60ca0fec 100644 --- a/lib/rdoc/markup/simple_markup/fragments.rb +++ b/lib/rdoc/markup/simple_markup/fragments.rb @@ -1,11 +1,10 @@ require 'rdoc/markup/simple_markup/lines.rb' -#require 'rdoc/markup/simple_markup/to_flow.rb' module SM ## # A Fragment is a chunk of text, subclassed as a paragraph, a list - # entry, or verbatim text + # entry, or verbatim text. class Fragment attr_reader :level, :param, :txt @@ -47,7 +46,7 @@ module SM ## # A paragraph is a fragment which gets wrapped to fit. We remove all - # newlines when we're created, and have them put back on output + # newlines when we're created, and have them put back on output. class Paragraph < Fragment type_name Line::PARAGRAPH @@ -67,7 +66,6 @@ module SM ## # A List is a fragment with some kind of label - # class ListBase < Paragraph # List types @@ -114,16 +112,17 @@ module SM ## # A horizontal rule + class Rule < Fragment type_name Line::RULE end - - # Collect groups of lines together. Each group - # will end up containing a flow of text + ## + # Collect groups of lines together. Each group will end up containing a flow + # of text class LineCollection - + def initialize @fragments = [] end @@ -136,17 +135,20 @@ module SM @fragments.each(&b) end - # For testing - def to_a + def to_a # :nodoc: @fragments.map {|fragment| fragment.to_s} end + ## # Factory for different fragment types + def fragment_for(*args) Fragment.for(*args) end - # tidy up at the end + ## + # Tidy up at the end + def normalize change_verbatim_blank_lines add_list_start_and_ends @@ -159,7 +161,6 @@ module SM end def accept(am, visitor) - visitor.start_accepting @fragments.each do |fragment| @@ -185,9 +186,8 @@ module SM visitor.end_accepting end - ####### + private - ####### # If you have: # @@ -197,14 +197,12 @@ module SM # # and more code # - # You'll end up with the fragments Paragraph, BlankLine, - # Verbatim, BlankLine, Verbatim, BlankLine, etc + # You'll end up with the fragments Paragraph, BlankLine, Verbatim, + # BlankLine, Verbatim, BlankLine, etc. # - # The BlankLine in the middle of the verbatim chunk needs to - # be changed to a real verbatim newline, and the two - # verbatim blocks merged - # - # + # The BlankLine in the middle of the verbatim chunk needs to be changed to + # a real verbatim newline, and the two verbatim blocks merged + def change_verbatim_blank_lines frag_block = nil blank_count = 0 @@ -232,9 +230,9 @@ module SM @fragments.compact! end - # List nesting is implicit given the level of - # Make it explicit, just to make life a tad - # easier for the output processors + ## + # List nesting is implicit given the level of indentation. Make it + # explicit, just to make life a tad easier for the output processors def add_list_start_and_ends level = 0 @@ -270,8 +268,9 @@ module SM @fragments = res end - # now insert start/ends between list entries at the - # same level that have different element types + ## + # Inserts start/ends between list entries at the same level that have + # different element types def add_list_breaks res = @fragments @@ -302,7 +301,8 @@ module SM end end - # Finally tidy up the blank lines: + ## + # Tidy up the blank lines: # * change Blank/ListEnd into ListEnd/Blank # * remove blank lines at the front @@ -324,5 +324,6 @@ module SM end end - + end + diff --git a/lib/rdoc/markup/simple_markup/inline.rb b/lib/rdoc/markup/simple_markup/inline.rb index ec1faf13aa..eafda011e8 100644 --- a/lib/rdoc/markup/simple_markup/inline.rb +++ b/lib/rdoc/markup/simple_markup/inline.rb @@ -1,7 +1,8 @@ module SM - # We manage a set of attributes. Each attribute has a symbol name - # and a bit value + ## + # We manage a set of attributes. Each attribute has a symbol name and a bit + # value class Attribute SPECIAL = 1 @@ -36,19 +37,21 @@ module SM end end - - # An AttrChanger records a change in attributes. It contains - # a bitmap of the attributes to turn on, and a bitmap of those to - # turn off + ## + # An AttrChanger records a change in attributes. It contains a bitmap of the + # attributes to turn on, and a bitmap of those to turn off AttrChanger = Struct.new(:turn_on, :turn_off) + class AttrChanger def to_s "Attr: +#{Attribute.as_string(@turn_on)}/-#{Attribute.as_string(@turn_on)}" end end + ## # An array of attributes which parallels the characters in a string + class AttrSpan def initialize(length) @attrs = Array.new(length, 0) @@ -89,46 +92,51 @@ module SM object_id, @type, SM::Attribute.as_string(type), text.dump] end end - + class AttributeManager NULL = "\000".freeze ## - # We work by substituting non-printing characters in to the - # text. For now I'm assuming that I can substitute - # a character in the range 0..8 for a 7 bit character - # without damaging the encoded string, but this might - # be optimistic - # + # We work by substituting non-printing characters in to the text. For now + # I'm assuming that I can substitute a character in the range 0..8 for a 7 + # bit character without damaging the encoded string, but this might be + # optimistic A_PROTECT = 004 PROTECT_ATTR = A_PROTECT.chr - # This maps delimiters that occur around words (such as - # *bold* or +tt+) where the start and end delimiters - # and the same. This lets us optimize the regexp + ## + # This maps delimiters that occur around words (such as *bold* or +tt+) + # where the start and end delimiters and the same. This lets us optimize + # the regexp + MATCHING_WORD_PAIRS = {} - # And this is used when the delimiters aren't the same. In this - # case the hash maps a pattern to the attribute character + ## + # And this is used when the delimiters aren't the same. In this case the + # hash maps a pattern to the attribute character + WORD_PAIR_MAP = {} + ## # This maps HTML tags to the corresponding attribute char + HTML_TAGS = {} - # And this maps _special_ sequences to a name. A special sequence - # is something like a WikiWord + ## + # And this maps _special_ sequences to a name. A special sequence is + # something like a WikiWord + SPECIAL = {} - # Return an attribute object with the given turn_on - # and turn_off bits set + ## + # Return an attribute object with the given turn_on and turn_off bits set def attribute(turn_on, turn_off) AttrChanger.new(turn_on, turn_off) end - def change_attribute(current, new) diff = current ^ new attribute(new & diff, current & diff) @@ -147,8 +155,10 @@ module SM res end - # Map attributes like textto the sequence \001\002\001\003, - # where is a per-attribute specific character + ## + # Map attributes like textto the sequence + # \001\002\001\003, where is a per-attribute specific + # character def convert_attrs(str, attrs) # first do matching ones @@ -194,10 +204,10 @@ module SM end end - # A \ in front of a character that would normally be - # processed turns off processing. We do this by turning - # \< into <#{PROTECT} - + ## + # A \ in front of a character that would normally be processed turns off + # processing. We do this by turning \< into <#{PROTECT} + PROTECTABLE = [ "<" << "\\" ] #" @@ -214,7 +224,7 @@ module SM add_word_pair("*", "*", :BOLD) add_word_pair("_", "_", :EM) add_word_pair("+", "+", :TT) - + add_html("em", :EM) add_html("i", :EM) add_html("b", :BOLD) @@ -253,7 +263,7 @@ module SM puts("Before flow, str='#{@str.dump}'") if $DEBUG_RDOC mask_protected_sequences - + @attrs = AttrSpan.new(@str.length) puts("After protecting, str='#{@str.dump}'") if $DEBUG_RDOC @@ -295,7 +305,6 @@ module SM current_attr = 0 str = "" - str_len = @str.length # skip leading invisible text @@ -328,7 +337,7 @@ module SM i += 1 end while i < str_len and @str[i] == "\0" end - + # tidy up trailing text if start_pos < str_len res << copy_string(start_pos, str_len) @@ -343,3 +352,4 @@ module SM end end + diff --git a/lib/rdoc/markup/simple_markup/lines.rb b/lib/rdoc/markup/simple_markup/lines.rb index 4e294f27dc..8ef66079b2 100644 --- a/lib/rdoc/markup/simple_markup/lines.rb +++ b/lib/rdoc/markup/simple_markup/lines.rb @@ -1,11 +1,10 @@ -########################################################################## -# -# We store the lines we're working on as objects of class Line. -# These contain the text of the line, along with a flag indicating the -# line type, and an indentation level - module SM + ## + # We store the lines we're working on as objects of class Line. These + # contain the text of the line, along with a flag indicating the line type, + # and an indentation level. + class Line INFINITY = 9999 @@ -85,15 +84,14 @@ module SM end end - ############################################################################### - # + ## # A container for all the lines - # class Lines + include Enumerable - attr_reader :lines # for debugging + attr_reader :lines # :nodoc: def initialize(lines) @lines = lines @@ -147,5 +145,8 @@ module SM def line_types @lines.map {|l| l.type } end + end + end + diff --git a/lib/rdoc/markup/simple_markup/preprocess.rb b/lib/rdoc/markup/simple_markup/preprocess.rb index 101c9bdeb1..c7d29ad48f 100644 --- a/lib/rdoc/markup/simple_markup/preprocess.rb +++ b/lib/rdoc/markup/simple_markup/preprocess.rb @@ -1,10 +1,9 @@ module SM - ## + ## # Handle common directives that can occur in a block of text: # # : include : filename - # class PreProcess @@ -13,12 +12,12 @@ module SM @include_path = include_path end - # Look for common options in a chunk of text. Options that - # we don't handle are passed back to our caller - # as |directive, param| + ## + # Look for common options in a chunk of text. Options that we don't handle + # are passed back to our caller as |directive, param| def handle(text) - text.gsub!(/^([ \t#]*):(\w+):\s*(.+)?\n/) do + text.gsub!(/^([ \t#]*):(\w+):\s*(.+)?\n/) do prefix = $1 directive = $2.downcase param = $3 @@ -34,11 +33,10 @@ module SM end end - ####### private - ####### - # Include a file, indenting it correctly + ## + # Include a file, indenting it correctly. def include_file(name, indent) if (full_name = find_include_file(name)) @@ -55,9 +53,9 @@ module SM end end - # Look for the given file in the directory containing the current - # file, and then in each of the directories specified in the - # RDOC_INCLUDE path + ## + # Look for the given file in the directory containing the current file, + # and then in each of the directories specified in the RDOC_INCLUDE path def find_include_file(name) to_search = [ File.dirname(@input_file_name) ].concat @include_path @@ -70,4 +68,6 @@ module SM end end + end + diff --git a/lib/rdoc/markup/simple_markup/to_flow.rb b/lib/rdoc/markup/simple_markup/to_flow.rb index 048e71abce..fc8c5f5ce6 100644 --- a/lib/rdoc/markup/simple_markup/to_flow.rb +++ b/lib/rdoc/markup/simple_markup/to_flow.rb @@ -40,7 +40,7 @@ module SM ## # Set up the standard mapping of attributes to HTML tags - # + def init_tags @attr_tags = [ InlineTag.new(SM::Attribute.bitmap_for(:BOLD), "", ""), @@ -50,24 +50,23 @@ module SM end ## - # Add a new set of HTML tags for an attribute. We allow - # separate start and end tags for flexibility - # + # Add a new set of HTML tags for an attribute. We allow separate start and + # end tags for flexibility + def add_tag(name, start, stop) @attr_tags << InlineTag.new(SM::Attribute.bitmap_for(name), start, stop) end ## - # Given an HTML tag, decorate it with class information - # and the like if required. This is a no-op in the base - # class, but is overridden in HTML output classes that - # implement style sheets + # Given an HTML tag, decorate it with class information and the like if + # required. This is a no-op in the base class, but is overridden in HTML + # output classes that implement style sheets def annotate(tag) tag end - ## + ## # Here's the client side of the visitor pattern def start_accepting @@ -116,13 +115,8 @@ module SM @res << Flow::H.new(fragment.head_level, convert_flow(am.flow(fragment.txt))) end - - ####################################################################### - private - ####################################################################### - def on_tags(res, item) attr_mask = item.turn_on return if attr_mask.zero? @@ -163,8 +157,6 @@ module SM res end - # some of these patterns are taken from SmartyPants... - def convert_string(item) CGI.escapeHTML(item) end @@ -178,11 +170,13 @@ module SM handled = true end end + raise "Unhandled special: #{special}" unless handled + special.text end - end end + diff --git a/lib/rdoc/markup/simple_markup/to_html.rb b/lib/rdoc/markup/simple_markup/to_html.rb index 26b5f4ce70..d78468684f 100644 --- a/lib/rdoc/markup/simple_markup/to_html.rb +++ b/lib/rdoc/markup/simple_markup/to_html.rb @@ -24,7 +24,7 @@ module SM ## # Set up the standard mapping of attributes to HTML tags - # + def init_tags @attr_tags = [ InlineTag.new(SM::Attribute.bitmap_for(:BOLD), "", ""), @@ -34,24 +34,23 @@ module SM end ## - # Add a new set of HTML tags for an attribute. We allow - # separate start and end tags for flexibility - # + # Add a new set of HTML tags for an attribute. We allow separate start and + # end tags for flexibility. + def add_tag(name, start, stop) @attr_tags << InlineTag.new(SM::Attribute.bitmap_for(name), start, stop) end ## - # Given an HTML tag, decorate it with class information - # and the like if required. This is a no-op in the base - # class, but is overridden in HTML output classes that - # implement style sheets + # Given an HTML tag, decorate it with class information and the like if + # required. This is a no-op in the base class, but is overridden in HTML + # output classes that implement style sheets. def annotate(tag) tag end - ## + ## # Here's the client side of the visitor pattern def start_accepting @@ -82,7 +81,7 @@ module SM end def accept_list_start(am, fragment) - @res << html_list_name(fragment.type, true) <<"\n" + @res << html_list_name(fragment.type, true) << "\n" @in_list_entry.push false end @@ -90,7 +89,7 @@ module SM if tag = @in_list_entry.pop @res << annotate(tag) << "\n" end - @res << html_list_name(fragment.type, false) <<"\n" + @res << html_list_name(fragment.type, false) << "\n" end def accept_list_item(am, fragment) @@ -110,6 +109,7 @@ module SM @res << convert_heading(fragment.head_level, am.flow(fragment.txt)) end + ## # This is a higher speed (if messier) version of wrap def wrap(txt, line_len = 76) @@ -139,12 +139,8 @@ module SM res end - ####################################################################### - private - ####################################################################### - def on_tags(res, item) attr_mask = item.turn_on return if attr_mask.zero? @@ -185,12 +181,12 @@ module SM res end + ## # some of these patterns are taken from SmartyPants... def convert_string(item) CGI.escapeHTML(item). - - + # convert -- to em-dash, (-- to en-dash) gsub(/---?/, '—'). #gsub(/--/, '–'). @@ -233,8 +229,8 @@ module SM def convert_heading(level, flow) res = - annotate("") + - convert_flow(flow) + + annotate("") + + convert_flow(flow) + annotate("\n") end @@ -249,21 +245,21 @@ module SM annotate("
  • ") when ListBase::UPPERALPHA - annotate("
  • ") + annotate("
  • ") when ListBase::LOWERALPHA - annotate("
  • ") + annotate("
  • ") when ListBase::LABELED annotate("
    ") + - convert_flow(am.flow(fragment.param)) + + convert_flow(am.flow(fragment.param)) + annotate("
    ") + annotate("
    ") when ListBase::NOTE annotate("") + annotate("") + - convert_flow(am.flow(fragment.param)) + + convert_flow(am.flow(fragment.param)) + annotate("") + annotate("") else @@ -273,7 +269,8 @@ module SM def list_end_for(fragment_type) case fragment_type - when ListBase::BULLET, ListBase::NUMBER, ListBase::UPPERALPHA, ListBase::LOWERALPHA + when ListBase::BULLET, ListBase::NUMBER, ListBase::UPPERALPHA, + ListBase::LOWERALPHA "
  • " when ListBase::LABELED "" @@ -287,3 +284,4 @@ module SM end end + diff --git a/lib/rdoc/markup/simple_markup/to_latex.rb b/lib/rdoc/markup/simple_markup/to_latex.rb index 6c16278652..b014b6990b 100644 --- a/lib/rdoc/markup/simple_markup/to_latex.rb +++ b/lib/rdoc/markup/simple_markup/to_latex.rb @@ -50,7 +50,7 @@ module SM ## # Set up the standard mapping of attributes to LaTeX - # + def init_tags @attr_tags = [ InlineTag.new(SM::Attribute.bitmap_for(:BOLD), l("\\textbf{"), l("}")), @@ -61,6 +61,7 @@ module SM ## # Escape a LaTeX string + def escape(str) # $stderr.print "FE: ", str s = str. @@ -80,13 +81,12 @@ module SM ## # Add a new set of LaTeX tags for an attribute. We allow # separate start and end tags for flexibility - # + def add_tag(name, start, stop) @attr_tags << InlineTag.new(SM::Attribute.bitmap_for(name), start, stop) end - - ## + ## # Here's the client side of the visitor pattern def start_accepting @@ -116,7 +116,7 @@ module SM end def accept_list_start(am, fragment) - @res << list_name(fragment.type, true) <<"\n" + @res << list_name(fragment.type, true) << "\n" @in_list_entry.push false end @@ -124,7 +124,7 @@ module SM if tag = @in_list_entry.pop @res << tag << "\n" end - @res << list_name(fragment.type, false) <<"\n" + @res << list_name(fragment.type, false) << "\n" end def accept_list_item(am, fragment) @@ -144,6 +144,7 @@ module SM @res << convert_heading(fragment.head_level, am.flow(fragment.txt)) end + ## # This is a higher speed (if messier) version of wrap def wrap(txt, line_len = 76) @@ -173,12 +174,8 @@ module SM res end - ####################################################################### - private - ####################################################################### - def on_tags(res, item) attr_mask = item.turn_on return if attr_mask.zero? @@ -220,13 +217,12 @@ module SM res end + ## # some of these patterns are taken from SmartyPants... def convert_string(item) - escape(item). - - + # convert ... to elipsis (and make sure .... becomes .) gsub(/\.\.\.\./, '.\ldots{}').gsub(/\.\.\./, '\ldots{}'). @@ -270,7 +266,7 @@ module SM when 4 then "\\subsubsection{" else "\\paragraph{" end + - convert_flow(flow) + + convert_flow(flow) + "}\n" end @@ -304,7 +300,8 @@ module SM def list_item_start(am, fragment) case fragment.type - when ListBase::BULLET, ListBase::NUMBER, ListBase::UPPERALPHA, ListBase::LOWERALPHA + when ListBase::BULLET, ListBase::NUMBER, ListBase::UPPERALPHA, + ListBase::LOWERALPHA "\\item " when ListBase::LABELED @@ -319,7 +316,8 @@ module SM def list_end_for(fragment_type) case fragment_type - when ListBase::BULLET, ListBase::NUMBER, ListBase::UPPERALPHA, ListBase::LOWERALPHA, ListBase::LABELED + when ListBase::BULLET, ListBase::NUMBER, ListBase::UPPERALPHA, + ListBase::LOWERALPHA, ListBase::LABELED "" when ListBase::NOTE "\\\\\n" @@ -331,3 +329,4 @@ module SM end end +