diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt index 804d65c..9512271 100644 --- a/COPYRIGHT.txt +++ b/COPYRIGHT.txt @@ -2,8 +2,13 @@ Redmine Wiki External Filter plugin that allows to filter macro blocks arguments using external program and display results on wiki. Copyright (C) 2010 Alexander Tsvyashchenko, http://www.ndl.kiev.ua -Based on wiki_latex_plugin by Nils Israel -Based on wiki_graphviz_plugin by tckz + +* Based on wiki_latex_plugin by Nils Israel +* Based on wiki_graphviz_plugin by tckz +* Includes FlowPlayer flash player, see http://www.flowplayer.org +* Includes CSS Browser Selector, see http://rafael.adm.br/css_browser_selector/ +* Thanks to Eike for his "Cross-Browser SVG Issues" article, + http://e.metaclarity.org/52/cross-browser-svg-issues/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/app/controllers/wiki_external_filter_controller.rb b/app/controllers/wiki_external_filter_controller.rb index 94a25bd..af0e553 100644 --- a/app/controllers/wiki_external_filter_controller.rb +++ b/app/controllers/wiki_external_filter_controller.rb @@ -13,7 +13,7 @@ class WikiExternalFilterController < ApplicationController content = read_fragment cache_key if (content) - send_data content[index], :type => config[macro]['content_type'], :disposition => 'inline', :filename => filename + send_data content[index], :type => config[macro]['outputs'][index]['content_type'], :disposition => 'inline', :filename => filename else render_404 end diff --git a/app/helpers/wiki_external_filter_helper.rb b/app/helpers/wiki_external_filter_helper.rb index 431a93f..d65bf41 100644 --- a/app/helpers/wiki_external_filter_helper.rb +++ b/app/helpers/wiki_external_filter_helper.rb @@ -47,7 +47,6 @@ module WikiExternalFilterHelper if content result[:source] = text result[:content] = content - result[:content_type] = info['content_type'] RAILS_DEFAULT_LOGGER.debug "from cache: #{name}" else result = self.build_forced(text, attachments, info) @@ -63,6 +62,8 @@ module WikiExternalFilterHelper result[:name] = name result[:macro] = macro + result[:content_types] = info['outputs'].map { |out| out['content_type'] } + result[:template] = info['template'] return result end @@ -79,18 +80,16 @@ module WikiExternalFilterHelper content = [] errors = "" - commands = info['commands']? info['commands'] : [info['command']] - - commands.each do |command| - RAILS_DEFAULT_LOGGER.info "executing command: #{command}" + info['outputs'].each do |out| + RAILS_DEFAULT_LOGGER.info "executing command: #{out['command']}" c = nil e = nil - Open4::popen4(command) { |pid, fin, fout, ferr| - fin.write info[:prolog] if info.key?(:prolog) + Open4::popen4(out['command']) { |pid, fin, fout, ferr| + fin.write out['prolog'] if out.key?('prolog') fin.write CGI.unescapeHTML(text) - fin.write info[:epilog] if info.key?(:epilog) + fin.write out['epilog'] if out.key?('epilog') fin.close c, e = [fout.read, ferr.read] } @@ -103,7 +102,6 @@ module WikiExternalFilterHelper result[:content] = content result[:errors] = errors - result[:content_type] = info['content_type'] result[:source] = text result[:status] = $?.exitstatus == 0 @@ -111,21 +109,35 @@ module WikiExternalFilterHelper end def render_tag(result) - render_to_string :template => 'wiki_external_filter/macro_inline', :layout => false, :locals => result + result = result.dup + result[:render_type] = 'inline' + html = render_common(result).chop + html << headers_common(result).chop + html end def render_block(result, wiki_name) result = result.dup + result[:render_type] = 'block' result[:wiki_name] = wiki_name - render_to_string :template => 'wiki_external_filter/macro_block', :layout => false, :locals => result + result[:inside] = render_common(result) + html = render_to_string(:template => 'wiki_external_filter/block', :layout => false, :locals => result).chop + html << headers_common(result).chop + html + end + + def render_common(result) + render_to_string :template => "wiki_external_filter/macro_#{result[:template]}", :layout => false, :locals => result + end + + def headers_common(result) + render_to_string :template => 'wiki_external_filter/headers', :layout => false, :locals => result end class Macro def initialize(view, source, attachments, macro, info) @view = view @view.controller.extend(WikiExternalFilterHelper) - source.gsub!(/
/, "") - source.gsub!(/<\/?p>/, "") @result = @view.controller.build(source, attachments, macro, info) end diff --git a/app/views/wiki_external_filter/block.html.erb b/app/views/wiki_external_filter/block.html.erb new file mode 100644 index 0000000..d613651 --- /dev/null +++ b/app/views/wiki_external_filter/block.html.erb @@ -0,0 +1,5 @@ +
+ <%= inside %> +
+ Goto source: [[<%= wiki_name %>]] +
diff --git a/app/views/wiki_external_filter/headers.html.erb b/app/views/wiki_external_filter/headers.html.erb new file mode 100644 index 0000000..8354618 --- /dev/null +++ b/app/views/wiki_external_filter/headers.html.erb @@ -0,0 +1,10 @@ +<% + content_for :header_tags do + if not @stylesheets_included + @stylesheets_included = true +%> + <%= stylesheet_link_tag "wiki_external_filter.css", :plugin => "wiki_external_filter", :media => :all %> +<% + end + end +%> diff --git a/app/views/wiki_external_filter/macro_block.html.erb b/app/views/wiki_external_filter/macro_block.html.erb deleted file mode 100644 index 03f3949..0000000 --- a/app/views/wiki_external_filter/macro_block.html.erb +++ /dev/null @@ -1,64 +0,0 @@ -
-<% - case content_type - when /image\// then -%> - 'filter', :macro => macro, :name => name) %>' alt="<%= h source %>" /> -<% - when /text\/plain/ then -%> -
<%= h content %>
-<% - when /\/.*(x|ht)ml/ then -%> -
<%= content %>
-<% - when /video\/x\-flv/ then - require 'RMagick' - image = Magick::Image::from_blob(content[0]).first -%> - 'filter', :macro => macro, :name => name, :index => 0) %>);background-repeat:no-repeat'><%= image_tag 'play_large.png', :plugin => 'wiki_external_filter', :style => "display:block;position:relative;left:#{image.columns / 2 - 83 / 2}px;top:#{image.rows / 2 - 83 / 2}px" %> -<% - @flowplayer_used = true -%> -<% - else -%> - 'filter', :macro => macro, :name => name) %>' type='<%= content_type %>' title="<%= h source %>"> - 'filter', :macro => macro, :name => name) %>' type='<%= content_type %>' title="<%= h source %>" /> - -<% - end -%> -
- Goto source: [[<%= wiki_name %>]] -
-<% - content_for :header_tags do -%> -<% - if not @stylesheets_included - @stylesheets_included = true -%> - <%= stylesheet_link_tag "wiki_external_filter.css", :plugin => "wiki_external_filter", :media => :all %> -<% - end -%> -<% - if @flowplayer_used - if not @flowplayer_scripts_included - @flowplayer_scripts_included = true -%> - <%= javascript_include_tag 'flowplayer.min.js', :plugin => 'wiki_external_filter' %> - -<% - end - end - end -%> diff --git a/app/views/wiki_external_filter/macro_flash-video.html.erb b/app/views/wiki_external_filter/macro_flash-video.html.erb new file mode 100644 index 0000000..d390975 --- /dev/null +++ b/app/views/wiki_external_filter/macro_flash-video.html.erb @@ -0,0 +1,22 @@ +<% + require 'RMagick' + image = Magick::Image::from_blob(content[0]).first +%> + ' href='<%= ActionController::Base.relative_url_root + "/wiki_external_filter/#{macro}.flv?name=#{name}" %>' title='<%= h source %>' style='display:block;width:<%= image.columns %>px;height:<%= image.rows + 24 %>px;background-image:url(<%= url_for(:controller => 'wiki_external_filter', :action => 'filter', :macro => macro, :name => name, :index => 0) %>);background-repeat:no-repeat'><%= image_tag 'play_large.png', :plugin => 'wiki_external_filter', :style => "display:block;position:relative;left:#{image.columns / 2 - 83 / 2}px;top:#{image.rows / 2 - 83 / 2}px" %> +<% + content_for :header_tags do + if not @flowplayer_scripts_included + @flowplayer_scripts_included = true +%> + <%= javascript_include_tag 'flowplayer.min.js', :plugin => 'wiki_external_filter' %> + +<% + end + end +%> diff --git a/app/views/wiki_external_filter/macro_image.html.erb b/app/views/wiki_external_filter/macro_image.html.erb new file mode 100644 index 0000000..dfb52fd --- /dev/null +++ b/app/views/wiki_external_filter/macro_image.html.erb @@ -0,0 +1 @@ + src='<%= url_for(:controller => 'wiki_external_filter', :action => 'filter', :macro => macro, :name => name, :index => 0) %>' alt="<%= h source %>" /> diff --git a/app/views/wiki_external_filter/macro_inline.html.erb b/app/views/wiki_external_filter/macro_inline.html.erb deleted file mode 100644 index 8dd3c2f..0000000 --- a/app/views/wiki_external_filter/macro_inline.html.erb +++ /dev/null @@ -1,61 +0,0 @@ -<% - case content_type - when /image\// then -%> - 'filter', :macro => macro, :name => name, :index => 0) %>' alt="<%= h source %>" /> -<% - when /text\/plain/ then -%> -
<%= h content[0] %>
-<% - when /\/.*(x|ht)ml/ then -%> -
<%= content[0] %>
-<% - when /video\/x\-flv/ then - require 'RMagick' - image = Magick::Image::from_blob(content[0]).first -%> - 'filter', :macro => macro, :name => name, :index => 0) %>);background-repeat:no-repeat'><%= image_tag 'play_large.png', :plugin => 'wiki_external_filter', :style => "display:block;position:relative;left:#{image.columns / 2 - 83 / 2}px;top:#{image.rows / 2 - 83 / 2}px" %> - -<% - @flowplayer_used = true -%> -<% - else -%> - 'filter', :macro => macro, :name => name, :index => 0) %>' type='<%= content_type %>' title="<%= h source %>"> - 'filter', :macro => macro, :name => name, :index => 0) %>' type='<%= content_type %>' title="<%= h source %>" /> - -<% - end -%> -<% - content_for :header_tags do -%> -<% - if not @stylesheets_included - @stylesheets_included = true -%> - <%= stylesheet_link_tag "wiki_external_filter.css", :plugin => "wiki_external_filter", :media => :all %> -<% - end -%> -<% - if @flowplayer_used - if not @flowplayer_scripts_included - @flowplayer_scripts_included = true -%> - <%= javascript_include_tag 'flowplayer.min.js', :plugin => 'wiki_external_filter' %> - -<% - end - end - end -%> diff --git a/app/views/wiki_external_filter/macro_svg.html.erb b/app/views/wiki_external_filter/macro_svg.html.erb new file mode 100644 index 0000000..ee9f751 --- /dev/null +++ b/app/views/wiki_external_filter/macro_svg.html.erb @@ -0,0 +1,27 @@ +' src='<%= url_for(:controller => 'wiki_external_filter', :action => 'filter', :macro => macro, :name => name, :index => 0) %>' alt='<%= h source %>' /> +' name='<%= name %>' data='<%= url_for(:controller => 'wiki_external_filter', :action => 'filter', :macro => macro, :name => name, :index => 0) %>' type='<%= content_types[0] %>' title="<%= h source %>"> +<% + if content.size > 1 +%> + src='<%= url_for(:controller => 'wiki_external_filter', :action => 'filter', :macro => macro, :name => name, :index => 1) %>' alt='<%= h source %>' /> +<% + end +%> + +<% + content_for :header_tags do + if not @svg_scripts_included + @svg_scripts_included = true +%> + <%= javascript_include_tag 'css_browser_selector.js', :plugin => 'wiki_external_filter' %> + +<% + end + end +%> diff --git a/app/views/wiki_external_filter/macro_text.html.erb b/app/views/wiki_external_filter/macro_text.html.erb new file mode 100644 index 0000000..a1628b4 --- /dev/null +++ b/app/views/wiki_external_filter/macro_text.html.erb @@ -0,0 +1 @@ +><%= h content[0] %> diff --git a/assets/javascripts/css_browser_selector.js b/assets/javascripts/css_browser_selector.js new file mode 100644 index 0000000..324b03b --- /dev/null +++ b/assets/javascripts/css_browser_selector.js @@ -0,0 +1,8 @@ +/* +CSS Browser Selector v0.3.5 (Feb 05, 2010) +Rafael Lima (http://rafael.adm.br) +http://rafael.adm.br/css_browser_selector +License: http://creativecommons.org/licenses/by/2.5/ +Contributors: http://rafael.adm.br/css_browser_selector#contributors +*/ +function css_browser_selector(u){var ua = u.toLowerCase(),is=function(t){return ua.indexOf(t)>-1;},g='gecko',w='webkit',s='safari',o='opera',h=document.documentElement,b=[(!(/opera|webtv/i.test(ua))&&/msie\s(\d)/.test(ua))?('ie ie'+RegExp.$1):is('firefox/2')?g+' ff2':is('firefox/3.5')?g+' ff3 ff3_5':is('firefox/3')?g+' ff3':is('gecko/')?g:is('opera')?o+(/version\/(\d+)/.test(ua)?' '+o+RegExp.$1:(/opera(\s|\/)(\d+)/.test(ua)?' '+o+RegExp.$2:'')):is('konqueror')?'konqueror':is('chrome')?w+' chrome':is('iron')?w+' iron':is('applewebkit/')?w+' '+s+(/version\/(\d+)/.test(ua)?' '+s+RegExp.$1:''):is('mozilla/')?g:'',is('j2me')?'mobile':is('iphone')?'iphone':is('ipod')?'ipod':is('mac')?'mac':is('darwin')?'mac':is('webtv')?'webtv':is('win')?'win':is('freebsd')?'freebsd':(is('x11')||is('linux'))?'linux':'','js']; c = b.join(' '); h.className += ' '+c; return c;}; css_browser_selector(navigator.userAgent); diff --git a/config/routes.rb b/config/routes.rb index 545be92..db7d3d4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,4 @@ ActionController::Routing::Routes.draw do |map| - map.connect 'wiki_external_filter/:filename', :controller => 'wiki_external_filter', :action => 'filter', :macro => 'flowplayer', :index => '1', :requirements => { :filename => /\S+\.flv/ } + map.connect 'wiki_external_filter/:filename', :controller => 'wiki_external_filter', :action => 'filter', :macro => 'video', :index => '1', :requirements => { :filename => /video\.flv/ } + map.connect 'wiki_external_filter/:filename', :controller => 'wiki_external_filter', :action => 'filter', :macro => 'video_url', :index => '1', :requirements => { :filename => /video_url\.flv/ } end diff --git a/config/wiki_external_filter.yml b/config/wiki_external_filter.yml index 729e42e..e938a91 100644 --- a/config/wiki_external_filter.yml +++ b/config/wiki_external_filter.yml @@ -1,28 +1,54 @@ development: &development plantuml: description: "Constructs UML diagram image from its textual description in PlantUML language, see http://plantuml.sourceforge.net" - command: "/usr/bin/plantuml -pipe" - content_type: "image/png" - prolog: "@startuml" - epilog: "@enduml" + template: image + outputs: + - command: "/usr/bin/plantuml -pipe" + content_type: "image/png" + prolog: "@startuml" + epilog: "@enduml" graphviz: description: "Constructs graph image from its textual description in DOT language, see http://www.graphviz.org" - command: "/usr/bin/dot -Tsvg" - content_type: "image/svg+xml" + template: svg + outputs: + - command: "/usr/bin/dot -Tsvg" + content_type: "image/svg+xml" + - command: "/usr/bin/dot -Tpng" + content_type: "image/png" ritex: description: "Converts WebTeX expression to MathML, see http://ritex.rubyforge.org/" - command: "(echo ''; /usr/bin/ritex) | xmllint --noent --nonet --catalogs --loaddtd - | sed 's/^'; /usr/bin/ritex) | xmllint --noent --nonet --catalogs --loaddtd - | sed 's/^