File: lib/redmine/wiki_formatting/textile/formatter.rb

Overview
Module Structure
Class Hierarchy
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: Redmine#21
  module: WikiFormatting#22
  module: Textile#23
  class: Formatter#24
includes
  TagHelper ( ActionView::Helpers )
  LinksHelper ( Redmine::WikiFormatting )
inherits from
  RedCloth3   
has properties
alias: inline_auto_link auto_link! #28
alias: inline_auto_mailto auto_mailto! #29
constant: RULES #32
method: initialize / 1 #34
method: to_html / 1 #41
method: get_section / 1 #46
method: update_section / 3 #52
method: extract_sections / 1 #61
method: hard_break / 1 #112
alias: smooth_offtags_without_code_highlighting smooth_offtags #116
method: smooth_offtags / 1 #118

Code

   1  # Redmine - project management software
   2  # Copyright (C) 2006-2011  Jean-Philippe Lang
   3  #
   4  # This program is free software; you can redistribute it and/or
   5  # modify it under the terms of the GNU General Public License
   6  # as published by the Free Software Foundation; either version 2
   7  # of the License, or (at your option) any later version.
   8  #
   9  # This program is distributed in the hope that it will be useful,
  10  # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  # GNU General Public License for more details.
  13  #
  14  # You should have received a copy of the GNU General Public License
  15  # along with this program; if not, write to the Free Software
  16  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  17 
  18  require 'redcloth3'
  19  require 'digest/md5'
  20 
  21  module Redmine
  22    module WikiFormatting
  23      module Textile
  24        class Formatter < RedCloth3
  25          include ActionView::Helpers::TagHelper
  26          include Redmine::WikiFormatting::LinksHelper
  27 
  28          alias :inline_auto_link :auto_link!
  29          alias :inline_auto_mailto :auto_mailto!
  30 
  31          # auto_link rule after textile rules so that it doesn't break !image_url! tags
  32          RULES = [:textile, :block_markdown_rule, :inline_auto_link, :inline_auto_mailto]
  33 
  34          def initialize(*args)
  35            super
  36            self.hard_breaks=true
  37            self.no_span_caps=true
  38            self.filter_styles=false
  39          end
  40 
  41          def to_html(*rules)
  42            @toc = []
  43            super(*RULES).to_s
  44          end
  45 
  46          def get_section(index)
  47            section = extract_sections(index)[1]
  48            hash = Digest::MD5.hexdigest(section)
  49            return section, hash
  50          end
  51 
  52          def update_section(index, update, hash=nil)
  53            t = extract_sections(index)
  54            if hash.present? && hash != Digest::MD5.hexdigest(t[1])
  55              raise Redmine::WikiFormatting::StaleSectionError
  56            end
  57            t[1] = update unless t[1].blank?
  58            t.reject(&:blank?).join "\n\n"
  59          end
  60 
  61          def extract_sections(index)
  62            @pre_list = []
  63            text = self.dup
  64            rip_offtags text, false, false
  65            before = ''
  66            s = ''
  67            after = ''
  68            i = 0
  69            l = 1
  70            started = false
  71            ended = false
  72            text.scan(/(((?:.*?)(\A|\r?\n\r?\n))(h(\d+)(#{A}#{C})\.(?::(\S+))? (.*?)$)|.*)/m).each do |all, content, lf, heading, level|
  73              if heading.nil?
  74                if ended
  75                  after << all
  76                elsif started
  77                  s << all
  78                else
  79                  before << all
  80                end
  81                break
  82              end
  83              i += 1
  84              if ended
  85                after << all
  86              elsif i == index
  87                l = level.to_i
  88                before << content
  89                s << heading
  90                started = true
  91              elsif i > index
  92                s << content
  93                if level.to_i > l
  94                  s << heading
  95                else
  96                  after << heading
  97                  ended = true
  98                end
  99              else
 100                before << all
 101              end
 102            end
 103            sections = [before.strip, s.strip, after.strip]
 104            sections.each {|section| smooth_offtags_without_code_highlighting section}
 105            sections
 106          end
 107 
 108        private
 109 
 110          # Patch for RedCloth.  Fixed in RedCloth r128 but _why hasn't released it yet.
 111          # <a href="http://code.whytheluckystiff.net/redcloth/changeset/128">http://code.whytheluckystiff.net/redcloth/changeset/128</a>
 112          def hard_break( text )
 113            text.gsub!( /(.)\n(?!\n|\Z| *([#*=]+(\s|$)|[{|]))/, "\\1<br />" ) if hard_breaks
 114          end
 115 
 116          alias :smooth_offtags_without_code_highlighting :smooth_offtags
 117          # Patch to add code highlighting support to RedCloth
 118          def smooth_offtags( text )
 119            unless @pre_list.empty?
 120              ## replace <pre> content
 121              text.gsub!(/<redpre#(\d+)>/) do
 122                content = @pre_list[$1.to_i]
 123                if content.match(/<code\s+class="(\w+)">\s?(.+)/m)
 124                  content = "<code class=\"#{$1} syntaxhl\">" +
 125                    Redmine::SyntaxHighlighting.highlight_by_language($2, $1)
 126                end
 127                content
 128              end
 129            end
 130          end
 131        end
 132      end
 133    end
 134  end