haml 3.1.0.alpha.33 → 3.1.0.alpha.36
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of haml might be problematic. Click here for more details.
- data/EDGE_GEM_VERSION +1 -1
- data/VERSION +1 -1
- data/vendor/sass/doc-src/SASS_CHANGELOG.md +177 -2
- data/vendor/sass/doc-src/SASS_REFERENCE.md +140 -3
- data/vendor/sass/lib/sass/cache_stores.rb +14 -0
- data/vendor/sass/lib/sass/cache_stores/active_support.rb +28 -0
- data/vendor/sass/lib/sass/cache_stores/base.rb +84 -0
- data/vendor/sass/lib/sass/cache_stores/filesystem.rb +56 -0
- data/vendor/sass/lib/sass/cache_stores/memory.rb +51 -0
- data/vendor/sass/lib/sass/cache_stores/null.rb +25 -0
- data/vendor/sass/lib/sass/engine.rb +86 -25
- data/vendor/sass/lib/sass/exec.rb +10 -1
- data/vendor/sass/lib/sass/importers/rails.rb +75 -0
- data/vendor/sass/lib/sass/less.rb +1 -1
- data/vendor/sass/lib/sass/plugin/compiler.rb +4 -1
- data/vendor/sass/lib/sass/plugin/configuration.rb +4 -2
- data/vendor/sass/lib/sass/plugin/rack.rb +15 -2
- data/vendor/sass/lib/sass/plugin/rails.rb +89 -9
- data/vendor/sass/lib/sass/plugin/staleness_checker.rb +30 -2
- data/vendor/sass/lib/sass/script/css_parser.rb +1 -1
- data/vendor/sass/lib/sass/script/functions.rb +126 -5
- data/vendor/sass/lib/sass/script/lexer.rb +1 -1
- data/vendor/sass/lib/sass/script/list.rb +76 -0
- data/vendor/sass/lib/sass/script/literal.rb +10 -1
- data/vendor/sass/lib/sass/script/number.rb +1 -1
- data/vendor/sass/lib/sass/script/operation.rb +3 -2
- data/vendor/sass/lib/sass/script/parser.rb +25 -12
- data/vendor/sass/lib/sass/scss/css_parser.rb +0 -5
- data/vendor/sass/lib/sass/scss/parser.rb +46 -7
- data/vendor/sass/lib/sass/scss/static_parser.rb +1 -1
- data/vendor/sass/lib/sass/tree/charset_node.rb +37 -0
- data/vendor/sass/lib/sass/tree/directive_node.rb +2 -2
- data/vendor/sass/lib/sass/tree/each_node.rb +54 -0
- data/vendor/sass/lib/sass/tree/if_node.rb +19 -0
- data/vendor/sass/lib/sass/tree/media_node.rb +75 -0
- data/vendor/sass/lib/sass/tree/prop_node.rb +1 -1
- data/vendor/sass/lib/sass/tree/root_node.rb +37 -5
- data/vendor/sass/lib/sass/tree/rule_node.rb +4 -6
- data/vendor/sass/lib/sass/util.rb +18 -1
- data/vendor/sass/test/sass/cache_test.rb +7 -7
- data/vendor/sass/test/sass/conversion_test.rb +28 -0
- data/vendor/sass/test/sass/engine_test.rb +214 -11
- data/vendor/sass/test/sass/functions_test.rb +69 -0
- data/vendor/sass/test/sass/plugin_test.rb +13 -4
- data/vendor/sass/test/sass/results/import_charset.css +4 -0
- data/vendor/sass/test/sass/results/import_charset_1_8.css +4 -0
- data/vendor/sass/test/sass/results/import_charset_ibm866.css +4 -0
- data/vendor/sass/test/sass/script_conversion_test.rb +27 -25
- data/vendor/sass/test/sass/script_test.rb +12 -1
- data/vendor/sass/test/sass/scss/css_test.rb +27 -8
- data/vendor/sass/test/sass/scss/scss_test.rb +77 -0
- data/vendor/sass/test/sass/templates/_imported_charset_ibm866.sass +4 -0
- data/vendor/sass/test/sass/templates/_imported_charset_utf8.sass +4 -0
- data/vendor/sass/test/sass/templates/import_charset.sass +7 -0
- data/vendor/sass/test/sass/templates/import_charset_1_8.sass +4 -0
- data/vendor/sass/test/sass/templates/import_charset_ibm866.sass +9 -0
- data/vendor/sass/test/sass/templates/script.sass +2 -2
- data/vendor/sass/test/test_helper.rb +8 -0
- metadata +27 -10
- data/REVISION +0 -1
- data/vendor/sass/lib/sass/cache_store.rb +0 -208
@@ -0,0 +1,75 @@
|
|
1
|
+
module Sass
|
2
|
+
module Importers
|
3
|
+
# An importer that wraps the Rails 3.1 view infrastructure.
|
4
|
+
# Loads Sass files as though they were views in Rails.
|
5
|
+
# Currently doesn't support caching.
|
6
|
+
#
|
7
|
+
# This is different from standard Rails rendering
|
8
|
+
# in that Sass doesn't have a concept of importing partials
|
9
|
+
# as a distinct action from importing other Sass files.
|
10
|
+
# Imports within Rails behave more like Sass imports:
|
11
|
+
# they will first attempt to find a non-partial file,
|
12
|
+
# and failing that will fall back on a partial.
|
13
|
+
#
|
14
|
+
# Each importer instance is local to a single request for a single view.
|
15
|
+
# It contains the ActionView::LookupContext for that request,
|
16
|
+
# as well as the controller prefix for the view being generated.
|
17
|
+
class Rails < Base
|
18
|
+
# Creates a new Rails importer that imports files as Rails views.
|
19
|
+
def initialize; end
|
20
|
+
|
21
|
+
# @see Base#find_relative
|
22
|
+
def find_relative(uri, base, options)
|
23
|
+
find_(uri, base.split('/')[0...-1].join('/'), options)
|
24
|
+
end
|
25
|
+
|
26
|
+
# @see Base#find
|
27
|
+
def find(uri, options)
|
28
|
+
find_(uri, nil, options)
|
29
|
+
end
|
30
|
+
|
31
|
+
# @see Base#mtime
|
32
|
+
def mtime(uri, options)
|
33
|
+
return unless template =
|
34
|
+
find_template(uri, nil, !:partial, options) ||
|
35
|
+
find_template(uri, nil, :partial, options)
|
36
|
+
template.updated_at
|
37
|
+
end
|
38
|
+
|
39
|
+
# @see Base#key
|
40
|
+
def key(uri, options)
|
41
|
+
[self.class.name + ":" + uri.split('/')[0...-1].join('/'),
|
42
|
+
uri.split('/')[-1] + "." + options[:syntax].to_s]
|
43
|
+
end
|
44
|
+
|
45
|
+
# @see Base#to_s
|
46
|
+
def to_s
|
47
|
+
"(Rails importer)"
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def find_(uri, prefix, options)
|
53
|
+
prepare_template(
|
54
|
+
find_template(uri, prefix, !:partial, options) ||
|
55
|
+
find_template(uri, prefix, :partial, options),
|
56
|
+
options)
|
57
|
+
end
|
58
|
+
|
59
|
+
def find_template(uri, prefix, partial, options)
|
60
|
+
return options[:_rails_lookup_context].
|
61
|
+
find_all(uri, prefix, partial).
|
62
|
+
find {|t| t.handler.is_a?(Sass::Plugin::TemplateHandler)}
|
63
|
+
end
|
64
|
+
|
65
|
+
def prepare_template(template, options)
|
66
|
+
return unless template
|
67
|
+
options[:syntax] = template.handler.syntax
|
68
|
+
options[:filename] = template.virtual_path
|
69
|
+
options[:_rails_filename] = template.identifier
|
70
|
+
options[:importer] = self
|
71
|
+
Sass::Engine.new(template.source, options)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -251,7 +251,7 @@ WARNING
|
|
251
251
|
e, rest = _to_sass_tree_plus_minus_eq(arr)
|
252
252
|
until rest.empty?
|
253
253
|
e2, rest = _to_sass_tree_plus_minus_eq(rest)
|
254
|
-
e = Sass::Script::Operation.new(e, e2, :
|
254
|
+
e = Sass::Script::Operation.new(e, e2, :space)
|
255
255
|
end
|
256
256
|
return e
|
257
257
|
end
|
@@ -318,7 +318,10 @@ module Sass::Plugin
|
|
318
318
|
# Finally, write the file
|
319
319
|
flag = 'w'
|
320
320
|
flag = 'wb' if Sass::Util.windows? && options[:unix_newlines]
|
321
|
-
File.open(css, flag)
|
321
|
+
File.open(css, flag) do |file|
|
322
|
+
file.set_encoding(result.encoding) unless Sass::Util.ruby1_8?
|
323
|
+
file.print(result)
|
324
|
+
end
|
322
325
|
end
|
323
326
|
|
324
327
|
def try_delete_css(css)
|
@@ -31,7 +31,7 @@ module Sass
|
|
31
31
|
# @return [{Symbol => Object}]
|
32
32
|
def options
|
33
33
|
@options ||= default_options.dup
|
34
|
-
@options[:cache_store] ||= Sass::
|
34
|
+
@options[:cache_store] ||= Sass::CacheStores::Filesystem.new(@options[:cache_location])
|
35
35
|
@options
|
36
36
|
end
|
37
37
|
|
@@ -113,7 +113,9 @@ module Sass
|
|
113
113
|
return if options[:template_location].is_a?(Array)
|
114
114
|
options[:template_location] =
|
115
115
|
case options[:template_location]
|
116
|
-
when nil
|
116
|
+
when nil
|
117
|
+
options[:css_location] ?
|
118
|
+
[[File.join(options[:css_location], 'sass'), options[:css_location]]] : []
|
117
119
|
when String; [[options[:template_location], options[:css_location]]]
|
118
120
|
else; options[:template_location].to_a
|
119
121
|
end
|
@@ -24,11 +24,21 @@ module Sass
|
|
24
24
|
# The locations and frequency {file:SASS_REFERENCE.md#options can be customized}.
|
25
25
|
# That's all there is to it!
|
26
26
|
class Rack
|
27
|
+
# The delay, in seconds, between update checks.
|
28
|
+
# Useful when many resources are requested for a single page.
|
29
|
+
# `nil` means no delay at all.
|
30
|
+
#
|
31
|
+
# @return [Float]
|
32
|
+
attr_accessor :dwell
|
33
|
+
|
27
34
|
# Initialize the middleware.
|
28
35
|
#
|
29
36
|
# @param app [#call] The Rack application
|
30
|
-
|
37
|
+
# @param dwell [Float] See \{#dwell}
|
38
|
+
def initialize(app, dwell = 1.0)
|
31
39
|
@app = app
|
40
|
+
@dwell = dwell
|
41
|
+
@check_after = Time.now.to_f
|
32
42
|
end
|
33
43
|
|
34
44
|
# Process a request, checking the Sass stylesheets for changes
|
@@ -37,7 +47,10 @@ module Sass
|
|
37
47
|
# @param env The Rack request environment
|
38
48
|
# @return [(#to_i, {String => String}, Object)] The Rack response
|
39
49
|
def call(env)
|
40
|
-
|
50
|
+
if @dwell.nil? || Time.now.to_f > @check_after
|
51
|
+
Sass::Plugin.check_for_updates
|
52
|
+
@check_after = Time.now.to_f + @dwell if @dwell
|
53
|
+
end
|
41
54
|
@app.call(env)
|
42
55
|
end
|
43
56
|
end
|
@@ -4,21 +4,101 @@ unless defined?(Sass::RAILS_LOADED)
|
|
4
4
|
module Sass::Plugin::Configuration
|
5
5
|
# Different default options in a rails envirionment.
|
6
6
|
def default_options
|
7
|
-
@default_options
|
8
|
-
|
9
|
-
:template_location => Sass::Util.rails_root + '/public/stylesheets/sass',
|
10
|
-
:css_location => Sass::Util.rails_root + '/public/stylesheets',
|
11
|
-
:cache_location => Sass::Util.rails_root + '/tmp/sass-cache',
|
12
|
-
:always_check => Sass::Util.rails_env == "development",
|
7
|
+
return @default_options if @default_options
|
8
|
+
opts = {
|
13
9
|
:quiet => Sass::Util.rails_env != "production",
|
14
|
-
:full_exception => Sass::Util.rails_env != "production"
|
15
|
-
|
10
|
+
:full_exception => Sass::Util.rails_env != "production",
|
11
|
+
:cache_location => Sass::Util.rails_root + '/tmp/sass-cache'
|
12
|
+
}
|
13
|
+
|
14
|
+
if Sass::Util.ap_geq?('3.1.0.beta')
|
15
|
+
require 'sass/importers/rails'
|
16
|
+
require 'sass/cache_stores/active_support'
|
17
|
+
opts.merge!(:load_paths => [Sass::Importers::Rails.new])
|
18
|
+
opts.merge!(:cache_store => Sass::CacheStores::ActiveSupport.new(Rails.cache)) if Rails.cache
|
19
|
+
else
|
20
|
+
opts.merge!(
|
21
|
+
:always_update => false,
|
22
|
+
:template_location => Sass::Util.rails_root + '/public/stylesheets/sass',
|
23
|
+
:css_location => Sass::Util.rails_root + '/public/stylesheets',
|
24
|
+
:always_check => Sass::Util.rails_env == "development")
|
25
|
+
end
|
26
|
+
|
27
|
+
@default_options = opts.freeze
|
16
28
|
end
|
17
29
|
end
|
18
30
|
|
19
31
|
Sass::Plugin.options.reverse_merge!(Sass::Plugin.default_options)
|
20
32
|
|
21
|
-
|
33
|
+
# Disable this for now, until we figure out how to get Rails
|
34
|
+
# to pass in the view.
|
35
|
+
if Sass::Util.ap_geq?('3.1.0.beta')
|
36
|
+
class Sass::Plugin::TemplateHandler
|
37
|
+
attr_reader :syntax
|
38
|
+
|
39
|
+
def initialize(syntax)
|
40
|
+
@syntax = syntax
|
41
|
+
end
|
42
|
+
|
43
|
+
def handles_encoding?; true; end
|
44
|
+
|
45
|
+
def call(template, view)
|
46
|
+
engine = Sass::Engine.new(template.source,
|
47
|
+
Sass::Plugin.engine_options.merge(
|
48
|
+
:syntax => @syntax,
|
49
|
+
:filename => template.virtual_path,
|
50
|
+
:_rails_lookup_context => view.lookup_context,
|
51
|
+
:importer => Sass::Importers::Rails.new))
|
52
|
+
|
53
|
+
template.data[:sass_importers] = engine.dependencies.map do |e|
|
54
|
+
[e.options[:filename], e.options[:importer]]
|
55
|
+
end
|
56
|
+
|
57
|
+
stylesheet =
|
58
|
+
begin
|
59
|
+
engine.render
|
60
|
+
rescue Sass::SyntaxError => e
|
61
|
+
Sass::Plugin::TemplateHandler.munge_exception e, view.lookup_context
|
62
|
+
Sass::SyntaxError.exception_to_css(e, Sass::Plugin.engine_options)
|
63
|
+
end
|
64
|
+
|
65
|
+
<<RUBY
|
66
|
+
begin
|
67
|
+
if Sass::Plugin::TemplateHandler.dependencies_changed?(
|
68
|
+
@_template.data[:sass_importers], #{Time.now.to_i}, lookup_context)
|
69
|
+
@_template.expire!
|
70
|
+
@_template.rerender(self)
|
71
|
+
else
|
72
|
+
#{stylesheet.inspect}
|
73
|
+
end
|
74
|
+
rescue Sass::SyntaxError => e
|
75
|
+
Sass::Plugin::TemplateHandler.munge_exception e, lookup_context
|
76
|
+
Sass::SyntaxError.exception_to_css(e, Sass::Plugin.engine_options)
|
77
|
+
end
|
78
|
+
RUBY
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.dependencies_changed?(deps, since, lookup_context)
|
82
|
+
opts = Sass::Plugin.engine_options.merge(:_rails_lookup_context => lookup_context)
|
83
|
+
deps.any? do |d, i|
|
84
|
+
return true unless time = i.mtime(d, opts)
|
85
|
+
time.to_i > since
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.munge_exception(e, lookup_context)
|
90
|
+
importer = Sass::Importers::Rails.new
|
91
|
+
opts = Sass::Plugin.engine_options.merge(:_rails_lookup_context => lookup_context)
|
92
|
+
e.sass_backtrace.each do |bt|
|
93
|
+
next unless engine = importer.find(bt[:filename], opts)
|
94
|
+
bt[:filename] = engine.options[:_rails_filename]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
ActionView::Template.register_template_handler(:sass, Sass::Plugin::TemplateHandler.new(:sass))
|
100
|
+
ActionView::Template.register_template_handler(:scss, Sass::Plugin::TemplateHandler.new(:scss))
|
101
|
+
elsif defined?(ActionController::Metal)
|
22
102
|
# Rails >= 3.0
|
23
103
|
require 'sass/plugin/rack'
|
24
104
|
Rails.configuration.middleware.use(Sass::Plugin::Rack)
|
@@ -53,6 +53,7 @@ module Sass
|
|
53
53
|
# @param css_file [String] The location of the CSS file to check.
|
54
54
|
# @param template_file [String] The location of the Sass or SCSS template
|
55
55
|
# that is compiled to `css_file`.
|
56
|
+
# @return [Boolean] Whether the stylesheet needs to be updated.
|
56
57
|
def stylesheet_needs_update?(css_file, template_file)
|
57
58
|
template_file = File.expand_path(template_file)
|
58
59
|
begin
|
@@ -61,8 +62,19 @@ module Sass
|
|
61
62
|
return true
|
62
63
|
end
|
63
64
|
|
64
|
-
|
65
|
-
|
65
|
+
stylesheet_modified_since?(template_file, css_mtime)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns whether a Sass or SCSS stylesheet has been modified since a given time.
|
69
|
+
#
|
70
|
+
# @param template_file [String] The location of the Sass or SCSS template.
|
71
|
+
# @param mtime [Fixnum] The modification time to check against.
|
72
|
+
# @param importer [Sass::Importers::Base] The importer used to locate the stylesheet.
|
73
|
+
# Defaults to the filesystem importer.
|
74
|
+
# @return [Boolean] Whether the stylesheet has been modified.
|
75
|
+
def stylesheet_modified_since?(template_file, mtime, importer = nil)
|
76
|
+
importer ||= @options[:filesystem_importer].new(".")
|
77
|
+
dependency_updated?(mtime).call(template_file, importer)
|
66
78
|
end
|
67
79
|
|
68
80
|
# Returns whether or not a given CSS file is out of date
|
@@ -75,10 +87,26 @@ module Sass
|
|
75
87
|
# @param css_file [String] The location of the CSS file to check.
|
76
88
|
# @param template_file [String] The location of the Sass or SCSS template
|
77
89
|
# that is compiled to `css_file`.
|
90
|
+
# @return [Boolean] Whether the stylesheet needs to be updated.
|
78
91
|
def self.stylesheet_needs_update?(css_file, template_file)
|
79
92
|
new(Plugin.engine_options).stylesheet_needs_update?(css_file, template_file)
|
80
93
|
end
|
81
94
|
|
95
|
+
# Returns whether a Sass or SCSS stylesheet has been modified since a given time.
|
96
|
+
#
|
97
|
+
# The distinction between this method and the instance-level \{#stylesheet\_modified\_since?}
|
98
|
+
# is that the instance method preserves mtime and stale-dependency caches,
|
99
|
+
# so it's better to use when checking multiple stylesheets at once.
|
100
|
+
#
|
101
|
+
# @param template_file [String] The location of the Sass or SCSS template.
|
102
|
+
# @param mtime [Fixnum] The modification time to check against.
|
103
|
+
# @param importer [Sass::Importers::Base] The importer used to locate the stylesheet.
|
104
|
+
# Defaults to the filesystem importer.
|
105
|
+
# @return [Boolean] Whether the stylesheet has been modified.
|
106
|
+
def self.stylesheet_modified_since?(template_file, mtime, importer = nil)
|
107
|
+
new(Plugin.engine_options).stylesheet_modified_since?(template_file, mtime, importer)
|
108
|
+
end
|
109
|
+
|
82
110
|
private
|
83
111
|
|
84
112
|
def dependencies_stale?(uri, importer, css_mtime)
|
@@ -113,6 +113,17 @@ module Sass::Script
|
|
113
113
|
# \{#abs abs($value)}
|
114
114
|
# : Returns the absolute value of a number.
|
115
115
|
#
|
116
|
+
# ## List Functions {#list-functions}
|
117
|
+
#
|
118
|
+
# \{#length length($list)}
|
119
|
+
# : Returns the length of a list.
|
120
|
+
#
|
121
|
+
# \{#nth nth($list, $n)}
|
122
|
+
# : Returns a specific item in a list.
|
123
|
+
#
|
124
|
+
# \{#join join($list1, $list2, \[$separator\])}
|
125
|
+
# : Joins together two lists into one.
|
126
|
+
#
|
116
127
|
# ## Introspection Functions
|
117
128
|
#
|
118
129
|
# \{#type_of type-of($value)}
|
@@ -705,7 +716,7 @@ module Sass::Script
|
|
705
716
|
# mix(#f00, #00f) => #7f007f
|
706
717
|
# mix(#f00, #00f, 25%) => #3f00bf
|
707
718
|
# mix(rgba(255, 0, 0, 0.5), #00f) => rgba(63, 0, 191, 0.75)
|
708
|
-
# @overload mix(color1, color2, weight
|
719
|
+
# @overload mix(color1, color2, weight: 50%)
|
709
720
|
# @param color1 [Color]
|
710
721
|
# @param color2 [Color]
|
711
722
|
# @param weight [Number] between 0% and 100%
|
@@ -912,7 +923,7 @@ module Sass::Script
|
|
912
923
|
# round(10.6px) => 11px
|
913
924
|
# @param value [Number] The number
|
914
925
|
# @return [Number] The rounded number
|
915
|
-
# @raise [
|
926
|
+
# @raise [ArgumentError] if `value` isn't a number
|
916
927
|
def round(value)
|
917
928
|
numeric_transformation(value) {|n| n.round}
|
918
929
|
end
|
@@ -925,7 +936,7 @@ module Sass::Script
|
|
925
936
|
# ciel(10.6px) => 11px
|
926
937
|
# @param value [Number] The number
|
927
938
|
# @return [Number] The rounded number
|
928
|
-
# @raise [
|
939
|
+
# @raise [ArgumentError] if `value` isn't a number
|
929
940
|
def ceil(value)
|
930
941
|
numeric_transformation(value) {|n| n.ceil}
|
931
942
|
end
|
@@ -938,7 +949,7 @@ module Sass::Script
|
|
938
949
|
# floor(10.6px) => 10px
|
939
950
|
# @param value [Number] The number
|
940
951
|
# @return [Number] The rounded number
|
941
|
-
# @raise [
|
952
|
+
# @raise [ArgumentError] if `value` isn't a number
|
942
953
|
def floor(value)
|
943
954
|
numeric_transformation(value) {|n| n.floor}
|
944
955
|
end
|
@@ -951,12 +962,122 @@ module Sass::Script
|
|
951
962
|
# abs(-10px) => 10px
|
952
963
|
# @param value [Number] The number
|
953
964
|
# @return [Number] The absolute value
|
954
|
-
# @raise [
|
965
|
+
# @raise [ArgumentError] if `value` isn't a number
|
955
966
|
def abs(value)
|
956
967
|
numeric_transformation(value) {|n| n.abs}
|
957
968
|
end
|
958
969
|
declare :abs, [:value]
|
959
970
|
|
971
|
+
# Return the length of a list.
|
972
|
+
#
|
973
|
+
# @example
|
974
|
+
# length(10px) => 1
|
975
|
+
# length(10px 20px 30px) => 3
|
976
|
+
# @param list [Literal] The list
|
977
|
+
# @return [Number] The length
|
978
|
+
def length(list)
|
979
|
+
Sass::Script::Number.new(list.to_a.size)
|
980
|
+
end
|
981
|
+
declare :length, [:list]
|
982
|
+
|
983
|
+
# Gets the nth item in a list.
|
984
|
+
#
|
985
|
+
# Note that unlike some languages, the first item in a Sass list is number 1,
|
986
|
+
# the second number 2, and so forth.
|
987
|
+
#
|
988
|
+
# @example
|
989
|
+
# nth(10px 20px 30px, 1) => 10px
|
990
|
+
# nth((Helvetica, Arial, sans-serif), 3) => sans-serif
|
991
|
+
# @param list [Literal] The list
|
992
|
+
# @param n [Number] The index into the list
|
993
|
+
# @return [Literal] The nth item in the list
|
994
|
+
# @raise [ArgumentError] If `n` isn't an integer between 1 and the list's length.
|
995
|
+
def nth(list, n)
|
996
|
+
assert_type n, :Number
|
997
|
+
if !n.int?
|
998
|
+
raise ArgumentError.new("List index #{n} must be an integer")
|
999
|
+
elsif n.to_i < 1
|
1000
|
+
raise ArgumentError.new("List index #{n} must be greater than or equal to 1")
|
1001
|
+
elsif n.to_i > (size = list.to_a.size)
|
1002
|
+
raise ArgumentError.new("List index is #{n} but list is only #{size} item#{'s' if size != 1} long")
|
1003
|
+
end
|
1004
|
+
|
1005
|
+
list.to_a[n.to_i - 1]
|
1006
|
+
end
|
1007
|
+
declare :nth, [:list, :n]
|
1008
|
+
|
1009
|
+
# Joins together two lists into a new list.
|
1010
|
+
#
|
1011
|
+
# Unless the `$separator` argument is passed,
|
1012
|
+
# if one list is comma-separated and one is space-separated,
|
1013
|
+
# the first parameter's separator is used for the resulting list.
|
1014
|
+
# If the lists have only one item each, spaces are used for the resulting list.
|
1015
|
+
#
|
1016
|
+
# @example
|
1017
|
+
# join(10px 20px, 30px 40px) => 10px 20px 30px 40px
|
1018
|
+
# join((blue, red), (#abc, #def)) => blue, red, #abc, #def
|
1019
|
+
# join(10px, 20px) => 10px 20px
|
1020
|
+
# join(10px, 20px, comma) => 10px, 20px
|
1021
|
+
# join((blue, red), (#abc, #def), space) => blue red #abc #def
|
1022
|
+
# @overload join(list1, list2, separator: auto)
|
1023
|
+
# @param list1 [Literal] The first list to join
|
1024
|
+
# @param list2 [Literal] The second list to join
|
1025
|
+
# @param separator [String] How the list separator (comma or space) should be determined.
|
1026
|
+
# If this is `comma` or `space`, that is always the separator;
|
1027
|
+
# if this is `auto` (the default), the separator is determined as explained above.
|
1028
|
+
def join(list1, list2, separator = Sass::Script::String.new("auto"))
|
1029
|
+
assert_type separator, :String
|
1030
|
+
unless %w[auto space comma].include?(separator.value)
|
1031
|
+
raise ArgumentError.new("Separator name must be space, comma, or auto")
|
1032
|
+
end
|
1033
|
+
sep1 = list1.separator if list1.is_a?(Sass::Script::List)
|
1034
|
+
sep2 = list2.separator if list2.is_a?(Sass::Script::List)
|
1035
|
+
Sass::Script::List.new(
|
1036
|
+
list1.to_a + list2.to_a,
|
1037
|
+
if separator.value == 'auto'
|
1038
|
+
sep1 || sep2 || :space
|
1039
|
+
else
|
1040
|
+
separator.value.to_sym
|
1041
|
+
end)
|
1042
|
+
end
|
1043
|
+
declare :join, [:list1, :list2]
|
1044
|
+
declare :join, [:list1, :list2, :separator]
|
1045
|
+
|
1046
|
+
# Appends a single value onto the end of a list.
|
1047
|
+
#
|
1048
|
+
# Unless the `$separator` argument is passed,
|
1049
|
+
# if the list has only one item,
|
1050
|
+
# the resulting list will be space-separated.
|
1051
|
+
#
|
1052
|
+
# @example
|
1053
|
+
# append(10px 20px, 30px) => 10px 20px 30px
|
1054
|
+
# append((blue, red), green) => blue, red, green
|
1055
|
+
# append(10px 20px, 30px 40px) => 10px 20px (30px 40px)
|
1056
|
+
# join(10px, 20px, comma) => 10px, 20px
|
1057
|
+
# join((blue, red), green, space) => blue red green
|
1058
|
+
# @overload join(list, val, separator: auto)
|
1059
|
+
# @param list1 [Literal] The first list to join
|
1060
|
+
# @param list2 [Literal] The second list to join
|
1061
|
+
# @param separator [String] How the list separator (comma or space) should be determined.
|
1062
|
+
# If this is `comma` or `space`, that is always the separator;
|
1063
|
+
# if this is `auto` (the default), the separator is determined as explained above.
|
1064
|
+
def append(list, val, separator = Sass::Script::String.new("auto"))
|
1065
|
+
assert_type separator, :String
|
1066
|
+
unless %w[auto space comma].include?(separator.value)
|
1067
|
+
raise ArgumentError.new("Separator name must be space, comma, or auto")
|
1068
|
+
end
|
1069
|
+
sep = list.separator if list.is_a?(Sass::Script::List)
|
1070
|
+
Sass::Script::List.new(
|
1071
|
+
list.to_a + [val],
|
1072
|
+
if separator.value == 'auto'
|
1073
|
+
sep || :space
|
1074
|
+
else
|
1075
|
+
separator.value.to_sym
|
1076
|
+
end)
|
1077
|
+
end
|
1078
|
+
declare :append, [:list, :val]
|
1079
|
+
declare :append, [:list, :val, :separator]
|
1080
|
+
|
960
1081
|
private
|
961
1082
|
|
962
1083
|
# This method implements the pattern of transforming a numeric value into
|