|
|
|
@ -29,57 +29,57 @@ |
|
|
|
|
|
|
|
|
|
module OpenProject::TextFormatting::Formatters |
|
|
|
|
module Textile |
|
|
|
|
module LegacyTextFormatting |
|
|
|
|
class LegacyTextFormatting |
|
|
|
|
include Redmine::WikiFormatting::Macros::Definitions |
|
|
|
|
include ActionView::Helpers::SanitizeHelper |
|
|
|
|
include ERB::Util # for h() |
|
|
|
|
include Redmine::I18n |
|
|
|
|
# used for the work package quick links |
|
|
|
|
include WorkPackagesHelper |
|
|
|
|
# Used for escaping helper 'h()' |
|
|
|
|
include ERB::Util |
|
|
|
|
# Rails helper |
|
|
|
|
include ActionView::Helpers::TagHelper |
|
|
|
|
include ActionView::Helpers::UrlHelper |
|
|
|
|
include ActionView::Helpers::TextHelper |
|
|
|
|
# For route path helpers |
|
|
|
|
include OpenProject::ObjectLinking |
|
|
|
|
# The WorkPackagesHelper is required to get access to the methods |
|
|
|
|
# 'work_package_css_classes' and 'work_package_quick_info'. |
|
|
|
|
include WorkPackagesHelper |
|
|
|
|
include OpenProject::StaticRouting::UrlHelpers |
|
|
|
|
# Truncation |
|
|
|
|
include OpenProject::TextFormatting::Truncation |
|
|
|
|
|
|
|
|
|
def initialize(project) |
|
|
|
|
@project = project |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
def controller; end |
|
|
|
|
|
|
|
|
|
class << self |
|
|
|
|
# Formats text according to system settings. |
|
|
|
|
# 2 ways to call this method: |
|
|
|
|
# * with a String: format_text(text, options) |
|
|
|
|
# * with an object and one of its attribute: format_text(issue, :description, options) |
|
|
|
|
def format_text(*args) |
|
|
|
|
options = args.last.is_a?(Hash) ? args.pop : {} |
|
|
|
|
case args.size |
|
|
|
|
when 1 |
|
|
|
|
obj = options[:object] |
|
|
|
|
text = args.shift |
|
|
|
|
when 2 |
|
|
|
|
obj = args.shift |
|
|
|
|
attr = args.shift |
|
|
|
|
text = obj.send(attr).to_s |
|
|
|
|
else |
|
|
|
|
raise ArgumentError, 'invalid arguments to format_text' |
|
|
|
|
end |
|
|
|
|
return '' if text.blank? |
|
|
|
|
|
|
|
|
|
def format_text(text, options) |
|
|
|
|
edit = !!options[:edit] |
|
|
|
|
# don't return html in edit mode when textile or text formatting is enabled |
|
|
|
|
return text if edit |
|
|
|
|
project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil) |
|
|
|
|
|
|
|
|
|
object = options[:object] |
|
|
|
|
project = options[:project] |
|
|
|
|
only_path = options.delete(:only_path) != false |
|
|
|
|
|
|
|
|
|
# offer 'plain' as readable version for 'no formatting' to callers |
|
|
|
|
format = options[:format] == 'plain' ? '' : options[:format] |
|
|
|
|
format = options.delete(:format) { :textile } |
|
|
|
|
text = OpenProject::TextFormatting::Formatters.formatter_for(format).new(text).to_html |
|
|
|
|
|
|
|
|
|
# TODO: transform modifications into WikiFormatting Helper, or at least ask the helper if he wants his stuff to be modified |
|
|
|
|
@parsed_headings = [] |
|
|
|
|
text = parse_non_pre_blocks(text) { |text| |
|
|
|
|
[:execute_macros, :parse_inline_attachments, :parse_wiki_links, :parse_redmine_links, :parse_headings, :parse_relative_urls].each do |method_name| |
|
|
|
|
send method_name, text, project, obj, attr, only_path, options |
|
|
|
|
send method_name, text, project, object, options[:attribute], only_path, options |
|
|
|
|
end |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if @parsed_headings.any? |
|
|
|
|
replace_toc(text, @parsed_headings) |
|
|
|
|
replace_toc(text, @parsed_headings, options) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
escape_non_macros(text) |
|
|
|
@ -452,7 +452,7 @@ module OpenProject::TextFormatting::Formatters |
|
|
|
|
tocitem = strip_tags(content.gsub(/<br \/>/, ' ')) |
|
|
|
|
anchor = item.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-') |
|
|
|
|
@parsed_headings << [level, anchor, tocitem] |
|
|
|
|
url = full_url(anchor) |
|
|
|
|
url = full_url(anchor, options[:request]) |
|
|
|
|
"<a name=\"#{anchor}\"></a>\n<h#{level} #{attrs}>#{content}<a href=\"#{url}\" class=\"wiki-anchor\">¶</a></h#{level}>" |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
@ -460,7 +460,7 @@ module OpenProject::TextFormatting::Formatters |
|
|
|
|
TOC_RE = /<p>\{\{([<>]?)toc\}\}<\/p>/i unless const_defined?(:TOC_RE) |
|
|
|
|
|
|
|
|
|
# Renders the TOC with given headings |
|
|
|
|
def replace_toc(text, headings) |
|
|
|
|
def replace_toc(text, headings, options) |
|
|
|
|
text.gsub!(TOC_RE) do |
|
|
|
|
if headings.empty? |
|
|
|
|
'' |
|
|
|
@ -488,7 +488,7 @@ module OpenProject::TextFormatting::Formatters |
|
|
|
|
elsif started |
|
|
|
|
out << '</li><li>' |
|
|
|
|
end |
|
|
|
|
url = full_url anchor |
|
|
|
|
url = full_url(anchor, options[:request]) |
|
|
|
|
out << "<a href=\"#{url}\">#{item}</a>" |
|
|
|
|
current = level |
|
|
|
|
started = true |
|
|
|
@ -503,17 +503,12 @@ module OpenProject::TextFormatting::Formatters |
|
|
|
|
# |
|
|
|
|
# displays the current url plus an optional anchor |
|
|
|
|
# |
|
|
|
|
def full_url(anchor_name = '') |
|
|
|
|
def full_url(anchor_name = '', current_request = nil) |
|
|
|
|
return "##{anchor_name}" if current_request.nil? |
|
|
|
|
current = request.original_fullpath |
|
|
|
|
current = current_request.original_fullpath |
|
|
|
|
return current if anchor_name.blank? |
|
|
|
|
"#{current}##{anchor_name}" |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
def current_request |
|
|
|
|
request rescue nil |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|