compass-core 1.0.3 → 1.1.0.alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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