@@ -80,19 +80,77 module Redmine | |||
|
80 | 80 | end |
|
81 | 81 | end |
|
82 | 82 | |
|
83 | module LinksHelper | |
|
84 | AUTO_LINK_RE = %r{ | |
|
85 | ( # leading text | |
|
86 | <\w+.*?>| # leading HTML tag, or | |
|
87 | [^=<>!:'"/]| # leading punctuation, or | |
|
88 | ^ # beginning of line | |
|
89 | ) | |
|
90 | ( | |
|
91 | (?:https?://)| # protocol spec, or | |
|
92 | (?:s?ftps?://)| | |
|
93 | (?:www\.) # www.* | |
|
94 | ) | |
|
95 | ( | |
|
96 | (\S+?) # url | |
|
97 | (\/)? # slash | |
|
98 | ) | |
|
99 | ((?:>)?|[^\w\=\/;\(\)]*?) # post | |
|
100 | (?=<|\s|$) | |
|
101 | }x unless const_defined?(:AUTO_LINK_RE) | |
|
102 | ||
|
103 | # Destructively remplaces urls into clickable links | |
|
104 | def auto_link!(text) | |
|
105 | text.gsub!(AUTO_LINK_RE) do | |
|
106 | all, leading, proto, url, post = $&, $1, $2, $3, $6 | |
|
107 | if leading =~ /<a\s/i || leading =~ /![<>=]?/ | |
|
108 | # don't replace URL's that are already linked | |
|
109 | # and URL's prefixed with ! !> !< != (textile images) | |
|
110 | all | |
|
111 | else | |
|
112 | # Idea below : an URL with unbalanced parethesis and | |
|
113 | # ending by ')' is put into external parenthesis | |
|
114 | if ( url[-1]==?) and ((url.count("(") - url.count(")")) < 0 ) ) | |
|
115 | url=url[0..-2] # discard closing parenth from url | |
|
116 | post = ")"+post # add closing parenth to post | |
|
117 | end | |
|
118 | tag = content_tag('a', proto + url, :href => "#{proto=="www."?"http://www.":proto}#{url}", :class => 'external') | |
|
119 | %(#{leading}#{tag}#{post}) | |
|
120 | end | |
|
121 | end | |
|
122 | end | |
|
123 | ||
|
124 | # Destructively remplaces email addresses into clickable links | |
|
125 | def auto_mailto!(text) | |
|
126 | text.gsub!(/([\w\.!#\$%\-+.]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do | |
|
127 | mail = $1 | |
|
128 | if text.match(/<a\b[^>]*>(.*)(#{Regexp.escape(mail)})(.*)<\/a>/) | |
|
129 | ||
|
130 | else | |
|
131 | content_tag('a', mail, :href => "mailto:#{mail}", :class => "email") | |
|
132 | end | |
|
133 | end | |
|
134 | end | |
|
135 | end | |
|
136 | ||
|
83 | 137 | # Default formatter module |
|
84 | 138 | module NullFormatter |
|
85 | 139 | class Formatter |
|
86 | 140 | include ActionView::Helpers::TagHelper |
|
87 | 141 | include ActionView::Helpers::TextHelper |
|
88 | 142 | include ActionView::Helpers::UrlHelper |
|
143 | include Redmine::WikiFormatting::LinksHelper | |
|
89 | 144 | |
|
90 | 145 | def initialize(text) |
|
91 | 146 | @text = text |
|
92 | 147 | end |
|
93 | 148 | |
|
94 | 149 | def to_html(*args) |
|
95 |
|
|
|
150 | t = CGI::escapeHTML(@text) | |
|
151 | auto_link!(t) | |
|
152 | auto_mailto!(t) | |
|
153 | simple_format(t) | |
|
96 | 154 | end |
|
97 | 155 | end |
|
98 | 156 |
@@ -23,6 +23,10 module Redmine | |||
|
23 | 23 | module Textile |
|
24 | 24 | class Formatter < RedCloth3 |
|
25 | 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! | |
|
26 | 30 | |
|
27 | 31 | # auto_link rule after textile rules so that it doesn't break !image_url! tags |
|
28 | 32 | RULES = [:textile, :block_markdown_rule, :inline_auto_link, :inline_auto_mailto] |
@@ -124,58 +128,6 module Redmine | |||
|
124 | 128 | end |
|
125 | 129 | end |
|
126 | 130 | end |
|
127 | ||
|
128 | AUTO_LINK_RE = %r{ | |
|
129 | ( # leading text | |
|
130 | <\w+.*?>| # leading HTML tag, or | |
|
131 | [^=<>!:'"/]| # leading punctuation, or | |
|
132 | ^ # beginning of line | |
|
133 | ) | |
|
134 | ( | |
|
135 | (?:https?://)| # protocol spec, or | |
|
136 | (?:s?ftps?://)| | |
|
137 | (?:www\.) # www.* | |
|
138 | ) | |
|
139 | ( | |
|
140 | (\S+?) # url | |
|
141 | (\/)? # slash | |
|
142 | ) | |
|
143 | ((?:>)?|[^\w\=\/;\(\)]*?) # post | |
|
144 | (?=<|\s|$) | |
|
145 | }x unless const_defined?(:AUTO_LINK_RE) | |
|
146 | ||
|
147 | # Turns all urls into clickable links (code from Rails). | |
|
148 | def inline_auto_link(text) | |
|
149 | text.gsub!(AUTO_LINK_RE) do | |
|
150 | all, leading, proto, url, post = $&, $1, $2, $3, $6 | |
|
151 | if leading =~ /<a\s/i || leading =~ /![<>=]?/ | |
|
152 | # don't replace URL's that are already linked | |
|
153 | # and URL's prefixed with ! !> !< != (textile images) | |
|
154 | all | |
|
155 | else | |
|
156 | # Idea below : an URL with unbalanced parethesis and | |
|
157 | # ending by ')' is put into external parenthesis | |
|
158 | if ( url[-1]==?) and ((url.count("(") - url.count(")")) < 0 ) ) | |
|
159 | url=url[0..-2] # discard closing parenth from url | |
|
160 | post = ")"+post # add closing parenth to post | |
|
161 | end | |
|
162 | tag = content_tag('a', proto + url, :href => "#{proto=="www."?"http://www.":proto}#{url}", :class => 'external') | |
|
163 | %(#{leading}#{tag}#{post}) | |
|
164 | end | |
|
165 | end | |
|
166 | end | |
|
167 | ||
|
168 | # Turns all email addresses into clickable links (code from Rails). | |
|
169 | def inline_auto_mailto(text) | |
|
170 | text.gsub!(/([\w\.!#\$%\-+.]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do | |
|
171 | mail = $1 | |
|
172 | if text.match(/<a\b[^>]*>(.*)(#{Regexp.escape(mail)})(.*)<\/a>/) | |
|
173 | ||
|
174 | else | |
|
175 | content_tag('a', mail, :href => "mailto:#{mail}", :class => "email") | |
|
176 | end | |
|
177 | end | |
|
178 | end | |
|
179 | 131 | end |
|
180 | 132 | end |
|
181 | 133 | end |
@@ -940,7 +940,7 RAW | |||
|
940 | 940 | def test_default_formatter |
|
941 | 941 | with_settings :text_formatting => 'unknown' do |
|
942 | 942 | text = 'a *link*: http://www.example.net/' |
|
943 | assert_equal '<p>a *link*: <a href="http://www.example.net/">http://www.example.net/</a></p>', textilizable(text) | |
|
943 | assert_equal '<p>a *link*: <a class="external" href="http://www.example.net/">http://www.example.net/</a></p>', textilizable(text) | |
|
944 | 944 | end |
|
945 | 945 | end |
|
946 | 946 |
@@ -36,8 +36,8 and an email address foo@example.net | |||
|
36 | 36 | DIFF |
|
37 | 37 | |
|
38 | 38 | expected = <<-EXPECTED |
|
39 | <p>This is a sample *text* with a link: <a href="http://www.redmine.org">http://www.redmine.org</a><br /> | |
|
40 | and an email address <a href="mailto:foo@example.net">foo@example.net</a></p> | |
|
39 | <p>This is a sample *text* with a link: <a class="external" href="http://www.redmine.org">http://www.redmine.org</a><br /> | |
|
40 | and an email address <a class="email" href="mailto:foo@example.net">foo@example.net</a></p> | |
|
41 | 41 | EXPECTED |
|
42 | 42 | |
|
43 | 43 | assert_equal expected.gsub(%r{[\r\n\t]}, ''), Redmine::WikiFormatting::NullFormatter::Formatter.new(raw).to_html.gsub(%r{[\r\n\t]}, '') |
General Comments 0
You need to be logged in to leave comments.
Login now