Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'master' into awesome_media

* master: (23 commits)
  [Sass] Proper fix for GH-275 that doesn't break other tests. Closes GH-281.
  Revert "Disable rubyforge releasing until we get a project set up."
  Disable rubyforge releasing until we get a project set up.
  Watch for updates on port 3124.
  [Sass] Support --unix-newlines on Unix.
  [Sass] Properly detect SCSS with -c.
  Fix a typo.
  Clean up a few tests.
  Track the original filename of a sass file even within imports.
  We don't need to assume anything about cached root nodes anymore.
  Propagate Util.dump and Util.load through to child nodes and importers.
  [Emacs] Allow indentation beneath for loops.
  [Sass] Make color names csae-insensitive.
  [Sass] Add a changelog entry about aab0567.
  [Sass] Add an #invert function.
  [Sass] Clean up a little.
  Fix bug in compressed output of SCSS selectors with newlines.
  [Sass] Get rid of Compiler#forbid_update?.
  Allow objects that are not sass trees to be placed into the sass cache.
  Fixed one last reference to Sass::Files.
  ...

Conflicts:
	test/sass/engine_test.rb
  • Loading branch information...
commit 4ac136265624cdb3e318c3c48587331077dffdee 2 parents 278a35f + 85aa757
Chris Eppstein authored
14 doc-src/SASS_CHANGELOG.md
View
@@ -5,6 +5,8 @@
## 3.2.0 (Unreleased)
+* Add an {Sass::Script::Functions#invert `invert` function} that takes the inverse of colors.
+
### Backwards Incompatibilities -- Must Read!
* When `@import` is given a path without `.sass`, `.scss`, or `.css` extension,
@@ -16,6 +18,18 @@
This flag hasn't been necessary since Rails 2.0.
Existing Rails 2.0 installations will continue to work.
+## 3.0.19 (Unreleased)
+
+* Make the alpha value for `rgba` colors respect {Sass::Script::Number::PRECISION}.
+
+* Remove all newlines in selectors in `:compressed` mode.
+
+* Make color names case-insensitive.
+
+* Properly detect SCSS files when using `sass -c`.
+
+* Allow the `--unix-newlines` flag to work on Unix, where it's a no-op.
+
## 3.0.18
[Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.18).
2  extra/update_watch.rb
View
@@ -1,7 +1,7 @@
require 'rubygems'
require 'sinatra'
require 'json'
-set :port, 3123
+set :port, 3124
set :environment, :production
enable :lock
Dir.chdir(File.dirname(__FILE__) + "/..")
11 lib/sass/cache_store.rb
View
@@ -45,21 +45,16 @@ def _retrieve(key, version, sha)
#
# @param key [String] The key to store it under.
# @param sha [String] The checksum for the contents that are being stored.
- # @param root [Sass::Tree::RootNode] The root of the tree to be stored.
+ # @param obj [Object] The object to cache.
def store(key, sha, root)
- orig_options = root.options
- begin
- _store(key, Sass::VERSION, sha, Sass::Util.dump(root))
- ensure
- root.options = orig_options
- end
+ _store(key, Sass::VERSION, sha, Sass::Util.dump(root))
end
# Retrieve a {Sass::Tree::RootNode}.
#
# @param key [String] The key the root element was stored under.
# @param sha [String] The checksum of the root element's content.
- # @return [Sass::Tree::RootNode] The root node.
+ # @return [Object] The cached object.
def retrieve(key, sha)
contents = _retrieve(key, Sass::VERSION, sha)
Sass::Util.load(contents) if contents
3  lib/sass/engine.rb
View
@@ -150,6 +150,9 @@ def self.normalize_options(options)
# assume it's using the default filesystem importer.
options[:importer] ||= options[:filesystem_importer].new(".") if options[:filename]
+ # Tracks the original filename of the top-level Sass file
+ options[:original_filename] = options[:original_filename] || options[:filename]
+
options[:cache_store] ||= Sass::FileCacheStore.new(options[:cache_location])
# Support both, because the docs said one and the other actually worked
# for quite a long time.
10 lib/sass/exec.rb
View
@@ -78,10 +78,8 @@ def set_opts(opts)
@options[:trace] = true
end
- if ::Sass::Util.windows?
- opts.on('--unix-newlines', 'Use Unix-style newlines in written files.') do
- @options[:unix_newlines] = true
- end
+ opts.on('--unix-newlines', 'Use Unix-style newlines in written files.') do
+ @options[:unix_newlines] = true if ::Sass::Util.windows?
end
opts.on_tail("-?", "-h", "--help", "Show this message") do
@@ -279,10 +277,10 @@ def process_result
input = @options[:input]
output = @options[:output]
- @options[:syntax] ||= :scss if input.is_a?(File) && input.path =~ /\.scss$/
+ @options[:for_engine][:syntax] ||= :scss if input.is_a?(File) && input.path =~ /\.scss$/
engine =
if input.is_a?(File) && !@options[:check_syntax]
- ::Sass::Engin.for_file(input.path, @options[:for_engine])
+ ::Sass::Engine.for_file(input.path, @options[:for_engine])
else
# We don't need to do any special handling of @options[:check_syntax] here,
# because the Sass syntax checking happens alongside evaluation
7 lib/sass/plugin/compiler.rb
View
@@ -169,12 +169,11 @@ def update_stylesheets(individual_files = [])
template_location_array.each do |template_location, css_location|
- Dir.glob(File.join(template_location, "**", "*.s[ca]ss")).sort.each do |file|
+ Dir.glob(File.join(template_location, "**", "[^_]*.s[ca]ss")).sort.each do |file|
# Get the relative path to the file
name = file.sub(template_location.sub(/\/*$/, '/'), "")
css = css_filename(name, css_location)
- next if forbid_update?(name)
if options[:always_update] || staleness_checker.stylesheet_needs_update?(css, file)
update_stylesheet file, css
else
@@ -343,9 +342,5 @@ def css_locations
def css_filename(name, path)
"#{path}/#{name}".gsub(/\.s[ac]ss$/, '.css')
end
-
- def forbid_update?(name)
- name.sub(/^.*\//, '')[0] == ?_
- end
end
end
2  lib/sass/script/color.rb
View
@@ -401,7 +401,7 @@ def smallest
end
def rgba_str
- "rgba(#{rgb.join(', ')}, #{Sass::Util.tolerate(alpha)})"
+ "rgba(#{rgb.join(', ')}, #{Number.round(alpha)})"
end
def hex_str
17 lib/sass/script/functions.rb
View
@@ -66,6 +66,9 @@ module Sass::Script
# \{#complement}
# : Returns the complement of a color.
#
+ # \{#invert}
+ # : Returns the inverse of a color.
+ #
# ## Opacity Functions
#
# \{#alpha} / \{#opacity}
@@ -655,6 +658,20 @@ def complement(color)
adjust_hue color, Number.new(180)
end
+ # Returns the inverse (negative) of a color.
+ # The red, green, and blue values are inverted, while the opacity is left alone.
+ #
+ # @param color [Color]
+ # @return [Color]
+ # @raise [ArgumentError] if `color` isn't a color
+ def invert(color)
+ assert_type color, :Color
+ color.with(
+ :red => (255 - color.red),
+ :green => (255 - color.green),
+ :blue => (255 - color.blue))
+ end
+
# Removes quotes from a string if the string is quoted,
# or returns the same string if it's not.
#
27 lib/sass/script/number.rb
View
@@ -10,6 +10,12 @@ module Sass::Script
# Numbers can also have more complex units, such as `1px*em/in`.
# These cannot be inputted directly in Sass code at the moment.
class Number < Literal
+ # The precision with which numbers will be printed to CSS files.
+ # For example, if this is `1000.0`,
+ # `3.1415926` will be printed as `3.142`.
+ # @api public
+ PRECISION = 1000.0
+
# The Ruby value of the number.
#
# @return [Numeric]
@@ -242,15 +248,7 @@ def to_s
#
# @return [String] The representation
def inspect(opts = {})
- value =
- if self.value.is_a?(Float) && (self.value.infinite? || self.value.nan?)
- self.value
- elsif int?
- self.value.to_i
- else
- Sass::Util.tolerate(self.value)
- end
- "#{value}#{unit_str}"
+ "#{self.class.round(self.value)}#{unit_str}"
end
alias_method :to_sass, :inspect
@@ -328,6 +326,17 @@ def unit_str
private
+ # @private
+ def self.round(num)
+ if num.is_a?(Float) && (num.infinite? || num.nan?)
+ num
+ elsif num % 1 == 0.0
+ num.to_i
+ else
+ (num * PRECISION).round / PRECISION
+ end
+ end
+
def operate(other, operation)
this = self
if [:+, :-, :<=, :<, :>, :>=].include?(operation)
2  lib/sass/script/parser.rb
View
@@ -246,7 +246,7 @@ def ident
return if @stop_at && @stop_at.include?(@lexer.peek.value)
name = @lexer.next
- if color = Color::HTML4_COLORS[name.value]
+ if color = Color::HTML4_COLORS[name.value.downcase]
return node(Color.new(color))
end
node(Script::String.new(name.value, :identifier))
12 lib/sass/tree/node.rb
View
@@ -250,13 +250,23 @@ def to_scss(tabs = 0, opts = {})
# Ensures that only {SAVED_OPTIONS} get saved.
def _around_dump
old_options = @options
+ old_children = @children
@options = {}
SAVED_OPTIONS.each do |opt|
@options[opt] = old_options[opt]
end
+ @options = Sass::Util.dump(@options)
+ @children = Sass::Util.dump(@children)
yield
ensure
- options = old_options
+ @options = old_options
+ @children = old_children
+ end
+
+ # Ensures that only {SAVED_OPTIONS} get saved.
+ def _after_load
+ @options = Sass::Util.load(@options)
+ @children = Sass::Util.load(@children)
end
# Restructures a static Sass tree (e.g. the output of \{#perform})
2  lib/sass/tree/rule_node.rb
View
@@ -134,7 +134,7 @@ def _to_s(tabs)
per_rule_indent, total_indent = [:nested, :expanded].include?(style) ? [rule_indent, ''] : ['', rule_indent]
total_rule = total_indent + resolved_rules.members.
- map {|seq| seq.to_a.join}.
+ map {|seq| seq.to_a.join.gsub(/([^,])\n/m, style == :compressed ? '\1 ' : "\\1\n")}.
join(rule_separator).split("\n").map do |line|
per_rule_indent + line.strip
end.join(line_separator)
39 lib/sass/util.rb
View
@@ -269,13 +269,18 @@ def version_geq(v1, v2)
#
# If any of these methods are undefined, they are not called.
#
+ # This will recursively call itself on members of arrays and hashes,
+ # but not of user-defined objects.
+ # This means that user-defined objects that need their members' `#_before_dump` etc. methods called
+ # must call `Haml::Util.dump` and `Haml::Util.load` manually on those members.
+ #
# @param obj [Object] The object to dump.
# @return [String] The dumped data.
def dump(obj)
obj._before_dump if obj.respond_to?(:_before_dump)
- return Marshal.dump(obj) unless obj.respond_to?(:_around_dump)
+ return convert_and_dump(obj) unless obj.respond_to?(:_around_dump)
res = nil
- obj._around_dump {res = Marshal.dump(obj)}
+ obj._around_dump {res = convert_and_dump(obj)}
res
ensure
obj._after_dump if obj.respond_to?(:_after_dump)
@@ -288,6 +293,13 @@ def dump(obj)
# @return [Object] The loaded object.
def load(data)
obj = Marshal.load(data)
+
+ if obj.is_a?(Array)
+ obj = obj.map {|e| Sass::Util.load(e)}
+ elsif obj.is_a?(Hash)
+ obj = map_hash(obj) {|k, v| [Sass::Util.load(k), Sass::Util.load(v)]}
+ end
+
obj._after_load if obj.respond_to?(:_after_load)
obj
end
@@ -611,20 +623,6 @@ def set_eql?(set1, set2)
set1.to_a.uniq.sort_by {|e| e.hash}.eql?(set2.to_a.uniq.sort_by {|e| e.hash})
end
- # The precision with which numbers will be printed to CSS files.
- # For example, if this is `1000.0`,
- # `3.1415926` will be printed as `3.142`.
- # @api public
- PRECISION = 1000.0
-
- # Round to the nearest decimal point digit
- # @param number - the number to tolerate
- # @param precision - a multiple of 10
- def tolerate(number, precision = PRECISION)
- n = (number * precision).round / precision.to_f
- n % 1 == 0 ? n.to_i : n
- end
-
## Static Method Stuff
# The context in which the ERB for \{#def\_static\_method} will be run.
@@ -676,5 +674,14 @@ def lcs_backtrace(c, x, y, i, j, &block)
return lcs_backtrace(c, x, y, i, j-1, &block) if c[i][j-1] > c[i-1][j]
return lcs_backtrace(c, x, y, i-1, j, &block)
end
+
+ def convert_and_dump(obj)
+ if obj.is_a?(Array)
+ obj = obj.map {|e| dump(e)}
+ elsif obj.is_a?(Hash)
+ obj = map_hash(obj) {|k, v| [dump(k), dump(v)]}
+ end
+ Marshal.dump(obj)
+ end
end
end
7 test/sass/cache_test.rb
View
@@ -57,6 +57,13 @@ def test_version_change_invalidates_cache_and_cleans_up
end
end
+ def test_arbitrary_objects_can_go_into_cache
+ cache = Sass::InMemoryCacheStore.new
+ an_object = {:foo => :bar}
+ cache.store("an_object", "", an_object)
+ assert_equal an_object, cache.retrieve("an_object", "")
+ end
+
private
def root_node
Sass::Engine.new(<<-SCSS, :syntax => :scss).to_tree
14 test/sass/engine_test.rb
View
@@ -4,6 +4,7 @@
require File.dirname(__FILE__) + '/test_helper'
require 'sass/engine'
require 'stringio'
+require 'mock_importer'
module Sass::Script::Functions::UserFunctions
def option(name)
@@ -2319,6 +2320,19 @@ def test_media_with_parent_references
assert_equal css_str, render(sass_str)
end
+ def test_original_filename_set
+ importer = MockImporter.new
+ importer.add_import("imported", "div{color:red}")
+
+ original_filename = filename_for_test
+ engine = Sass::Engine.new('@import "imported"; div{color:blue}',
+ :filename => original_filename, :load_paths => [importer], :syntax => :scss)
+ engine.render
+
+ assert_equal original_filename, engine.options[:original_filename]
+ assert_equal original_filename, importer.engine("imported").options[:original_filename]
+ end
+
private
9 test/sass/functions_test.rb
View
@@ -469,6 +469,15 @@ def tets_complement_tests_types
assert_error_message("\"foo\" is not a color for `complement'", "complement(\"foo\")")
end
+ def test_invert
+ assert_equal("#112233", evaluate("invert(#edc)"))
+ assert_equal("rgba(245, 235, 225, 0.5)", evaluate("invert(rgba(10, 20, 30, 0.5))"))
+ end
+
+ def test_invert_tests_types
+ assert_error_message("\"foo\" is not a color for `invert'", "invert(\"foo\")")
+ end
+
def test_unquote
assert_equal('foo', evaluate('unquote("foo")'))
assert_equal('foo', evaluate('unquote(foo)'))
22 test/sass/importer_test.rb
View
@@ -5,6 +5,8 @@
class ImporterTest < Test::Unit::TestCase
class FruitImporter < Sass::Importers::Base
+ attr_reader :cached
+
def find(name, context = nil)
if name =~ %r{fruits/(\w+)(\.s[ac]ss)?}
fruit = $1
@@ -29,6 +31,13 @@ def find(name, context = nil)
def key(name, context)
[self.class.name, name]
end
+
+ def _around_dump
+ @cached = true
+ yield
+ ensure
+ @cached = false
+ end
end
# This class proves that you can override the extension scheme for importers
@@ -79,4 +88,17 @@ def test_extension_overrides
ensure
FileUtils.rm_rf(absolutize("tmp"))
end
+
+ def test_caching_importer
+ source = "p\n foo: bar"
+ importer = FruitImporter.new
+ filename = filename_for_test
+ engine = Sass::Engine.new(source, :filename => filename, :importer => importer)
+ engine.to_tree # Trigger caching
+
+ sha = Digest::SHA1.hexdigest(source)
+ cache = engine.options[:cache_store]
+ cached_tree = cache.retrieve(cache.key(*importer.key(filename, engine.options)), sha)
+ assert cached_tree.options[:importer].cached, "Importer's _around_dump method should have been called"
+ end
end
49 test/sass/mock_importer.rb
View
@@ -0,0 +1,49 @@
+class MockImporter < Sass::Importers::Base
+ def initialize(name = "mock")
+ @name = name
+ @imports = Hash.new({})
+ end
+
+ def find_relative(uri, base, options)
+ nil
+ end
+
+ def find(uri, options)
+ contents = @imports[uri][:contents]
+ return unless contents
+ options[:syntax] = @imports[uri][:syntax]
+ options[:filename] = uri
+ options[:importer] = self
+ @imports[uri][:engine] = Sass::Engine.new(contents, options)
+ end
+
+ def mtime(uri, options)
+ @imports[uri][:mtime]
+ end
+
+ def key(uri, options)
+ ["mock", uri]
+ end
+
+ def to_s
+ @name
+ end
+
+ # Methods for testing
+
+ def add_import(uri, contents, syntax = :scss, mtime = Time.now - 10)
+ @imports[uri] = {
+ :contents => contents,
+ :mtime => mtime,
+ :syntax => syntax
+ }
+ end
+
+ def touch(uri)
+ @imports[uri][:mtime] = Time.now
+ end
+
+ def engine(uri)
+ @imports[uri][:engine]
+ end
+end
10 test/sass/script_test.rb
View
@@ -79,6 +79,10 @@ def test_rgba_number_math
assert_equal "rgba(100, 100, 100, 0.75)", resolve("rgba(50, 50, 50, 0.75) * 2")
end
+ def test_rgba_rounding
+ assert_equal "rgba(10, 1, 0, 0.123)", resolve("rgba(10.0, 1.23456789, 0.0, 0.1234567)")
+ end
+
def test_compressed_colors
assert_equal "#123456", resolve("#123456", :style => :compressed)
assert_equal "rgba(1, 2, 3, 0.5)", resolve("rgba(1, 2, 3, 0.5)", :style => :compressed)
@@ -372,6 +376,12 @@ def test_colors_with_wrong_number_of_digits
"Colors must have either three or six digits: '#abcdEFA'") {eval("#abcdEFA")}
end
+ def test_case_insensitive_color_names
+ assert_equal "blue", resolve("BLUE")
+ assert_equal "red", resolve("rEd")
+ assert_equal "#7f4000", resolve("mix(GrEeN, ReD)")
+ end
+
# Regression Tests
def test_funcall_has_higher_precedence_than_color_name
14 test/sass/scss/scss_test.rb
View
@@ -1199,4 +1199,18 @@ def test_interpolation
ul li\#{$bar} a span.label { foo: bar; }
SCSS
end
+
+ def test_newlines_removed_from_selectors_when_compressed
+ assert_equal <<CSS, render(<<SCSS, :style=>:compressed)
+z a,z b{display:block}
+CSS
+a,
+b {
+ z & {
+ display: block;
+ }
+}
+SCSS
+
+ end
end
5 test/sass/test_helper.rb
View
@@ -1,5 +1,8 @@
+test_dir = File.dirname(__FILE__)
+$:.unshift test_dir unless $:.include?(test_dir)
+
class Test::Unit::TestCase
def absolutize(file)
"#{File.dirname(__FILE__)}/#{file}"
end
-end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.