compass-core 1.0.3 → 1.1.0.alpha.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0bc443885f23b14cbf53e402b2be7524191e37c5
4
- data.tar.gz: 0a77182ae5551affb04aae0a73569ec2c8b10b8e
3
+ metadata.gz: 37fdc459e4eb96443065947423224cb16de88158
4
+ data.tar.gz: 09edd8d021b0ea190429518c8faf7bdfaa0f5bd7
5
5
  SHA512:
6
- metadata.gz: f10425d639ac0785927fbfa9aeece35d6586a23e296404b518a31c165ba5b801b5f8987288ee39014b3e9c7b3466e6354698bc54cd62f509694311d83fb70db4
7
- data.tar.gz: d0499181e5dfebcae9b9f61d2b6f25cb6b1c7bf76cdbb8bad42e732dff532b3e7f218c38109df049ada90014c7332b6ac8d8ce49ed15c2fd0a6048befc5299d5
6
+ metadata.gz: 80091874627dab8a8dbb53e5fdf472972c0892263d64a629a56a700dd24a3b54fc36b9355d066c3e27f0b93b20488ea57c145b8c47a2d0d70cd651709c945017
7
+ data.tar.gz: 2c14c31cbb5dc2da31b517347e76dfa33acfc88ed78f8f7125bd0d9eae7531cbb150cb17b6fb885a1ca358866bb2a59720d54ac7b9d814b606e6b9f2f02c0c64
@@ -85,7 +85,8 @@ module Compass
85
85
  :sprite_load_path,
86
86
  :required_libraries,
87
87
  :loaded_frameworks,
88
- :framework_path
88
+ :framework_path,
89
+ :asset_collections
89
90
  ]
90
91
 
91
92
  ARRAY_ATTRIBUTE_OPTIONS = {
@@ -93,6 +94,7 @@ module Compass
93
94
  }
94
95
 
