jeremy-RedCloth 4.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +135 -0
 - data/COPYING +18 -0
 - data/Manifest +56 -0
 - data/README +171 -0
 - data/Rakefile +205 -0
 - data/bin/redcloth +28 -0
 - data/ext/mingw-rbconfig.rb +176 -0
 - data/ext/redcloth_scan/extconf.rb +9 -0
 - data/ext/redcloth_scan/redcloth.h +178 -0
 - data/ext/redcloth_scan/redcloth_attributes.c.rl +56 -0
 - data/ext/redcloth_scan/redcloth_attributes.java.rl +96 -0
 - data/ext/redcloth_scan/redcloth_attributes.rl +33 -0
 - data/ext/redcloth_scan/redcloth_common.c.rl +18 -0
 - data/ext/redcloth_scan/redcloth_common.java.rl +18 -0
 - data/ext/redcloth_scan/redcloth_common.rl +111 -0
 - data/ext/redcloth_scan/redcloth_inline.c.rl +159 -0
 - data/ext/redcloth_scan/redcloth_inline.java.rl +108 -0
 - data/ext/redcloth_scan/redcloth_inline.rl +159 -0
 - data/ext/redcloth_scan/redcloth_scan.c.rl +237 -0
 - data/ext/redcloth_scan/redcloth_scan.java.rl +573 -0
 - data/ext/redcloth_scan/redcloth_scan.rl +325 -0
 - data/extras/ragel_profiler.rb +73 -0
 - data/lib/case_sensitive_require/RedCloth.rb +6 -0
 - data/lib/redcloth.rb +37 -0
 - data/lib/redcloth/erb_extension.rb +27 -0
 - data/lib/redcloth/formatters/base.rb +57 -0
 - data/lib/redcloth/formatters/html.rb +353 -0
 - data/lib/redcloth/formatters/latex.rb +275 -0
 - data/lib/redcloth/formatters/latex_entities.yml +2414 -0
 - data/lib/redcloth/textile_doc.rb +103 -0
 - data/lib/redcloth/version.rb +28 -0
 - data/setup.rb +1585 -0
 - data/test/basic.yml +922 -0
 - data/test/code.yml +229 -0
 - data/test/definitions.yml +82 -0
 - data/test/extra_whitespace.yml +64 -0
 - data/test/filter_html.yml +177 -0
 - data/test/filter_pba.yml +20 -0
 - data/test/helper.rb +108 -0
 - data/test/html.yml +311 -0
 - data/test/images.yml +254 -0
 - data/test/instiki.yml +38 -0
 - data/test/links.yml +275 -0
 - data/test/lists.yml +283 -0
 - data/test/poignant.yml +89 -0
 - data/test/sanitize_html.yml +42 -0
 - data/test/table.yml +336 -0
 - data/test/test_custom_tags.rb +58 -0
 - data/test/test_erb.rb +13 -0
 - data/test/test_extensions.rb +31 -0
 - data/test/test_formatters.rb +24 -0
 - data/test/test_parser.rb +73 -0
 - data/test/test_restrictions.rb +41 -0
 - data/test/textism.yml +480 -0
 - data/test/threshold.yml +772 -0
 - data/test/validate_fixtures.rb +74 -0
 - metadata +133 -0
 
| 
         @@ -0,0 +1,57 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module RedCloth::Formatters
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Base
         
     | 
| 
      
 3 
     | 
    
         
            +
                
         
     | 
| 
      
 4 
     | 
    
         
            +
                def pba(opts)
         
     | 
| 
      
 5 
     | 
    
         
            +
                  opts.delete(:style) if filter_styles
         
     | 
| 
      
 6 
     | 
    
         
            +
                  opts.delete(:class) if filter_classes
         
     | 
| 
      
 7 
     | 
    
         
            +
                  opts.delete(:id) if filter_ids
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  atts = ''
         
     | 
| 
      
 10 
     | 
    
         
            +
                  opts[:"text-align"] = opts.delete(:align)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  opts[:style] += ';' if opts[:style] && (opts[:style][-1..-1] != ';')
         
     | 
| 
      
 12 
     | 
    
         
            +
                  [:float, :"text-align", :"vertical-align"].each do |a|
         
     | 
| 
      
 13 
     | 
    
         
            +
                    opts[:style] = "#{a}:#{opts[a]};#{opts[:style]}" if opts[a]
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
                  [:"padding-right", :"padding-left"].each do |a|
         
     | 
| 
      
 16 
     | 
    
         
            +
                    opts[:style] = "#{a}:#{opts[a]}em;#{opts[:style]}" if opts[a]
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
                  [:style, :class, :lang, :id, :colspan, :rowspan, :title, :start, :align].each do |a|
         
     | 
| 
      
 19 
     | 
    
         
            +
                    atts << " #{a}=\"#{ html_esc(opts[a].to_s, :html_escape_attributes) }\"" if opts[a]
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
                  atts
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
                
         
     | 
| 
      
 24 
     | 
    
         
            +
                def ignore(opts)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  opts[:text]
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
                alias_method :notextile, :ignore
         
     | 
| 
      
 28 
     | 
    
         
            +
                
         
     | 
| 
      
 29 
     | 
    
         
            +
                def redcloth_version(opts)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  p(:text => "#{opts[:prefix]}#{RedCloth::VERSION}")
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                def inline_redcloth_version(opts)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  RedCloth::VERSION::STRING
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
                
         
     | 
| 
      
 37 
     | 
    
         
            +
                [:del_phrase, :sup_phrase, :sub_phrase, :span_phrase].each do |phrase_method|
         
     | 
| 
      
 38 
     | 
    
         
            +
                  method = phrase_method.to_s.split('_')[0]
         
     | 
| 
      
 39 
     | 
    
         
            +
                  define_method(phrase_method) do |opts|
         
     | 
| 
      
 40 
     | 
    
         
            +
                    "#{opts[:beginning_space]}#{self.send(method, opts)}"
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
                
         
     | 
| 
      
 44 
     | 
    
         
            +
                def method_missing(method, opts)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  opts[:text] || ""
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
                
         
     | 
| 
      
 48 
     | 
    
         
            +
                def before_transform(text)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
                
         
     | 
| 
      
 52 
     | 
    
         
            +
                def after_transform(text)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
              end
         
     | 
| 
      
 57 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,353 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module RedCloth::Formatters::HTML
         
     | 
| 
      
 2 
     | 
    
         
            +
              include RedCloth::Formatters::Base
         
     | 
| 
      
 3 
     | 
    
         
            +
              
         
     | 
| 
      
 4 
     | 
    
         
            +
              # escapement for regular HTML (not in PRE tag)
         
     | 
| 
      
 5 
     | 
    
         
            +
              def escape(text)
         
     | 
| 
      
 6 
     | 
    
         
            +
                html_esc(text)
         
     | 
| 
      
 7 
     | 
    
         
            +
              end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              # escapement for HTML in a PRE tag
         
     | 
| 
      
 10 
     | 
    
         
            +
              def escape_pre(text)
         
     | 
| 
      
 11 
     | 
    
         
            +
                html_esc(text, :html_escape_preformatted)
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
              
         
     | 
| 
      
 14 
     | 
    
         
            +
              # escaping for HTML attributes
         
     | 
| 
      
 15 
     | 
    
         
            +
              def escape_attribute(text)
         
     | 
| 
      
 16 
     | 
    
         
            +
                html_esc(text, :html_escape_attributes)
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
              
         
     | 
| 
      
 19 
     | 
    
         
            +
              def after_transform(text)
         
     | 
