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