diff options
Diffstat (limited to 'actionpack/lib/action_view/helpers/asset_tag_helper.rb')
-rw-r--r-- | actionpack/lib/action_view/helpers/asset_tag_helper.rb | 135 |
1 files changed, 119 insertions, 16 deletions
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index 63b181509a..898da3c7e4 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -1,6 +1,7 @@ require 'cgi' require 'action_view/helpers/url_helper' require 'action_view/helpers/tag_helper' +require 'active_support/core_ext/file' module ActionView module Helpers #:nodoc: @@ -273,17 +274,20 @@ module ActionView # javascript_include_tag :all, :cache => true, :recursive => true def javascript_include_tag(*sources) options = sources.extract_options!.stringify_keys - cache = options.delete("cache") + concat = options.delete("concat") + cache = concat || options.delete("cache") recursive = options.delete("recursive") - if ActionController::Base.perform_caching && cache + if concat || (ActionController::Base.perform_caching && cache) joined_javascript_name = (cache == true ? "all" : cache) + ".js" - joined_javascript_path = File.join(JAVASCRIPTS_DIR, joined_javascript_name) + joined_javascript_path = File.join(joined_javascript_name[/^#{File::SEPARATOR}/] ? ASSETS_DIR : JAVASCRIPTS_DIR, joined_javascript_name) - write_asset_file_contents(joined_javascript_path, compute_javascript_paths(sources, recursive)) unless File.exists?(joined_javascript_path) + unless ActionController::Base.perform_caching && File.exists?(joined_javascript_path) + write_asset_file_contents(joined_javascript_path, compute_javascript_paths(sources, recursive)) + end javascript_src_tag(joined_javascript_name, options) else - expand_javascript_sources(sources, recursive).collect { |source| javascript_src_tag(source, options) }.join("\n") + ensure_javascript_sources!(expand_javascript_sources(sources, recursive)).collect { |source| javascript_src_tag(source, options) }.join("\n") end end @@ -412,19 +416,28 @@ module ActionView # The <tt>:recursive</tt> option is also available for caching: # # stylesheet_link_tag :all, :cache => true, :recursive => true + # + # To force concatenation (even in development mode) set <tt>:concat</tt> to true. This is useful if + # you have too many stylesheets for IE to load. + # + # stylesheet_link_tag :all, :concat => true + # def stylesheet_link_tag(*sources) options = sources.extract_options!.stringify_keys - cache = options.delete("cache") + concat = options.delete("concat") + cache = concat || options.delete("cache") recursive = options.delete("recursive") - if ActionController::Base.perform_caching && cache + if concat || (ActionController::Base.perform_caching && cache) joined_stylesheet_name = (cache == true ? "all" : cache) + ".css" - joined_stylesheet_path = File.join(STYLESHEETS_DIR, joined_stylesheet_name) + joined_stylesheet_path = File.join(joined_stylesheet_name[/^#{File::SEPARATOR}/] ? ASSETS_DIR : STYLESHEETS_DIR, joined_stylesheet_name) - write_asset_file_contents(joined_stylesheet_path, compute_stylesheet_paths(sources, recursive)) unless File.exists?(joined_stylesheet_path) + unless ActionController::Base.perform_caching && File.exists?(joined_stylesheet_path) + write_asset_file_contents(joined_stylesheet_path, compute_stylesheet_paths(sources, recursive)) + end stylesheet_tag(joined_stylesheet_name, options) else - expand_stylesheet_sources(sources, recursive).collect { |source| stylesheet_tag(source, options) }.join("\n") + ensure_stylesheet_sources!(expand_stylesheet_sources(sources, recursive)).collect { |source| stylesheet_tag(source, options) }.join("\n") end end @@ -444,6 +457,21 @@ module ActionView end alias_method :path_to_image, :image_path # aliased to avoid conflicts with an image_path named route + # Computes the path to a video asset in the public videos directory. + # Full paths from the document root will be passed through. + # Used internally by +video_tag+ to build the video path. + # + # ==== Examples + # video_path("hd") # => /videos/hd + # video_path("hd.avi") # => /videos/hd.avi + # video_path("trailers/hd.avi") # => /videos/trailers/hd.avi + # video_path("/trailers/hd.avi") # => /videos/hd.avi + # video_path("http://www.railsapplication.com/vid/hd.avi") # => http://www.railsapplication.com/vid/hd.avi + def video_path(source) + compute_public_path(source, 'videos') + end + alias_method :path_to_video, :video_path # aliased to avoid conflicts with an video_path named route + # Returns an html image tag for the +source+. The +source+ can be a full # path or a file that exists in your public images directory. # @@ -480,8 +508,8 @@ module ActionView def image_tag(source, options = {}) options.symbolize_keys! - options[:src] = path_to_image(source) - options[:alt] ||= File.basename(options[:src], '.*').split('.').first.to_s.capitalize + src = options[:src] = path_to_image(source) + options[:alt] ||= File.basename(src, '.*').split('.').first.to_s.capitalize if size = options.delete(:size) options[:width], options[:height] = size.split("x") if size =~ %r{^\d+x\d+$} @@ -489,12 +517,64 @@ module ActionView if mouseover = options.delete(:mouseover) options[:onmouseover] = "this.src='#{image_path(mouseover)}'" - options[:onmouseout] = "this.src='#{image_path(options[:src])}'" + options[:onmouseout] = "this.src='#{src}'" end tag("img", options) end + # Returns an html video tag for the +sources+. If +sources+ is a string, + # a single video tag will be returned. If +sources+ is an array, a video + # tag with nested source tags for each source will be returned. The + # +sources+ can be full paths or files that exists in your public videos + # directory. + # + # ==== Options + # You can add HTML attributes using the +options+. The +options+ supports + # two additional keys for convenience and conformance: + # + # * <tt>:poster</tt> - Set an image (like a screenshot) to be shown + # before the video loads. The path is calculated like the +src+ of +image_tag+. + # * <tt>:size</tt> - Supplied as "{Width}x{Height}", so "30x45" becomes + # width="30" and height="45". <tt>:size</tt> will be ignored if the + # value is not in the correct format. + # + # ==== Examples + # video_tag("trailer") # => + # <video src="/videos/trailer" /> + # video_tag("trailer.ogg") # => + # <video src="/videos/trailer.ogg" /> + # video_tag("trailer.ogg", :controls => true, :autobuffer => true) # => + # <video autobuffer="autobuffer" controls="controls" src="/videos/trailer.ogg" /> + # video_tag("trailer.m4v", :size => "16x10", :poster => "screenshot.png") # => + # <video src="/videos/trailer.m4v" width="16" height="10" poster="/images/screenshot.png" /> + # video_tag("/trailers/hd.avi", :size => "16x16") # => + # <video src="/trailers/hd.avi" width="16" height="16" /> + # video_tag("/trailers/hd.avi", :height => '32', :width => '32') # => + # <video height="32" src="/trailers/hd.avi" width="32" /> + # video_tag(["trailer.ogg", "trailer.flv"]) # => + # <video><source src="trailer.ogg" /><source src="trailer.ogg" /><source src="trailer.flv" /></video> + # video_tag(["trailer.ogg", "trailer.flv"] :size => "160x120") # => + # <video height="120" width="160"><source src="trailer.ogg" /><source src="trailer.flv" /></video> + def video_tag(sources, options = {}) + options.symbolize_keys! + + options[:poster] = path_to_image(options[:poster]) if options[:poster] + + if size = options.delete(:size) + options[:width], options[:height] = size.split("x") if size =~ %r{^\d+x\d+$} + end + + if sources.is_a?(Array) + content_tag("video", options) do + sources.map { |source| tag("source", :src => source) }.join + end + else + options[:src] = path_to_video(sources) + tag("video", options) + end + end + def self.cache_asset_timestamps @@cache_asset_timestamps end @@ -655,13 +735,28 @@ module ActionView end end + def ensure_stylesheet_sources!(sources) + sources.each do |source| + asset_file_path!(path_to_stylesheet(source)) + end + return sources + end + + def ensure_javascript_sources!(sources) + sources.each do |source| + asset_file_path!(path_to_javascript(source)) + end + return sources + end + def join_asset_file_contents(paths) - paths.collect { |path| File.read(asset_file_path(path)) }.join("\n\n") + paths.collect { |path| File.read(asset_file_path!(path)) }.join("\n\n") end def write_asset_file_contents(joined_asset_path, asset_paths) + FileUtils.mkdir_p(File.dirname(joined_asset_path)) - File.open(joined_asset_path, "w+") { |cache| cache.write(join_asset_file_contents(asset_paths)) } + File.atomic_write(joined_asset_path) { |cache| cache.write(join_asset_file_contents(asset_paths)) } # Set mtime to the latest of the combined files to allow for # consistent ETag without a shared filesystem. @@ -673,6 +768,14 @@ module ActionView File.join(ASSETS_DIR, path.split('?').first) end + def asset_file_path!(path) + unless path =~ %r{^[-a-z]+://} + absolute_path = asset_file_path(path) + raise(Errno::ENOENT, "Asset file not found at '#{absolute_path}'" ) unless File.exist?(absolute_path) + return absolute_path + end + end + def collect_asset_files(*path) dir = path.first @@ -682,4 +785,4 @@ module ActionView end end end -end
\ No newline at end of file +end |