| 
      
 20 
     | 
    
         
            +
                text.chomp!
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
                
         
     | 
| 
      
 23 
     | 
    
         
            +
              [:h1, :h2, :h3, :h4, :h5, :h6, :p, :pre, :div].each do |m|
         
     | 
| 
      
 24 
     | 
    
         
            +
                define_method(m) do |opts|
         
     | 
| 
      
 25 
     | 
    
         
            +
                  "<#{m}#{pba(opts)}>#{opts[:text]}</#{m}>\n"
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
              
         
     | 
| 
      
 29 
     | 
    
         
            +
              [:strong, :code, :em, :i, :b, :ins, :sup, :sub, :span, :cite].each do |m|
         
     | 
| 
      
 30 
     | 
    
         
            +
                define_method(m) do |opts|
         
     | 
| 
      
 31 
     | 
    
         
            +
                  opts[:block] = true
         
     | 
| 
      
 32 
     | 
    
         
            +
                  "<#{m}#{pba(opts)}>#{opts[:text]}</#{m}>"
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
              
         
     | 
| 
      
 36 
     | 
    
         
            +
              def hr(opts)
         
     | 
| 
      
 37 
     | 
    
         
            +
                "<hr />\n"
         
     | 
| 
      
 38 
     | 
    
         
            +
              end
         
     | 
| 
      
 39 
     | 
    
         
            +
              
         
     | 
| 
      
 40 
     | 
    
         
            +
              def acronym(opts)
         
     | 
| 
      
 41 
     | 
    
         
            +
                opts[:block] = true
         
     | 
| 
      
 42 
     | 
    
         
            +
                "<acronym#{pba(opts)}>#{caps(:text => opts[:text])}</acronym>"
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
              
         
     | 
| 
      
 45 
     | 
    
         
            +
              def caps(opts)
         
     | 
| 
      
 46 
     | 
    
         
            +
                if no_span_caps
         
     | 
| 
      
 47 
     | 
    
         
            +
                  opts[:text]
         
     | 
| 
      
 48 
     | 
    
         
            +
                else
         
     | 
| 
      
 49 
     | 
    
         
            +
                  opts[:class] = 'caps'
         
     | 
| 
      
 50 
     | 
    
         
            +
                  span(opts)
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
              
         
     | 
| 
      
 54 
     | 
    
         
            +
              def del(opts)
         
     | 
| 
      
 55 
     | 
    
         
            +
                opts[:block] = true
         
     | 
| 
      
 56 
     | 
    
         
            +
                "<del#{pba(opts)}>#{opts[:text]}</del>"
         
     | 
| 
      
 57 
     | 
    
         
            +
              end
         
     | 
| 
      
 58 
     | 
    
         
            +
              
         
     | 
| 
      
 59 
     | 
    
         
            +
              [:ol, :ul].each do |m|
         
     | 
| 
      
 60 
     | 
    
         
            +
                define_method("#{m}_open") do |opts|
         
     | 
| 
      
 61 
     | 
    
         
            +
                  opts[:block] = true
         
     | 
| 
      
 62 
     | 
    
         
            +
                  "#{"\n" if opts[:nest] > 1}#{"\t" * (opts[:nest] - 1)}<#{m}#{pba(opts)}>\n"
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
                define_method("#{m}_close") do |opts|
         
     | 
| 
      
 65 
     | 
    
         
            +
                  "#{li_close}#{"\t" * (opts[:nest] - 1)}</#{m}>#{"\n" if opts[:nest] <= 1}"
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
              end
         
     | 
| 
      
 68 
     | 
    
         
            +
              
         
     | 
| 
      
 69 
     | 
    
         
            +
              def li_open(opts)
         
     | 
| 
      
 70 
     | 
    
         
            +
                "#{li_close unless opts.delete(:first)}#{"\t" * opts[:nest]}<li#{pba(opts)}>#{opts[:text]}"
         
     | 
| 
      
 71 
     | 
    
         
            +
              end
         
     | 
| 
      
 72 
     | 
    
         
            +
              
         
     | 
| 
      
 73 
     | 
    
         
            +
              def li_close(opts=nil)
         
     | 
| 
      
 74 
     | 
    
         
            +
                "</li>\n"
         
     | 
| 
      
 75 
     | 
    
         
            +
              end
         
     | 
| 
      
 76 
     | 
    
         
            +
              
         
     | 
| 
      
 77 
     | 
    
         
            +
              def dl_open(opts)
         
     | 
| 
      
 78 
     | 
    
         
            +
                opts[:block] = true
         
     | 
| 
      
 79 
     | 
    
         
            +
                "<dl#{pba(opts)}>\n"
         
     | 
| 
      
 80 
     | 
    
         
            +
              end
         
     | 
| 
      
 81 
     | 
    
         
            +
              
         
     | 
| 
      
 82 
     | 
    
         
            +
              def dl_close(opts=nil)
         
     | 
| 
      
 83 
     | 
    
         
            +
                "</dl>\n"
         
     | 
| 
      
 84 
     | 
    
         
            +
              end
         
     | 
| 
      
 85 
     | 
    
         
            +
              
         
     | 
| 
      
 86 
     | 
    
         
            +
              [:dt, :dd].each do |m|
         
     | 
| 
      
 87 
     | 
    
         
            +
                define_method(m) do |opts|
         
     | 
| 
      
 88 
     | 
    
         
            +
                  "\t<#{m}#{pba(opts)}>#{opts[:text]}</#{m}>\n"
         
     | 
| 
      
 89 
     | 
    
         
            +
                end
         
     | 
| 
      
 90 
     | 
    
         
            +
              end
         
     | 
| 
      
 91 
     | 
    
         
            +
              
         
     | 
| 
      
 92 
     | 
    
         
            +
              def td(opts)
         
     | 
| 
      
 93 
     | 
    
         
            +
                tdtype = opts[:th] ? 'th' : 'td'
         
     | 
| 
      
 94 
     | 
    
         
            +
                "\t\t<#{tdtype}#{pba(opts)}>#{opts[:text]}</#{tdtype}>\n"
         
     | 
| 
      
 95 
     | 
    
         
            +
              end
         
     | 
| 
      
 96 
     | 
    
         
            +
              
         
     | 
| 
      
 97 
     | 
    
         
            +
              def tr_open(opts)
         
     | 
| 
      
 98 
     | 
    
         
            +
                "\t<tr#{pba(opts)}>\n"
         
     | 
| 
      
 99 
     | 
    
         
            +
              end
         
     | 
| 
      
 100 
     | 
    
         
            +
              
         
     | 
| 
      
 101 
     | 
    
         
            +
              def tr_close(opts)
         
     | 
| 
      
 102 
     | 
    
         
            +
                "\t</tr>\n"
         
     | 
| 
      
 103 
     | 
    
         
            +
              end
         
     | 
| 
      
 104 
     | 
    
         
            +
              
         
     | 
| 
      
 105 
     | 
    
         
            +
              def table_open(opts)
         
     | 
| 
      
 106 
     | 
    
         
            +
                "<table#{pba(opts)}>\n"
         
     | 
| 
      
 107 
     | 
    
         
            +
              end
         
     | 
| 
      
 108 
     | 
    
         
            +
              
         
     | 
| 
      
 109 
     | 
    
         
            +
              def table_close(opts)
         
     | 
| 
      
 110 
     | 
    
         
            +
                "</table>\n"
         
     | 
| 
      
 111 
     | 
    
         
            +
              end
         
     | 
| 
      
 112 
     | 
    
         
            +
              
         
     | 