95
96
  RUNTIME_READONLY_ATTRIBUTES = [
97
+ :additional_import_paths,
96
98
  :cache,
97
99
  attributes_for_directory(:cache, nil),
98
100
  :chunky_png_options,
@@ -170,6 +172,6 @@ module Compass
170
172
  end
171
173
  end
172
174
 
173
- %w(defaults inheritance paths data watch adapters).each do |lib|
175
+ %w(defaults inheritance paths data watch adapters asset_collection).each do |lib|
174
176
  require "compass/configuration/#{lib}"
175
177
  end
@@ -51,7 +51,10 @@ module Compass
51
51
  else
52
52
  path
53
53
  end
54
- end
54
+ end +
55
+ (asset_collections || []).map do |asset_collection|
56
+ asset_collection.sass_path
57
+ end.compact
55
58
  end
56
59
 
57
60
  def absolute_path?(path)
@@ -79,7 +82,7 @@ module Compass
79
82
 
80
83
  def sass_load_paths
81
84
  load_paths = []
82
- load_paths << sass_path if sass_path && File.directory?(sass_path)
85
+ load_paths << sass_path if sass_path
83
86
  Compass::Frameworks::ALL.each do |f|
84
87
  load_paths << f.stylesheets_directory if File.directory?(f.stylesheets_directory)
85
88
  end
@@ -0,0 +1,260 @@
1
+ class Compass::Configuration::AbstractAssetCollection
2
+ include Compass::Core::HTTPUtil
3
+
4
+ attr_writer :configuration
5
+
6
+ def configuration
7
+ @configuration || Compass.configuration
8
+ end
9
+
10
+ def as_filesystem_path(url_path)
11
+ if File::SEPARATOR == '/'
12
+ url_path
13
+ else
14
+ relative_path = url_path.gsub(%r{/}, File::SEPARATOR)
15
+ end
16
+ end
17
+
18
+ def includes_image?(relative_path)
19
+ # Treat root relative urls (without a protocol) like normal if they start with the images path.
20
+ if relative_path.start_with?("#{http_images_path}/")
21
+ relative_path = relative_path[(http_images_path.size + 1)..-1]
22
+ end
23
+ fs_relative_path = as_filesystem_path(relative_path)
24
+ absolute_path = File.join(images_path, fs_relative_path)
25
+ if File.exists?(absolute_path)
26
+ [relative_path, absolute_path]
27
+ else
28
+ nil
29
+ end
30
+ end
31
+
32
+ def includes_font?(relative_path)
33
+ # Treat root relative urls (without a protocol) like normal if they start with the fonts path.
34
+ if relative_path.start_with?("#{http_fonts_path}/")
35
+ relative_path = relative_path[(http_fonts_path.size + 1)..-1]
36
+ end
37
+ fs_relative_path = as_filesystem_path(relative_path)
38
+ absolute_path = File.join(fonts_path, fs_relative_path)
39
+ if File.exists?(absolute_path)
40
+ [relative_path, absolute_path]
41
+ end
42
+ end
43
+
44
+ def includes_generated_image?(relative_path)
45
+ nil
46
+ end
47
+
48
+ def root_path
49
+ Sass::Util.abstract!
50
+ end
51
+
52
+ def http_path
53
+ Sass::Util.abstract!
54
+ end
55
+
56
+ def sass_path
57
+ Sass::Util.abstract!
58
+ end
59
+
60
+ def images_path
61
+ Sass::Util.abstract!
62
+ end
63
+
64
+ def http_images_path
65
+ Sass::Util.abstract!
66
+ end
67
+
68
+ def fonts_path
69
+ Sass::Util.abstract!
70
+ end
71
+
72
+ def http_fonts_path
73
+ Sass::Util.abstract!
74
+ end
75
+
76
+ def asset_host
77
+ Sass::Util.abstract!
78
+ end
79
+
80
+ def asset_cache_buster
81
+ Sass::Util.abstract!
82
+ end
83
+ end
84
+
85
+ class Compass::Configuration::AssetCollection < Compass::Configuration::AbstractAssetCollection
86
+ include Compass::Util
87
+
88
+ attr_reader :options
89
+
90
+ # @param options The paths to the asset collection.
91
+ # @option :root_path The absolute path to the asset collection
92
+ # @option :root_dir A relative path to the asset collection from the project path.
93
+ # @option :http_path Web root location of assets in this collection.
94
+ # Starts with '/'.
95
+ # @option :http_dir Web root location of assets in this collection.
96
+ # Relative to the project's `http_path`.
97
+ # @option :sass_dir Sass directory to be added to the Sass import paths.
98
+ # Relative to the :root_path or :root_dir. Defaults to `sass`.
99
+ # @option :fonts_dir Directory of fonts to be added to the font look up path.
100
+ # Relative to the :root_path or :root_dir. Defaults to `fonts`.
101
+ # @option :http_fonts_dir Where to find fonts on the webserver relative to
102
+ # the http_path or http_dir. Defaults to <http_path>/<fonts_dir>.
103
+ # Can be overridden by setting :http_fonts_path.
104
+ # @option :http_fonts_path Where to find fonts on the webserver.
105
+ # @option :images_dir Directory of images to be added to the image look up path.
106
+ # Relative to the :root_path or :root_dir. Defaults to `images`.
107
+ # @option :http_images_dir Where to find images on the webserver relative to
108
+ # the http_path or http_dir. Defaults to <http_path>/<images_dir>.
109
+ # Can be overridden by setting :http_images_path.
110
+ # @option :http_images_path Where to find images on the webserver.
111
+ # @option :asset_host A string starting with 'http://' for a single host,
112
+ # or a lambda or proc that will compute the asset host for assets in this collection.
113
+ # If :http_dir is set instead of http_path, this defaults to the project's asset_host.
114
+ # @option :asset_cache_buster A string, :none, or
115
+ # or a lambda or proc that will compute the cache_buster for assets in this collection.
116
+ # If :http_dir is set instead of http_path, this defaults to the project's asset_cache_buster.
117
+ def initialize(options, configuration = nil)
118
+ assert_valid_keys(options, :root_path, :root_dir, :http_path, :http_dir, :sass_dir,
119
+ :fonts_dir, :http_fonts_dir, :http_fonts_path,
120
+ :images_dir, :http_images_dir, :http_images_path,
121
+ :asset_host, :asset_cache_buster)
122
+ symbolize_keys!(options)
123
+ unless options.has_key?(:root_path) || options.has_key?(:root_dir)
124
+ raise ArgumentError, "Either :root_path or :root_dir must be specified."
125
+ end
126
+ unless options.has_key?(:http_path) || options.has_key?(:http_dir)
127
+ raise ArgumentError, "Either :http_path or :http_dir must be specified."
128
+ end
129
+ @options = options
130
+ @configuration = configuration
131
+ end
132
+
133
+ def root_path
134
+ return @root_path if defined?(@root_path)
135
+ @root_path = @options[:root_path] || File.join(configuration.project_path, @options[:root_dir])
136
+ end
137
+
138
+ def http_path
139
+ return @http_path if defined?(@http_path)
140
+ @http_path = @options[:http_path] || url_join(configuration.http_path, @options[:http_dir])
141
+ end
142
+
143
+ def sass_path
144
+ return @sass_path if defined?(@sass_path)
145
+ @sass_path = if options[:sass_dir]
146
+ File.join(root_path, options[:sass_dir])
147
+ end
148
+ end
149
+
150
+ def images_path
151
+ return @images_path if defined?(@images_path)
152
+ @images_path = if options[:images_dir]
153
+ File.join(root_path, options[:images_dir])
154
+ end
155
+ end
156
+
157
+ def http_images_path
158
+ return @http_images_path if defined?(@http_images_path)
159
+ @http_images_path = if options[:http_images_path]
160
+ options[:http_images_path]
161
+ elsif options[:http_images_dir]
162
+ url_join(http_path, options[:http_images_dir])
163
+ elsif options[:images_dir]
164
+ url_join(http_path, options[:images_dir])
165
+ end
166
+ end
167
+
168
+
169
+ def fonts_path
170
+ return @fonts_path if defined?(@fonts_path)
171
+ @fonts_path = if options[:fonts_dir]
172
+ File.join(root_path, options[:fonts_dir])
173
+ end
174
+ end
175
+
176
+ def http_fonts_path
177
+ return @http_fonts_path if defined?(@http_fonts_path)
178
+ @http_fonts_path = if options[:http_fonts_path]
179
+ options[:http_fonts_path]
180
+ elsif options[:http_fonts_dir]
181
+ url_join(http_path, options[:http_fonts_dir])
182
+ elsif options[:fonts_dir]
183
+ url_join(http_path, options[:fonts_dir])
184
+ end
185
+ end
186
+
187
+ def asset_host
188
+ return options[:asset_host] if options.has_key?(:asset_host)
189
+ if options[:http_dir]
190
+ configuration.asset_host
191
+ end
192
+ end
193
+
194
+ def asset_cache_buster
195
+ return options[:asset_cache_buster] if options.has_key?(:asset_cache_buster)
196
+ if options[:http_dir]
197
+ configuration.asset_cache_buster
198
+ end
199
+ end
200
+ end
201
+
202
+ class Compass::Configuration::DefaultAssetCollection < Compass::Configuration::AbstractAssetCollection
203
+ def includes_generated_image?(relative_path)
204
+ # Treat root relative urls (without a protocol) like normal if they start with the images path.
205
+ if relative_path.start_with?("#{http_generated_images_path}/")
206
+ relative_path = relative_path[(http_generated_images_path.size + 1)..-1]
207
+ end
208
+ fs_relative_path = as_filesystem_path(relative_path)
209
+ absolute_path = File.join(generated_images_path, fs_relative_path)
210
+ if File.exists?(absolute_path)
211
+ [relative_path, absolute_path]
212
+ else
213
+ nil
214
+ end
215
+ end
216
+
217
+ def root_path
218
+ configuration.project_path
219
+ end
220
+
221
+ def http_path
222
+ configuration.http_path
223
+ end
224
+
225
+ def sass_path
226
+ configuration.sass_path
227
+ end
228
+
229
+ def images_path
230
+ configuration.images_path
231
+ end
232
+
233
+ def http_images_path
234
+ configuration.http_images_path
235
+ end
236
+
237
+ def generated_images_path
238
+ configuration.generated_images_path
239
+ end
240
+
241
+ def http_generated_images_path
242
+ configuration.http_generated_images_path
243
+ end
244
+
245
+ def fonts_path
246
+ configuration.fonts_path
247
+ end
248
+
249
+ def http_fonts_path
250
+ configuration.http_fonts_path
251
+ end
252
+
253
+ def asset_host
254
+ configuration.asset_host
255
+ end
256
+
257
+ def asset_cache_buster
258
+ configuration.asset_cache_buster
259
+ end
260
+ end
@@ -81,7 +81,7 @@ module Compass
81
81
  end
82
82
 
83
83
  def initialize(name, attr_hash = nil)
84
- raise "I need a name!" unless name
84
+ raise "I need a name!" unless name && (name.is_a?(String) || name.is_a?(Symbol))
85
85
  @name = name
86
86
  set_all(attr_hash) if attr_hash
87
87
  self.top_level = self
@@ -95,6 +95,14 @@ module Compass
95
95
  end
96
96
  end
97
97
 
98
+ alias http_path_without_error= http_path=
99
+ def http_path=(path)
100
+ if path == :relative
101
+ raise ArgumentError, ":relative is no longer a valid value for http_path. Please set relative_assets = true instead."
102
+ end
103
+ self.http_path_without_error = path
104
+ end
105
+
98
106
  def add_import_path(*paths)
99
107
  paths.map!{|p| defined?(Pathname) && Pathname === p ? p.to_s : p}
100
108
  # The @added_import_paths variable works around an issue where
@@ -106,6 +114,15 @@ module Compass
106
114
  end
107
115
  end
108
116
 
117
+
118
+ # Add a location where sass, image, and font assets can be found.
119
+ # @see AssetCollection#initialize for options
120
+ def add_asset_collection(options)
121
+ @url_resolver = nil
122
+ @asset_collections ||= []
123
+ @asset_collections << AssetCollection.new(options)
124
+ end
125
+
109
126
  # When called with a block, defines the asset host url to be used.
110
127
  # The block must return a string that starts with a protocol (E.g. http).
111
128
  # The block will be passed the root-relative url of the asset.
@@ -192,7 +209,15 @@ module Compass
192
209
 
193
210
  def relative_assets?
194
211
  # the http_images_path is deprecated, but here for backwards compatibility.
195
- relative_assets || http_images_path == :relative
212
+ relative_assets
213
+ end
214
+
215
+ def url_resolver
216
+ if top_level == self
217
+ @url_resolver = Compass::Core::AssetUrlResolver.new(asset_collections.to_a, self)
218
+ else
219
+ top_level.url_resolver
220
+ end
196
221
  end
197
222
  end
198
223
  end
@@ -65,6 +65,8 @@ require "sass/plugin"
65
65
  require 'compass/util'
66
66
  require "compass/frameworks"
67
67
  require "compass/core/caniuse"
68
+ require "compass/core/http_util"
69
+ require "compass/core/asset_url_resolver"
68
70
  require 'compass/core/sass_extensions'
69
71
  require 'compass/error'
70
72
  require 'compass/browser_support'
@@ -0,0 +1,130 @@
1
+ class Compass::Core::AssetUrlResolver
2
+ include Compass::Core::HTTPUtil
3
+
4
+ class AssetNotFound < Sass::SyntaxError
5
+ def initialize(type, path, asset_collections)
6
+ asset_search_paths = asset_collections.map{|ac| ac.send(:"#{type}s_path") }
7
+ super("Could not find #{path} in #{ asset_search_paths.join(", ")}")
8
+ end
9
+ end
10
+
11
+ attr_accessor :asset_collections
12
+ attr_accessor :configuration
13
+
14
+ def initialize(asset_collections, configuration = nil)
15
+ @configuration = configuration || Compass.configuration
16
+ @asset_collections = asset_collections.dup
17
+ unless @asset_collections.find {|ac| Compass::Configuration::DefaultAssetCollection === ac }
18
+ @asset_collections.unshift(Compass::Configuration::DefaultAssetCollection.new)
19
+ end
20
+ if configuration
21
+ @asset_collections.each {|ac| ac.configuration = configuration }
22
+ end
23
+ end
24
+
25
+ # Compute a url for a given asset type (:image or :font)
26
+ def compute_url(type, relative_path, relative_to_css_url = nil, use_cache_buster = true)
27
+ # pass through fully specified urls
28
+ return relative_path if relative_path.start_with?("http://")
29
+
30
+ # If the image has an target reference, remove it (Common with SVG)
31
+ clean_relative_path, target = relative_path.split("#", 2)
32
+
33
+ # If the image has a query, remove it
34
+ clean_relative_path, query = clean_relative_path.split("?", 2)
35
+
36
+ # Get rid of silliness in the url
37
+ clean_relative_path = expand_url_path(clean_relative_path)
38
+
39
+ # Find the asset collection that includes this asset
40
+ asset_collection, clean_relative_path, real_path = find_collection(type, clean_relative_path)
41
+
42
+ # Didn't find the asset, but it's a full url so just return it.
43
+ return relative_path if asset_collection.nil? && relative_path.start_with?("/")
44
+
45
+ # Raise an error for relative paths if we didn't find it on the search path.
46
+ raise AssetNotFound.new(type, relative_path, @asset_collections) unless asset_collection
47
+
48
+ # Make a root-relative url (starting with /)
49
+ asset_url = url_join(asset_collection.send(:"http_#{type}s_path"), clean_relative_path)
50
+
51
+ # Compute asset cache buster
52
+ busted_path, busted_query = cache_buster(asset_collection, asset_url, real_path) if use_cache_buster
53
+ asset_url = busted_path if busted_path
54
+ query = [query, busted_query].compact.join("&") if busted_query
55
+
56
+ # Convert path to a relative url if a css file is specified.
57
+ relative_url = compute_relative_path(relative_to_css_url, asset_url) if relative_to_css_url
58
+
59
+ # Compute asset host when not relative and one is provided
60
+ asset_host = if asset_collection.asset_host && relative_url.nil?
61
+ asset_collection.asset_host.call(asset_url)
62
+ end
63
+
64
+ # build the full url
65
+ url = url_join(asset_host || "", relative_url || asset_url)
66
+ url << "?" if query
67
+ url << query if query
68
+ url << "#" if target
69
+ url << target if target
70
+ return url
71
+ end
72
+
73
+ protected
74
+
75
+ def find_collection(type, relative_path)
76
+ asset_collection = nil
77
+ clean_relative_path = nil
78
+ absolute_path = nil
79
+ @asset_collections.each do |ac|
80
+ cp, ap = ac.send(:"includes_#{type}?", relative_path)
81
+ if ap
82
+ asset_collection = ac
83
+ absolute_path = ap
84
+ clean_relative_path = cp
85
+ break
86
+ end
87
+ end
88
+ [asset_collection, clean_relative_path, absolute_path]
89
+ end
90
+
91
+ def absolute_path?(path)
92
+ path[0..0] == "/" || path[0..3] == "http"
93
+ end
94
+
95
+ def cache_buster(asset_collection, path, real_path)
96
+ cache_buster = compute_cache_buster(asset_collection, path, real_path)
97
+ return [path, nil] if cache_buster.nil?
98
+ cache_buster = {:query => cache_buster} if cache_buster.is_a?(String)
99
+ [cache_buster[:path] || path, cache_buster[:query]]
100
+ end
101
+
102
+
103
+ def compute_cache_buster(asset_collection, path, real_path)
104
+ file = nil
105
+ if asset_collection.asset_cache_buster == :none
106
+ nil
107
+ elsif asset_collection.asset_cache_buster
108
+ args = [path]
109
+ if asset_collection.asset_cache_buster.arity > 1
110
+ file = File.new(real_path)
111
+ args << file
112
+ end
113
+ asset_collection.asset_cache_buster.call(*args)
114
+ else
115
+ default_cache_buster(path, real_path)
116
+ end
117
+ ensure
118
+ file.close if file
119
+ end
120
+
121
+ def default_cache_buster(path, real_path)
122
+ if File.readable?(real_path)
123
+ File.mtime(real_path).to_i.to_s
124
+ else
125
+ Compass::Util.compass_warn("WARNING: '#{real_path}' cannot be read.")
126
+ nil
127
+ end
128
+ end
129
+
130
+ end
@@ -69,7 +69,7 @@ class Compass::Core::CanIUse
69
69
  end
70
70
 
71
71
  # returns the prefixes needed by the list of browsers given
72
- def prefixes(browsers = browsers())
72
+ def prefixes(browsers = browsers)
73
73
  result = browsers.map{|b| all_prefixes(b) }
74
74
  result.flatten!
75
75
  result.uniq!
@@ -1,6 +1,5 @@
1
1
  module Compass
2
2
  module Core
3
- # This file intentionally does nothing.
4
- # The build process will generate a VERSION constant here.
3
+ VERSION = "1.1.0.alpha.0"
5
4
  end
6
5
  end
@@ -0,0 +1,57 @@
1
+ module Compass::Core::HTTPUtil
2
+ # like File#join, but always uses '/' instead of File::SEPARATOR
3
+ def url_join(*args)
4
+ args.inject("") do |m, a|
5
+ m << "/" unless m.end_with?('/') || a.start_with?('/') if m.length > 0
6
+ m.gsub!(%r{/+$}, '') if a.start_with?('/')
7
+ m << a
8
+ end
9
+ end
10
+
11
+ # Eliminates parent directory references (E.g. "..") and
12
+ # self directory references references (E.g. ".") from urls.
13
+ # Removes any duplicated separators (E.g. //)
14
+ # path should not include the protol, host, query param or target.
15
+ def expand_url_path(url)
16
+ # We remove the leading path otherwise we think there's an extra segment that can be removed
17
+ prefix = "/" if url.start_with?("/")
18
+ segments = url.gsub(%r{//+}, '/').split("/")
19
+ segments.shift if prefix
20
+ segments.push("") if url.end_with?("/")
21
+ segments.reverse!
22
+ result_segments = []
23
+ parent_count = 0
24
+ segments.each do |segment|
25
+ if segment == ".."
26
+ parent_count += 1
27
+ elsif segment == "."
28
+ # skip it
29
+ elsif parent_count > 0
30
+ parent_count -= 1
31
+ else
32
+ result_segments << segment
33
+ end
34
+ end
35
+ if parent_count > 0
36
+ raise ArgumentError, "Invalid URL: #{url} (not enough parent directories)"
37
+ end
38
+ result_segments.reverse!
39
+ prefix.to_s + result_segments.join("/")
40
+ end
41
+
42
+ # Compute a relative path from one url to another
43
+ # the urls should be only the path component (no host, query, or target)
44
+ def compute_relative_path(from_url, to_url)
45
+ from_components = expand_url_path(from_url).split("/")
46
+ from_components.pop # drop the filename from the source
47
+ to_components = expand_url_path(to_url).split("/")
48
+ to_base = to_components.pop
49
+ while from_components.first == to_components.first
50
+ break if from_components.empty?
51
+ from_components.shift
52
+ to_components.shift
53
+ end
54
+
55
+ ([".."] * from_components.size + to_components + [to_base]).join("/")
56
+ end
57
+ end
@@ -83,8 +83,7 @@ module Compass::Core::SassExtensions::Functions::Configuration
83
83
  end
84
84
  declare :add_sass_configuration, [:project_path]
85
85
 
86
- OPTION_TRANSFORMER = Hash.new() {|h, k| proc {|v, ctx| v.value } }
87
- OPTION_TRANSFORMER[:asset_cache_buster] = proc do |v, ctx|
86
+ def self.make_cache_buster_proc(v, ctx)
88
87
  proc do |url, file|
89
88
  if ctx.environment.function(v.value) || Sass::Script::Functions.callable?(v.value.tr('-', '_'))
90
89
  result = ctx.call(v, ctx.quoted_string(url),
@@ -108,7 +107,8 @@ module Compass::Core::SassExtensions::Functions::Configuration
108
107
  end
109
108
  end
110
109
  end
111
- OPTION_TRANSFORMER[:asset_host] = proc do |v, ctx|
110
+
111
+ def self.make_asset_host_proc(v, ctx)
112
112
  proc do |file|
113
113
  if ctx.environment.function(v.value) || Sass::Script::Functions.callable?(v.value.tr('-', '_'))
114
114
  result = ctx.call(v, ctx.quoted_string(file))
@@ -122,6 +122,39 @@ module Compass::Core::SassExtensions::Functions::Configuration
122
122
  raise ArgumentError, "#{v.value} is not a function."
123
123
  end
124
124
  end
125
+
126
+ end
127
+
128
+ OPTION_TRANSFORMER = Hash.new() {|h, k| proc {|v, ctx| v.value } }
129
+ OPTION_TRANSFORMER[:asset_cache_buster] = proc {|v, ctx| make_cache_buster_proc(v, ctx) }
130
+ OPTION_TRANSFORMER[:asset_host] = proc {|v, ctx| make_asset_host_proc(v, ctx) }
131
+
132
+ OPTION_TRANSFORMER[:asset_collections] = proc do |v, ctx|
133
+ v = list([v], :comma) if v.is_a?(Sass::Script::Value::Map)
134
+ ctx.assert_type(v, :List)
135
+
136
+ asset_collections = []
137
+
138
+ v.value.each do |map|
139
+ ctx.assert_type(map, :Map)
140
+ asset_collection = {}
141
+ map.value.keys.each do |key|
142
+ ctx.assert_type key, :String
143
+ ctx.assert_type map.value[key], :String unless map.value[key].value.nil?
144
+ underscored = key.value.tr("-", "_")
145
+ case underscored
146
+ when "asset_host"
147
+ asset_collection[underscored] = make_asset_host_proc(map.value[key], ctx)
148
+ when "asset_cache_buster"
149
+ asset_collection[underscored] = make_cache_buster_proc(map.value[key], ctx)
150
+ else
151
+ asset_collection[underscored] = map.value[key].value
152
+ end
153
+ end
154
+ asset_collections << Compass::Configuration::AssetCollection.new(asset_collection)
155
+ end
156
+
157
+ asset_collections
125
158
  end
126
159
 
127
160
  def add_configuration(options)
@@ -144,7 +177,8 @@ module Compass::Core::SassExtensions::Functions::Configuration
144
177
  private
145
178
 
146
179
  def runtime_writable_attributes
147
- Compass::Configuration::ATTRIBUTES - Compass::Configuration::RUNTIME_READONLY_ATTRIBUTES
180
+ (Compass::Configuration::ATTRIBUTES + Compass::Configuration::ARRAY_ATTRIBUTES) -
181
+ Compass::Configuration::RUNTIME_READONLY_ATTRIBUTES
148
182
  end
149
183
 
150
184
  def common_parent_directory(directory1, directory2)
@@ -20,21 +20,15 @@ module Compass::Core::SassExtensions::Functions::Urls
20
20
  end
21
21
  end
22
22
  def stylesheet_url(path, only_path = bool(false))
23
- # Compute the path to the stylesheet, either root relative or stylesheet relative
24
- # or nil if the http_images_path is not set in the configuration.
25
- http_stylesheets_path = if relative?
26
- compute_relative_path(Compass.configuration.css_path)
27
- elsif Compass.configuration.http_stylesheets_path
28
- Compass.configuration.http_stylesheets_path
29
- else
30
- Compass.configuration.http_root_relative(Compass.configuration.css_dir)
23
+ url = url_join(Compass.configuration.http_stylesheets_path, path.value)
24
+ if Compass.configuration.relative_assets?
25
+ url = compute_relative_path(current_css_url_path, url)
31
26
  end
32
27
 
33
- path = "#{http_stylesheets_path}/#{path.value}"
34
28
  if only_path.to_bool
35
- unquoted_string(clean_path(path))
29
+ unquoted_string(expand_url_path(url))
36
30
  else
37
- clean_url(path)
31
+ unquoted_string("url('#{expand_url_path(url)}')")
38
32
  end
39
33
  end
40
34
  end
@@ -48,60 +42,12 @@ module Compass::Core::SassExtensions::Functions::Urls
48
42
  end
49
43
  end
50
44
  def font_url(path, only_path = bool(false), cache_buster = bool(true))
51
- path = path.value # get to the string value of the literal.
52
-
53
- # Short curcuit if they have provided an absolute url.
54
- if absolute_path?(path)
55
- return unquoted_string("url(#{path})")
56
- end
57
-
58
- # Compute the path to the font file, either root relative or stylesheet relative
59
- # or nil if the http_fonts_path cannot be determined from the configuration.
60
- http_fonts_path = if relative?
61
- compute_relative_path(Compass.configuration.fonts_path)
62
- else
63
- Compass.configuration.http_fonts_path
64
- end
65
-
66
- # Compute the real path to the font on the file system if the fonts_dir is set.
67
- real_path = if Compass.configuration.fonts_dir
68
- File.join(Compass.configuration.fonts_path, path.gsub(/[?#].*$/,""))
69
- end
70
-
71
- # prepend the path to the font if there's one
72
- if http_fonts_path
73
- http_fonts_path = "#{http_fonts_path}/" unless http_fonts_path[-1..-1] == "/"
74
- path = "#{http_fonts_path}#{path}"
75
- end
76
-
77
- # Compute the asset host unless in relative mode.
78
- asset_host = if !relative? && Compass.configuration.asset_host
79
- Compass.configuration.asset_host.call(path)
80
- end
81
-
82
- # Compute and append the cache buster if there is one.
83
- if cache_buster.to_bool
84
- path, anchor = path.split("#", 2)
85
- if cache_buster.is_a?(Sass::Script::Value::String)
86
- path += "#{path["?"] ? "&" : "?"}#{cache_buster.value}"
87
- else
88
- path = cache_busted_path(path, real_path)
89
- end
90
- path = "#{path}#{"#" if anchor}#{anchor}"
91
- end
92
-
93
- # prepend the asset host if there is one.
94
- path = "#{asset_host}#{'/' unless path[0..0] == "/"}#{path}" if asset_host
95
-
96
- if only_path.to_bool
97
- unquoted_string(clean_path(path))
98
- else
99
- clean_url(path)
100
- end
45
+ resolve_asset_url(:font, path, only_path, cache_buster)
101
46
  end
102
47
  end
103
48
 
104
49
  module ImageUrl
50
+ include Compass::Core::HTTPUtil
105
51
  def self.included(base)
106
52
  if base.respond_to?(:declare)
107
53
  base.declare :image_url, [:path]
@@ -110,64 +56,7 @@ module Compass::Core::SassExtensions::Functions::Urls
110
56
  end
111
57
  end
112
58
  def image_url(path, only_path = bool(false), cache_buster = bool(true))
113
- path = path.value # get to the string value of the literal.
114
-
115
- if path =~ %r{^#{Regexp.escape(Compass.configuration.http_images_path)}/(.*)}
116
- # Treat root relative urls (without a protocol) like normal if they start with
117
- # the images path.
118
- path = $1
119
- elsif absolute_path?(path)
120
- # Short curcuit if they have provided an absolute url.
121
- return unquoted_string("url(#{path})")
122
- end
123
-
124
- # Compute the path to the image, either root relative or stylesheet relative
125
- # or nil if the http_images_path is not set in the configuration.
126
- http_images_path = if relative?
127
- compute_relative_path(Compass.configuration.images_path)
128
- elsif Compass.configuration.http_images_path
129
- Compass.configuration.http_images_path
130
- else
131
- Compass.configuration.http_root_relative(Compass.configuration.images_dir)
132
- end
133
-
134
- # Compute the real path to the image on the file stystem if the images_dir is set.
135
- real_path = if Compass.configuration.images_path
136
- File.join(Compass.configuration.images_path, path.gsub(/#.*$/,""))
137
- else
138
- File.join(Compass.configuration.project_path, path.gsub(/#.*$/,""))
139
- end
140
-
141
- # prepend the path to the image if there's one
142
- if http_images_path
143
- http_images_path = "#{http_images_path}/" unless http_images_path[-1..-1] == "/"
144
- path = "#{http_images_path}#{path}"
145
- end
146
-
147
- # Compute the asset host unless in relative mode.
148
- asset_host = if !relative? && Compass.configuration.asset_host
149
- Compass.configuration.asset_host.call(path)
150
- end
151
-
152
- # Compute and append the cache buster if there is one.
153
- if cache_buster.to_bool
154
- path, anchor = path.split("#", 2)
155
- if cache_buster.is_a?(Sass::Script::Value::String)
156
- path += "#{path["?"] ? "&" : "?"}#{cache_buster.value}"
157
- else
158
- path = cache_busted_path(path, real_path)
159
- end
160
- path = "#{path}#{"#" if anchor}#{anchor}"
161
- end
162
-
163
- # prepend the asset host if there is one.
164
- path = "#{asset_host}#{'/' unless path[0..0] == "/"}#{path}" if asset_host
165
-
166
- if only_path.to_bool
167
- unquoted_string(clean_path(path))
168
- else
169
- clean_url(path)
170
- end
59
+ resolve_asset_url(:image, path, only_path, cache_buster)
171
60
  end
172
61
  end
173
62
 
@@ -179,135 +68,26 @@ module Compass::Core::SassExtensions::Functions::Urls
179
68
  end
180
69
  end
181
70
  def generated_image_url(path, cache_buster = bool(false))
182
- path = path.value # get to the string value of the literal.
183
-
184
- if path =~ %r{^#{Regexp.escape(Compass.configuration.http_generated_images_path)}/(.*)}
185
- # Treat root relative urls (without a protocol) like normal if they start with
186
- # the generated_images path.
187
- path = $1
188
- elsif absolute_path?(path)
189
- # Short curcuit if they have provided an absolute url.
190
- return unquoted_string("url(#{path})")
191
- end
192
-
193
- # Compute the path to the image, either root relative or stylesheet relative
194
- # or nil if the http_generated_images_path is not set in the configuration.
195
- http_generated_images_path = if relative?
196
- compute_relative_path(Compass.configuration.generated_images_path)
197
- elsif Compass.configuration.http_generated_images_path
198
- Compass.configuration.http_generated_images_path
199
- else
200
- Compass.configuration.http_root_relative(Compass.configuration.generated_images_dir)
201
- end
202
-
203
- # Compute the real path to the image on the file stystem if the generated_images_dir is set.
204
- real_path = if Compass.configuration.generated_images_path
205
- File.join(Compass.configuration.generated_images_path, path.gsub(/#.*$/,""))
206
- else
207
- File.join(Compass.configuration.project_path, path.gsub(/#.*$/,""))
208
- end
209
-
210
- # prepend the path to the image if there's one
211
- if http_generated_images_path
212
- http_generated_images_path = "#{http_generated_images_path}/" unless http_generated_images_path[-1..-1] == "/"
213
- path = "#{http_generated_images_path}#{path}"
214
- end
215
-
216
- # Compute the asset host unless in relative mode.
217
- asset_host = if !relative? && Compass.configuration.asset_host
218
- Compass.configuration.asset_host.call(path)
219
- end
220
-
221
- # Compute and append the cache buster if there is one.
222
- if cache_buster.to_bool
223
- path, anchor = path.split("#", 2)
224
- if cache_buster.is_a?(Sass::Script::Value::String)
225
- path += "#{path["?"] ? "&" : "?"}#{cache_buster.value}"
226
- else
227
- path = cache_busted_path(path, real_path)
228
- end
229
- path = "#{path}#{"#" if anchor}#{anchor}"
230
- end
231
-
232
- # prepend the asset host if there is one.
233
- path = "#{asset_host}#{'/' unless path[0..0] == "/"}#{path}" if asset_host
234
-
235
- clean_url(path)
71
+ resolve_asset_url(:generated_image, path, bool(false), cache_buster)
236
72
  end
237
73
  end
238
74
 
239
75
  private
240
76
 
241
- # Emits a path, taking off any leading "./"
242
- def clean_path(url)
243
- url = url.to_s
244
- url = url[0..1] == "./" ? url[2..-1] : url
245
- end
246
-
247
- # Emits a url, taking off any leading "./"
248
- def clean_url(url)
249
- unquoted_string("url('#{clean_path(url)}')")
250
- end
251
-
252
- def relative?
253
- Compass.configuration.relative_assets?
254
- end
255
-
256
- def absolute_path?(path)
257
- path[0..0] == "/" || path[0..3] == "http"
258
- end
259
-
260
- def compute_relative_path(path)
261
- if (target_css_file = options[:css_filename])
262
- target_path = Pathname.new(File.expand_path(path))
263
- source_path = Pathname.new(File.dirname(File.expand_path(target_css_file)))
264
- target_path.relative_path_from(source_path).to_s
77
+ def current_css_url_path
78
+ if options[:css_filename] && options[:css_filename].start_with?("#{Compass.configuration.css_path}/")
79
+ url_join(Compass.configuration.http_stylesheets_path, options[:css_filename][(Compass.configuration.css_path.size + 1)..-1])
265
80
  end
266
81
  end
267
82
 
268
- def cache_busted_path(path, real_path)
269
- cache_buster = compute_cache_buster(path, real_path)
270
- if cache_buster.nil?
271
- return path
272
- elsif cache_buster.is_a?(String)
273
- cache_buster = {:query => cache_buster}
274
- else
275
- path = cache_buster[:path] if cache_buster[:path]
276
- end
277
-
278
- if cache_buster[:query]
279
- "#{path}#{path["?"] ? "&" : "?"}#{cache_buster[:query]}"
83
+ def resolve_asset_url(type, path, only_path, cache_buster)
84
+ path = path.value # get to the string value of the literal.
85
+ css_file = current_css_url_path if Compass.configuration.relative_assets?
86
+ url = Compass.configuration.url_resolver.compute_url(type, path, css_file, cache_buster.to_bool)
87
+ if only_path.to_bool
88
+ unquoted_string(url)
280
89
  else
281
- path
90
+ unquoted_string("url('#{url}')")
282
91
  end
283
92
  end
284
-
285
- def compute_cache_buster(path, real_path)
286
- file = nil
287
- if Compass.configuration.asset_cache_buster
288
- args = [path]
289
- if Compass.configuration.asset_cache_buster.arity > 1
290
- begin
291
- file = File.new(real_path) if real_path
292
- rescue Errno::ENOENT
293
- # pass
294
- end
295
- args << file
296
- end
297
- Compass.configuration.asset_cache_buster.call(*args)
298
- elsif real_path
299
- default_cache_buster(path, real_path)
300
- end
301
- ensure
302
- file.close if file
303
- end
304
-
305
- def default_cache_buster(path, real_path)
306
- if File.readable?(real_path)
307
- File.mtime(real_path).to_i.to_s
308
- else
309
- $stderr.puts "WARNING: '#{File.basename(path)}' was not found (or cannot be read) in #{File.dirname(real_path)}"
310
- end
311
- end
312
-
313
93
  end
@@ -16,4 +16,19 @@ module Compass::Util
16
16
  end
17
17
  end
18
18
 
19
+ def assert_valid_keys(hash, *keys)
20
+ keys = keys.inject([]) {|m, k| m << k; m << k.to_s if k.is_a?(Symbol); m}
21
+ invalid_keys = hash.keys - keys
22
+ if invalid_keys.any?
23
+ raise ArgumentError, "Invalid key#{'s' if invalid_keys.size > 1} found: #{invalid_keys.map{|k| k.inspect}.join(", ")}"
24
+ end
25
+ end
26
+
27
+ def symbolize_keys!(hash)
28
+ hash.keys.select {|k| k.is_a?(String)}.each do |k|
29
+ hash[k.to_sym] = hash.delete(k)
30
+ end
31
+ nil
32
+ end
33
+
19
34
  end
@@ -275,9 +275,9 @@ $css-sel2-support-threshold: $critical-usage-threshold !default;
275
275
  $old-range: map-get($ranges, $browser);
276
276
  @if $old-range {
277
277
  $old-min: nth($old-range, 1);
278
- $old-max: if(length($old-range) == 1, $old-min, nth($old-range, 2));
278
+ $old-max: nth($old-range, 2);
279
279
  $new-min: nth($new-range, 1);
280
- $new-max: if(length($new-range) == 1, $new-min, nth($new-range, 2));
280
+ $new-max: nth($new-range, 2);
281
281
  $maximin: if(compare-browser-versions($browser, $old-min, $new-min) > 0,
282
282
  $old-min, $new-min);
283
283
  $minimax: if(compare-browser-versions($browser, $old-max, $new-max) < 0,
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: compass-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.1.0.alpha.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Eppstein
@@ -11,68 +11,68 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2015-01-16 00:00:00.000000000 Z
14
+ date: 2014-08-26 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: sass
18
18
  requirement: !ruby/object:Gem::Requirement
19
19
  requirements:
20
- - - ">="
20
+ - - '>='
21
21
  - !ruby/object:Gem::Version
22
22
  version: 3.3.0
23
- - - "<"
23
+ - - <
24
24
  - !ruby/object:Gem::Version
25
25
  version: '3.5'
26
26
  type: :runtime
27
27
  prerelease: false
28
28
  version_requirements: !ruby/object:Gem::Requirement
29
29
  requirements:
30
- - - ">="
30
+ - - '>='
31
31
  - !ruby/object:Gem::Version
32
32
  version: 3.3.0
33
- - - "<"
33
+ - - <
34
34
  - !ruby/object:Gem::Version
35
35
  version: '3.5'
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: multi_json
38
38
  requirement: !ruby/object:Gem::Requirement
39
39
  requirements:
40
- - - "~>"
40
+ - - ~>
41
41
  - !ruby/object:Gem::Version
42
42
  version: '1.0'
43
43
  type: :runtime
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
46
46
  requirements:
47
- - - "~>"
47
+ - - ~>
48
48
  - !ruby/object:Gem::Version
49
49
  version: '1.0'
50
50
  - !ruby/object:Gem::Dependency
51
51
  name: bundler
52
52
  requirement: !ruby/object:Gem::Requirement
53
53
  requirements:
54
- - - ">="
54
+ - - '>='
55
55
  - !ruby/object:Gem::Version
56
56
  version: '0'
57
57
  type: :development
58
58
  prerelease: false
59
59
  version_requirements: !ruby/object:Gem::Requirement
60
60
  requirements:
61
- - - ">="
61
+ - - '>='
62
62
  - !ruby/object:Gem::Version
63
63
  version: '0'
64
64
  - !ruby/object:Gem::Dependency
65
65
  name: rake
66
66
  requirement: !ruby/object:Gem::Requirement
67
67
  requirements:
68
- - - ">="
68
+ - - '>='
69
69
  - !ruby/object:Gem::Version
70
70
  version: '0'
71
71
  type: :development
72
72
  prerelease: false
73
73
  version_requirements: !ruby/object:Gem::Requirement
74
74
  requirements:
75
- - - ">="
75
+ - - '>='
76
76
  - !ruby/object:Gem::Version
77
77
  version: '0'
78
78
  description: The Compass core stylesheet library and minimum required ruby extensions.
@@ -84,22 +84,23 @@ executables: []
84
84
  extensions: []
85
85
  extra_rdoc_files: []
86
86
  files:
87
- - LICENSE.txt
88
- - VERSION
89
87
  - data/caniuse.json
90
88
  - data/caniuse_extras/css-placeholder.json
91
89
  - lib/compass-core.rb
92
90
  - lib/compass/browser_support.rb
93
91
  - lib/compass/configuration.rb
94
92
  - lib/compass/configuration/adapters.rb
93
+ - lib/compass/configuration/asset_collection.rb
95
94
  - lib/compass/configuration/data.rb
96
95
  - lib/compass/configuration/defaults.rb
97
96
  - lib/compass/configuration/inheritance.rb
98
97
  - lib/compass/configuration/paths.rb
99
98
  - lib/compass/configuration/watch.rb
100
99
  - lib/compass/core.rb
100
+ - lib/compass/core/asset_url_resolver.rb
101
101
  - lib/compass/core/caniuse.rb
102
102
  - lib/compass/core/generated_version.rb
103
+ - lib/compass/core/http_util.rb
103
104
  - lib/compass/core/sass_extensions.rb
104
105
  - lib/compass/core/sass_extensions/functions.rb
105
106
  - lib/compass/core/sass_extensions/functions/colors.rb
@@ -229,6 +230,7 @@ files:
229
230
  - templates/project/manifest.rb
230
231
  - templates/project/print.sass
231
232
  - templates/project/screen.sass
233
+ - LICENSE.txt
232
234
  homepage: http://compass-style.org/reference/compass/
233
235
  licenses:
234
236
  - MIT
@@ -239,17 +241,17 @@ require_paths:
239
241
  - lib
240
242
  required_ruby_version: !ruby/object:Gem::Requirement
241
243
  requirements:
242
- - - ">="
244
+ - - '>='
243
245
  - !ruby/object:Gem::Version
244
246
  version: '0'
245
247
  required_rubygems_version: !ruby/object:Gem::Requirement
246
248
  requirements:
247
- - - ">="
249
+ - - '>'
248
250
  - !ruby/object:Gem::Version
249
- version: '0'
251
+ version: 1.3.1
250
252
  requirements: []
251
253
  rubyforge_project:
252
- rubygems_version: 2.4.3
254
+ rubygems_version: 2.0.3
253
255
  signing_key:
254
256
  specification_version: 4
255
257
  summary: The Compass core stylesheet library
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 1.0.3