From a3b9a5aa5fe344cf33a47ccbf1d26a95fbe4e255 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Mon, 27 Oct 2008 11:08:29 +0000 Subject: Makes wiki text formatter pluggable. Original patch #2025 by Yuki Sonoda slightly edited. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@1955 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/wiki_formatting.rb | 193 +++++++++-------------------------------- 1 file changed, 41 insertions(+), 152 deletions(-) (limited to 'lib/redmine/wiki_formatting.rb') diff --git a/lib/redmine/wiki_formatting.rb b/lib/redmine/wiki_formatting.rb index 7dffff492..1525dbc19 100644 --- a/lib/redmine/wiki_formatting.rb +++ b/lib/redmine/wiki_formatting.rb @@ -1,5 +1,5 @@ -# redMine - project management software -# Copyright (C) 2006-2007 Jean-Philippe Lang +# Redmine - project management software +# Copyright (C) 2006-2008 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -15,176 +15,65 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -require 'redcloth3' -require 'coderay' - module Redmine module WikiFormatting - - private - - class TextileFormatter < RedCloth3 - - # auto_link rule after textile rules so that it doesn't break !image_url! tags - RULES = [:textile, :block_markdown_rule, :inline_auto_link, :inline_auto_mailto, :inline_toc, :inline_macros] + @@formatters = {} + + class << self + def map + yield self + end - def initialize(*args) - super - self.hard_breaks=true - self.no_span_caps=true + def register(name, formatter, helper) + raise ArgumentError, "format name '#{name}' is already taken" if @@formatters[name] + @@formatters[name.to_sym] = {:formatter => formatter, :helper => helper} end - def to_html(*rules, &block) - @toc = [] - @macros_runner = block - super(*RULES).to_s + def formatter_for(name) + entry = @@formatters[name.to_sym] + (entry && entry[:formatter]) || Redmine::WikiFormatting::NullFormatter::Formatter end - - private - - # Patch for RedCloth. Fixed in RedCloth r128 but _why hasn't released it yet. - # http://code.whytheluckystiff.net/redcloth/changeset/128 - def hard_break( text ) - text.gsub!( /(.)\n(?!\n|\Z|>| *(>? *[#*=]+(\s|$)|[{|]))/, "\\1
\n" ) if hard_breaks + + def helper_for(name) + entry = @@formatters[name.to_sym] + (entry && entry[:helper]) || Redmine::WikiFormatting::NullFormatter::Helper end - # Patch to add code highlighting support to RedCloth - def smooth_offtags( text ) - unless @pre_list.empty? - ## replace
 content
-          text.gsub!(//) do
-            content = @pre_list[$1.to_i]
-            if content.match(/\s?(.+)/m)
-              content = "" + 
-                CodeRay.scan($2, $1.downcase).html(:escape => false, :line_numbers => :inline)
-            end
-            content
-          end
-        end
+      def format_names
+        @@formatters.keys.map
       end
       
-      # Patch to add 'table of content' support to RedCloth
-      def textile_p_withtoc(tag, atts, cite, content)
-        # removes wiki links from the item
-        toc_item = content.gsub(/(\[\[|\]\])/, '')
-        # removes styles
-        # eg. %{color:red}Triggers% => Triggers
-        toc_item.gsub! %r[%\{[^\}]*\}([^%]+)%], '\\1'
+      def to_html(format, text, options = {}, &block)
+        formatter_for(format).new(text).to_html(&block)
+      end
+    end
+    
+    # Default formatter module
+    module NullFormatter
+      class Formatter
+        include ActionView::Helpers::TagHelper
+        include ActionView::Helpers::TextHelper
         
-        # replaces non word caracters by dashes
-        anchor = toc_item.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-')
-
-        unless anchor.blank?
-          if tag =~ /^h(\d)$/
-            @toc << [$1.to_i, anchor, toc_item]
-          end
-          atts << " id=\"#{anchor}\""
-          content = content + ""
+        def initialize(text)
+          @text = text
         end
-        textile_p(tag, atts, cite, content)
-      end
-
-      alias :textile_h1 :textile_p_withtoc
-      alias :textile_h2 :textile_p_withtoc
-      alias :textile_h3 :textile_p_withtoc
-      
-      def inline_toc(text)
-        text.gsub!(/

\{\{([<>]?)toc\}\}<\/p>/i) do - div_class = 'toc' - div_class << ' right' if $1 == '>' - div_class << ' left' if $1 == '<' - out = "

    " - @toc.each do |heading| - level, anchor, toc_item = heading - out << "
  • #{toc_item}
  • \n" - end - out << '
' - out + + def to_html(*args) + simple_format(auto_link(CGI::escapeHTML(@text))) end end - MACROS_RE = / - (!)? # escaping - ( - \{\{ # opening tag - ([\w]+) # macro name - (\(([^\}]*)\))? # optional arguments - \}\} # closing tag - ) - /x unless const_defined?(:MACROS_RE) - - def inline_macros(text) - text.gsub!(MACROS_RE) do - esc, all, macro = $1, $2, $3.downcase - args = ($5 || '').split(',').each(&:strip) - if esc.nil? - begin - @macros_runner.call(macro, args) - rescue => e - "
Error executing the #{macro} macro (#{e})
" - end || all - else - all - end + module Helper + def wikitoolbar_for(field_id) end - end - AUTO_LINK_RE = %r{ - ( # leading text - <\w+.*?>| # leading HTML tag, or - [^=<>!:'"/]| # leading punctuation, or - ^ # beginning of line - ) - ( - (?:https?://)| # protocol spec, or - (?:ftp://)| - (?:www\.) # www.* - ) - ( - (\S+?) # url - (\/)? # slash - ) - ([^\w\=\/;\(\)]*?) # post - (?=<|\s|$) - }x unless const_defined?(:AUTO_LINK_RE) - - # Turns all urls into clickable links (code from Rails). - def inline_auto_link(text) - text.gsub!(AUTO_LINK_RE) do - all, leading, proto, url, post = $&, $1, $2, $3, $6 - if leading =~ /=]?/ - # don't replace URL's that are already linked - # and URL's prefixed with ! !> !< != (textile images) - all - else - # Idea below : an URL with unbalanced parethesis and - # ending by ')' is put into external parenthesis - if ( url[-1]==?) and ((url.count("(") - url.count(")")) < 0 ) ) - url=url[0..-2] # discard closing parenth from url - post = ")"+post # add closing parenth to post - end - %(#{leading}#{proto + url}#{post}) - end + def heads_for_wiki_formatter end - end - - # Turns all email addresses into clickable links (code from Rails). - def inline_auto_mailto(text) - text.gsub!(/([\w\.!#\$%\-+.]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do - mail = $1 - if text.match(/]*>(.*)(#{Regexp.escape(mail)})(.*)<\/a>/) - mail - else - %{} - end + + def initial_page_content(page) + page.pretty_title.to_s end end end - - public - - def self.to_html(text, options = {}, &block) - TextileFormatter.new(text).to_html(&block) - end end end -- cgit v1.2.3