| 
      
 113 
     | 
    
         
            +
              def bc_open(opts)
         
     | 
| 
      
 114 
     | 
    
         
            +
                opts[:block] = true
         
     | 
| 
      
 115 
     | 
    
         
            +
                "<pre#{pba(opts)}>"
         
     | 
| 
      
 116 
     | 
    
         
            +
              end
         
     | 
| 
      
 117 
     | 
    
         
            +
              
         
     | 
| 
      
 118 
     | 
    
         
            +
              def bc_close(opts)
         
     | 
| 
      
 119 
     | 
    
         
            +
                "</pre>\n"
         
     | 
| 
      
 120 
     | 
    
         
            +
              end
         
     | 
| 
      
 121 
     | 
    
         
            +
              
         
     | 
| 
      
 122 
     | 
    
         
            +
              def bq_open(opts)
         
     | 
| 
      
 123 
     | 
    
         
            +
                opts[:block] = true
         
     | 
| 
      
 124 
     | 
    
         
            +
                cite = opts[:cite] ? " cite=\"#{ escape_attribute opts[:cite] }\"" : ''
         
     | 
| 
      
 125 
     | 
    
         
            +
                "<blockquote#{cite}#{pba(opts)}>\n"
         
     | 
| 
      
 126 
     | 
    
         
            +
              end
         
     | 
| 
      
 127 
     | 
    
         
            +
              
         
     | 
| 
      
 128 
     | 
    
         
            +
              def bq_close(opts)
         
     | 
| 
      
 129 
     | 
    
         
            +
                "</blockquote>\n"
         
     | 
| 
      
 130 
     | 
    
         
            +
              end
         
     | 
| 
      
 131 
     | 
    
         
            +
              
         
     | 
| 
      
 132 
     | 
    
         
            +
              LINK_TEXT_WITH_TITLE_RE = /
         
     | 
