summaryrefslogtreecommitdiffstats
path: root/lib/redmine/wiki_formatting.rb
diff options
context:
space:
mode:
authorJean-Philippe Lang <jp_lang@yahoo.fr>2008-10-27 11:08:29 +0000
committerJean-Philippe Lang <jp_lang@yahoo.fr>2008-10-27 11:08:29 +0000
commita3b9a5aa5fe344cf33a47ccbf1d26a95fbe4e255 (patch)
tree6b19387c81e2d865a57cf3357340deffdbc5e858 /lib/redmine/wiki_formatting.rb
parent9b624fd1d6f66bbe60d738522d9fc5fd547ef3af (diff)
downloadredmine-a3b9a5aa5fe344cf33a47ccbf1d26a95fbe4e255.tar.gz
redmine-a3b9a5aa5fe344cf33a47ccbf1d26a95fbe4e255.zip
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
Diffstat (limited to 'lib/redmine/wiki_formatting.rb')
-rw-r--r--lib/redmine/wiki_formatting.rb193
1 files changed, 41 insertions, 152 deletions
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.
- # <a href="http://code.whytheluckystiff.net/redcloth/changeset/128">http://code.whytheluckystiff.net/redcloth/changeset/128</a>
- def hard_break( text )
- text.gsub!( /(.)\n(?!\n|\Z|>| *(>? *[#*=]+(\s|$)|[{|]))/, "\\1<br />\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 <pre> content
- text.gsub!(/<redpre#(\d+)>/) do
- content = @pre_list[$1.to_i]
- if content.match(/<code\s+class="(\w+)">\s?(.+)/m)
- content = "<code class=\"#{$1} CodeRay\">" +
- 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 + "<a href=\"##{anchor}\" class=\"wiki-anchor\">&para;</a>"
+ 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!(/<p>\{\{([<>]?)toc\}\}<\/p>/i) do
- div_class = 'toc'
- div_class << ' right' if $1 == '>'
- div_class << ' left' if $1 == '<'
- out = "<ul class=\"#{div_class}\">"
- @toc.each do |heading|
- level, anchor, toc_item = heading
- out << "<li class=\"heading#{level}\"><a href=\"##{anchor}\">#{toc_item}</a></li>\n"
- end
- out << '</ul>'
- 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
- "<div class=\"flash error\">Error executing the <strong>#{macro}</strong> macro (#{e})</div>"
- 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 =~ /<a\s/i || 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}<a class="external" href="#{proto=="www."?"http://www.":proto}#{url}">#{proto + url}</a>#{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(/<a\b[^>]*>(.*)(#{Regexp.escape(mail)})(.*)<\/a>/)
- mail
- else
- %{<a href="mailto:#{mail}" class="email">#{mail}</a>}
- 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