compass 0.10.0.pre5 → 0.10.0.pre6
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.
- data/CHANGELOG.markdown +48 -0
- data/VERSION.yml +1 -1
- data/examples/css3/extensions/compass-colors/README.markdown +50 -0
- data/examples/css3/extensions/compass-colors/VERSION.yml +5 -0
- data/examples/css3/extensions/compass-colors/example/config.rb +13 -0
- data/examples/css3/extensions/compass-colors/example/src/_split_compliment_theme.sass +28 -0
- data/examples/css3/extensions/compass-colors/example/src/screen.sass +40 -0
- data/examples/css3/extensions/compass-colors/lib/compass-colors.rb +9 -0
- data/examples/css3/extensions/compass-colors/lib/compass-colors/compass_extension.rb +7 -0
- data/examples/css3/extensions/compass-colors/lib/compass-colors/hsl.rb +109 -0
- data/examples/css3/extensions/compass-colors/lib/compass-colors/sass_extensions.rb +112 -0
- data/examples/css3/extensions/compass-colors/spec/approximate_color_matching.rb +43 -0
- data/examples/css3/extensions/compass-colors/spec/sass_extensions_spec.rb +54 -0
- data/examples/css3/extensions/compass-colors/templates/analogous/_theme.sass +28 -0
- data/examples/css3/extensions/compass-colors/templates/analogous/manifest.rb +1 -0
- data/examples/css3/extensions/compass-colors/templates/basic/_theme.sass +7 -0
- data/examples/css3/extensions/compass-colors/templates/basic/manifest.rb +1 -0
- data/examples/css3/extensions/compass-colors/templates/complementary/_theme.sass +20 -0
- data/examples/css3/extensions/compass-colors/templates/complementary/manifest.rb +1 -0
- data/examples/css3/extensions/compass-colors/templates/split_complement/_theme.sass +28 -0
- data/examples/css3/extensions/compass-colors/templates/split_complement/manifest.rb +1 -0
- data/examples/css3/extensions/compass-colors/templates/triadic/_theme.sass +28 -0
- data/examples/css3/extensions/compass-colors/templates/triadic/manifest.rb +1 -0
- data/examples/css3/gradients.html.haml +60 -0
- data/examples/css3/index.html.haml +10 -8
- data/examples/css3/src/fancy-fonts.sass +1 -1
- data/examples/css3/src/gradients.sass +69 -0
- data/examples/css3/src/main.sass +38 -10
- data/frameworks/blueprint/stylesheets/blueprint/_liquid.sass +12 -10
- data/frameworks/blueprint/stylesheets/blueprint/modules/_buttons.sass +1 -1
- data/frameworks/blueprint/stylesheets/blueprint/modules/_colors.sass +1 -1
- data/frameworks/blueprint/stylesheets/blueprint/modules/_debug.sass +1 -1
- data/frameworks/blueprint/stylesheets/blueprint/modules/_fancy_type.sass +1 -1
- data/frameworks/blueprint/stylesheets/blueprint/modules/_form.sass +1 -1
- data/frameworks/blueprint/stylesheets/blueprint/modules/_grid.sass +1 -1
- data/frameworks/blueprint/stylesheets/blueprint/modules/_interaction.sass +1 -1
- data/frameworks/blueprint/stylesheets/blueprint/modules/_link_icons.sass +1 -1
- data/frameworks/blueprint/stylesheets/blueprint/modules/_liquid.sass +1 -1
- data/frameworks/blueprint/stylesheets/blueprint/modules/_reset.sass +1 -1
- data/frameworks/blueprint/stylesheets/blueprint/modules/_rtl.sass +1 -1
- data/frameworks/blueprint/stylesheets/blueprint/modules/_scaffolding.sass +1 -1
- data/frameworks/blueprint/stylesheets/blueprint/modules/_typography.sass +1 -1
- data/frameworks/blueprint/stylesheets/blueprint/modules/_utilities.sass +1 -1
- data/frameworks/compass/stylesheets/compass/css3/_gradient.sass +54 -36
- data/frameworks/compass/stylesheets/compass/layout/_sticky_footer.sass +1 -0
- data/frameworks/compass/stylesheets/compass/utilities/general/_hacks.sass +7 -7
- data/frameworks/compass/stylesheets/compass/utilities/lists/_horizontal_list.sass +6 -2
- data/lib/compass.rb +1 -1
- data/lib/compass/app_integration/rails.rb +6 -0
- data/lib/compass/app_integration/rails/{action_controller.rb → actionpack2/action_controller.rb} +0 -0
- data/lib/compass/app_integration/rails/{sass_plugin.rb → actionpack2/sass_plugin.rb} +0 -0
- data/lib/compass/app_integration/rails/{urls.rb → actionpack2/urls.rb} +0 -0
- data/lib/compass/app_integration/rails/installer.rb +8 -5
- data/lib/compass/app_integration/rails/runtime.rb +8 -4
- data/lib/compass/commands/installer_command.rb +1 -3
- data/lib/compass/commands/project_base.rb +1 -3
- data/lib/compass/commands/write_configuration.rb +5 -2
- data/lib/compass/compiler.rb +7 -0
- data/lib/compass/configuration/adapters.rb +3 -3
- data/lib/compass/configuration/defaults.rb +4 -0
- data/lib/compass/configuration/helpers.rb +16 -0
- data/lib/compass/configuration/inheritance.rb +6 -2
- data/lib/compass/configuration/serialization.rb +8 -3
- data/lib/compass/exec.rb +5 -1
- data/lib/compass/frameworks.rb +15 -5
- data/lib/compass/logger.rb +8 -4
- data/lib/compass/sass_extensions/functions.rb +3 -2
- data/lib/compass/sass_extensions/functions/gradient_support.rb +186 -0
- data/lib/compass/sass_extensions/functions/image_size.rb +97 -0
- data/test/compass_test.rb +1 -1
- data/test/configuration_test.rb +30 -0
- data/test/fixtures/stylesheets/compass/100x150.jpg +0 -0
- data/test/fixtures/stylesheets/compass/css/gradients.css +71 -0
- data/test/fixtures/stylesheets/compass/css/image_size.css +15 -0
- data/test/fixtures/stylesheets/compass/css/layout.css +1 -0
- data/test/fixtures/stylesheets/compass/images/100x150.gif +0 -0
- data/test/fixtures/stylesheets/compass/images/100x150.jpeg +0 -0
- data/test/fixtures/stylesheets/compass/images/100x150.jpg +0 -0
- data/test/fixtures/stylesheets/compass/images/100x150.png +0 -0
- data/test/fixtures/stylesheets/compass/sass/gradients.sass +48 -0
- data/test/fixtures/stylesheets/compass/sass/image_size.sass +12 -0
- metadata +70 -15
- data/examples/css3/src/gradient.sass +0 -10
- data/lib/compass/sass_extensions/functions/color_stop.rb +0 -10
@@ -31,6 +31,7 @@ module Compass
|
|
31
31
|
if config.is_a?(Compass::Configuration::Data)
|
32
32
|
config
|
33
33
|
elsif config.respond_to?(:read)
|
34
|
+
filename ||= config.to_s if config.is_a?(Pathname)
|
34
35
|
Compass::Configuration::Data.new_from_string(config.read, filename)
|
35
36
|
elsif config.is_a?(Hash)
|
36
37
|
Compass::Configuration::Data.new(filename, config)
|
@@ -88,6 +89,12 @@ module Compass
|
|
88
89
|
end
|
89
90
|
end
|
90
91
|
|
92
|
+
def discover_extensions!
|
93
|
+
if File.exists?(configuration.extensions_path)
|
94
|
+
Compass::Frameworks.discover(configuration.extensions_path)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
91
98
|
# Returns a full path to the relative path to the project directory
|
92
99
|
def projectize(path, project_path = nil)
|
93
100
|
project_path ||= configuration.project_path
|
@@ -112,6 +119,15 @@ module Compass
|
|
112
119
|
possible_files.detect{|f| File.exists?(f)}
|
113
120
|
end
|
114
121
|
|
122
|
+
def handle_configuration_change!
|
123
|
+
if (compiler = Compass.compiler).new_config?
|
124
|
+
compiler.clean!
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def compiler
|
129
|
+
Compass::Compiler.new(*Compass.configuration.to_compiler_arguments)
|
130
|
+
end
|
115
131
|
end
|
116
132
|
end
|
117
133
|
|
@@ -145,13 +145,17 @@ module Compass
|
|
145
145
|
end
|
146
146
|
end
|
147
147
|
|
148
|
-
def
|
148
|
+
def chain
|
149
149
|
instances = [self]
|
150
150
|
instances << instances.last.inherited_data while instances.last.inherited_data
|
151
|
+
instances
|
152
|
+
end
|
153
|
+
|
154
|
+
def debug
|
151
155
|
normalized_attrs = {}
|
152
156
|
ATTRIBUTES.each do |prop|
|
153
157
|
values = []
|
154
|
-
|
158
|
+
chain.each do |instance|
|
155
159
|
values << {
|
156
160
|
:raw => (instance.send("raw_#{prop}") rescue nil),
|
157
161
|
:value => (instance.send("#{prop}_without_default") rescue nil),
|
@@ -10,7 +10,7 @@ module Compass
|
|
10
10
|
module ClassMethods
|
11
11
|
def new_from_file(config_file)
|
12
12
|
data = Data.new(config_file)
|
13
|
-
data.
|
13
|
+
data._parse(config_file)
|
14
14
|
data
|
15
15
|
end
|
16
16
|
|
@@ -22,8 +22,12 @@ module Compass
|
|
22
22
|
end
|
23
23
|
|
24
24
|
module InstanceMethods
|
25
|
-
# parses a configuration file which is a ruby script
|
26
25
|
def parse(config_file)
|
26
|
+
raise Compass::Error, "Compass.configuration.parse(filename) has been removed. Please call Compass.add_project_configuration(filename) instead."
|
27
|
+
end
|
28
|
+
|
29
|
+
# parses a configuration file which is a ruby script
|
30
|
+
def _parse(config_file)
|
27
31
|
unless File.readable?(config_file)
|
28
32
|
raise Compass::Error, "Configuration file, #{config_file}, not found or not readable."
|
29
33
|
end
|
@@ -37,6 +41,7 @@ module Compass
|
|
37
41
|
eval(contents, bind, filename)
|
38
42
|
ATTRIBUTES.each do |prop|
|
39
43
|
value = eval(prop.to_s, bind) rescue nil
|
44
|
+
value = value.to_s if value.is_a?(Pathname)
|
40
45
|
self.send("#{prop}=", value) unless value.nil?
|
41
46
|
end
|
42
47
|
if @added_import_paths
|
@@ -73,7 +78,7 @@ module Compass
|
|
73
78
|
def serialize_property(prop, value)
|
74
79
|
%Q(#{prop} = #{value.inspect}\n)
|
75
80
|
end
|
76
|
-
|
81
|
+
|
77
82
|
def issue_deprecation_warnings
|
78
83
|
if http_images_path == :relative
|
79
84
|
$stderr.puts "DEPRECATION WARNING: Please set relative_assets = true to enable relative paths."
|
data/lib/compass/exec.rb
CHANGED
@@ -6,7 +6,11 @@ require 'compass/actions'
|
|
6
6
|
require 'compass/installers'
|
7
7
|
require 'compass/commands'
|
8
8
|
require 'rbconfig'
|
9
|
-
|
9
|
+
begin
|
10
|
+
require 'win32console' if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
|
11
|
+
rescue LoadError
|
12
|
+
$boring = true
|
13
|
+
end
|
10
14
|
|
11
15
|
module Compass::Exec
|
12
16
|
end
|
data/lib/compass/frameworks.rb
CHANGED
@@ -27,11 +27,20 @@ module Compass
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
+
def detect_registration
|
31
|
+
@registered = nil
|
32
|
+
yield
|
33
|
+
@registered
|
34
|
+
ensure
|
35
|
+
@registered = nil
|
36
|
+
end
|
37
|
+
|
30
38
|
def register(name, *arguments)
|
39
|
+
@registered = Framework.new(name, *arguments)
|
31
40
|
if idx = ALL.index(self[name])
|
32
|
-
ALL[idx] =
|
41
|
+
ALL[idx] = @registered
|
33
42
|
else
|
34
|
-
ALL <<
|
43
|
+
ALL << @registered
|
35
44
|
end
|
36
45
|
end
|
37
46
|
|
@@ -54,9 +63,10 @@ module Compass
|
|
54
63
|
File.join(directory, File.basename(directory)+".rb")
|
55
64
|
]
|
56
65
|
loader = loaders.detect{|l| File.exists?(l)}
|
57
|
-
|
58
|
-
require loader
|
59
|
-
|
66
|
+
registered_framework = detect_registration do
|
67
|
+
require loader if loader
|
68
|
+
end
|
69
|
+
unless registered_framework
|
60
70
|
register File.basename(directory), directory
|
61
71
|
end
|
62
72
|
end
|
data/lib/compass/logger.rb
CHANGED
@@ -2,12 +2,13 @@ module Compass
|
|
2
2
|
|
3
3
|
class Logger
|
4
4
|
|
5
|
-
DEFAULT_ACTIONS = [:directory, :exists, :remove, :create, :overwrite, :compile, :error, :identical]
|
5
|
+
DEFAULT_ACTIONS = [:directory, :exists, :remove, :create, :overwrite, :compile, :error, :identical, :warning]
|
6
6
|
|
7
7
|
COLORS = { :clear => 0, :red => 31, :green => 32, :yellow => 33 }
|
8
8
|
|
9
9
|
ACTION_COLORS = {
|
10
10
|
:error => :red,
|
11
|
+
:warning => :yellow,
|
11
12
|
:compile => :green,
|
12
13
|
:overwrite => :yellow,
|
13
14
|
:create => :green,
|
@@ -36,7 +37,6 @@ module Compass
|
|
36
37
|
end
|
37
38
|
|
38
39
|
def red
|
39
|
-
return yield unless Compass.configuration.color_output
|
40
40
|
$stderr.write(color(:red))
|
41
41
|
$stdout.write(color(:red))
|
42
42
|
yield
|
@@ -46,8 +46,12 @@ module Compass
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def color(c)
|
49
|
-
if c && COLORS.has_key?(c.to_sym)
|
50
|
-
|
49
|
+
if Compass.configuration.color_output && c && COLORS.has_key?(c.to_sym)
|
50
|
+
if defined?($boring) && $boring
|
51
|
+
""
|
52
|
+
else
|
53
|
+
"\e[#{COLORS[c.to_sym]}m"
|
54
|
+
end
|
51
55
|
else
|
52
56
|
""
|
53
57
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Compass::SassExtensions::Functions
|
2
2
|
end
|
3
3
|
|
4
|
-
%w(selectors enumerate urls display inline_image
|
4
|
+
%w(selectors enumerate urls display inline_image image_size gradient_support font_files).each do |func|
|
5
5
|
require "compass/sass_extensions/functions/#{func}"
|
6
6
|
end
|
7
7
|
|
@@ -11,7 +11,8 @@ module Sass::Script::Functions
|
|
11
11
|
include Compass::SassExtensions::Functions::Urls
|
12
12
|
include Compass::SassExtensions::Functions::Display
|
13
13
|
include Compass::SassExtensions::Functions::InlineImage
|
14
|
-
include Compass::SassExtensions::Functions::
|
14
|
+
include Compass::SassExtensions::Functions::ImageSize
|
15
|
+
include Compass::SassExtensions::Functions::GradientSupport::Functions
|
15
16
|
include Compass::SassExtensions::Functions::FontFiles
|
16
17
|
end
|
17
18
|
|
@@ -0,0 +1,186 @@
|
|
1
|
+
module Compass::SassExtensions::Functions::GradientSupport
|
2
|
+
|
3
|
+
class List < Sass::Script::Literal
|
4
|
+
attr_accessor :values
|
5
|
+
def initialize(*values)
|
6
|
+
self.values = values
|
7
|
+
end
|
8
|
+
def inspect
|
9
|
+
to_s
|
10
|
+
end
|
11
|
+
def to_s
|
12
|
+
values.map{|v| v.to_s}.join(", ")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class ColorStop < Sass::Script::Literal
|
17
|
+
attr_accessor :color, :stop
|
18
|
+
def initialize(color, stop = nil)
|
19
|
+
self.color, self.stop = color, stop
|
20
|
+
end
|
21
|
+
def inspect
|
22
|
+
to_s
|
23
|
+
end
|
24
|
+
def to_s
|
25
|
+
s = "#{color}"
|
26
|
+
if stop
|
27
|
+
s << " "
|
28
|
+
if stop.unitless?
|
29
|
+
s << stop.times(Sass::Script::Number.new(100, ["%"])).to_s
|
30
|
+
else
|
31
|
+
s << stop.to_s
|
32
|
+
end
|
33
|
+
end
|
34
|
+
s
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
module Functions
|
39
|
+
# returns the opposite position of a side or corner.
|
40
|
+
def grad_opposite_position(position)
|
41
|
+
opposite = position.value.split(/ +/).map do |pos|
|
42
|
+
case pos
|
43
|
+
when "top" then "bottom"
|
44
|
+
when "bottom" then "top"
|
45
|
+
when "left" then "right"
|
46
|
+
when "right" then "left"
|
47
|
+
when "center" then "center"
|
48
|
+
else
|
49
|
+
raise Sass::SyntaxError, "Cannot determine the opposite of #{pos}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
Sass::Script::String.new(opposite.join(" "))
|
53
|
+
end
|
54
|
+
|
55
|
+
# returns color-stop() calls for use in webkit.
|
56
|
+
def grad_color_stops(color_list)
|
57
|
+
normalize_stops!(color_list)
|
58
|
+
max = color_list.values.last.stop
|
59
|
+
color_stops = color_list.values.map do |pos|
|
60
|
+
# have to convert absolute units to percentages for use in color stop functions.
|
61
|
+
stop = pos.stop
|
62
|
+
stop = stop.div(max).times(Sass::Script::Number.new(100,["%"])) if stop.numerator_units == max.numerator_units
|
63
|
+
"color-stop(#{stop}, #{pos.color})"
|
64
|
+
end
|
65
|
+
Sass::Script::String.new(color_stops.join(", "))
|
66
|
+
end
|
67
|
+
|
68
|
+
# returns the end position of the gradient from the color stop
|
69
|
+
def grad_end_position(color_list, radial = Sass::Script::Bool.new(false))
|
70
|
+
default = Sass::Script::Number.new(100)
|
71
|
+
grad_position(color_list, Sass::Script::Number.new(color_list.values.size), default, radial)
|
72
|
+
end
|
73
|
+
|
74
|
+
def grad_position(color_list, index, default, radial = Sass::Script::Bool.new(false))
|
75
|
+
stop = color_list.values[index.value - 1].stop
|
76
|
+
if stop && radial.to_bool
|
77
|
+
orig_stop = stop
|
78
|
+
if stop.unitless?
|
79
|
+
if stop.value <= 1
|
80
|
+
# A unitless number is assumed to be a percentage when it's between 0 and 1
|
81
|
+
stop = stop.times(Sass::Script::Number.new(100, ["%"]))
|
82
|
+
else
|
83
|
+
# Otherwise, a unitless number is assumed to be in pixels
|
84
|
+
stop = stop.times(Sass::Script::Number.new(1, ["px"]))
|
85
|
+
end
|
86
|
+
end
|
87
|
+
if stop.numerator_units == ["%"] && color_list.values.last.stop && color_list.values.last.stop.numerator_units == ["px"]
|
88
|
+
stop = stop.times(color_list.values.last.stop).div(Sass::Script::Number.new(100, ["%"]))
|
89
|
+
end
|
90
|
+
Compass::Logger.new.record(:warning, "Webkit only supports pixels for the start and end stops for radial gradients. Got: #{orig_stop}") if stop.numerator_units != ["px"]
|
91
|
+
stop.div(Sass::Script::Number.new(1, stop.numerator_units, stop.denominator_units))
|
92
|
+
elsif stop
|
93
|
+
stop
|
94
|
+
else
|
95
|
+
default
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# the given a position, return a point in percents
|
100
|
+
def grad_point(position)
|
101
|
+
position = position.value
|
102
|
+
position = if position[" "]
|
103
|
+
if position =~ /(top|bottom|center) (left|right|center)/
|
104
|
+
"#{$2} #{$1}"
|
105
|
+
else
|
106
|
+
position
|
107
|
+
end
|
108
|
+
else
|
109
|
+
case position
|
110
|
+
when /top|bottom/
|
111
|
+
"left #{position}"
|
112
|
+
when /left|right/
|
113
|
+
"#{position} top"
|
114
|
+
else
|
115
|
+
position
|
116
|
+
end
|
117
|
+
end
|
118
|
+
Sass::Script::String.new(position.
|
119
|
+
gsub(/top/, "0%").
|
120
|
+
gsub(/bottom/, "100%").
|
121
|
+
gsub(/left/,"0%").
|
122
|
+
gsub(/right/,"100%").
|
123
|
+
gsub(/center/, "50%"))
|
124
|
+
end
|
125
|
+
|
126
|
+
def color_stops(*args)
|
127
|
+
List.new(*args.map do |arg|
|
128
|
+
case arg
|
129
|
+
when Sass::Script::Color
|
130
|
+
ColorStop.new(arg)
|
131
|
+
when Sass::Script::String
|
132
|
+
color, stop = arg.value.split(/ +/, 2)
|
133
|
+
color = Sass::Script::Parser.parse(color, 0, 0)
|
134
|
+
if stop =~ /^(\d+)?(?:\.(\d+))?(%)?$/
|
135
|
+
integral, decimal, percent = $1, $2, $3
|
136
|
+
number = "#{integral || 0}.#{decimal || 0}".to_f
|
137
|
+
number = number / 100 if percent
|
138
|
+
if number > 1
|
139
|
+
raise Sass::SyntaxError, "A color stop location must be between 0#{"%" if percent} and 1#{"00%" if percent}. Got: #{stop}"
|
140
|
+
end
|
141
|
+
stop = Sass::Script::Number.new(number)
|
142
|
+
elsif !stop.nil?
|
143
|
+
number = Sass::Script::Parser.parse(stop, 0, 0)
|
144
|
+
unless number.is_a?(Sass::Script::Number)
|
145
|
+
raise Sass::SyntaxError, "A color stop location must be a number. Got: #{stop}"
|
146
|
+
end
|
147
|
+
stop = number
|
148
|
+
end
|
149
|
+
ColorStop.new(color, stop)
|
150
|
+
else
|
151
|
+
raise Sass::SyntaxError, "Not a valid color stop: #{arg}"
|
152
|
+
end
|
153
|
+
end)
|
154
|
+
end
|
155
|
+
private
|
156
|
+
def normalize_stops!(color_list)
|
157
|
+
positions = color_list.values
|
158
|
+
# fill in the start and end positions, if unspecified
|
159
|
+
positions.first.stop = Sass::Script::Number.new(0) unless positions.first.stop
|
160
|
+
positions.last.stop = Sass::Script::Number.new(100, ["%"]) unless positions.last.stop
|
161
|
+
# fill in empty values
|
162
|
+
for i in 0...positions.size
|
163
|
+
if positions[i].stop.nil?
|
164
|
+
num = 2.0
|
165
|
+
for j in (i+1)...positions.size
|
166
|
+
if positions[j].stop
|
167
|
+
positions[i].stop = positions[i-1].stop.plus((positions[j].stop.minus(positions[i-1].stop)).div(Sass::Script::Number.new(num)))
|
168
|
+
break
|
169
|
+
else
|
170
|
+
num += 1
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
# normalize unitless numbers
|
176
|
+
positions.each do |pos|
|
177
|
+
if pos.stop.unitless? && pos.stop.value <= 1
|
178
|
+
pos.stop = pos.stop.times(Sass::Script::Number.new(100, ["%"]))
|
179
|
+
elsif pos.stop.unitless?
|
180
|
+
pos.stop = pos.stop.times(Sass::Script::Number.new(1, ["px"]))
|
181
|
+
end
|
182
|
+
end
|
183
|
+
nil
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module Compass::SassExtensions::Functions::ImageSize
|
2
|
+
# Returns the width of the image relative to the images directory
|
3
|
+
def image_width(image_file)
|
4
|
+
image_path = real_path(image_file)
|
5
|
+
width = ImageProperties.new(image_path).size.first
|
6
|
+
Sass::Script::Number.new(width,["px"])
|
7
|
+
end
|
8
|
+
|
9
|
+
# Returns the height of the image relative to the images directory
|
10
|
+
def image_height(image_file)
|
11
|
+
image_path = real_path(image_file)
|
12
|
+
height = ImageProperties.new(image_path).size.last
|
13
|
+
Sass::Script::Number.new(height, ["px"])
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def real_path(image_file)
|
18
|
+
path = image_file.value
|
19
|
+
# Compute the real path to the image on the file stystem if the images_dir is set.
|
20
|
+
if Compass.configuration.images_path
|
21
|
+
File.join(Compass.configuration.images_path, path)
|
22
|
+
else
|
23
|
+
File.join(Compass.configuration.project_path, path)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class ImageProperties
|
28
|
+
def initialize(file)
|
29
|
+
@file = file
|
30
|
+
@file_type = File.extname(@file)[1..-1]
|
31
|
+
end
|
32
|
+
|
33
|
+
def size
|
34
|
+
@dimensions ||= send(:"get_size_for_#{@file_type}")
|
35
|
+
rescue NoMethodError
|
36
|
+
raise Sass::SyntaxError, "Unrecognized file type: #{@file_type}"
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
def get_size_for_png
|
41
|
+
IO.read(@file)[0x10..0x18].unpack('NN')
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_size_for_gif
|
45
|
+
size = IO.read(@file)[6..10].unpack('SS')
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_size_for_jpg
|
49
|
+
get_size_for_jpeg
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_size_for_jpeg
|
53
|
+
jpeg = JPEG.new(@file)
|
54
|
+
[jpeg.width, jpeg.height]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class JPEG
|
59
|
+
attr_reader :width, :height, :bits
|
60
|
+
|
61
|
+
def initialize(file)
|
62
|
+
if file.kind_of? IO
|
63
|
+
examine(file)
|
64
|
+
else
|
65
|
+
File.open(file, 'rb') { |io| examine(io) }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
def examine(io)
|
71
|
+
raise 'malformed JPEG' unless io.getc == 0xFF && io.getc == 0xD8 # SOI
|
72
|
+
|
73
|
+
class << io
|
74
|
+
def readint; (readchar << 8) + readchar; end
|
75
|
+
def readframe; read(readint - 2); end
|
76
|
+
def readsof; [readint, readchar, readint, readint, readchar]; end
|
77
|
+
def next
|
78
|
+
c = readchar while c != 0xFF
|
79
|
+
c = readchar while c == 0xFF
|
80
|
+
c
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
while marker = io.next
|
85
|
+
case marker
|
86
|
+
when 0xC0..0xC3, 0xC5..0xC7, 0xC9..0xCB, 0xCD..0xCF # SOF markers
|
87
|
+
length, @bits, @height, @width, components = io.readsof
|
88
|
+
raise 'malformed JPEG' unless length == 8 + components * 3
|
89
|
+
when 0xD9, 0xDA then break # EOI, SOS
|
90
|
+
when 0xFE then @comment = io.readframe # COM
|
91
|
+
when 0xE1 then io.readframe # APP1, contains EXIF tag
|
92
|
+
else io.readframe # ignore frame
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|