@@ -220,8 +220,9 module ApplicationHelper | |||||
220 |
|
220 | |||
221 | project = options[:project] || @project |
|
221 | project = options[:project] || @project | |
222 |
|
222 | |||
223 | # turn wiki links into html links |
|
223 | # Wiki links | |
224 |
# |
|
224 | # | |
|
225 | # Examples: | |||
225 | # [[mypage]] |
|
226 | # [[mypage]] | |
226 | # [[mypage|mytext]] |
|
227 | # [[mypage|mytext]] | |
227 | # wiki links can refer other project wikis, using project name or identifier: |
|
228 | # wiki links can refer other project wikis, using project name or identifier: | |
@@ -229,47 +230,94 module ApplicationHelper | |||||
229 | # [[project:|mytext]] |
|
230 | # [[project:|mytext]] | |
230 | # [[project:mypage]] |
|
231 | # [[project:mypage]] | |
231 | # [[project:mypage|mytext]] |
|
232 | # [[project:mypage|mytext]] | |
232 | text = text.gsub(/\[\[([^\]\|]+)(\|([^\]\|]+))?\]\]/) do |m| |
|
233 | text = text.gsub(/(!)?(\[\[([^\]\|]+)(\|([^\]\|]+))?\]\])/) do |m| | |
233 | link_project = project |
|
234 | link_project = project | |
234 | page = $1 |
|
235 | esc, all, page, title = $1, $2, $3, $5 | |
235 | title = $3 |
|
236 | if esc.nil? | |
236 | if page =~ /^([^\:]+)\:(.*)$/ |
|
237 | if page =~ /^([^\:]+)\:(.*)$/ | |
237 | link_project = Project.find_by_name($1) || Project.find_by_identifier($1) |
|
238 | link_project = Project.find_by_name($1) || Project.find_by_identifier($1) | |
238 |
page = |
|
239 | page = $2 | |
239 | title = $1 if page.blank? |
|
240 | title ||= $1 if page.blank? | |
240 | end |
|
241 | end | |
241 |
|
242 | |||
242 | if link_project && link_project.wiki |
|
243 | if link_project && link_project.wiki | |
243 | # check if page exists |
|
244 | # check if page exists | |
244 | wiki_page = link_project.wiki.find_page(page) |
|
245 | wiki_page = link_project.wiki.find_page(page) | |
245 | link_to((title || page), format_wiki_link.call(link_project, Wiki.titleize(page)), |
|
246 | link_to((title || page), format_wiki_link.call(link_project, Wiki.titleize(page)), | |
246 | :class => ('wiki-page' + (wiki_page ? '' : ' new'))) |
|
247 | :class => ('wiki-page' + (wiki_page ? '' : ' new'))) | |
|
248 | else | |||
|
249 | # project or wiki doesn't exist | |||
|
250 | title || page | |||
|
251 | end | |||
247 | else |
|
252 | else | |
248 | # project or wiki doesn't exist |
|
253 | all | |
249 | title || page |
|
|||
250 | end |
|
254 | end | |
251 | end |
|
255 | end | |
252 |
|
256 | |||
253 | # turn issue and revision ids into links |
|
257 | # Redmine links | |
254 |
# |
|
258 | # | |
255 | # #52 -> <a href="/issues/show/52">#52</a> |
|
259 | # Examples: | |
256 | # r52 -> <a href="/repositories/revision/6?rev=52">r52</a> (project.id is 6) |
|
260 | # Issues: | |
257 | text = text.gsub(%r{([\s\(,-^])(#|r)(\d+)(?=[[:punct:]]|\s|<|$)}) do |m| |
|
261 | # #52 -> Link to issue #52 | |
258 | leading, otype, oid = $1, $2, $3 |
|
262 | # Changesets: | |
|
263 | # r52 -> Link to revision 52 | |||
|
264 | # Documents: | |||
|
265 | # document#17 -> Link to document with id 17 | |||
|
266 | # document:Greetings -> Link to the document with title "Greetings" | |||
|
267 | # document:"Some document" -> Link to the document with title "Some document" | |||
|
268 | # Versions: | |||
|
269 | # version#3 -> Link to version with id 3 | |||
|
270 | # version:1.0.0 -> Link to version named "1.0.0" | |||
|
271 | # version:"1.0 beta 2" -> Link to version named "1.0 beta 2" | |||
|
272 | # Attachments: | |||
|
273 | # attachment:file.zip -> Link to the attachment of the current object named file.zip | |||
|
274 | text = text.gsub(%r{([\s\(,-^])(!)?(attachment|document|version)?((#|r)(\d+)|(:)([^"][^\s<>]+|"[^"]+"))(?=[[:punct:]]|\s|<|$)}) do |m| | |||
|
275 | leading, esc, prefix, sep, oid = $1, $2, $3, $5 || $7, $6 || $8 | |||
259 | link = nil |
|
276 | link = nil | |
260 | if otype == 'r' |
|
277 | if esc.nil? | |
261 | if project && (changeset = project.changesets.find_by_revision(oid)) |
|
278 | if prefix.nil? && sep == 'r' | |
262 | link = link_to("r#{oid}", {:controller => 'repositories', :action => 'revision', :id => project.id, :rev => oid}, :class => 'changeset', |
|
279 | if project && (changeset = project.changesets.find_by_revision(oid)) | |
263 | :title => truncate(changeset.comments, 100)) |
|
280 | link = link_to("r#{oid}", {:controller => 'repositories', :action => 'revision', :id => project.id, :rev => oid}, :class => 'changeset', | |
264 | end |
|
281 | :title => truncate(changeset.comments, 100)) | |
265 |
|
|
282 | end | |
266 | if issue = Issue.find_by_id(oid.to_i, :include => [:project, :status], :conditions => Project.visible_by(User.current)) |
|
283 | elsif sep == '#' | |
267 | link = link_to("##{oid}", {:controller => 'issues', :action => 'show', :id => oid}, :class => 'issue', |
|
284 | oid = oid.to_i | |
268 | :title => "#{truncate(issue.subject, 100)} (#{issue.status.name})") |
|
285 | case prefix | |
269 | link = content_tag('del', link) if issue.closed? |
|
286 | when nil | |
|
287 | if issue = Issue.find_by_id(oid, :include => [:project, :status], :conditions => Project.visible_by(User.current)) | |||
|
288 | link = link_to("##{oid}", {:controller => 'issues', :action => 'show', :id => oid}, :class => 'issue', | |||
|
289 | :title => "#{truncate(issue.subject, 100)} (#{issue.status.name})") | |||
|
290 | link = content_tag('del', link) if issue.closed? | |||
|
291 | end | |||
|
292 | when 'document' | |||
|
293 | if document = Document.find_by_id(oid, :include => [:project], :conditions => Project.visible_by(User.current)) | |||
|
294 | link = link_to h(document.title), {:controller => 'documents', :action => 'show', :id => document}, :class => 'document' | |||
|
295 | end | |||
|
296 | when 'version' | |||
|
297 | if version = Version.find_by_id(oid, :include => [:project], :conditions => Project.visible_by(User.current)) | |||
|
298 | link = link_to h(version.name), {:controller => 'versions', :action => 'show', :id => version}, :class => 'version' | |||
|
299 | end | |||
|
300 | end | |||
|
301 | elsif sep == ':' | |||
|
302 | # removes the double quotes if any | |||
|
303 | name = oid.gsub(%r{^"(.*)"$}, "\\1") | |||
|
304 | case prefix | |||
|
305 | when 'document' | |||
|
306 | if project && document = project.documents.find_by_title(name) | |||
|
307 | link = link_to h(document.title), {:controller => 'documents', :action => 'show', :id => document}, :class => 'document' | |||
|
308 | end | |||
|
309 | when 'version' | |||
|
310 | if project && version = project.versions.find_by_name(name) | |||
|
311 | link = link_to h(version.name), {:controller => 'versions', :action => 'show', :id => version}, :class => 'version' | |||
|
312 | end | |||
|
313 | when 'attachment' | |||
|
314 | if attachments && attachment = attachments.detect {|a| a.filename == name } | |||
|
315 | link = link_to h(attachment.filename), {:controller => 'attachments', :action => 'download', :id => attachment}, :class => 'attachment' | |||
|
316 | end | |||
|
317 | end | |||
270 | end |
|
318 | end | |
271 | end |
|
319 | end | |
272 |
leading + (link || "#{ |
|
320 | leading + (link || "#{prefix}#{sep}#{oid}") | |
273 | end |
|
321 | end | |
274 |
|
322 | |||
275 | text |
|
323 | text |
@@ -395,15 +395,15 class RedCloth < String | |||||
395 | # Elements to handle |
|
395 | # Elements to handle | |
396 | GLYPHS = [ |
|
396 | GLYPHS = [ | |
397 | # [ /([^\s\[{(>])?\'([dmst]\b|ll\b|ve\b|\s|:|$)/, '\1’\2' ], # single closing |
|
397 | # [ /([^\s\[{(>])?\'([dmst]\b|ll\b|ve\b|\s|:|$)/, '\1’\2' ], # single closing | |
398 |
|
|
398 | # [ /([^\s\[{(>#{PUNCT_Q}][#{PUNCT_Q}]*)\'/, '\1’' ], # single closing | |
399 |
|
|
399 | # [ /\'(?=[#{PUNCT_Q}]*(s\b|[\s#{PUNCT_NOQ}]))/, '’' ], # single closing | |
400 |
|
|
400 | # [ /\'/, '‘' ], # single opening | |
401 | [ /</, '<' ], # less-than |
|
401 | [ /</, '<' ], # less-than | |
402 | [ />/, '>' ], # greater-than |
|
402 | [ />/, '>' ], # greater-than | |
403 | # [ /([^\s\[{(])?"(\s|:|$)/, '\1”\2' ], # double closing |
|
403 | # [ /([^\s\[{(])?"(\s|:|$)/, '\1”\2' ], # double closing | |
404 |
|
|
404 | # [ /([^\s\[{(>#{PUNCT_Q}][#{PUNCT_Q}]*)"/, '\1”' ], # double closing | |
405 |
|
|
405 | # [ /"(?=[#{PUNCT_Q}]*[\s#{PUNCT_NOQ}])/, '”' ], # double closing | |
406 |
|
|
406 | # [ /"/, '“' ], # double opening | |
407 | [ /\b( )?\.{3}/, '\1…' ], # ellipsis |
|
407 | [ /\b( )?\.{3}/, '\1…' ], # ellipsis | |
408 | [ /\b([A-Z][A-Z0-9]{2,})\b(?:[(]([^)]*)[)])/, '<acronym title="\2">\1</acronym>' ], # 3+ uppercase acronym |
|
408 | [ /\b([A-Z][A-Z0-9]{2,})\b(?:[(]([^)]*)[)])/, '<acronym title="\2">\1</acronym>' ], # 3+ uppercase acronym | |
409 | [ /(^|[^"][>\s])([A-Z][A-Z0-9 ]+[A-Z0-9])([^<A-Za-z0-9]|$)/, '\1<span class="caps">\2</span>\3', :no_span_caps ], # 3+ uppercase caps |
|
409 | [ /(^|[^"][>\s])([A-Z][A-Z0-9 ]+[A-Z0-9])([^<A-Za-z0-9]|$)/, '\1<span class="caps">\2</span>\3', :no_span_caps ], # 3+ uppercase caps |
@@ -21,4 +21,14 wiki_contents_002: | |||||
21 | page_id: 2 |
|
21 | page_id: 2 | |
22 | id: 2 |
|
22 | id: 2 | |
23 | version: 1 |
|
23 | version: 1 | |
24 | author_id: 1 No newline at end of file |
|
24 | author_id: 1 | |
|
25 | comments: | |||
|
26 | wiki_contents_003: | |||
|
27 | text: |- | |||
|
28 | h1. Start page | |||
|
29 | ||||
|
30 | E-commerce web site start page | |||
|
31 | updated_on: 2007-03-08 00:18:07 +01:00 | |||
|
32 | page_id: 3 | |||
|
33 | id: 3 | |||
|
34 | version: 1 |
@@ -9,4 +9,9 wiki_pages_002: | |||||
9 | title: Another_page |
|
9 | title: Another_page | |
10 | id: 2 |
|
10 | id: 2 | |
11 | wiki_id: 1 |
|
11 | wiki_id: 1 | |
|
12 | wiki_pages_003: | |||
|
13 | created_on: 2007-03-08 00:18:07 +01:00 | |||
|
14 | title: Start_page | |||
|
15 | id: 3 | |||
|
16 | wiki_id: 2 | |||
12 | No newline at end of file |
|
17 |
@@ -4,3 +4,9 wikis_001: | |||||
4 | start_page: CookBook documentation |
|
4 | start_page: CookBook documentation | |
5 | project_id: 1 |
|
5 | project_id: 1 | |
6 | id: 1 |
|
6 | id: 1 | |
|
7 | wikis_002: | |||
|
8 | status: 1 | |||
|
9 | start_page: Start page | |||
|
10 | project_id: 2 | |||
|
11 | id: 2 | |||
|
12 | No newline at end of file |
@@ -20,7 +20,7 require File.dirname(__FILE__) + '/../../test_helper' | |||||
20 | class ApplicationHelperTest < HelperTestCase |
|
20 | class ApplicationHelperTest < HelperTestCase | |
21 | include ApplicationHelper |
|
21 | include ApplicationHelper | |
22 | include ActionView::Helpers::TextHelper |
|
22 | include ActionView::Helpers::TextHelper | |
23 | fixtures :projects, :repositories, :changesets, :trackers, :issue_statuses, :issues |
|
23 | fixtures :projects, :repositories, :changesets, :trackers, :issue_statuses, :issues, :documents, :versions, :wikis, :wiki_pages, :wiki_contents | |
24 |
|
24 | |||
25 | def setup |
|
25 | def setup | |
26 | super |
|
26 | super | |
@@ -66,12 +66,52 class ApplicationHelperTest < HelperTestCase | |||||
66 | def test_redmine_links |
|
66 | def test_redmine_links | |
67 | issue_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3}, |
|
67 | issue_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3}, | |
68 | :class => 'issue', :title => 'Error 281 when updating a recipe (New)') |
|
68 | :class => 'issue', :title => 'Error 281 when updating a recipe (New)') | |
|
69 | ||||
69 | changeset_link = link_to('r1', {:controller => 'repositories', :action => 'revision', :id => 1, :rev => 1}, |
|
70 | changeset_link = link_to('r1', {:controller => 'repositories', :action => 'revision', :id => 1, :rev => 1}, | |
70 | :class => 'changeset', :title => 'My very first commit') |
|
71 | :class => 'changeset', :title => 'My very first commit') | |
71 |
|
72 | |||
|
73 | document_link = link_to('Test document', {:controller => 'documents', :action => 'show', :id => 1}, | |||
|
74 | :class => 'document') | |||
|
75 | ||||
|
76 | version_link = link_to('1.0', {:controller => 'versions', :action => 'show', :id => 2}, | |||
|
77 | :class => 'version') | |||
|
78 | ||||
72 | to_test = { |
|
79 | to_test = { | |
73 | '#3, #3 and #3.' => "#{issue_link}, #{issue_link} and #{issue_link}.", |
|
80 | '#3, #3 and #3.' => "#{issue_link}, #{issue_link} and #{issue_link}.", | |
74 | 'r1' => changeset_link |
|
81 | 'r1' => changeset_link, | |
|
82 | 'document#1' => document_link, | |||
|
83 | 'document:"Test document"' => document_link, | |||
|
84 | 'version#2' => version_link, | |||
|
85 | 'version:1.0' => version_link, | |||
|
86 | 'version:"1.0"' => version_link, | |||
|
87 | # escaping | |||
|
88 | '!#3.' => '#3.', | |||
|
89 | '!r1' => 'r1', | |||
|
90 | '!document#1' => 'document#1', | |||
|
91 | '!document:"Test document"' => 'document:"Test document"', | |||
|
92 | '!version#2' => 'version#2', | |||
|
93 | '!version:1.0' => 'version:1.0', | |||
|
94 | '!version:"1.0"' => 'version:"1.0"', | |||
|
95 | } | |||
|
96 | @project = Project.find(1) | |||
|
97 | to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) } | |||
|
98 | end | |||
|
99 | ||||
|
100 | def test_wiki_links | |||
|
101 | to_test = { | |||
|
102 | '[[CookBook documentation]]' => '<a href="/wiki/ecookbook/CookBook_documentation" class="wiki-page">CookBook documentation</a>', | |||
|
103 | '[[Another page|Page]]' => '<a href="/wiki/ecookbook/Another_page" class="wiki-page">Page</a>', | |||
|
104 | # page that doesn't exist | |||
|
105 | '[[Unknown page]]' => '<a href="/wiki/ecookbook/Unknown_page" class="wiki-page new">Unknown page</a>', | |||
|
106 | '[[Unknown page|404]]' => '<a href="/wiki/ecookbook/Unknown_page" class="wiki-page new">404</a>', | |||
|
107 | # link to another project wiki | |||
|
108 | '[[onlinestore:]]' => '<a href="/wiki/onlinestore/" class="wiki-page">onlinestore</a>', | |||
|
109 | '[[onlinestore:|Wiki]]' => '<a href="/wiki/onlinestore/" class="wiki-page">Wiki</a>', | |||
|
110 | '[[onlinestore:Start page]]' => '<a href="/wiki/onlinestore/Start_page" class="wiki-page">Start page</a>', | |||
|
111 | '[[onlinestore:Start page|Text]]' => '<a href="/wiki/onlinestore/Start_page" class="wiki-page">Text</a>', | |||
|
112 | '[[onlinestore:Unknown page]]' => '<a href="/wiki/onlinestore/Unknown_page" class="wiki-page new">Unknown page</a>', | |||
|
113 | # escaping | |||
|
114 | '![[Another page|Page]]' => '[[Another page|Page]]', | |||
75 | } |
|
115 | } | |
76 | @project = Project.find(1) |
|
116 | @project = Project.find(1) | |
77 | to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) } |
|
117 | to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) } |
General Comments 0
You need to be logged in to leave comments.
Login now