Mercurial > hg > soundsoftware-site
comparison .svn/pristine/e7/e71ffb368169655507e0a27da44ca924f654e9c2.svn-base @ 1517:dffacf8a6908 redmine-2.5
Update to Redmine SVN revision 13367 on 2.5-stable branch
author | Chris Cannam |
---|---|
date | Tue, 09 Sep 2014 09:29:00 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
1516:b450a9d58aed | 1517:dffacf8a6908 |
---|---|
1 # Redmine - project management software | |
2 # Copyright (C) 2006-2014 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 'digest/md5' | |
19 | |
20 module Redmine | |
21 module WikiFormatting | |
22 class StaleSectionError < Exception; end | |
23 | |
24 @@formatters = {} | |
25 | |
26 class << self | |
27 def map | |
28 yield self | |
29 end | |
30 | |
31 def register(name, formatter, helper, options={}) | |
32 name = name.to_s | |
33 raise ArgumentError, "format name '#{name}' is already taken" if @@formatters[name] | |
34 @@formatters[name] = { | |
35 :formatter => formatter, | |
36 :helper => helper, | |
37 :label => options[:label] || name.humanize | |
38 } | |
39 end | |
40 | |
41 def formatter | |
42 formatter_for(Setting.text_formatting) | |
43 end | |
44 | |
45 def formatter_for(name) | |
46 entry = @@formatters[name.to_s] | |
47 (entry && entry[:formatter]) || Redmine::WikiFormatting::NullFormatter::Formatter | |
48 end | |
49 | |
50 def helper_for(name) | |
51 entry = @@formatters[name.to_s] | |
52 (entry && entry[:helper]) || Redmine::WikiFormatting::NullFormatter::Helper | |
53 end | |
54 | |
55 def format_names | |
56 @@formatters.keys.map | |
57 end | |
58 | |
59 def formats_for_select | |
60 @@formatters.map {|name, options| [options[:label], name]} | |
61 end | |
62 | |
63 def to_html(format, text, options = {}) | |
64 text = if Setting.cache_formatted_text? && text.size > 2.kilobyte && cache_store && cache_key = cache_key_for(format, text, options[:object], options[:attribute]) | |
65 # Text retrieved from the cache store may be frozen | |
66 # We need to dup it so we can do in-place substitutions with gsub! | |
67 cache_store.fetch cache_key do | |
68 formatter_for(format).new(text).to_html | |
69 end.dup | |
70 else | |
71 formatter_for(format).new(text).to_html | |
72 end | |
73 text | |
74 end | |
75 | |
76 # Returns true if the text formatter supports single section edit | |
77 def supports_section_edit? | |
78 (formatter.instance_methods & ['update_section', :update_section]).any? | |
79 end | |
80 | |
81 # Returns a cache key for the given text +format+, +text+, +object+ and +attribute+ or nil if no caching should be done | |
82 def cache_key_for(format, text, object, attribute) | |
83 if object && attribute && !object.new_record? && format.present? | |
84 "formatted_text/#{format}/#{object.class.model_name.cache_key}/#{object.id}-#{attribute}-#{Digest::MD5.hexdigest text}" | |
85 end | |
86 end | |
87 | |
88 # Returns the cache store used to cache HTML output | |
89 def cache_store | |
90 ActionController::Base.cache_store | |
91 end | |
92 end | |
93 | |
94 module LinksHelper | |
95 AUTO_LINK_RE = %r{ | |
96 ( # leading text | |
97 <\w+.*?>| # leading HTML tag, or | |
98 [\s\(\[,;]| # leading punctuation, or | |
99 ^ # beginning of line | |
100 ) | |
101 ( | |
102 (?:https?://)| # protocol spec, or | |
103 (?:s?ftps?://)| | |
104 (?:www\.) # www.* | |
105 ) | |
106 ( | |
107 ([^<]\S*?) # url | |
108 (\/)? # slash | |
109 ) | |
110 ((?:>)?|[^[:alnum:]_\=\/;\(\)]*?) # post | |
111 (?=<|\s|$) | |
112 }x unless const_defined?(:AUTO_LINK_RE) | |
113 | |
114 # Destructively remplaces urls into clickable links | |
115 def auto_link!(text) | |
116 text.gsub!(AUTO_LINK_RE) do | |
117 all, leading, proto, url, post = $&, $1, $2, $3, $6 | |
118 if leading =~ /<a\s/i || leading =~ /![<>=]?/ | |
119 # don't replace URL's that are already linked | |
120 # and URL's prefixed with ! !> !< != (textile images) | |
121 all | |
122 else | |
123 # Idea below : an URL with unbalanced parethesis and | |
124 # ending by ')' is put into external parenthesis | |
125 if ( url[-1]==?) and ((url.count("(") - url.count(")")) < 0 ) ) | |
126 url=url[0..-2] # discard closing parenth from url | |
127 post = ")"+post # add closing parenth to post | |
128 end | |
129 content = proto + url | |
130 href = "#{proto=="www."?"http://www.":proto}#{url}" | |
131 %(#{leading}<a class="external" href="#{ERB::Util.html_escape href}">#{ERB::Util.html_escape content}</a>#{post}).html_safe | |
132 end | |
133 end | |
134 end | |
135 | |
136 # Destructively remplaces email addresses into clickable links | |
137 def auto_mailto!(text) | |
138 text.gsub!(/([\w\.!#\$%\-+.]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do | |
139 mail = $1 | |
140 if text.match(/<a\b[^>]*>(.*)(#{Regexp.escape(mail)})(.*)<\/a>/) | |
141 mail | |
142 else | |
143 %(<a class="email" href="mailto:#{ERB::Util.html_escape mail}">#{ERB::Util.html_escape mail}</a>).html_safe | |
144 end | |
145 end | |
146 end | |
147 end | |
148 | |
149 # Default formatter module | |
150 module NullFormatter | |
151 class Formatter | |
152 include ActionView::Helpers::TagHelper | |
153 include ActionView::Helpers::TextHelper | |
154 include ActionView::Helpers::UrlHelper | |
155 include Redmine::WikiFormatting::LinksHelper | |
156 | |
157 def initialize(text) | |
158 @text = text | |
159 end | |
160 | |
161 def to_html(*args) | |
162 t = CGI::escapeHTML(@text) | |
163 auto_link!(t) | |
164 auto_mailto!(t) | |
165 simple_format(t, {}, :sanitize => false) | |
166 end | |
167 end | |
168 | |
169 module Helper | |
170 def wikitoolbar_for(field_id) | |
171 end | |
172 | |
173 def heads_for_wiki_formatter | |
174 end | |
175 | |
176 def initial_page_content(page) | |
177 page.pretty_title.to_s | |
178 end | |
179 end | |
180 end | |
181 end | |
182 end |