@@ -1,5 +1,5 | |||
|
1 |
# |
|
|
2 |
# Copyright (C) 2006-200 |
|
|
1 | # Redmine - project management software | |
|
2 | # Copyright (C) 2006-2010 Jean-Philippe Lang | |
|
3 | 3 | # |
|
4 | 4 | # This program is free software; you can redistribute it and/or |
|
5 | 5 | # modify it under the terms of the GNU General Public License |
@@ -451,7 +451,7 module ApplicationHelper | |||
|
451 | 451 | text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr) { |macro, args| exec_macro(macro, obj, args) } |
|
452 | 452 | |
|
453 | 453 | parse_non_pre_blocks(text) do |text| |
|
454 | [:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links].each do |method_name| | |
|
454 | [:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links, :parse_headings].each do |method_name| | |
|
455 | 455 | send method_name, text, project, obj, attr, only_path, options |
|
456 | 456 | end |
|
457 | 457 | end |
@@ -673,6 +673,38 module ApplicationHelper | |||
|
673 | 673 | leading + (link || "#{prefix}#{sep}#{identifier}") |
|
674 | 674 | end |
|
675 | 675 | end |
|
676 | ||
|
677 | TOC_RE = /<p>\{\{([<>]?)toc\}\}<\/p>/i unless const_defined?(:TOC_RE) | |
|
678 | HEADING_RE = /<h(1|2|3)( [^>]+)?>(.+?)<\/h(1|2|3)>/i unless const_defined?(:HEADING_RE) | |
|
679 | ||
|
680 | # Headings and TOC | |
|
681 | # Adds ids and links to headings and renders the TOC if needed unless options[:headings] is set to false | |
|
682 | def parse_headings(text, project, obj, attr, only_path, options) | |
|
683 | headings = [] | |
|
684 | text.gsub!(HEADING_RE) do | |
|
685 | level, attrs, content = $1, $2, $3 | |
|
686 | item = strip_tags(content).strip | |
|
687 | anchor = item.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-') | |
|
688 | headings << [level, anchor, item] | |
|
689 | "<h#{level} #{attrs} id=\"#{anchor}\">#{content}<a href=\"##{anchor}\" class=\"wiki-anchor\">¶</a></h#{level}>" | |
|
690 | end unless options[:headings] == false | |
|
691 | ||
|
692 | text.gsub!(TOC_RE) do | |
|
693 | if headings.empty? | |
|
694 | '' | |
|
695 | else | |
|
696 | div_class = 'toc' | |
|
697 | div_class << ' right' if $1 == '>' | |
|
698 | div_class << ' left' if $1 == '<' | |
|
699 | out = "<ul class=\"#{div_class}\">" | |
|
700 | headings.each do |level, anchor, item| | |
|
701 | out << "<li class=\"heading#{level}\"><a href=\"##{anchor}\">#{item}</a></li>\n" | |
|
702 | end | |
|
703 | out << '</ul>' | |
|
704 | out | |
|
705 | end | |
|
706 | end | |
|
707 | end | |
|
676 | 708 | |
|
677 | 709 | # Same as Rails' simple_format helper without using paragraphs |
|
678 | 710 | def simple_format_without_paragraph(text) |
@@ -112,7 +112,7 module Redmine | |||
|
112 | 112 | @included_wiki_pages ||= [] |
|
113 | 113 | raise 'Circular inclusion detected' if @included_wiki_pages.include?(page.title) |
|
114 | 114 | @included_wiki_pages << page.title |
|
115 | out = textilizable(page.content, :text, :attachments => page.attachments) | |
|
115 | out = textilizable(page.content, :text, :attachments => page.attachments, :headings => false) | |
|
116 | 116 | @included_wiki_pages.pop |
|
117 | 117 | out |
|
118 | 118 | end |
@@ -1,5 +1,5 | |||
|
1 | 1 | # Redmine - project management software |
|
2 |
# Copyright (C) 2006-200 |
|
|
2 | # Copyright (C) 2006-2010 Jean-Philippe Lang | |
|
3 | 3 | # |
|
4 | 4 | # This program is free software; you can redistribute it and/or |
|
5 | 5 | # modify it under the terms of the GNU General Public License |
@@ -24,7 +24,7 module Redmine | |||
|
24 | 24 | include ActionView::Helpers::TagHelper |
|
25 | 25 | |
|
26 | 26 | # auto_link rule after textile rules so that it doesn't break !image_url! tags |
|
27 |
RULES = [:textile, :block_markdown_rule, :inline_auto_link, :inline_auto_mailto |
|
|
27 | RULES = [:textile, :block_markdown_rule, :inline_auto_link, :inline_auto_mailto] | |
|
28 | 28 | |
|
29 | 29 | def initialize(*args) |
|
30 | 30 | super |
@@ -61,51 +61,6 module Redmine | |||
|
61 | 61 | end |
|
62 | 62 | end |
|
63 | 63 | |
|
64 | # Patch to add 'table of content' support to RedCloth | |
|
65 | def textile_p_withtoc(tag, atts, cite, content) | |
|
66 | # removes wiki links from the item | |
|
67 | toc_item = content.gsub(/(\[\[([^\]\|]*)(\|([^\]]*))?\]\])/) { $4 || $2 } | |
|
68 | # sanitizes titles from links | |
|
69 | # see redcloth3.rb, same as "#{pre}#{text}#{post}" | |
|
70 | toc_item.gsub!(LINK_RE) { [$2, $4, $9].join } | |
|
71 | # sanitizes image links from titles | |
|
72 | toc_item.gsub!(IMAGE_RE) { [$5].join } | |
|
73 | # removes styles | |
|
74 | # eg. %{color:red}Triggers% => Triggers | |
|
75 | toc_item.gsub! %r[%\{[^\}]*\}([^%]+)%], '\\1' | |
|
76 | ||
|
77 | # replaces non word caracters by dashes | |
|
78 | anchor = toc_item.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-') | |
|
79 | ||
|
80 | unless anchor.blank? | |
|
81 | if tag =~ /^h(\d)$/ | |
|
82 | @toc << [$1.to_i, anchor, toc_item] | |
|
83 | end | |
|
84 | atts << " id=\"#{anchor}\"" | |
|
85 | content = content + "<a href=\"##{anchor}\" class=\"wiki-anchor\">¶</a>" | |
|
86 | end | |
|
87 | textile_p(tag, atts, cite, content) | |
|
88 | end | |
|
89 | ||
|
90 | alias :textile_h1 :textile_p_withtoc | |
|
91 | alias :textile_h2 :textile_p_withtoc | |
|
92 | alias :textile_h3 :textile_p_withtoc | |
|
93 | ||
|
94 | def inline_toc(text) | |
|
95 | text.gsub!(/<p>\{\{([<>]?)toc\}\}<\/p>/i) do | |
|
96 | div_class = 'toc' | |
|
97 | div_class << ' right' if $1 == '>' | |
|
98 | div_class << ' left' if $1 == '<' | |
|
99 | out = "<ul class=\"#{div_class}\">" | |
|
100 | @toc.each do |heading| | |
|
101 | level, anchor, toc_item = heading | |
|
102 | out << "<li class=\"heading#{level}\"><a href=\"##{anchor}\">#{toc_item}</a></li>\n" | |
|
103 | end | |
|
104 | out << '</ul>' | |
|
105 | out | |
|
106 | end | |
|
107 | end | |
|
108 | ||
|
109 | 64 | AUTO_LINK_RE = %r{ |
|
110 | 65 | ( # leading text |
|
111 | 66 | <\w+.*?>| # leading HTML tag, or |
@@ -1,5 +1,5 | |||
|
1 | 1 | # Redmine - project management software |
|
2 |
# Copyright (C) 2006-200 |
|
|
2 | # Copyright (C) 2006-2010 Jean-Philippe Lang | |
|
3 | 3 | # |
|
4 | 4 | # This program is free software; you can redistribute it and/or |
|
5 | 5 | # modify it under the terms of the GNU General Public License |
@@ -422,6 +422,8 Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor. | |||
|
422 | 422 | h2. Subtitle with [[Wiki|another Wiki]] link |
|
423 | 423 | |
|
424 | 424 | h2. Subtitle with %{color:red}red text% |
|
425 | ||
|
426 | h2. Subtitle with *some* _modifiers_ | |
|
425 | 427 | |
|
426 | 428 | h1. Another title |
|
427 | 429 | |
@@ -436,11 +438,31 RAW | |||
|
436 | 438 | '<li class="heading2"><a href="#Subtitle-with-a-Wiki-link">Subtitle with a Wiki link</a></li>' + |
|
437 | 439 | '<li class="heading2"><a href="#Subtitle-with-another-Wiki-link">Subtitle with another Wiki link</a></li>' + |
|
438 | 440 | '<li class="heading2"><a href="#Subtitle-with-red-text">Subtitle with red text</a></li>' + |
|
441 | '<li class="heading2"><a href="#Subtitle-with-some-modifiers">Subtitle with some modifiers</a></li>' + | |
|
439 | 442 | '<li class="heading1"><a href="#Another-title">Another title</a></li>' + |
|
440 | 443 | '<li class="heading2"><a href="#An-Internet-link-inside-subtitle">An Internet link inside subtitle</a></li>' + |
|
441 | 444 | '<li class="heading2"><a href="#Project-Name">Project Name</a></li>' + |
|
442 | 445 | '</ul>' |
|
443 | 446 | |
|
447 | @project = Project.find(1) | |
|
448 | assert textilizable(raw).gsub("\n", "").include?(expected) | |
|
449 | end | |
|
450 | ||
|
451 | def test_table_of_content_should_contain_included_page_headings | |
|
452 | raw = <<-RAW | |
|
453 | {{toc}} | |
|
454 | ||
|
455 | h1. Included | |
|
456 | ||
|
457 | {{include(Child_1)}} | |
|
458 | RAW | |
|
459 | ||
|
460 | expected = '<ul class="toc">' + | |
|
461 | '<li class="heading1"><a href="#Included">Included</a></li>' + | |
|
462 | '<li class="heading1"><a href="#Child-page-1">Child page 1</a></li>' + | |
|
463 | '</ul>' | |
|
464 | ||
|
465 | @project = Project.find(1) | |
|
444 | 466 | assert textilizable(raw).gsub("\n", "").include?(expected) |
|
445 | 467 | end |
|
446 | 468 |
@@ -20,6 +20,9 require File.dirname(__FILE__) + '/../../../../test_helper' | |||
|
20 | 20 | class Redmine::WikiFormatting::MacrosTest < HelperTestCase |
|
21 | 21 | include ApplicationHelper |
|
22 | 22 | include ActionView::Helpers::TextHelper |
|
23 | include ActionView::Helpers::SanitizeHelper | |
|
24 | extend ActionView::Helpers::SanitizeHelper::ClassMethods | |
|
25 | ||
|
23 | 26 | fixtures :projects, :roles, :enabled_modules, :users, |
|
24 | 27 | :repositories, :changesets, |
|
25 | 28 | :trackers, :issue_statuses, :issues, |
General Comments 0
You need to be logged in to leave comments.
Login now