| 
      
 133 
     | 
    
         
            +
                      ([^"]+?)         # $text
         
     | 
| 
      
 134 
     | 
    
         
            +
                      \s?
         
     | 
| 
      
 135 
     | 
    
         
            +
                      \(([^)]+?)\)     # $title
         
     | 
| 
      
 136 
     | 
    
         
            +
                      $
         
     | 
| 
      
 137 
     | 
    
         
            +
                  /x
         
     | 
| 
      
 138 
     | 
    
         
            +
              def link(opts)
         
     | 
| 
      
 139 
     | 
    
         
            +
                if opts[:name] =~ LINK_TEXT_WITH_TITLE_RE
         
     | 
| 
      
 140 
     | 
    
         
            +
                  md = LINK_TEXT_WITH_TITLE_RE.match(opts[:name])
         
     | 
| 
      
 141 
     | 
    
         
            +
                  opts[:name] = md[1]
         
     | 
| 
      
 142 
     | 
    
         
            +
                  opts[:title] = md[2]
         
     | 
| 
      
 143 
     | 
    
         
            +
                end
         
     | 
| 
      
 144 
     | 
    
         
            +
                "<a href=\"#{escape_attribute opts[:href]}\"#{pba(opts)}>#{opts[:name]}</a>"
         
     | 
| 
      
 145 
     | 
    
         
            +
              end
         
     | 
| 
      
 146 
     | 
    
         
            +
              
         
     | 
| 
      
 147 
     | 
    
         
            +
              def image(opts)
         
     | 
| 
      
 148 
     | 
    
         
            +
                opts.delete(:align)
         
     | 
| 
      
 149 
     | 
    
         
            +
                opts[:alt] = opts[:title]
         
     | 
| 
      
 150 
     | 
    
         
            +
                img = "<img src=\"#{escape_attribute opts[:src]}\"#{pba(opts)} alt=\"#{escape_attribute opts[:alt].to_s}\" />"  
         
     | 
| 
      
 151 
     | 
    
         
            +
                img = "<a href=\"#{escape_attribute opts[:href]}\">#{img}</a>" if opts[:href]
         
     | 
| 
      
 152 
     | 
    
         
            +
                img
         
     | 
| 
      
 153 
     | 
    
         
            +
              end
         
     | 
| 
      
 154 
     | 
    
         
            +
              
         
     | 
| 
      
 155 
     | 
    
         
            +
              def footno(opts)
         
     | 
| 
      
 156 
     | 
    
         
            +
                opts[:id] ||= opts[:text]
         
     | 
| 
      
 157 
     | 
    
         
            +
                %Q{<sup class="footnote"><a href=\"#fn#{opts[:id]}\">#{opts[:text]}</a></sup>}
         
     | 
| 
      
 158 
     | 
    
         
            +
              end
         
     | 
| 
      
 159 
     | 
    
         
            +
              
         
     | 
| 
      
 160 
     | 
    
         
            +
              def fn(opts)
         
     | 
| 
      
 161 
     | 
    
         
            +
                no = opts[:id]
         
     | 
| 
      
 162 
     | 
    
         
            +
                opts[:id] = "fn#{no}"
         
     | 
| 
      
 163 
     | 
    
         
            +
                opts[:class] = ["footnote", opts[:class]].compact.join(" ")
         
     | 
| 
      
 164 
     | 
    
         
            +
                "<p#{pba(opts)}><sup>#{no}</sup> #{opts[:text]}</p>\n"
         
     | 
| 
      
 165 
     | 
    
         
            +
              end
         
     | 
| 
      
 166 
     | 
    
         
            +
              
         
     | 
| 
      
 167 
     | 
    
         
            +
              def snip(opts)
         
     | 
| 
      
 168 
     | 
    
         
            +
                "<pre#{pba(opts)}><code>#{opts[:text]}</code></pre>\n"
         
     | 
| 
      
 169 
     | 
    
         
            +
              end
         
     | 
| 
      
 170 
     | 
    
         
            +
              
         
     | 
| 
      
 171 
     | 
    
         
            +
              def quote1(opts)
         
     | 
| 
      
 172 
     | 
    
         
            +
                "‘#{opts[:text]}’"
         
     | 
| 
      
 173 
     | 
    
         
            +
              end
         
     | 
| 
      
 174 
     | 
    
         
            +
              
         
     | 
| 
      
 175 
     | 
    
         
            +
              def quote2(opts)
         
     | 
| 
      
 176 
     | 
    
         
            +
                "“#{opts[:text]}”"
         
     | 
| 
      
 177 
     | 
    
         
            +
              end
         
     | 
| 
      
 178 
     | 
    
         
            +
              
         
     | 
| 
      
 179 
     | 
    
         
            +
              def multi_paragraph_quote(opts)
         
     | 
| 
      
 180 
     | 
    
         
            +
                "“#{opts[:text]}"
         
     | 
| 
      
 181 
     | 
    
         
            +
              end
         
     | 
| 
      
 182 
     | 
    
         
            +
              
         
     | 
| 
      
 183 
     | 
    
         
            +
              def ellipsis(opts)
         
     | 
| 
      
 184 
     | 
    
         
            +
                "#{opts[:text]}…"
         
     | 
| 
      
 185 
     | 
    
         
            +
              end
         
     | 
| 
      
 186 
     | 
    
         
            +
              
         
     | 
| 
      
 187 
     | 
    
         
            +
              def emdash(opts)
         
     | 
| 
      
 188 
     | 
    
         
            +
                "—"
         
     | 
| 
      
 189 
     | 
    
         
            +
              end
         
     | 
| 
      
 190 
     | 
    
         
            +
              
         
     | 
| 
      
 191 
     | 
    
         
            +
              def endash(opts)
         
     | 
| 
      
 192 
     | 
    
         
            +
                " – "
         
     | 
| 
      
 193 
     | 
    
         
            +
              end
         
     | 
| 
      
 194 
     | 
    
         
            +
              
         
     | 
| 
      
 195 
     | 
    
         
            +
              def arrow(opts)
         
     | 
| 
      
 196 
     | 
    
         
            +
                "→"
         
     | 
| 
      
 197 
     | 
    
         
            +
              end
         
     | 
| 
      
 198 
     | 
    
         
            +
              
         
     | 
| 
      
 199 
     | 
    
         
            +
              def dim(opts)
         
     | 
| 
      
 200 
     | 
    
         
            +
                opts[:text].gsub!('x', '×')
         
     | 
| 
      
 201 
     | 
    
         
            +
                opts[:text].gsub!("'", '′')
         
     | 
| 
      
 202 
     | 
    
         
            +
                opts[:text].gsub!('"', '″')
         
     | 
| 
      
 203 
     | 
    
         
            +
                opts[:text]
         
     | 
| 
      
 204 
     | 
    
         
            +
              end
         
     | 
| 
      
 205 
     | 
    
         
            +
              
         
     | 
| 
      
 206 
     | 
    
         
            +
              def trademark(opts)
         
     | 
| 
      
 207 
     | 
    
         
            +
                "™"
         
     | 
| 
      
 208 
     | 
    
         
            +
              end
         
     | 
| 
      
 209 
     | 
    
         
            +
              
         
     | 
| 
      
 210 
     | 
    
         
            +
              def registered(opts)
         
     | 
| 
      
 211 
     | 
    
         
            +
                "®"
         
     | 
| 
      
 212 
     | 
    
         
            +
              end
         
     | 
| 
      
 213 
     | 
    
         
            +
              
         
     | 
| 
      
 214 
     | 
    
         
            +
              def copyright(opts)
         
     | 
| 
      
 215 
     | 
    
         
            +
                "©"
         
     | 
| 
      
 216 
     | 
    
         
            +
              end
         
     | 
| 
      
 217 
     | 
    
         
            +
              
         
     | 
| 
      
 218 
     | 
    
         
            +
              def entity(opts)
         
     | 
| 
      
 219 
     | 
    
         
            +
                "&#{opts[:text]};"
         
     | 
| 
      
 220 
     | 
    
         
            +
              end
         
     | 
| 
      
 221 
     | 
    
         
            +
              
         
     | 
| 
      
 222 
     | 
    
         
            +
              def amp(opts)
         
     | 
| 
      
 223 
     | 
    
         
            +
                "&"
         
     | 
| 
      
 224 
     | 
    
         
            +
              end
         
     | 
| 
      
 225 
     | 
    
         
            +
              
         
     | 
| 
      
 226 
     | 
    
         
            +
              def gt(opts)
         
     | 
| 
      
 227 
     | 
    
         
            +
                ">"
         
     | 
| 
      
 228 
     | 
    
         
            +
              end
         
     | 
| 
      
 229 
     | 
    
         
            +
              
         
     | 
| 
      
 230 
     | 
    
         
            +
              def lt(opts)
         
     | 
| 
      
 231 
     | 
    
         
            +
                "<"
         
     | 
| 
      
 232 
     | 
    
         
            +
              end
         
     | 
| 
      
 233 
     | 
    
         
            +
              
         
     | 
| 
      
 234 
     | 
    
         
            +
              def br(opts)
         
     | 
| 
      
 235 
     | 
    
         
            +
                if hard_breaks == false
         
     | 
| 
      
 236 
     | 
    
         
            +
                  "\n"
         
     | 
| 
      
 237 
     | 
    
         
            +
                else
         
     | 
| 
      
 238 
     | 
    
         
            +
                  "<br />\n"
         
     | 
| 
      
 239 
     | 
    
         
            +
                end
         
     | 
| 
      
 240 
     | 
    
         
            +
              end
         
     | 
| 
      
 241 
     | 
    
         
            +
              
         
     | 
| 
      
 242 
     | 
    
         
            +
              def quot(opts)
         
     | 
| 
      
 243 
     | 
    
         
            +
                """
         
     | 
| 
      
 244 
     | 
    
         
            +
              end
         
     | 
| 
      
 245 
     | 
    
         
            +
              
         
     | 
| 
      
 246 
     | 
    
         
            +
              def squot(opts)
         
     | 
| 
      
 247 
     | 
    
         
            +
                "’"
         
     | 
| 
      
 248 
     | 
    
         
            +
              end
         
     | 
| 
      
 249 
     | 
    
         
            +
              
         
     | 
| 
      
 250 
     | 
    
         
            +
              def apos(opts)
         
     | 
| 
      
 251 
     | 
    
         
            +
                "'"
         
     | 
| 
      
 252 
     | 
    
         
            +
              end
         
     | 
| 
      
 253 
     | 
    
         
            +
              
         
     | 
| 
      
 254 
     | 
    
         
            +
              def html(opts)
         
     | 
| 
      
 255 
     | 
    
         
            +
                "#{opts[:text]}\n"
         
     | 
| 
      
 256 
     | 
    
         
            +
              end
         
     | 
| 
      
 257 
     | 
    
         
            +
              
         
     | 
| 
      
 258 
     | 
    
         
            +
              def html_block(opts)
         
     | 
| 
      
 259 
     | 
    
         
            +
                inline_html(:text => "#{opts[:indent_before_start]}#{opts[:start_tag]}#{opts[:indent_after_start]}") + 
         
     | 
| 
      
 260 
     | 
    
         
            +
                "#{opts[:text]}" +
         
     | 
| 
      
 261 
     | 
    
         
            +
                inline_html(:text => "#{opts[:indent_before_end]}#{opts[:end_tag]}#{opts[:indent_after_end]}")
         
     | 
| 
      
 262 
     | 
    
         
            +
              end
         
     | 
| 
      
 263 
     | 
    
         
            +
              
         
     | 
| 
      
 264 
     | 
    
         
            +
              def notextile(opts)
         
     | 
| 
      
 265 
     | 
    
         
            +
                if filter_html
         
     | 
| 
      
 266 
     | 
    
         
            +
                  html_esc(opts[:text], :html_escape_preformatted)
         
     | 
| 
      
 267 
     | 
    
         
            +
                else
         
     | 
| 
      
 268 
     | 
    
         
            +
                  opts[:text]
         
     | 
| 
      
 269 
     | 
    
         
            +
                end
         
     | 
| 
      
 270 
     | 
    
         
            +
              end
         
     | 
| 
      
 271 
     | 
    
         
            +
              
         
     | 
| 
      
 272 
     | 
    
         
            +
              def inline_html(opts)
         
     | 
| 
      
 273 
     | 
    
         
            +
                if filter_html
         
     | 
| 
      
 274 
     | 
    
         
            +
                  html_esc(opts[:text], :html_escape_preformatted)
         
     | 
| 
      
 275 
     | 
    
         
            +
                else
         
     | 
| 
      
 276 
     | 
    
         
            +
                  "#{opts[:text]}" # nil-safe
         
     | 
| 
      
 277 
     | 
    
         
            +
                end
         
     | 
| 
      
 278 
     | 
    
         
            +
              end
         
     | 
| 
      
 279 
     | 
    
         
            +
              
         
     | 
| 
      
 280 
     | 
    
         
            +
              def ignored_line(opts)
         
     | 
| 
      
 281 
     | 
    
         
            +
                opts[:text] + "\n"
         
     | 
| 
      
 282 
     | 
    
         
            +
              end
         
     | 
| 
      
 283 
     | 
    
         
            +
              
         
     | 
| 
      
 284 
     | 
    
         
            +
              def before_transform(text)
         
     | 
| 
      
 285 
     | 
    
         
            +
                clean_html(text) if sanitize_html
         
     | 
| 
      
 286 
     | 
    
         
            +
              end
         
     | 
| 
      
 287 
     | 
    
         
            +
              
         
     | 
| 
      
 288 
     | 
    
         
            +
              # HTML cleansing stuff
         
     | 
| 
      
 289 
     | 
    
         
            +
              BASIC_TAGS = {
         
     | 
| 
      
 290 
     | 
    
         
            +
                  'a' => ['href', 'title'],
         
     | 
| 
      
 291 
     | 
    
         
            +
                  'img' => ['src', 'alt', 'title'],
         
     | 
| 
      
 292 
     | 
    
         
            +
                  'br' => [],
         
     | 
| 
      
 293 
     | 
    
         
            +
                  'i' => nil,
         
     | 
| 
      
 294 
     | 
    
         
            +
                  'u' => nil, 
         
     | 
| 
      
 295 
     | 
    
         
            +
                  'b' => nil,
         
     | 
| 
      
 296 
     | 
    
         
            +
                  'pre' => nil,
         
     | 
| 
      
 297 
     | 
    
         
            +
                  'kbd' => nil,
         
     | 
| 
      
 298 
     | 
    
         
            +
                  'code' => ['lang'],
         
     | 
| 
      
 299 
     | 
    
         
            +
                  'cite' => nil,
         
     | 
| 
      
 300 
     | 
    
         
            +
                  'strong' => nil,
         
     | 
| 
      
 301 
     | 
    
         
            +
                  'em' => nil,
         
     | 
| 
      
 302 
     | 
    
         
            +
                  'ins' => nil,
         
     | 
| 
      
 303 
     | 
    
         
            +
                  'sup' => nil,
         
     | 
| 
      
 304 
     | 
    
         
            +
                  'sub' => nil,
         
     | 
| 
      
 305 
     | 
    
         
            +
                  'del' => nil,
         
     | 
| 
      
 306 
     | 
    
         
            +
                  'table' => nil,
         
     | 
| 
      
 307 
     | 
    
         
            +
                  'tr' => nil,
         
     | 
| 
      
 308 
     | 
    
         
            +
                  'td' => ['colspan', 'rowspan'],
         
     | 
| 
      
 309 
     | 
    
         
            +
                  'th' => nil,
         
     | 
| 
      
 310 
     | 
    
         
            +
                  'ol' => ['start'],
         
     | 
| 
      
 311 
     | 
    
         
            +
                  'ul' => nil,
         
     | 
| 
      
 312 
     | 
    
         
            +
                  'li' => nil,
         
     | 
| 
      
 313 
     | 
    
         
            +
                  'p' => nil,
         
     | 
| 
      
 314 
     | 
    
         
            +
                  'h1' => nil,
         
     | 
| 
      
 315 
     | 
    
         
            +
                  'h2' => nil,
         
     | 
| 
      
 316 
     | 
    
         
            +
                  'h3' => nil,
         
     | 
| 
      
 317 
     | 
    
         
            +
                  'h4' => nil,
         
     | 
| 
      
 318 
     | 
    
         
            +
                  'h5' => nil,
         
     | 
| 
      
 319 
     | 
    
         
            +
                  'h6' => nil, 
         
     | 
| 
      
 320 
     | 
    
         
            +
                  'blockquote' => ['cite'],
         
     | 
| 
      
 321 
     | 
    
         
            +
                  'notextile' => nil
         
     | 
| 
      
 322 
     | 
    
         
            +
              }
         
     | 
| 
      
 323 
     | 
    
         
            +
              
         
     | 
| 
      
 324 
     | 
    
         
            +
              # Clean unauthorized tags.
         
     | 
| 
      
 325 
     | 
    
         
            +
              def clean_html( text, allowed_tags = BASIC_TAGS )
         
     | 
| 
      
 326 
     | 
    
         
            +
                text.gsub!( /<!\[CDATA\[/, '' )
         
     | 
| 
      
 327 
     | 
    
         
            +
                text.gsub!( /<(\/*)([A-Za-z]\w*)([^>]*?)(\s?\/?)>/ ) do |m|
         
     | 
| 
      
 328 
     | 
    
         
            +
                  raw = $~
         
     | 
| 
      
 329 
     | 
    
         
            +
                  tag = raw[2].downcase
         
     | 
| 
      
 330 
     | 
    
         
            +
                  if allowed_tags.has_key? tag
         
     | 
| 
      
 331 
     | 
    
         
            +
                    pcs = [tag]
         
     | 
| 
      
 332 
     | 
    
         
            +
                    allowed_tags[tag].each do |prop|
         
     | 
| 
      
 333 
     | 
    
         
            +
                      ['"', "'", ''].each do |q|
         
     | 
| 
      
 334 
     | 
    
         
            +
                        q2 = ( q != '' ? q : '\s' )
         
     | 
| 
      
 335 
     | 
    
         
            +
                        if raw[3] =~ /#{prop}\s*=\s*#{q}([^#{q2}]+)#{q}/i
         
     | 
| 
      
 336 
     | 
    
         
            +
                          attrv = $1
         
     | 
| 
      
 337 
     | 
    
         
            +
                          next if (prop == 'src' or prop == 'href') and not attrv =~ %r{^(http|https|ftp):}
         
     | 
| 
      
 338 
     | 
    
         
            +
                          pcs << "#{prop}=\"#{attrv.gsub('"', '\\"')}\""
         
     | 
| 
      
 339 
     | 
    
         
            +
                          break
         
     | 
| 
      
 340 
     | 
    
         
            +
                        end
         
     | 
| 
      
 341 
     | 
    
         
            +
                      end
         
     | 
| 
      
 342 
     | 
    
         
            +
                    end if allowed_tags[tag]
         
     | 
| 
      
 343 
     | 
    
         
            +
                    "<#{raw[1]}#{pcs.join " "}#{raw[4]}>"
         
     | 
| 
      
 344 
     | 
    
         
            +
                  else # Unauthorized tag
         
     | 
| 
      
 345 
     | 
    
         
            +
                    if block_given?
         
     | 
| 
      
 346 
     | 
    
         
            +
                      yield m
         
     | 
| 
      
 347 
     | 
    
         
            +
                    else
         
     | 
| 
      
 348 
     | 
    
         
            +
                      ''
         
     | 
| 
      
 349 
     | 
    
         
            +
                    end
         
     | 
| 
      
 350 
     | 
    
         
            +
                  end
         
     | 
| 
      
 351 
     | 
    
         
            +
                end
         
     | 
| 
      
 352 
     | 
    
         
            +
              end
         
     | 
| 
      
 353 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,275 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'yaml' 
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module RedCloth::Formatters::LATEX
         
     | 
| 
      
 4 
     | 
    
         
            +
              include RedCloth::Formatters::Base
         
     | 
| 
      
 5 
     | 
    
         
            +
              
         
     | 
| 
      
 6 
     | 
    
         
            +
              ENTITIES = YAML::load(File.read(File.dirname(__FILE__)+'/latex_entities.yml')) 
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              module Settings
         
     | 
| 
      
 9 
     | 
    
         
            +
                # Maps CSS style names to latex formatting options
         
     | 
| 
      
 10 
     | 
    
         
            +
                def latex_image_styles
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @latex_image_class_styles ||= {}
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              RedCloth::TextileDoc.send(:include, Settings)
         
     | 
| 
      
 16 
     | 
    
         
            +
              
         
     | 
| 
      
 17 
     | 
    
         
            +
              def escape(text)
         
     | 
| 
      
 18 
     | 
    
         
            +
                latex_esc(text)
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              def escape_pre(text)
         
     | 
| 
      
 22 
     | 
    
         
            +
                text
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
              
         
     | 
| 
      
 25 
     | 
    
         
            +
              # headers
         
     | 
| 
      
 26 
     | 
    
         
            +
              { :h1 => 'section*',
         
     | 
| 
      
 27 
     | 
    
         
            +
                :h2 => 'subsection*',
         
     | 
| 
      
 28 
     | 
    
         
            +
                :h3 => 'subsubsection*',
         
     | 
| 
      
 29 
     | 
    
         
            +
                :h4 => 'textbf',
         
     | 
| 
      
 30 
     | 
    
         
            +
                :h5 => 'textbf',
         
     | 
| 
      
 31 
     | 
    
         
            +
                :h6 => 'textbf',
         
     | 
| 
      
 32 
     | 
    
         
            +
              }.each do |m,tag| 
         
     | 
| 
      
 33 
     | 
    
         
            +
                define_method(m) do |opts| 
         
     | 
| 
      
 34 
     | 
    
         
            +
                  "\\#{tag}{#{opts[:text]}}\n\n" 
         
     | 
| 
      
 35 
     | 
    
         
            +
                end 
         
     | 
| 
      
 36 
     | 
    
         
            +
              end 
         
     | 
| 
      
 37 
     | 
    
         
            +
              
         
     | 
| 
      
 38 
     | 
    
         
            +
              # commands 
         
     | 
| 
      
 39 
     | 
    
         
            +
              { :strong => 'textbf',
         
     | 
| 
      
 40 
     | 
    
         
            +
                :em => 'emph',
         
     | 
| 
      
 41 
     | 
    
         
            +
                :i  => 'textit',
         
     | 
| 
      
 42 
     | 
    
         
            +
                :b  => 'textbf',
         
     | 
| 
      
 43 
     | 
    
         
            +
                :ins => 'underline',
         
     | 
| 
      
 44 
     | 
    
         
            +
                :del => 'sout',
         
     | 
| 
      
 45 
     | 
    
         
            +
                :acronym => 'MakeUppercase',
         
     | 
| 
      
 46 
     | 
    
         
            +
                :caps => 'MakeUppercase',
         
     | 
| 
      
 47 
     | 
    
         
            +
              }.each do |m,tag|
         
     | 
| 
      
 48 
     | 
    
         
            +
                define_method(m) do |opts|
         
     | 
| 
      
 49 
     | 
    
         
            +
                  "\\#{tag}{#{opts[:text]}}"
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
              end
         
     | 
| 
      
 52 
     | 
    
         
            +
              
         
     | 
| 
      
 53 
     | 
    
         
            +
              { :sup => '\ensuremath{^\textrm{#1}}',
         
     | 
| 
      
 54 
     | 
    
         
            +
                :sub => '\ensuremath{_\textrm{#1}}',
         
     | 
| 
      
 55 
     | 
    
         
            +
              }.each do |m, expr|
         
     | 
| 
      
 56 
     | 
    
         
            +
                define_method(m) do |opts|
         
     | 
| 
      
 57 
     | 
    
         
            +
                  expr.sub('#1', opts[:text])
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
              end
         
     | 
| 
      
 60 
     | 
    
         
            +
              
         
     | 
| 
      
 61 
     | 
    
         
            +
              # environments
         
     | 
| 
      
 62 
     | 
    
         
            +
              { :pre  => 'verbatim',
         
     | 
| 
      
 63 
     | 
    
         
            +
                :code => 'verbatim',
         
     | 
| 
      
 64 
     | 
    
         
            +
                :cite => 'quote',
         
     | 
| 
      
 65 
     | 
    
         
            +
                }.each do |m, env|
         
     | 
| 
      
 66 
     | 
    
         
            +
                define_method(m) do |opts|
         
     | 
| 
      
 67 
     | 
    
         
            +
                  begin_chunk(env) + opts[:text] + end_chunk(env)
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
              end
         
     | 
| 
      
 70 
     | 
    
         
            +
              
         
     | 
| 
      
 71 
     | 
    
         
            +
              # ignore (or find a good solution later)
         
     | 
| 
      
 72 
     | 
    
         
            +
              [ :span,
         
     | 
| 
      
 73 
     | 
    
         
            +
                :div,
         
     | 
| 
      
 74 
     | 
    
         
            +
                ].each do |m|
         
     | 
| 
      
 75 
     | 
    
         
            +
                define_method(m) do |opts|
         
     | 
| 
      
 76 
     | 
    
         
            +
                  opts[:text].to_s
         
     | 
| 
      
 77 
     | 
    
         
            +
                end
         
     | 
| 
      
 78 
     | 
    
         
            +
              end
         
     | 
| 
      
 79 
     | 
    
         
            +
              
         
     | 
| 
      
 80 
     | 
    
         
            +
              { :ol => 'enumerate',
         
     | 
| 
      
 81 
     | 
    
         
            +
                :ul => 'itemize',
         
     | 
| 
      
 82 
     | 
    
         
            +
                }.each do |m, env|
         
     | 
| 
      
 83 
     | 
    
         
            +
                define_method("#{m}_open") do |opts|
         
     | 
| 
      
 84 
     | 
    
         
            +
                  opts[:block] = true
         
     | 
| 
      
 85 
     | 
    
         
            +
                  "\\begin{#{env}}\n"
         
     | 
| 
      
 86 
     | 
    
         
            +
                end
         
     | 
| 
      
 87 
     | 
    
         
            +
                define_method("#{m}_close") do |opts|
         
     | 
| 
      
 88 
     | 
    
         
            +
                  "#{li_close}\\end{#{env}}\n\n"
         
     | 
| 
      
 89 
     | 
    
         
            +
                end
         
     | 
| 
      
 90 
     | 
    
         
            +
              end
         
     | 
| 
      
 91 
     | 
    
         
            +
              
         
     | 
| 
      
 92 
     | 
    
         
            +
              def li_open(opts)
         
     | 
| 
      
 93 
     | 
    
         
            +
                "#{li_close unless opts.delete(:first)}\t\\item #{opts[:text]}"
         
     | 
| 
      
 94 
     | 
    
         
            +
              end
         
     | 
| 
      
 95 
     | 
    
         
            +
              
         
     | 
| 
      
 96 
     | 
    
         
            +
              def li_close(opts=nil)
         
     | 
| 
      
 97 
     | 
    
         
            +
                "\n"
         
     | 
| 
      
 98 
     | 
    
         
            +
              end
         
     | 
| 
      
 99 
     | 
    
         
            +
              
         
     | 
| 
      
 100 
     | 
    
         
            +
              def p(opts)
         
     | 
| 
      
 101 
     | 
    
         
            +
                opts[:text] + "\n\n"
         
     | 
| 
      
 102 
     | 
    
         
            +
              end
         
     | 
| 
      
 103 
     | 
    
         
            +
              
         
     | 
| 
      
 104 
     | 
    
         
            +
              def td(opts)
         
     | 
| 
      
 105 
     | 
    
         
            +
                column = @table_row.size
         
     | 
| 
      
 106 
     | 
    
         
            +
                if opts[:colspan]
         
     | 
| 
      
 107 
     | 
    
         
            +
                  opts[:text] = "\\multicolumn{#{opts[:colspan]}}{ #{"l " * opts[:colspan].to_i}}{#{opts[:text]}}"
         
     | 
| 
      
 108 
     | 
    
         
            +
                end
         
     | 
| 
      
 109 
     | 
    
         
            +
                if opts[:rowspan]
         
     | 
| 
      
 110 
     | 
    
         
            +
                  @table_multirow_next[column] = opts[:rowspan].to_i - 1
         
     | 
| 
      
 111 
     | 
    
         
            +
                  opts[:text] = "\\multirow{#{opts[:rowspan]}}{*}{#{opts[:text]}}"
         
     | 
| 
      
 112 
     | 
    
         
            +
                end
         
     | 
| 
      
 113 
     | 
    
         
            +
                @table_row.push(opts[:text])
         
     | 
| 
      
 114 
     | 
    
         
            +
                return ""
         
     | 
| 
      
 115 
     | 
    
         
            +
              end
         
     | 
| 
      
 116 
     | 
    
         
            +
              
         
     | 
| 
      
 117 
     | 
    
         
            +
              def tr_open(opts)
         
     | 
| 
      
 118 
     | 
    
         
            +
                @table_row = []
         
     | 
| 
      
 119 
     | 
    
         
            +
                return ""
         
     | 
| 
      
 120 
     | 
    
         
            +
              end
         
     | 
| 
      
 121 
     | 
    
         
            +
              
         
     | 
| 
      
 122 
     | 
    
         
            +
              def tr_close(opts)
         
     | 
| 
      
 123 
     | 
    
         
            +
                multirow_columns = @table_multirow.find_all {|c,n| n > 0}
         
     | 
| 
      
 124 
     | 
    
         
            +
                multirow_columns.each do |c,n|
         
     | 
| 
      
 125 
     | 
    
         
            +
                  @table_row.insert(c,"")
         
     | 
| 
      
 126 
     | 
    
         
            +
                  @table_multirow[c] -= 1
         
     | 
| 
      
 127 
     | 
    
         
            +
                end
         
     | 
| 
      
 128 
     | 
    
         
            +
                @table_multirow.merge!(@table_multirow_next)
         
     | 
| 
      
 129 
     | 
    
         
            +
                @table_multirow_next = {}
         
     | 
| 
      
 130 
     | 
    
         
            +
                @table.push(@table_row)
         
     | 
| 
      
 131 
     | 
    
         
            +
                return ""
         
     | 
| 
      
 132 
     | 
    
         
            +
              end
         
     | 
| 
      
 133 
     | 
    
         
            +
              
         
     | 
| 
      
 134 
     | 
    
         
            +
              # We need to know the column count before opening tabular context.
         
     | 
| 
      
 135 
     | 
    
         
            +
              def table_open(opts)
         
     | 
| 
      
 136 
     | 
    
         
            +
                @table = []
         
     | 
| 
      
 137 
     | 
    
         
            +
                @table_multirow = {}
         
     | 
| 
      
 138 
     | 
    
         
            +
                @table_multirow_next = {}
         
     | 
| 
      
 139 
     | 
    
         
            +
                return ""
         
     | 
| 
      
 140 
     | 
    
         
            +
              end
         
     | 
| 
      
 141 
     | 
    
         
            +
              
         
     | 
| 
      
 142 
     | 
    
         
            +
              def table_close(opts)
         
     | 
| 
      
 143 
     | 
    
         
            +
                output = "\\begin{tabular}{ #{"l " * @table[0].size }}\n"
         
     | 
| 
      
 144 
     | 
    
         
            +
                @table.each do |row|
         
     | 
| 
      
 145 
     | 
    
         
            +
                  output << "  #{row.join(" & ")} \\\\\n"
         
     | 
| 
      
 146 
     | 
    
         
            +
                end
         
     | 
| 
      
 147 
     | 
    
         
            +
                output << "\\end{tabular}\n"
         
     | 
| 
      
 148 
     | 
    
         
            +
                output
         
     | 
| 
      
 149 
     | 
    
         
            +
              end
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
              def bc_open(opts)
         
     | 
| 
      
 152 
     | 
    
         
            +
                opts[:block] = true
         
     | 
| 
      
 153 
     | 
    
         
            +
                begin_chunk("verbatim") + "\n"
         
     | 
| 
      
 154 
     | 
    
         
            +
              end
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
              def bc_close(opts)
         
     | 
| 
      
 157 
     | 
    
         
            +
                end_chunk("verbatim") + "\n"
         
     | 
| 
      
 158 
     | 
    
         
            +
              end
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
              def bq_open(opts)
         
     | 
| 
      
 161 
     | 
    
         
            +
                opts[:block] = true
         
     | 
| 
      
 162 
     | 
    
         
            +
                "\\begin{quotation}\n"
         
     | 
| 
      
 163 
     | 
    
         
            +
              end
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
      
 165 
     | 
    
         
            +
              def bq_close(opts)
         
     | 
| 
      
 166 
     | 
    
         
            +
                "\\end{quotation}\n\n"
         
     | 
| 
      
 167 
     | 
    
         
            +
              end
         
     | 
| 
      
 168 
     | 
    
         
            +
              
         
     | 
| 
      
 169 
     | 
    
         
            +
              def link(opts)
         
     | 
| 
      
 170 
     | 
    
         
            +
                "\\href{#{opts[:href]}}{#{opts[:name]}}"
         
     | 
| 
      
 171 
     | 
    
         
            +
              end
         
     | 
| 
      
 172 
     | 
    
         
            +
              
         
     | 
| 
      
 173 
     | 
    
         
            +
              # FIXME: use includegraphics with security verification
         
     | 
| 
      
 174 
     | 
    
         
            +
              #
         
     | 
| 
      
 175 
     | 
    
         
            +
              # Remember to use '\RequirePackage{graphicx}' in your LaTeX header
         
     | 
| 
      
 176 
     | 
    
         
            +
              # 
         
     | 
| 
      
 177 
     | 
    
         
            +
              # FIXME: Look at dealing with width / height gracefully as this should be 
         
     | 
| 
      
 178 
     | 
    
         
            +
              # specified in a unit like cm rather than px.
         
     | 
| 
      
 179 
     | 
    
         
            +
              def image(opts)
         
     | 
| 
      
 180 
     | 
    
         
            +
                # Don't know how to use remote links, plus can we trust them?
         
     | 
| 
      
 181 
     | 
    
         
            +
                return "" if opts[:src] =~ /^\w+\:\/\//
         
     | 
| 
      
 182 
     | 
    
         
            +
                # Resolve CSS styles if any have been set
         
     | 
| 
      
 183 
     | 
    
         
            +
                styling = opts[:class].to_s.split(/\s+/).collect { |style| latex_image_styles[style] }.compact.join ','
         
     | 
| 
      
 184 
     | 
    
         
            +
                # Build latex code
         
     | 
| 
      
 185 
     | 
    
         
            +
                [ "\\begin{figure}[htp]",
         
     | 
| 
      
 186 
     | 
    
         
            +
                  "  \\includegraphics[#{styling}]{#{opts[:src]}}",
         
     | 
| 
      
 187 
     | 
    
         
            +
                 ("  \\caption{#{escape opts[:title]}}" if opts[:title]),
         
     | 
| 
      
 188 
     | 
    
         
            +
                 ("  \\label{#{escape opts[:alt]}}" if opts[:alt]),
         
     | 
| 
      
 189 
     | 
    
         
            +
                  "\\end{figure}",
         
     | 
| 
      
 190 
     | 
    
         
            +
                ].compact.join "\n"
         
     | 
| 
      
 191 
     | 
    
         
            +
              end
         
     | 
| 
      
 192 
     | 
    
         
            +
              
         
     | 
| 
      
 193 
     | 
    
         
            +
              def footno(opts)
         
     | 
| 
      
 194 
     | 
    
         
            +
                # TODO: insert a placeholder until we know the footnote content.
         
     | 
| 
      
 195 
     | 
    
         
            +
                # For this to work, we need some kind of post-processing...
         
     | 
| 
      
 196 
     | 
    
         
            +
                "\\footnotemark[#{opts[:text]}]"
         
     | 
| 
      
 197 
     | 
    
         
            +
              end
         
     | 
| 
      
 198 
     | 
    
         
            +
              
         
     | 
| 
      
 199 
     | 
    
         
            +
              def fn(opts)
         
     | 
| 
      
 200 
     | 
    
         
            +
                "\\footnotetext[#{opts[:id]}]{#{opts[:text]}}"
         
     | 
| 
      
 201 
     | 
    
         
            +
              end
         
     | 
| 
      
 202 
     | 
    
         
            +
              
         
     | 
| 
      
 203 
     | 
    
         
            +
              def snip(opts)
         
     | 
| 
      
 204 
     | 
    
         
            +
                "\\begin{verbatim}#{opts[:text]}\\end{verbatim}"
         
     | 
| 
      
 205 
     | 
    
         
            +
              end
         
     | 
| 
      
 206 
     | 
    
         
            +
              
         
     | 
| 
      
 207 
     | 
    
         
            +
              def quote1(opts)
         
     | 
| 
      
 208 
     | 
    
         
            +
                "`#{opts[:text]}'"
         
     | 
| 
      
 209 
     | 
    
         
            +
              end
         
     | 
| 
      
 210 
     | 
    
         
            +
              
         
     | 
| 
      
 211 
     | 
    
         
            +
              def quote2(opts)
         
     | 
| 
      
 212 
     | 
    
         
            +
                "``#{opts[:text]}\""
         
     | 
| 
      
 213 
     | 
    
         
            +
              end
         
     | 
| 
      
 214 
     | 
    
         
            +
              
         
     | 
| 
      
 215 
     | 
    
         
            +
              def ellipsis(opts)
         
     | 
| 
      
 216 
     | 
    
         
            +
                "#{opts[:text]}\\ldots{}"
         
     | 
| 
      
 217 
     | 
    
         
            +
              end
         
     | 
| 
      
 218 
     | 
    
         
            +
              
         
     | 
| 
      
 219 
     | 
    
         
            +
              def emdash(opts)
         
     | 
| 
      
 220 
     | 
    
         
            +
                "---"
         
     | 
| 
      
 221 
     | 
    
         
            +
              end
         
     | 
| 
      
 222 
     | 
    
         
            +
              
         
     | 
| 
      
 223 
     | 
    
         
            +
              def endash(opts)
         
     | 
| 
      
 224 
     | 
    
         
            +
                "--"
         
     | 
| 
      
 225 
     | 
    
         
            +
              end
         
     | 
| 
      
 226 
     | 
    
         
            +
              
         
     | 
| 
      
 227 
     | 
    
         
            +
              def arrow(opts)
         
     | 
| 
      
 228 
     | 
    
         
            +
                "\\rightarrow{}"
         
     | 
| 
      
 229 
     | 
    
         
            +
              end
         
     | 
| 
      
 230 
     | 
    
         
            +
              
         
     | 
| 
      
 231 
     | 
    
         
            +
              def trademark(opts)
         
     | 
| 
      
 232 
     | 
    
         
            +
                "\\texttrademark{}"
         
     | 
| 
      
 233 
     | 
    
         
            +
              end
         
     | 
| 
      
 234 
     | 
    
         
            +
              
         
     | 
| 
      
 235 
     | 
    
         
            +
              def registered(opts)
         
     | 
| 
      
 236 
     | 
    
         
            +
                "\\textregistered{}"
         
     | 
| 
      
 237 
     | 
    
         
            +
              end
         
     | 
| 
      
 238 
     | 
    
         
            +
              
         
     | 
| 
      
 239 
     | 
    
         
            +
              def copyright(opts)
         
     | 
| 
      
 240 
     | 
    
         
            +
                "\\copyright{}"
         
     | 
| 
      
 241 
     | 
    
         
            +
              end
         
     | 
| 
      
 242 
     | 
    
         
            +
              
         
     | 
| 
      
 243 
     | 
    
         
            +
              # TODO: what do we do with (unknown) unicode entities ? 
         
     | 
| 
      
 244 
     | 
    
         
            +
              #
         
     | 
| 
      
 245 
     | 
    
         
            +
              def entity(opts)
         
     | 
| 
      
 246 
     | 
    
         
            +
                text = opts[:text][0..0] == '#' ? opts[:text][1..-1] : opts[:text] 
         
     | 
| 
      
 247 
     | 
    
         
            +
                ENTITIES[text]
         
     | 
| 
      
 248 
     | 
    
         
            +
              end
         
     | 
| 
      
 249 
     | 
    
         
            +
              
         
     | 
| 
      
 250 
     | 
    
         
            +
              def dim(opts)
         
     | 
| 
      
 251 
     | 
    
         
            +
                space = opts[:space] ? " " : ''
         
     | 
| 
      
 252 
     | 
    
         
            +
                "#{opts[:text]}#{space}\\texttimes{}#{space}"
         
     | 
| 
      
 253 
     | 
    
         
            +
              end
         
     | 
| 
      
 254 
     | 
    
         
            +
              
         
     | 
| 
      
 255 
     | 
    
         
            +
              private
         
     | 
| 
      
 256 
     | 
    
         
            +
              
         
     | 
| 
      
 257 
     | 
    
         
            +
              # Use this for block level commands that use \begin
         
     | 
| 
      
 258 
     | 
    
         
            +
              def begin_chunk(type)
         
     | 
| 
      
 259 
     | 
    
         
            +
                chunk_counter[type] += 1
         
     | 
| 
      
 260 
     | 
    
         
            +
                return "\\begin{#{type}}" if 1 == chunk_counter[type]
         
     | 
| 
      
 261 
     | 
    
         
            +
                ''
         
     | 
| 
      
 262 
     | 
    
         
            +
              end
         
     | 
| 
      
 263 
     | 
    
         
            +
              
         
     | 
| 
      
 264 
     | 
    
         
            +
              # Use this for block level commands that use \end
         
     | 
| 
      
 265 
     | 
    
         
            +
              def end_chunk(type)
         
     | 
| 
      
 266 
     | 
    
         
            +
                chunk_counter[type] -= 1
         
     | 
| 
      
 267 
     | 
    
         
            +
                raise RuntimeError, "Bad latex #{type} nesting detected" if chunk_counter[type] < 0 # This should never need to happen
         
     | 
| 
      
 268 
     | 
    
         
            +
                return "\\end{#{type}}" if 0 == chunk_counter[type]
         
     | 
| 
      
 269 
     | 
    
         
            +
                ''
         
     | 
| 
      
 270 
     | 
    
         
            +
              end
         
     | 
| 
      
 271 
     | 
    
         
            +
              
         
     | 
| 
      
 272 
     | 
    
         
            +
              def chunk_counter
         
     | 
| 
      
 273 
     | 
    
         
            +
                @chunk_counter ||= Hash.new 0
         
     | 
| 
      
 274 
     | 
    
         
            +
              end
         
     | 
| 
      
 275 
     | 
    
         
            +
            end
         
     |