end
MACROS_RE = /
+ (!)? # escaping
+ (
\{\{ # opening tag
([\w]+) # macro name
(\(([^\}]*)\))? # optional arguments
\}\} # closing tag
+ )
/x unless const_defined?(:MACROS_RE)
def inline_macros(text)
text.gsub!(MACROS_RE) do
- all, macro = $&, $1.downcase
- args = ($3 || '').split(',').each(&:strip)
- begin
- @macros_runner.call(macro, args)
- rescue => e
- "<div class=\"flash error\">Error executing the <strong>#{macro}</strong> macro (#{e})</div>"
- end || all
+ esc, all, macro = $1, $2, $3.downcase
+ args = ($5 || '').split(',').each(&:strip)
+ if esc.nil?
+ begin
+ @macros_runner.call(macro, args)
+ rescue => e
+ "<div class=\"flash error\">Error executing the <strong>#{macro}</strong> macro (#{e})</div>"
+ end || all
+ else
+ all
+ end
end
end
end
# Builtin macros
- desc "Example macro."
+ desc "Sample macro."
macro :hello_world do |obj, args|
"Hello world! Object: #{obj.class.name}, " + (args.empty? ? "Called with no argument." : "Arguments: #{args.join(', ')}")
end
out = ''
@@available_macros.keys.collect(&:to_s).sort.each do |macro|
out << content_tag('dt', content_tag('code', macro))
- out << content_tag('dd', simple_format(@@available_macros[macro.to_sym]))
+ out << content_tag('dd', textilizable(@@available_macros[macro.to_sym]))
end
content_tag('dl', out)
end
+
+ desc "Include a wiki page. Example:\n\n !{{include(Foo)}}"
+ macro :include do |obj, args|
+ if @project && !@project.wiki.nil?
+ page = @project.wiki.find_page(args.first)
+ if page && page.content
+ @included_wiki_pages ||= []
+ raise 'Circular inclusion detected' if @included_wiki_pages.include?(page.title)
+ @included_wiki_pages << page.title
+ out = textilizable(page.content, :text)
+ @included_wiki_pages.pop
+ out
+ else
+ raise "Page #{args.first} doesn't exist"
+ end
+ end
+ end
end
end
end
def test_macro_hello_world
text = "{{hello_world}}"
assert textilizable(text).match(/Hello world!/)
+ # escaping
+ text = "!{{hello_world}}"
+ assert_equal '<p>{{hello_world}}</p>', textilizable(text)
end
def test_date_format_default