diff --git a/lib/redmine/wiki_formatting/macros.rb b/lib/redmine/wiki_formatting/macros.rb index 9ef4ffd06..701b22c4e 100644 --- a/lib/redmine/wiki_formatting/macros.rb +++ b/lib/redmine/wiki_formatting/macros.rb @@ -202,14 +202,48 @@ module Redmine desc "Includes a wiki page. Examples:\n\n" + "{{include(Foo)}}\n" + + "{{include(Foo, section)}} -- to include a spacific section of Foo page\n" + "{{include(projectname:Foo)}} -- to include a page of a specific project wiki" macro :include do |obj, args| - page = Wiki.find_page(args.first.to_s, :project => @project) + title, section_name = args[0], args[1] + page = Wiki.find_page(title, :project => @project) raise 'Page not found' if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project) @included_wiki_pages ||= [] - raise 'Circular inclusion detected' if @included_wiki_pages.include?(page.id) - @included_wiki_pages << page.id - out = textilizable(page.content, :text, :attachments => page.attachments, :headings => false) + + if section_name + regex = nil + case Setting.text_formatting + when "textile" + regex = '(?:\A|\r?\n\s*\r?\n)h\d+\.[ \t]+(.*?)(?=\r?\n\s*\r?\n|\z)' + when "markdown" + regex = '(?:\A|\r?\n)#+ +(.*?)(?=\r?\n|\z)' + end + + section_index = 0 + if regex + page.content.text.scan(/#{regex}/m).each.with_index(1) do |matched, i| + if matched.first.gsub(/[\r?\n]/, '') == section_name + section_index = i + break + end + end + end + + section_text = nil + if section_index > 0 && Redmine::WikiFormatting.supports_section_edit? + section_text, _hash = Redmine::WikiFormatting.formatter.new(page.content.text).get_section(section_index) + end + + raise 'Section not found' if section_text.nil? + included_key = "#{page.id}:#{section_index}" + raise 'Circular inclusion detected' if @included_wiki_pages.include?(page.id) || @included_wiki_pages.include?(included_key) + @included_wiki_pages << included_key + out = textilizable(section_text, :attachments => page.attachments, :headings => false) + else + raise 'Circular inclusion detected' if @included_wiki_pages.include?(page.id) + @included_wiki_pages << page.id + out = textilizable(page.content, :text, :attachments => page.attachments, :headings => false) + end @included_wiki_pages.pop out end diff --git a/test/unit/lib/redmine/wiki_formatting/macros_test.rb b/test/unit/lib/redmine/wiki_formatting/macros_test.rb index 7b0dfa6da..f1e9ede2b 100644 --- a/test/unit/lib/redmine/wiki_formatting/macros_test.rb +++ b/test/unit/lib/redmine/wiki_formatting/macros_test.rb @@ -194,6 +194,15 @@ class Redmine::WikiFormatting::MacrosTest < Redmine::HelperTest text = "{{include(Another page)}}" assert_include 'This is a link to a ticket', textilizable(text) + # include a content of a spacific section + text = "{{include(Page_with_sections, Heading 1)}}" + assert_not_include 'Title', textilizable(text) + assert_include 'Heading 1', textilizable(text) + assert_not_include 'Heading 2', textilizable(text) + + text = "{{include(Page_with_sections, Heading 3)}}" + assert_include 'Section not found', textilizable(text) + @project = nil # include a page of a specific project wiki text = "{{include(ecookbook:Another page)}}"