sassc 2.1.0.pre1-x64-mingw32

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.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.gitmodules +3 -0
  4. data/.travis.yml +11 -0
  5. data/CHANGELOG.md +66 -0
  6. data/CODE_OF_CONDUCT.md +10 -0
  7. data/Gemfile +2 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +68 -0
  10. data/Rakefile +30 -0
  11. data/lib/sassc.rb +57 -0
  12. data/lib/sassc/dependency.rb +17 -0
  13. data/lib/sassc/engine.rb +139 -0
  14. data/lib/sassc/error.rb +37 -0
  15. data/lib/sassc/functions_handler.rb +75 -0
  16. data/lib/sassc/import_handler.rb +50 -0
  17. data/lib/sassc/importer.rb +31 -0
  18. data/lib/sassc/native.rb +70 -0
  19. data/lib/sassc/native/lib_c.rb +21 -0
  20. data/lib/sassc/native/native_context_api.rb +147 -0
  21. data/lib/sassc/native/native_functions_api.rb +164 -0
  22. data/lib/sassc/native/sass2scss_api.rb +10 -0
  23. data/lib/sassc/native/sass_input_style.rb +13 -0
  24. data/lib/sassc/native/sass_output_style.rb +12 -0
  25. data/lib/sassc/native/sass_value.rb +97 -0
  26. data/lib/sassc/native/string_list.rb +10 -0
  27. data/lib/sassc/sass_2_scss.rb +9 -0
  28. data/lib/sassc/script.rb +19 -0
  29. data/lib/sassc/script/functions.rb +8 -0
  30. data/lib/sassc/script/value.rb +137 -0
  31. data/lib/sassc/script/value/bool.rb +32 -0
  32. data/lib/sassc/script/value/color.rb +95 -0
  33. data/lib/sassc/script/value/list.rb +136 -0
  34. data/lib/sassc/script/value/map.rb +69 -0
  35. data/lib/sassc/script/value/number.rb +389 -0
  36. data/lib/sassc/script/value/string.rb +96 -0
  37. data/lib/sassc/script/value_conversion.rb +69 -0
  38. data/lib/sassc/script/value_conversion/base.rb +13 -0
  39. data/lib/sassc/script/value_conversion/bool.rb +13 -0
  40. data/lib/sassc/script/value_conversion/color.rb +18 -0
  41. data/lib/sassc/script/value_conversion/list.rb +25 -0
  42. data/lib/sassc/script/value_conversion/map.rb +21 -0
  43. data/lib/sassc/script/value_conversion/number.rb +13 -0
  44. data/lib/sassc/script/value_conversion/string.rb +17 -0
  45. data/lib/sassc/util.rb +231 -0
  46. data/lib/sassc/util/normalized_map.rb +117 -0
  47. data/lib/sassc/version.rb +5 -0
  48. data/sassc.gemspec +57 -0
  49. data/test/custom_importer_test.rb +127 -0
  50. data/test/engine_test.rb +314 -0
  51. data/test/error_test.rb +29 -0
  52. data/test/fixtures/paths.scss +10 -0
  53. data/test/functions_test.rb +303 -0
  54. data/test/native_test.rb +213 -0
  55. data/test/output_style_test.rb +107 -0
  56. data/test/sass_2_scss_test.rb +14 -0
  57. data/test/test_helper.rb +45 -0
  58. metadata +242 -0
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SassC::Script::Value::String < SassC::Script::Value
4
+
5
+ # The Ruby value of the string.
6
+ attr_reader :value
7
+
8
+ # Whether this is a CSS string or a CSS identifier.
9
+ # The difference is that strings are written with double-quotes,
10
+ # while identifiers aren't.
11
+ #
12
+ # @return [Symbol] `:string` or `:identifier`
13
+ attr_reader :type
14
+
15
+ # Returns the quoted string representation of `contents`.
16
+ #
17
+ # @options opts :quote [String]
18
+ # The preferred quote style for quoted strings. If `:none`, strings are
19
+ # always emitted unquoted. If `nil`, quoting is determined automatically.
20
+ # @options opts :sass [String]
21
+ # Whether to quote strings for Sass source, as opposed to CSS. Defaults to `false`.
22
+ def self.quote(contents, opts = {})
23
+ quote = opts[:quote]
24
+
25
+ # Short-circuit if there are no characters that need quoting.
26
+ unless contents =~ /[\n\\"']|\#\{/
27
+ quote ||= '"'
28
+ return "#{quote}#{contents}#{quote}"
29
+ end
30
+
31
+ if quote.nil?
32
+ if contents.include?('"')
33
+ if contents.include?("'")
34
+ quote = '"'
35
+ else
36
+ quote = "'"
37
+ end
38
+ else
39
+ quote = '"'
40
+ end
41
+ end
42
+
43
+ # Replace single backslashes with multiples.
44
+ contents = contents.gsub("\\", "\\\\\\\\")
45
+
46
+ # Escape interpolation.
47
+ contents = contents.gsub('#{', "\\\#{") if opts[:sass]
48
+
49
+ if quote == '"'
50
+ contents = contents.gsub('"', "\\\"")
51
+ else
52
+ contents = contents.gsub("'", "\\'")
53
+ end
54
+
55
+ contents = contents.gsub(/\n(?![a-fA-F0-9\s])/, "\\a").gsub("\n", "\\a ")
56
+ "#{quote}#{contents}#{quote}"
57
+ end
58
+
59
+ # Creates a new string.
60
+ #
61
+ # @param value [String] See \{#value}
62
+ # @param type [Symbol] See \{#type}
63
+ # @param deprecated_interp_equivalent [String?]
64
+ # If this was created via a potentially-deprecated string interpolation,
65
+ # this is the replacement expression that should be suggested to the user.
66
+ def initialize(value, type = :identifier)
67
+ super(value)
68
+ @type = type
69
+ end
70
+
71
+ # @see Value#plus
72
+ def plus(other)
73
+ if other.is_a?(SassC::Script::Value::String)
74
+ other_value = other.value
75
+ else
76
+ other_value = other.to_s(:quote => :none)
77
+ end
78
+ SassC::Script::Value::String.new(value + other_value, type)
79
+ end
80
+
81
+ # @see Value#to_s
82
+ def to_s(opts = {})
83
+ return @value.gsub(/\n\s*/, ' ') if opts[:quote] == :none || @type == :identifier
84
+ self.class.quote(value, opts)
85
+ end
86
+
87
+ # @see Value#to_sass
88
+ def to_sass(opts = {})
89
+ to_s(opts.merge(:sass => true))
90
+ end
91
+
92
+ def inspect
93
+ String.quote(value)
94
+ end
95
+
96
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SassC::Script::ValueConversion
4
+
5
+ def self.from_native(native_value, options)
6
+ case value_tag = SassC::Native.value_get_tag(native_value)
7
+ when :sass_null
8
+ # no-op
9
+ when :sass_string
10
+ value = SassC::Native.string_get_value(native_value)
11
+ type = SassC::Native.string_get_type(native_value)
12
+ argument = SassC::Script::Value::String.new(value, type)
13
+ argument
14
+ when :sass_boolean
15
+ value = SassC::Native.boolean_get_value(native_value)
16
+ argument = SassC::Script::Value::Bool.new(value)
17
+ argument
18
+ when :sass_number
19
+ value = SassC::Native.number_get_value(native_value)
20
+ unit = SassC::Native.number_get_unit(native_value)
21
+ argument = SassC::Script::Value::Number.new(value, unit)
22
+ argument
23
+ when :sass_color
24
+ red, green, blue, alpha = SassC::Native.color_get_r(native_value), SassC::Native.color_get_g(native_value), SassC::Native.color_get_b(native_value), SassC::Native.color_get_a(native_value)
25
+ argument = SassC::Script::Value::Color.new(red:red, green:green, blue:blue, alpha:alpha)
26
+ argument.options = options
27
+ argument
28
+ when :sass_map
29
+ values = {}
30
+ length = SassC::Native::map_get_length native_value
31
+ (0..length-1).each do |index|
32
+ key = SassC::Native::map_get_key(native_value, index)
33
+ value = SassC::Native::map_get_value(native_value, index)
34
+ values[from_native(key, options)] = from_native(value, options)
35
+ end
36
+ argument = SassC::Script::Value::Map.new values
37
+ argument
38
+ when :sass_list
39
+ length = SassC::Native::list_get_length(native_value)
40
+ items = (0...length).map do |index|
41
+ native_item = SassC::Native::list_get_value(native_value, index)
42
+ from_native(native_item, options)
43
+ end
44
+ SassC::Script::Value::List.new(items, separator: :space)
45
+ else
46
+ raise UnsupportedValue.new("Sass argument of type #{value_tag} unsupported")
47
+ end
48
+ end
49
+
50
+ def self.to_native(value)
51
+ case value_name = value.class.name.split("::").last
52
+ when "String"
53
+ SassC::Script::ValueConversion::String.new(value).to_native
54
+ when "Color"
55
+ SassC::Script::ValueConversion::Color.new(value).to_native
56
+ when "Number"
57
+ SassC::Script::ValueConversion::Number.new(value).to_native
58
+ when "Map"
59
+ SassC::Script::ValueConversion::Map.new(value).to_native
60
+ when "List"
61
+ SassC::Script::ValueConversion::List.new(value).to_native
62
+ when "Bool"
63
+ SassC::Script::ValueConversion::Bool.new(value).to_native
64
+ else
65
+ raise SassC::UnsupportedValue.new("Sass return type #{value_name} unsupported")
66
+ end
67
+ end
68
+
69
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SassC
4
+ module Script
5
+ module ValueConversion
6
+ class Base
7
+ def initialize(value)
8
+ @value = value
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SassC
4
+ module Script
5
+ module ValueConversion
6
+ class Bool < Base
7
+ def to_native
8
+ Native::make_boolean(@value.value)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SassC
4
+ module Script
5
+ module ValueConversion
6
+ class Color < Base
7
+ def to_native
8
+ Native::make_color(
9
+ @value.red,
10
+ @value.green,
11
+ @value.blue,
12
+ @value.alpha
13
+ )
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SassC
4
+ module Script
5
+ module ValueConversion
6
+ SEPARATORS = {
7
+ space: :sass_space,
8
+ comma: :sass_comma
9
+ }
10
+
11
+ class List < Base
12
+ def to_native
13
+ list = @value.to_a
14
+ sep = SEPARATORS.fetch(@value.separator)
15
+ native_list = Native::make_list(list.size, sep)
16
+ list.each_with_index do |item, index|
17
+ native_item = ValueConversion.to_native(item)
18
+ Native::list_set_value(native_list, index, native_item)
19
+ end
20
+ native_list
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SassC
4
+ module Script
5
+ module ValueConversion
6
+ class Map < Base
7
+ def to_native
8
+ hash = @value.to_h
9
+ native_map = Native::make_map( hash.size )
10
+ hash.each_with_index do |(key, value), index|
11
+ key = ValueConversion.to_native key
12
+ value = ValueConversion.to_native value
13
+ Native::map_set_key( native_map, index, key )
14
+ Native::map_set_value( native_map, index, value )
15
+ end
16
+ return native_map
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SassC
4
+ module Script
5
+ module ValueConversion
6
+ class Number < Base
7
+ def to_native
8
+ Native::make_number(@value.value, @value.numerator_units.first)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SassC
4
+ module Script
5
+ module ValueConversion
6
+ class String < Base
7
+ def to_native(opts = {})
8
+ if opts[:quote] == :none || @value.type == :identifier
9
+ Native::make_string(@value.to_s)
10
+ else
11
+ Native::make_qstring(@value.to_s)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
data/lib/sassc/util.rb ADDED
@@ -0,0 +1,231 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "erb"
4
+ require "set"
5
+ require "enumerator"
6
+ require "stringio"
7
+ require "rbconfig"
8
+ require "uri"
9
+ require "thread"
10
+ require "pathname"
11
+
12
+ # A module containing various useful functions.
13
+
14
+ module SassC::Util
15
+
16
+ extend self
17
+
18
+ # An array of ints representing the Ruby version number.
19
+ # @api public
20
+ RUBY_VERSION_COMPONENTS = RUBY_VERSION.split(".").map {|s| s.to_i}
21
+
22
+ # The Ruby engine we're running under. Defaults to `"ruby"`
23
+ # if the top-level constant is undefined.
24
+ # @api public
25
+ RUBY_ENGINE = defined?(::RUBY_ENGINE) ? ::RUBY_ENGINE : "ruby"
26
+
27
+ # Maps the keys in a hash according to a block.
28
+ # @example
29
+ # map_keys({:foo => "bar", :baz => "bang"}) {|k| k.to_s}
30
+ # #=> {"foo" => "bar", "baz" => "bang"}
31
+ # @param hash [Hash] The hash to map
32
+ # @yield [key] A block in which the keys are transformed
33
+ # @yieldparam key [Object] The key that should be mapped
34
+ # @yieldreturn [Object] The new value for the key
35
+ # @return [Hash] The mapped hash
36
+ # @see #map_vals
37
+ # @see #map_hash
38
+ def map_keys(hash)
39
+ map_hash(hash) {|k, v| [yield(k), v]}
40
+ end
41
+
42
+ # Restricts the numeric `value` to be within `min` and `max`, inclusive.
43
+ # If the value is lower than `min`
44
+ def clamp(value, min, max)
45
+ return min if value < min
46
+ return max if value > max
47
+ return value
48
+ end
49
+
50
+ # Like [Fixnum.round], but leaves rooms for slight floating-point
51
+ # differences.
52
+ #
53
+ # @param value [Numeric]
54
+ # @return [Numeric]
55
+ def round(value)
56
+ # If the number is within epsilon of X.5, round up (or down for negative
57
+ # numbers).
58
+ mod = value % 1
59
+ mod_is_half = (mod - 0.5).abs < SassC::Script::Value::Number.epsilon
60
+ if value > 0
61
+ !mod_is_half && mod < 0.5 ? value.floor : value.ceil
62
+ else
63
+ mod_is_half || mod < 0.5 ? value.floor : value.ceil
64
+ end
65
+ end
66
+
67
+ # Return an array of all possible paths through the given arrays.
68
+ #
69
+ # @param arrs [Array<Array>]
70
+ # @return [Array<Arrays>]
71
+ #
72
+ # @example
73
+ # paths([[1, 2], [3, 4], [5]]) #=>
74
+ # # [[1, 3, 5],
75
+ # # [2, 3, 5],
76
+ # # [1, 4, 5],
77
+ # # [2, 4, 5]]
78
+ def paths(arrs)
79
+ arrs.inject([[]]) do |paths, arr|
80
+ arr.map {|e| paths.map {|path| path + [e]}}.flatten(1)
81
+ end
82
+ end
83
+
84
+ # Returns information about the caller of the previous method.
85
+ #
86
+ # @param entry [String] An entry in the `#caller` list, or a similarly formatted string
87
+ # @return [[String, Integer, (String, nil)]]
88
+ # An array containing the filename, line, and method name of the caller.
89
+ # The method name may be nil
90
+ def caller_info(entry = nil)
91
+ # JRuby evaluates `caller` incorrectly when it's in an actual default argument.
92
+ entry ||= caller[1]
93
+ info = entry.scan(/^((?:[A-Za-z]:)?.*?):(-?.*?)(?::.*`(.+)')?$/).first
94
+ info[1] = info[1].to_i
95
+ # This is added by Rubinius to designate a block, but we don't care about it.
96
+ info[2].sub!(/ \{\}\Z/, '') if info[2]
97
+ info
98
+ end
99
+
100
+ # Throws a NotImplementedError for an abstract method.
101
+ #
102
+ # @param obj [Object] `self`
103
+ # @raise [NotImplementedError]
104
+ def abstract(obj)
105
+ raise NotImplementedError.new("#{obj.class} must implement ##{caller_info[2]}")
106
+ end
107
+
108
+ # Prints a deprecation warning for the caller method.
109
+ #
110
+ # @param obj [Object] `self`
111
+ # @param message [String] A message describing what to do instead.
112
+ def deprecated(obj, message = nil)
113
+ obj_class = obj.is_a?(Class) ? "#{obj}." : "#{obj.class}#"
114
+ full_message = "DEPRECATION WARNING: #{obj_class}#{caller_info[2]} " +
115
+ "will be removed in a future version of Sass.#{("\n" + message) if message}"
116
+ SassC::Util.sass_warn full_message
117
+ end
118
+
119
+ # Silences all Sass warnings within a block.
120
+ #
121
+ # @yield A block in which no Sass warnings will be printed
122
+ def silence_sass_warnings
123
+ old_level, Sass.logger.log_level = Sass.logger.log_level, :error
124
+ yield
125
+ ensure
126
+ SassC.logger.log_level = old_level
127
+ end
128
+
129
+ # The same as `Kernel#warn`, but is silenced by \{#silence\_sass\_warnings}.
130
+ #
131
+ # @param msg [String]
132
+ def sass_warn(msg)
133
+ Sass.logger.warn("#{msg}\n")
134
+ end
135
+
136
+ ## Cross Rails Version Compatibility
137
+
138
+ # Returns the root of the Rails application,
139
+ # if this is running in a Rails context.
140
+ # Returns `nil` if no such root is defined.
141
+ #
142
+ # @return [String, nil]
143
+ def rails_root
144
+ if defined?(::Rails.root)
145
+ return ::Rails.root.to_s if ::Rails.root
146
+ raise "ERROR: Rails.root is nil!"
147
+ end
148
+ return RAILS_ROOT.to_s if defined?(RAILS_ROOT)
149
+ nil
150
+ end
151
+
152
+ # Returns the environment of the Rails application,
153
+ # if this is running in a Rails context.
154
+ # Returns `nil` if no such environment is defined.
155
+ #
156
+ # @return [String, nil]
157
+ def rails_env
158
+ return ::Rails.env.to_s if defined?(::Rails.env)
159
+ return RAILS_ENV.to_s if defined?(RAILS_ENV)
160
+ nil
161
+ end
162
+
163
+ ## Cross-OS Compatibility
164
+ #
165
+ # These methods are cached because some of them are called quite frequently
166
+ # and even basic checks like String#== are too costly to be called repeatedly.
167
+
168
+ # Whether or not this is running on Windows.
169
+ #
170
+ # @return [Boolean]
171
+ def windows?
172
+ return @windows if defined?(@windows)
173
+ @windows = (RbConfig::CONFIG['host_os'] =~ /mswin|windows|mingw/i)
174
+ end
175
+
176
+ # Whether or not this is running on IronRuby.
177
+ #
178
+ # @return [Boolean]
179
+ def ironruby?
180
+ return @ironruby if defined?(@ironruby)
181
+ @ironruby = RUBY_ENGINE == "ironruby"
182
+ end
183
+
184
+ # Whether or not this is running on Rubinius.
185
+ #
186
+ # @return [Boolean]
187
+ def rbx?
188
+ return @rbx if defined?(@rbx)
189
+ @rbx = RUBY_ENGINE == "rbx"
190
+ end
191
+
192
+ # Whether or not this is running on JRuby.
193
+ #
194
+ # @return [Boolean]
195
+ def jruby?
196
+ return @jruby if defined?(@jruby)
197
+ @jruby = RUBY_PLATFORM =~ /java/
198
+ end
199
+
200
+ # Returns an array of ints representing the JRuby version number.
201
+ #
202
+ # @return [Array<Integer>]
203
+ def jruby_version
204
+ @jruby_version ||= ::JRUBY_VERSION.split(".").map {|s| s.to_i}
205
+ end
206
+
207
+ # Returns `path` relative to `from`.
208
+ #
209
+ # This is like `Pathname#relative_path_from` except it accepts both strings
210
+ # and pathnames, it handles Windows path separators correctly, and it throws
211
+ # an error rather than crashing if the paths use different encodings
212
+ # (https://github.com/ruby/ruby/pull/713).
213
+ #
214
+ # @param path [String, Pathname]
215
+ # @param from [String, Pathname]
216
+ # @return [Pathname?]
217
+ def relative_path_from(path, from)
218
+ pathname(path.to_s).relative_path_from(pathname(from.to_s))
219
+ rescue NoMethodError => e
220
+ raise e unless e.name == :zero?
221
+
222
+ # Work around https://github.com/ruby/ruby/pull/713.
223
+ path = path.to_s
224
+ from = from.to_s
225
+ raise ArgumentError("Incompatible path encodings: #{path.inspect} is #{path.encoding}, " +
226
+ "#{from.inspect} is #{from.encoding}")
227
+ end
228
+
229
+ singleton_methods.each {|method| module_function method}
230
+
231
+ end