-# redMine - project management software
-# Copyright (C) 2006-2007 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2010 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
text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr) { |macro, args| exec_macro(macro, obj, args) }
parse_non_pre_blocks(text) do |text|
- [:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links].each do |method_name|
+ [:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links, :parse_headings].each do |method_name|
send method_name, text, project, obj, attr, only_path, options
end
end
leading + (link || "#{prefix}#{sep}#{identifier}")
end
end
+
+ TOC_RE = /<p>\{\{([<>]?)toc\}\}<\/p>/i unless const_defined?(:TOC_RE)
+ HEADING_RE = /<h(1|2|3)( [^>]+)?>(.+?)<\/h(1|2|3)>/i unless const_defined?(:HEADING_RE)
+
+ # Headings and TOC
+ # Adds ids and links to headings and renders the TOC if needed unless options[:headings] is set to false
+ def parse_headings(text, project, obj, attr, only_path, options)
+ headings = []
+ text.gsub!(HEADING_RE) do
+ level, attrs, content = $1, $2, $3
+ item = strip_tags(content).strip
+ anchor = item.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-')
+ headings << [level, anchor, item]
+ "<h#{level} #{attrs} id=\"#{anchor}\">#{content}<a href=\"##{anchor}\" class=\"wiki-anchor\">¶</a></h#{level}>"
+ end unless options[:headings] == false
+
+ text.gsub!(TOC_RE) do
+ if headings.empty?
+ ''
+ else
+ div_class = 'toc'
+ div_class << ' right' if $1 == '>'
+ div_class << ' left' if $1 == '<'
+ out = "<ul class=\"#{div_class}\">"
+ headings.each do |level, anchor, item|
+ out << "<li class=\"heading#{level}\"><a href=\"##{anchor}\">#{item}</a></li>\n"
+ end
+ out << '</ul>'
+ out
+ end
+ end
+ end
# Same as Rails' simple_format helper without using paragraphs
def simple_format_without_paragraph(text)
@included_wiki_pages ||= []
raise 'Circular inclusion detected' if @included_wiki_pages.include?(page.title)
@included_wiki_pages << page.title
- out = textilizable(page.content, :text, :attachments => page.attachments)
+ out = textilizable(page.content, :text, :attachments => page.attachments, :headings => false)
@included_wiki_pages.pop
out
end
# Redmine - project management software
-# Copyright (C) 2006-2008 Jean-Philippe Lang
+# Copyright (C) 2006-2010 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
include ActionView::Helpers::TagHelper
# 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]
+ RULES = [:textile, :block_markdown_rule, :inline_auto_link, :inline_auto_mailto]
def initialize(*args)
super
end
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(/(\[\[([^\]\|]*)(\|([^\]]*))?\]\])/) { $4 || $2 }
- # sanitizes titles from links
- # see redcloth3.rb, same as "#{pre}#{text}#{post}"
- toc_item.gsub!(LINK_RE) { [$2, $4, $9].join }
- # sanitizes image links from titles
- toc_item.gsub!(IMAGE_RE) { [$5].join }
- # removes styles
- # eg. %{color:red}Triggers% => Triggers
- toc_item.gsub! %r[%\{[^\}]*\}([^%]+)%], '\\1'
-
- # 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\">¶</a>"
- 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
- end
- end
-
AUTO_LINK_RE = %r{
( # leading text
<\w+.*?>| # leading HTML tag, or
# Redmine - project management software
-# Copyright (C) 2006-2009 Jean-Philippe Lang
+# Copyright (C) 2006-2010 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
h2. Subtitle with [[Wiki|another Wiki]] link
h2. Subtitle with %{color:red}red text%
+
+h2. Subtitle with *some* _modifiers_
h1. Another title
'<li class="heading2"><a href="#Subtitle-with-a-Wiki-link">Subtitle with a Wiki link</a></li>' +
'<li class="heading2"><a href="#Subtitle-with-another-Wiki-link">Subtitle with another Wiki link</a></li>' +
'<li class="heading2"><a href="#Subtitle-with-red-text">Subtitle with red text</a></li>' +
+ '<li class="heading2"><a href="#Subtitle-with-some-modifiers">Subtitle with some modifiers</a></li>' +
'<li class="heading1"><a href="#Another-title">Another title</a></li>' +
'<li class="heading2"><a href="#An-Internet-link-inside-subtitle">An Internet link inside subtitle</a></li>' +
'<li class="heading2"><a href="#Project-Name">Project Name</a></li>' +
'</ul>'
+ @project = Project.find(1)
+ assert textilizable(raw).gsub("\n", "").include?(expected)
+ end
+
+ def test_table_of_content_should_contain_included_page_headings
+ raw = <<-RAW
+{{toc}}
+
+h1. Included
+
+{{include(Child_1)}}
+RAW
+
+ expected = '<ul class="toc">' +
+ '<li class="heading1"><a href="#Included">Included</a></li>' +
+ '<li class="heading1"><a href="#Child-page-1">Child page 1</a></li>' +
+ '</ul>'
+
+ @project = Project.find(1)
assert textilizable(raw).gsub("\n", "").include?(expected)
end
class Redmine::WikiFormatting::MacrosTest < HelperTestCase
include ApplicationHelper
include ActionView::Helpers::TextHelper
+ include ActionView::Helpers::SanitizeHelper
+ extend ActionView::Helpers::SanitizeHelper::ClassMethods
+
fixtures :projects, :roles, :enabled_modules, :users,
:repositories, :changesets,
:trackers, :issue_statuses, :issues,