1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Cleanup RDoc

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@15019 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
drbrain 2008-01-13 03:35:34 +00:00
parent ec519b9b43
commit 0feac89d2d
8 changed files with 201 additions and 211 deletions

View file

@ -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 # SimpleMarkup parses plain text documents and attempts to decompose
# them into their constituent parts. Some of these parts are high-level: # them into their constituent parts. Some of these parts are high-level:
# paragraphs, chunks of verbatim text, list entries and the like. Other # paragraphs, chunks of verbatim text, list entries and the like. Other
@ -65,7 +67,7 @@
# #
# ant:: a little insect that is known # ant:: a little insect that is known
# to enjoy picnics # to enjoy picnics
# #
# This latter style guarantees that the list bodies' left margins are # This latter style guarantees that the list bodies' left margins are
# aligned: think of them as a two column table. # aligned: think of them as a two column table.
# #
@ -107,19 +109,13 @@
# #
# = Using SimpleMarkup # = Using SimpleMarkup
# #
# For information on using SimpleMarkup programatically, # For information on using SimpleMarkup programatically, see SM::SimpleMarkup.
# see SM::SimpleMarkup. #--
#
# Author:: Dave Thomas, dave@pragmaticprogrammer.com # Author:: Dave Thomas, dave@pragmaticprogrammer.com
# Version:: 0.0 # Version:: 0.0
# License:: Ruby license # License:: Ruby license
module SM
require 'rdoc/markup/simple_markup/fragments'
require 'rdoc/markup/simple_markup/lines.rb'
module SM #:nodoc:
# == Synopsis # == Synopsis
# #
@ -162,25 +158,18 @@ module SM #:nodoc:
# h.add_tag(:STRIKE, "<strike>", "</strike>") # h.add_tag(:STRIKE, "<strike>", "</strike>")
# #
# puts "<body>" + p.convert(ARGF.read, h) + "</body>" # puts "<body>" + p.convert(ARGF.read, h) + "</body>"
#
# == Output Formatters
#
# _missing_
#
#
class SimpleMarkup class SimpleMarkup
SPACE = ?\s SPACE = ?\s
# List entries look like: # List entries look like:
# * text # * text
# 1. text # 1. text
# [label] text # [label] text
# label:: text # label:: text
# #
# Flag it as a list entry, and # Flag it as a list entry, and work out the indent for subsequent lines
# work out the indent for subsequent lines
SIMPLE_LIST_RE = /^( SIMPLE_LIST_RE = /^(
( \* (?# bullet) ( \* (?# bullet)
@ -197,12 +186,10 @@ module SM #:nodoc:
)(?:\s+|$) )(?:\s+|$)
)/x )/x
## ##
# take a block of text and use various heuristics to determine # Take a block of text and use various heuristics to determine it's
# it's structure (paragraphs, lists, and so on). Invoke an # structure (paragraphs, lists, and so on). Invoke an event handler as we
# event handler as we identify significant chunks. # identify significant chunks.
#
def initialize def initialize
@am = AttributeManager.new @am = AttributeManager.new
@ -210,41 +197,39 @@ module SM #:nodoc:
end end
## ##
# Add to the sequences used to add formatting to an individual word # Add to the sequences used to add formatting to an individual word (such
# (such as *bold*). Matching entries will generate attibutes # as *bold*). Matching entries will generate attibutes that the output
# that the output formatters can recognize by their +name+ # formatters can recognize by their +name+.
def add_word_pair(start, stop, name) def add_word_pair(start, stop, name)
@am.add_word_pair(start, stop, name) @am.add_word_pair(start, stop, name)
end end
## ##
# Add to the sequences recognized as general markup # Add to the sequences recognized as general markup.
#
def add_html(tag, name) def add_html(tag, name)
@am.add_html(tag, name) @am.add_html(tag, name)
end end
## ##
# Add to other inline sequences. For example, we could add # Add to other inline sequences. For example, we could add WikiWords using
# WikiWords using something like: # something like:
# #
# parser.add_special(/\b([A-Z][a-z]+[A-Z]\w+)/, :WIKIWORD) # parser.add_special(/\b([A-Z][a-z]+[A-Z]\w+)/, :WIKIWORD)
# #
# Each wiki word will be presented to the output formatter # Each wiki word will be presented to the output formatter via the
# via the accept_special method # accept_special method.
#
def add_special(pattern, name) def add_special(pattern, name)
@am.add_special(pattern, name) @am.add_special(pattern, name)
end end
##
# We take a string, split it into lines, work out the type of # We take a string, split it into lines, work out the type of each line,
# each line, and from there deduce groups of lines (for example # and from there deduce groups of lines (for example all lines in a
# all lines in a paragraph). We then invoke the output formatter # paragraph). We then invoke the output formatter using a Visitor to
# using a Visitor to display the result # display the result.
def convert(str, op) def convert(str, op)
@lines = Lines.new(str.split(/\r?\n/).collect { |aLine| @lines = Lines.new(str.split(/\r?\n/).collect { |aLine|
@ -258,16 +243,11 @@ module SM #:nodoc:
group.accept(@am, op) group.accept(@am, op)
end end
#######
private private
#######
## ##
# Look through the text at line indentation. We flag each line as being # 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) def assign_types_to_lines(margin = 0, level = 0)
@ -362,23 +342,24 @@ module SM #:nodoc:
end end
end end
# Handle labeled list entries, We have a special case ##
# to deal with. Because the labels can be long, they force # Handle labeled list entries, We have a special case to deal with.
# the remaining block of text over the to right: # 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 # this is a long label that I wrote:: and here is the
# block of text with # block of text with
# a silly margin # a silly margin
# #
# So we allow the special case. If the label is followed # So we allow the special case. If the label is followed by nothing, and
# by nothing, and if the following line is indented, then # if the following line is indented, then we take the indent of that line
# we take the indent of that line as the new margin # as the new margin.
# #
# this is a long label that I wrote:: # this is a long label that I wrote::
# here is a more reasonably indented block which # here is a more reasonably indented block which
# will ab attached to the label. # will be attached to the label.
# #
def handled_labeled_list(line, level, margin, offset, prefix) def handled_labeled_list(line, level, margin, offset, prefix)
prefix_length = prefix.length prefix_length = prefix.length
text = line.text text = line.text
@ -425,12 +406,12 @@ module SM #:nodoc:
return true return true
end end
# Return a block consisting of fragments which are ##
# paragraphs, list entries or verbatim text. We merge consecutive # Return a block consisting of fragments which are paragraphs, list
# lines of the same type and level together. We are also slightly # entries or verbatim text. We merge consecutive lines of the same type
# tricky with lists: the lines following a list introduction # and level together. We are also slightly tricky with lists: the lines
# look like paragraph lines at the next level, and we remap them # following a list introduction look like paragraph lines at the next
# into list entries instead # level, and we remap them into list entries instead.
def group_lines def group_lines
@lines.rewind @lines.rewind
@ -460,17 +441,23 @@ module SM #:nodoc:
block block
end 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 def content
@lines.as_text @lines.as_text
end end
public :content public :content
## for debugging, return the list of line types ##
# For debugging, return the list of line types.
def get_line_types def get_line_types
@lines.line_types @lines.line_types
end end
public :get_line_types public :get_line_types
end end
end end

View file

@ -1,11 +1,10 @@
require 'rdoc/markup/simple_markup/lines.rb' require 'rdoc/markup/simple_markup/lines.rb'
#require 'rdoc/markup/simple_markup/to_flow.rb'
module SM module SM
## ##
# A Fragment is a chunk of text, subclassed as a paragraph, a list # A Fragment is a chunk of text, subclassed as a paragraph, a list
# entry, or verbatim text # entry, or verbatim text.
class Fragment class Fragment
attr_reader :level, :param, :txt attr_reader :level, :param, :txt
@ -47,7 +46,7 @@ module SM
## ##
# A paragraph is a fragment which gets wrapped to fit. We remove all # 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 class Paragraph < Fragment
type_name Line::PARAGRAPH type_name Line::PARAGRAPH
@ -67,7 +66,6 @@ module SM
## ##
# A List is a fragment with some kind of label # A List is a fragment with some kind of label
#
class ListBase < Paragraph class ListBase < Paragraph
# List types # List types
@ -114,16 +112,17 @@ module SM
## ##
# A horizontal rule # A horizontal rule
class Rule < Fragment class Rule < Fragment
type_name Line::RULE type_name Line::RULE
end end
##
# Collect groups of lines together. Each group # Collect groups of lines together. Each group will end up containing a flow
# will end up containing a flow of text # of text
class LineCollection class LineCollection
def initialize def initialize
@fragments = [] @fragments = []
end end
@ -136,17 +135,20 @@ module SM
@fragments.each(&b) @fragments.each(&b)
end end
# For testing def to_a # :nodoc:
def to_a
@fragments.map {|fragment| fragment.to_s} @fragments.map {|fragment| fragment.to_s}
end end
##
# Factory for different fragment types # Factory for different fragment types
def fragment_for(*args) def fragment_for(*args)
Fragment.for(*args) Fragment.for(*args)
end end
# tidy up at the end ##
# Tidy up at the end
def normalize def normalize
change_verbatim_blank_lines change_verbatim_blank_lines
add_list_start_and_ends add_list_start_and_ends
@ -159,7 +161,6 @@ module SM
end end
def accept(am, visitor) def accept(am, visitor)
visitor.start_accepting visitor.start_accepting
@fragments.each do |fragment| @fragments.each do |fragment|
@ -185,9 +186,8 @@ module SM
visitor.end_accepting visitor.end_accepting
end end
#######
private private
#######
# If you have: # If you have:
# #
@ -197,14 +197,12 @@ module SM
# #
# and more code # and more code
# #
# You'll end up with the fragments Paragraph, BlankLine, # You'll end up with the fragments Paragraph, BlankLine, Verbatim,
# Verbatim, BlankLine, Verbatim, BlankLine, etc # BlankLine, Verbatim, BlankLine, etc.
# #
# The BlankLine in the middle of the verbatim chunk needs to # The BlankLine in the middle of the verbatim chunk needs to be changed to
# be changed to a real verbatim newline, and the two # a real verbatim newline, and the two verbatim blocks merged
# verbatim blocks merged
#
#
def change_verbatim_blank_lines def change_verbatim_blank_lines
frag_block = nil frag_block = nil
blank_count = 0 blank_count = 0
@ -232,9 +230,9 @@ module SM
@fragments.compact! @fragments.compact!
end end
# List nesting is implicit given the level of ##
# Make it explicit, just to make life a tad # List nesting is implicit given the level of indentation. Make it
# easier for the output processors # explicit, just to make life a tad easier for the output processors
def add_list_start_and_ends def add_list_start_and_ends
level = 0 level = 0
@ -270,8 +268,9 @@ module SM
@fragments = res @fragments = res
end 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 def add_list_breaks
res = @fragments res = @fragments
@ -302,7 +301,8 @@ module SM
end end
end end
# Finally tidy up the blank lines: ##
# Tidy up the blank lines:
# * change Blank/ListEnd into ListEnd/Blank # * change Blank/ListEnd into ListEnd/Blank
# * remove blank lines at the front # * remove blank lines at the front
@ -324,5 +324,6 @@ module SM
end end
end end
end end

View file

@ -1,7 +1,8 @@
module SM 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 class Attribute
SPECIAL = 1 SPECIAL = 1
@ -36,19 +37,21 @@ module SM
end end
end end
##
# An AttrChanger records a change in attributes. It contains # An AttrChanger records a change in attributes. It contains a bitmap of the
# a bitmap of the attributes to turn on, and a bitmap of those to # attributes to turn on, and a bitmap of those to turn off
# turn off
AttrChanger = Struct.new(:turn_on, :turn_off) AttrChanger = Struct.new(:turn_on, :turn_off)
class AttrChanger class AttrChanger
def to_s def to_s
"Attr: +#{Attribute.as_string(@turn_on)}/-#{Attribute.as_string(@turn_on)}" "Attr: +#{Attribute.as_string(@turn_on)}/-#{Attribute.as_string(@turn_on)}"
end end
end end
##
# An array of attributes which parallels the characters in a string # An array of attributes which parallels the characters in a string
class AttrSpan class AttrSpan
def initialize(length) def initialize(length)
@attrs = Array.new(length, 0) @attrs = Array.new(length, 0)
@ -89,46 +92,51 @@ module SM
object_id, @type, SM::Attribute.as_string(type), text.dump] object_id, @type, SM::Attribute.as_string(type), text.dump]
end end
end end
class AttributeManager class AttributeManager
NULL = "\000".freeze NULL = "\000".freeze
## ##
# We work by substituting non-printing characters in to the # We work by substituting non-printing characters in to the text. For now
# text. For now I'm assuming that I can substitute # I'm assuming that I can substitute a character in the range 0..8 for a 7
# a character in the range 0..8 for a 7 bit character # bit character without damaging the encoded string, but this might be
# without damaging the encoded string, but this might # optimistic
# be optimistic
#
A_PROTECT = 004 A_PROTECT = 004
PROTECT_ATTR = A_PROTECT.chr PROTECT_ATTR = A_PROTECT.chr
# This maps delimiters that occur around words (such as ##
# *bold* or +tt+) where the start and end delimiters # This maps delimiters that occur around words (such as *bold* or +tt+)
# and the same. This lets us optimize the regexp # where the start and end delimiters and the same. This lets us optimize
# the regexp
MATCHING_WORD_PAIRS = {} 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 = {} WORD_PAIR_MAP = {}
##
# This maps HTML tags to the corresponding attribute char # This maps HTML tags to the corresponding attribute char
HTML_TAGS = {} 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 = {} 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) def attribute(turn_on, turn_off)
AttrChanger.new(turn_on, turn_off) AttrChanger.new(turn_on, turn_off)
end end
def change_attribute(current, new) def change_attribute(current, new)
diff = current ^ new diff = current ^ new
attribute(new & diff, current & diff) attribute(new & diff, current & diff)
@ -147,8 +155,10 @@ module SM
res res
end end
# Map attributes like <b>text</b>to the sequence \001\002<char>\001\003<char>, ##
# where <char> is a per-attribute specific character # Map attributes like <b>text</b>to the sequence
# \001\002<char>\001\003<char>, where <char> is a per-attribute specific
# character
def convert_attrs(str, attrs) def convert_attrs(str, attrs)
# first do matching ones # first do matching ones
@ -194,10 +204,10 @@ module SM
end end
end end
# A \ in front of a character that would normally be ##
# processed turns off processing. We do this by turning # A \ in front of a character that would normally be processed turns off
# \< into <#{PROTECT} # processing. We do this by turning \< into <#{PROTECT}
PROTECTABLE = [ "<" << "\\" ] #" PROTECTABLE = [ "<" << "\\" ] #"
@ -214,7 +224,7 @@ module SM
add_word_pair("*", "*", :BOLD) add_word_pair("*", "*", :BOLD)
add_word_pair("_", "_", :EM) add_word_pair("_", "_", :EM)
add_word_pair("+", "+", :TT) add_word_pair("+", "+", :TT)
add_html("em", :EM) add_html("em", :EM)
add_html("i", :EM) add_html("i", :EM)
add_html("b", :BOLD) add_html("b", :BOLD)
@ -253,7 +263,7 @@ module SM
puts("Before flow, str='#{@str.dump}'") if $DEBUG_RDOC puts("Before flow, str='#{@str.dump}'") if $DEBUG_RDOC
mask_protected_sequences mask_protected_sequences
@attrs = AttrSpan.new(@str.length) @attrs = AttrSpan.new(@str.length)
puts("After protecting, str='#{@str.dump}'") if $DEBUG_RDOC puts("After protecting, str='#{@str.dump}'") if $DEBUG_RDOC
@ -295,7 +305,6 @@ module SM
current_attr = 0 current_attr = 0
str = "" str = ""
str_len = @str.length str_len = @str.length
# skip leading invisible text # skip leading invisible text
@ -328,7 +337,7 @@ module SM
i += 1 i += 1
end while i < str_len and @str[i] == "\0" end while i < str_len and @str[i] == "\0"
end end
# tidy up trailing text # tidy up trailing text
if start_pos < str_len if start_pos < str_len
res << copy_string(start_pos, str_len) res << copy_string(start_pos, str_len)
@ -343,3 +352,4 @@ module SM
end end
end end

View file

@ -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 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 class Line
INFINITY = 9999 INFINITY = 9999
@ -85,15 +84,14 @@ module SM
end end
end end
############################################################################### ##
#
# A container for all the lines # A container for all the lines
#
class Lines class Lines
include Enumerable include Enumerable
attr_reader :lines # for debugging attr_reader :lines # :nodoc:
def initialize(lines) def initialize(lines)
@lines = lines @lines = lines
@ -147,5 +145,8 @@ module SM
def line_types def line_types
@lines.map {|l| l.type } @lines.map {|l| l.type }
end end
end end
end end

View file

@ -1,10 +1,9 @@
module SM module SM
## ##
# Handle common directives that can occur in a block of text: # Handle common directives that can occur in a block of text:
# #
# : include : filename # : include : filename
#
class PreProcess class PreProcess
@ -13,12 +12,12 @@ module SM
@include_path = include_path @include_path = include_path
end end
# Look for common options in a chunk of text. Options that ##
# we don't handle are passed back to our caller # Look for common options in a chunk of text. Options that we don't handle
# as |directive, param| # are passed back to our caller as |directive, param|
def handle(text) def handle(text)
text.gsub!(/^([ \t#]*):(\w+):\s*(.+)?\n/) do text.gsub!(/^([ \t#]*):(\w+):\s*(.+)?\n/) do
prefix = $1 prefix = $1
directive = $2.downcase directive = $2.downcase
param = $3 param = $3
@ -34,11 +33,10 @@ module SM
end end
end end
#######
private private
#######
# Include a file, indenting it correctly ##
# Include a file, indenting it correctly.
def include_file(name, indent) def include_file(name, indent)
if (full_name = find_include_file(name)) if (full_name = find_include_file(name))
@ -55,9 +53,9 @@ module SM
end end
end end
# Look for the given file in the directory containing the current ##
# file, and then in each of the directories specified in the # Look for the given file in the directory containing the current file,
# RDOC_INCLUDE path # and then in each of the directories specified in the RDOC_INCLUDE path
def find_include_file(name) def find_include_file(name)
to_search = [ File.dirname(@input_file_name) ].concat @include_path to_search = [ File.dirname(@input_file_name) ].concat @include_path
@ -70,4 +68,6 @@ module SM
end end
end end
end end

View file

@ -40,7 +40,7 @@ module SM
## ##
# Set up the standard mapping of attributes to HTML tags # Set up the standard mapping of attributes to HTML tags
#
def init_tags def init_tags
@attr_tags = [ @attr_tags = [
InlineTag.new(SM::Attribute.bitmap_for(:BOLD), "<b>", "</b>"), InlineTag.new(SM::Attribute.bitmap_for(:BOLD), "<b>", "</b>"),
@ -50,24 +50,23 @@ module SM
end end
## ##
# Add a new set of HTML tags for an attribute. We allow # Add a new set of HTML tags for an attribute. We allow separate start and
# separate start and end tags for flexibility # end tags for flexibility
#
def add_tag(name, start, stop) def add_tag(name, start, stop)
@attr_tags << InlineTag.new(SM::Attribute.bitmap_for(name), start, stop) @attr_tags << InlineTag.new(SM::Attribute.bitmap_for(name), start, stop)
end end
## ##
# Given an HTML tag, decorate it with class information # Given an HTML tag, decorate it with class information and the like if
# and the like if required. This is a no-op in the base # required. This is a no-op in the base class, but is overridden in HTML
# class, but is overridden in HTML output classes that # output classes that implement style sheets
# implement style sheets
def annotate(tag) def annotate(tag)
tag tag
end end
## ##
# Here's the client side of the visitor pattern # Here's the client side of the visitor pattern
def start_accepting def start_accepting
@ -116,13 +115,8 @@ module SM
@res << Flow::H.new(fragment.head_level, convert_flow(am.flow(fragment.txt))) @res << Flow::H.new(fragment.head_level, convert_flow(am.flow(fragment.txt)))
end end
#######################################################################
private private
#######################################################################
def on_tags(res, item) def on_tags(res, item)
attr_mask = item.turn_on attr_mask = item.turn_on
return if attr_mask.zero? return if attr_mask.zero?
@ -163,8 +157,6 @@ module SM
res res
end end
# some of these patterns are taken from SmartyPants...
def convert_string(item) def convert_string(item)
CGI.escapeHTML(item) CGI.escapeHTML(item)
end end
@ -178,11 +170,13 @@ module SM
handled = true handled = true
end end
end end
raise "Unhandled special: #{special}" unless handled raise "Unhandled special: #{special}" unless handled
special.text special.text
end end
end end
end end

View file

@ -24,7 +24,7 @@ module SM
## ##
# Set up the standard mapping of attributes to HTML tags # Set up the standard mapping of attributes to HTML tags
#
def init_tags def init_tags
@attr_tags = [ @attr_tags = [
InlineTag.new(SM::Attribute.bitmap_for(:BOLD), "<b>", "</b>"), InlineTag.new(SM::Attribute.bitmap_for(:BOLD), "<b>", "</b>"),
@ -34,24 +34,23 @@ module SM
end end
## ##
# Add a new set of HTML tags for an attribute. We allow # Add a new set of HTML tags for an attribute. We allow separate start and
# separate start and end tags for flexibility # end tags for flexibility.
#
def add_tag(name, start, stop) def add_tag(name, start, stop)
@attr_tags << InlineTag.new(SM::Attribute.bitmap_for(name), start, stop) @attr_tags << InlineTag.new(SM::Attribute.bitmap_for(name), start, stop)
end end
## ##
# Given an HTML tag, decorate it with class information # Given an HTML tag, decorate it with class information and the like if
# and the like if required. This is a no-op in the base # required. This is a no-op in the base class, but is overridden in HTML
# class, but is overridden in HTML output classes that # output classes that implement style sheets.
# implement style sheets
def annotate(tag) def annotate(tag)
tag tag
end end
## ##
# Here's the client side of the visitor pattern # Here's the client side of the visitor pattern
def start_accepting def start_accepting
@ -82,7 +81,7 @@ module SM
end end
def accept_list_start(am, fragment) 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 @in_list_entry.push false
end end
@ -90,7 +89,7 @@ module SM
if tag = @in_list_entry.pop if tag = @in_list_entry.pop
@res << annotate(tag) << "\n" @res << annotate(tag) << "\n"
end end
@res << html_list_name(fragment.type, false) <<"\n" @res << html_list_name(fragment.type, false) << "\n"
end end
def accept_list_item(am, fragment) def accept_list_item(am, fragment)
@ -110,6 +109,7 @@ module SM
@res << convert_heading(fragment.head_level, am.flow(fragment.txt)) @res << convert_heading(fragment.head_level, am.flow(fragment.txt))
end end
##
# This is a higher speed (if messier) version of wrap # This is a higher speed (if messier) version of wrap
def wrap(txt, line_len = 76) def wrap(txt, line_len = 76)
@ -139,12 +139,8 @@ module SM
res res
end end
#######################################################################
private private
#######################################################################
def on_tags(res, item) def on_tags(res, item)
attr_mask = item.turn_on attr_mask = item.turn_on
return if attr_mask.zero? return if attr_mask.zero?
@ -185,12 +181,12 @@ module SM
res res
end end
##
# some of these patterns are taken from SmartyPants... # some of these patterns are taken from SmartyPants...
def convert_string(item) def convert_string(item)
CGI.escapeHTML(item). CGI.escapeHTML(item).
# convert -- to em-dash, (-- to en-dash) # convert -- to em-dash, (-- to en-dash)
gsub(/---?/, '&#8212;'). #gsub(/--/, '&#8211;'). gsub(/---?/, '&#8212;'). #gsub(/--/, '&#8211;').
@ -233,8 +229,8 @@ module SM
def convert_heading(level, flow) def convert_heading(level, flow)
res = res =
annotate("<h#{level}>") + annotate("<h#{level}>") +
convert_flow(flow) + convert_flow(flow) +
annotate("</h#{level}>\n") annotate("</h#{level}>\n")
end end
@ -249,21 +245,21 @@ module SM
annotate("<li>") annotate("<li>")
when ListBase::UPPERALPHA when ListBase::UPPERALPHA
annotate("<li type=\"A\">") annotate("<li type=\"A\">")
when ListBase::LOWERALPHA when ListBase::LOWERALPHA
annotate("<li type=\"a\">") annotate("<li type=\"a\">")
when ListBase::LABELED when ListBase::LABELED
annotate("<dt>") + annotate("<dt>") +
convert_flow(am.flow(fragment.param)) + convert_flow(am.flow(fragment.param)) +
annotate("</dt>") + annotate("</dt>") +
annotate("<dd>") annotate("<dd>")
when ListBase::NOTE when ListBase::NOTE
annotate("<tr>") + annotate("<tr>") +
annotate("<td valign=\"top\">") + annotate("<td valign=\"top\">") +
convert_flow(am.flow(fragment.param)) + convert_flow(am.flow(fragment.param)) +
annotate("</td>") + annotate("</td>") +
annotate("<td>") annotate("<td>")
else else
@ -273,7 +269,8 @@ module SM
def list_end_for(fragment_type) def list_end_for(fragment_type)
case fragment_type case fragment_type
when ListBase::BULLET, ListBase::NUMBER, ListBase::UPPERALPHA, ListBase::LOWERALPHA when ListBase::BULLET, ListBase::NUMBER, ListBase::UPPERALPHA,
ListBase::LOWERALPHA
"</li>" "</li>"
when ListBase::LABELED when ListBase::LABELED
"</dd>" "</dd>"
@ -287,3 +284,4 @@ module SM
end end
end end

View file

@ -50,7 +50,7 @@ module SM
## ##
# Set up the standard mapping of attributes to LaTeX # Set up the standard mapping of attributes to LaTeX
#
def init_tags def init_tags
@attr_tags = [ @attr_tags = [
InlineTag.new(SM::Attribute.bitmap_for(:BOLD), l("\\textbf{"), l("}")), InlineTag.new(SM::Attribute.bitmap_for(:BOLD), l("\\textbf{"), l("}")),
@ -61,6 +61,7 @@ module SM
## ##
# Escape a LaTeX string # Escape a LaTeX string
def escape(str) def escape(str)
# $stderr.print "FE: ", str # $stderr.print "FE: ", str
s = str. s = str.
@ -80,13 +81,12 @@ module SM
## ##
# Add a new set of LaTeX tags for an attribute. We allow # Add a new set of LaTeX tags for an attribute. We allow
# separate start and end tags for flexibility # separate start and end tags for flexibility
#
def add_tag(name, start, stop) def add_tag(name, start, stop)
@attr_tags << InlineTag.new(SM::Attribute.bitmap_for(name), start, stop) @attr_tags << InlineTag.new(SM::Attribute.bitmap_for(name), start, stop)
end end
##
##
# Here's the client side of the visitor pattern # Here's the client side of the visitor pattern
def start_accepting def start_accepting
@ -116,7 +116,7 @@ module SM
end end
def accept_list_start(am, fragment) 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 @in_list_entry.push false
end end
@ -124,7 +124,7 @@ module SM
if tag = @in_list_entry.pop if tag = @in_list_entry.pop
@res << tag << "\n" @res << tag << "\n"
end end
@res << list_name(fragment.type, false) <<"\n" @res << list_name(fragment.type, false) << "\n"
end end
def accept_list_item(am, fragment) def accept_list_item(am, fragment)
@ -144,6 +144,7 @@ module SM
@res << convert_heading(fragment.head_level, am.flow(fragment.txt)) @res << convert_heading(fragment.head_level, am.flow(fragment.txt))
end end
##
# This is a higher speed (if messier) version of wrap # This is a higher speed (if messier) version of wrap
def wrap(txt, line_len = 76) def wrap(txt, line_len = 76)
@ -173,12 +174,8 @@ module SM
res res
end end
#######################################################################
private private
#######################################################################
def on_tags(res, item) def on_tags(res, item)
attr_mask = item.turn_on attr_mask = item.turn_on
return if attr_mask.zero? return if attr_mask.zero?
@ -220,13 +217,12 @@ module SM
res res
end end
##
# some of these patterns are taken from SmartyPants... # some of these patterns are taken from SmartyPants...
def convert_string(item) def convert_string(item)
escape(item). escape(item).
# convert ... to elipsis (and make sure .... becomes .<elipsis>) # convert ... to elipsis (and make sure .... becomes .<elipsis>)
gsub(/\.\.\.\./, '.\ldots{}').gsub(/\.\.\./, '\ldots{}'). gsub(/\.\.\.\./, '.\ldots{}').gsub(/\.\.\./, '\ldots{}').
@ -270,7 +266,7 @@ module SM
when 4 then "\\subsubsection{" when 4 then "\\subsubsection{"
else "\\paragraph{" else "\\paragraph{"
end + end +
convert_flow(flow) + convert_flow(flow) +
"}\n" "}\n"
end end
@ -304,7 +300,8 @@ module SM
def list_item_start(am, fragment) def list_item_start(am, fragment)
case fragment.type case fragment.type
when ListBase::BULLET, ListBase::NUMBER, ListBase::UPPERALPHA, ListBase::LOWERALPHA when ListBase::BULLET, ListBase::NUMBER, ListBase::UPPERALPHA,
ListBase::LOWERALPHA
"\\item " "\\item "
when ListBase::LABELED when ListBase::LABELED
@ -319,7 +316,8 @@ module SM
def list_end_for(fragment_type) def list_end_for(fragment_type)
case 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 when ListBase::NOTE
"\\\\\n" "\\\\\n"
@ -331,3 +329,4 @@ module SM
end end
end end