Skip to content

Commit

Permalink
Merge branch 'master' into awesome_media
Browse files Browse the repository at this point in the history
* master: (23 commits)
  [Sass] Proper fix for sassGH-275 that doesn't break other tests. Closes sassGH-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
chriseppstein committed Sep 25, 2010
2 parents 278a35f + 85aa757 commit 4ac1362
Show file tree
Hide file tree
Showing 21 changed files with 227 additions and 51 deletions.
14 changes: 14 additions & 0 deletions doc-src/SASS_CHANGELOG.md
Expand Up @@ -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,
Expand All @@ -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).
Expand Down
2 changes: 1 addition & 1 deletion extra/update_watch.rb
@@ -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__) + "/..")
Expand Down
11 changes: 3 additions & 8 deletions lib/sass/cache_store.rb
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions lib/sass/engine.rb
Expand Up @@ -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.
Expand Down
10 changes: 4 additions & 6 deletions lib/sass/exec.rb
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
7 changes: 1 addition & 6 deletions lib/sass/plugin/compiler.rb
Expand Up @@ -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
Expand Down Expand Up @@ -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 changes: 1 addition & 1 deletion lib/sass/script/color.rb
Expand Up @@ -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
Expand Down
17 changes: 17 additions & 0 deletions lib/sass/script/functions.rb
Expand Up @@ -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}
Expand Down Expand Up @@ -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.
#
Expand Down
27 changes: 18 additions & 9 deletions lib/sass/script/number.rb
Expand Up @@ -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]
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion lib/sass/script/parser.rb
Expand Up @@ -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))
Expand Down
12 changes: 11 additions & 1 deletion lib/sass/tree/node.rb
Expand Up @@ -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})
Expand Down
2 changes: 1 addition & 1 deletion lib/sass/tree/rule_node.rb
Expand Up @@ -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)
Expand Down
39 changes: 23 additions & 16 deletions lib/sass/util.rb
Expand Up @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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 changes: 7 additions & 0 deletions test/sass/cache_test.rb
Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions test/sass/engine_test.rb
Expand Up @@ -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)
Expand Down Expand Up @@ -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

Expand Down
9 changes: 9 additions & 0 deletions test/sass/functions_test.rb
Expand Up @@ -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)'))
Expand Down

0 comments on commit 4ac1362

Please sign in to comment.