diff -urN redmine-1.3.0/app/helpers/application_helper.rb redmine-1.3.0_macros_escaping/app/helpers/application_helper.rb --- redmine-1.3.0/app/helpers/application_helper.rb 2011-12-10 16:53:33.000000000 +0200 +++ redmine-1.3.0_macros_escaping/app/helpers/application_helper.rb 2011-12-27 00:21:55.751959515 +0200 @@ -19,6 +19,7 @@ require 'forwardable' require 'cgi' +require 'digest/md5' module ApplicationHelper include Redmine::WikiFormatting::Macros::Definitions @@ -487,6 +488,8 @@ project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil) only_path = options.delete(:only_path) == false ? false : true + text, macros_grabbed = preprocess_macros(text) + options[:macros_grabbed] = macros_grabbed text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr) @parsed_headings = [] @@ -497,6 +500,10 @@ end end + # Any macros not parsed by this point must be in
blocks - and, hence, should be
+ # restored to their original state.
+ restore_macros(text, macros_grabbed) unless text.nil?
+
if @parsed_headings.any?
replace_toc(text, @parsed_headings)
end
@@ -788,16 +795,35 @@
(
\{\{ # opening tag
([\w]+) # macro name
- (\(([^\}]*)\))? # optional arguments
+ (\((.*?)\))? # optional arguments
\}\} # closing tag
- )
- /x unless const_defined?(:MACROS_RE)
+ )
+ /xm unless const_defined?(:MACROS_RE)
+
+ def preprocess_macros(text)
+ macros_grabbed = {}
+ text = text.gsub(MACROS_RE) do |s|
+ esc, all, macro = $1, $2, $3.downcase
+ if esc.nil? and (WikiExternalFilterHelper.has_macro macro rescue false)
+ args = $5
+ key = Digest::MD5.hexdigest("#{macro}:#{args}")
+ macros_grabbed[key] = {:macro => macro, :args => args, :raw => s}
+ "{{_macros_grabbed(#{key})}}"
+ else
+ s
+ end
+ end
+ [text, macros_grabbed]
+ end
# Macros substitution
def parse_macros(text, project, obj, attr, only_path, options)
text.gsub!(MACROS_RE) do
esc, all, macro = $1, $2, $3.downcase
args = ($5 || '').split(',').each(&:strip)
+ if macro == '_macros_grabbed' and options[:macros_grabbed].member? args.first
+ macro, args = options[:macros_grabbed][args.first].values_at(:macro, :args)
+ end
if esc.nil?
begin
exec_macro(macro, obj, args)
@@ -807,6 +833,18 @@
else
all
end
+ end
+ end
+
+ # Macros restoration to their original state - used for blocks.
+ def restore_macros(text, macros_grabbed)
+ text.gsub!(MACROS_RE) do
+ all, macro, args = $&, $3.downcase, $5
+ if macro == '_macros_grabbed' and macros_grabbed.member? args
+ "#{macros_grabbed[args].values_at(:raw)}"
+ else
+ all
+ end
end
end