lib/sinatra/exstatic_assets.rb in sinatra-exstatic-assets-3.0.0 vs lib/sinatra/exstatic_assets.rb in sinatra-exstatic-assets-3.1.0

- old
+ new

@@ -1,6 +1,7 @@ require 'sinatra/base' +require 'digest/sha1' # @see https://sinatrarb.com/intro The framework module Sinatra # A Sinatra extension for helping with static assets. You probably want to start with {Helpers}. @@ -55,30 +56,32 @@ end # Encapsulates an asset, be it a stylesheet, an imageā€¦ - class Asset < ::String + class Asset < String attr_reader :fullpath # @param [String] filename Either the file name (and path relative to the public folder) or the external HTTP link. # @param [String] asset_dir The asset directory. When used with Sinatra this will default to the directory defined by the `public_folder` setting. - def initialize( filename, asset_dir=nil ) # TODO failure strategy + def initialize( filename, asset_dir=nil, timestamp_format=nil ) # TODO failure strategy if asset_dir.nil? + # TODO should this strip the leading slash? filename, asset_dir = [File.basename(filename), File.dirname(filename)] end # TODO fail if asset_dir.nil? super filename + @timestamp_format = timestamp_format @fullpath = File.join( asset_dir, filename ) unless is_uri? end # If the asset is a local file this gets the timestamp. # @return [Integer] def timestamp - @timestamp ||= !is_uri? && exists? && mtime_int + @timestamp ||= !is_uri? && exists? && send(@timestamp_format) end # Takes the timestamp and returns it as a querystring. # @return [String] `?ts=TIMESTAMP` def querystring @@ -133,20 +136,42 @@ # @param [Hash] options # @option options [TrueClass] :absolute see Sinatra::Helpers#uri # @option options [TrueClass] :script_name Whether to prepend the SCRIPT_NAME env variable. # @return [String] # @see Sinatra::Helpers#uri - def sss_url_for(addr, options=nil) - options ||= {} - opts = {timestamp: true}.merge options - absolute = opts.delete :absolute + def sss_url_for(addr, options, url_opts) + absolute = url_opts.delete :absolute absolute = false if absolute.nil? + scr = url_opts.delete(:script_name) script_name = - !addr.is_uri? || - opts.delete(:script_name) && addr.start_with?("/") - + if addr.is_uri? + false + elsif addr.start_with?("/") + scr.nil? ? + true : + scr + else + false + end href = uri addr, absolute, script_name + + timestamp = + if scr == false + false + else + # timestamp | + # nil t + # f | f + # t | t + if options[:timestamp] && options[:timestamp] == false + false + else + true + end + end + opts = {timestamp: timestamp}.merge options + addr.respond_to?(:querystring) && opts[:timestamp] ? "#{href}#{addr.querystring}" : href end @@ -165,53 +190,76 @@ # @param [Hash] options # @option options [String] :asset_dir The directory the asset is held. Defaults to Sinatra's `public_folder` setting. # @option options [Hash] :url_options Options for devising the URL. # @option options [TrueClass] :script_name Whether to prepend the SCRIPT_NAME env variable. # @return [Tag] - def sss_stylesheet_tag(source, options = {}) - asset_dir = options.delete(:asset_dir) || settings.public_folder - asset = Asset.new source, asset_dir - href = sss_url_for( asset, options.delete(:url_options) ) + def sss_stylesheet_tag(source, options, url_opts) + asset = Asset.new source, options.delete(:asset_dir), options.delete(:timestamp_format) + href = sss_url_for asset, options, url_opts Tag.new "link", DEFAULT_CSS.merge(:href => href) .merge(options) end # Default options for the javascript script tags. DEFAULT_JS = { # :type => "text/javascript", - :charset => "utf-8" + :charset => "utf-8", } # Produce a javascript script tag. # @see #sss_stylesheet_tag but there is no `closed` option here. - def sss_javascript_tag(source, options = {}) - asset = Asset.new source, settings.public_folder - href = sss_url_for asset, options.delete(:url_options) + def sss_javascript_tag(source, options, url_opts) + asset = Asset.new source, options.delete(:asset_dir), options.delete(:timestamp_format) + href = sss_url_for asset, options, url_opts Tag.new("script", DEFAULT_JS.merge(:src => href) .merge(options) ) {} end # Make's sure the options don't get mixed up with the other args. def sss_extract_options(a) opts = a.last.respond_to?(:keys) ? - a.pop : + a.pop || {} : {} - opts ||= {} - [a, opts] + + url_opts = opts.empty? ? + {} : + { + absolute: opts.delete(:absolute), + script_name: opts.delete(:script_name), + }.reject{|k,v| v.nil? } + a = [nil] if a == [] + [a, opts, url_opts] end # @see #sss_stylesheet_tag - def sss_image_tag(source, options = {}) - options[:src] = sss_url_for Asset.new( source, settings.public_folder ), options.delete(:url_options) + def sss_image_tag(source, options, url_opts) + options[:src] = sss_url_for Asset.new( source, options.delete(:asset_dir), options.delete(:timestamp_format) ), options, url_opts Tag.new "img", options end + + # @param [String] source + # @param [Hash] options + # @option options [TrueClass] :script_name whether to append the script_name environment variable or not + # @example + # favicon_tag + # # => <link href="/favicon.ico" rel="icon"> + def sss_favicon_tag(source, options, url_opts) + source = "/favicon.ico" if source.nil? or source.empty? + + # xhtml style like <link rel="shortcut icon" href="http://example.com/myicon.ico" /> + options[:rel] ||= settings.xhtml ? "shortcut icon" : "icon" + asset = Asset.new source, options.delete(:asset_dir), options.delete(:timestamp_format) + options[:href] = sss_url_for asset, options.merge(timestamp: false), url_opts + Tag.new "link", options + end + end # These are the helpers available to a Sinatra app using the extension. # @example # # For a classic app @@ -257,15 +305,21 @@ # @option options [Hash] :url_options Options for devising the URL. (see sss_url_for) # @return [#to_s] # @example # javascript_tag "http://code.jquery.com/jquery-1.9.1.min.js" # # => <script charset="utf-8" src="http://code.jquery.com/jquery-1.9.1.min.js"></script> - %w{image_tag stylesheet_tag javascript_tag}.each do |method_name| - define_method method_name do |*sources| - list, options = sss_extract_options sources + %w{image_tag stylesheet_tag javascript_tag favicon_tag}.each do |method_name| + define_method method_name do |*args| + list, options, url_opts = sss_extract_options args list.map {|source| - send "sss_#{method_name}", source, options + asset_dir = options.delete(:asset_dir) || + settings.static_assets_dir || + settings.public_folder + timestamp_format = options.delete(:timestamp_format) || + settings.timestamp_format || + :mtime_int # default + send "sss_#{method_name}", source, options.merge({asset_dir: asset_dir, timestamp_format: timestamp_format}), url_opts }.join "\n" end end @@ -274,37 +328,21 @@ alias_method :stylesheet, :stylesheet_tag alias_method :javascript_include_tag, :javascript_tag alias_method :js_tag, :javascript_tag alias_method :script_tag, :javascript_tag - # @param [String] source - # @param [Hash] options - # @option options [Hash] :url_options script_name - # @example - # favicon_tag - # # => <link href="/favicon.ico" rel="icon"> - def favicon_tag(*args) - source, options = sss_extract_options args - source = "favicon.ico" if source.nil? or source.empty? - - # xhtml style like <link rel="shortcut icon" href="http://example.com/myicon.ico" /> - options[:rel] ||= settings.xhtml ? "shortcut icon" : "icon" - - url_options = options.delete(:url_options) || {} - options[:href] = sss_url_for(Asset.new(source), url_options.merge(timestamp: false)) - - Tag.new "link", options - end - alias_method :link_favicon_tag, :favicon_tag alias_method :favicon, :favicon_tag end # Extending + # @see {Sinatra::Exstatic::Formats} to extend timestamp_format def self.registered(app) app.helpers Exstatic::Helpers app.disable :xhtml + app.set :static_assets_dir, nil + app.set :timestamp_format, :mtime_int end end register Exstatic end