haml 3.0.0.beta.3 → 3.0.0.rc.1
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/.yardopts +2 -0
- data/REMEMBER +4 -11
- data/Rakefile +24 -2
- data/VERSION +1 -1
- data/lib/haml.rb +5 -2
- data/lib/haml/exec.rb +11 -4
- data/lib/haml/filters.rb +3 -0
- data/lib/haml/helpers.rb +2 -10
- data/lib/haml/helpers/action_view_extensions.rb +4 -2
- data/lib/haml/helpers/action_view_mods.rb +6 -4
- data/lib/haml/html.rb +0 -1
- data/lib/haml/precompiler.rb +37 -30
- data/lib/haml/railtie.rb +6 -2
- data/lib/haml/root.rb +4 -0
- data/lib/haml/template.rb +2 -0
- data/lib/haml/util.rb +74 -0
- data/lib/haml/util/subset_map.rb +101 -0
- data/lib/sass.rb +1 -0
- data/lib/sass/engine.rb +36 -31
- data/lib/sass/files.rb +1 -1
- data/lib/sass/plugin.rb +21 -0
- data/lib/sass/plugin/staleness_checker.rb +9 -9
- data/lib/sass/script.rb +1 -2
- data/lib/sass/script/color.rb +4 -3
- data/lib/sass/script/css_lexer.rb +11 -1
- data/lib/sass/script/css_parser.rb +4 -1
- data/lib/sass/script/funcall.rb +9 -0
- data/lib/sass/script/interpolation.rb +21 -0
- data/lib/sass/script/lexer.rb +30 -13
- data/lib/sass/script/node.rb +1 -1
- data/lib/sass/script/number.rb +4 -5
- data/lib/sass/script/parser.rb +13 -14
- data/lib/sass/script/string.rb +8 -2
- data/lib/sass/script/string_interpolation.rb +27 -4
- data/lib/sass/scss.rb +3 -0
- data/lib/sass/scss/css_parser.rb +5 -3
- data/lib/sass/scss/parser.rb +146 -64
- data/lib/sass/scss/rx.rb +9 -1
- data/lib/sass/scss/sass_parser.rb +11 -0
- data/lib/sass/scss/script_lexer.rb +2 -0
- data/lib/sass/scss/static_parser.rb +48 -0
- data/lib/sass/selector.rb +353 -0
- data/lib/sass/selector/abstract_sequence.rb +40 -0
- data/lib/sass/selector/comma_sequence.rb +80 -0
- data/lib/sass/selector/sequence.rb +194 -0
- data/lib/sass/selector/simple.rb +107 -0
- data/lib/sass/selector/simple_sequence.rb +161 -0
- data/lib/sass/tree/comment_node.rb +1 -0
- data/lib/sass/tree/debug_node.rb +1 -0
- data/lib/sass/tree/directive_node.rb +1 -0
- data/lib/sass/tree/extend_node.rb +60 -0
- data/lib/sass/tree/for_node.rb +1 -0
- data/lib/sass/tree/if_node.rb +2 -0
- data/lib/sass/tree/import_node.rb +2 -0
- data/lib/sass/tree/mixin_def_node.rb +1 -0
- data/lib/sass/tree/mixin_node.rb +21 -5
- data/lib/sass/tree/node.rb +59 -12
- data/lib/sass/tree/prop_node.rb +20 -21
- data/lib/sass/tree/root_node.rb +8 -17
- data/lib/sass/tree/rule_node.rb +49 -100
- data/lib/sass/tree/variable_node.rb +1 -0
- data/lib/sass/tree/warn_node.rb +1 -0
- data/lib/sass/tree/while_node.rb +1 -0
- data/test/haml/engine_test.rb +185 -3
- data/test/haml/helper_test.rb +25 -2
- data/test/haml/template_test.rb +2 -2
- data/test/haml/templates/helpers.haml +13 -0
- data/test/haml/util/subset_map_test.rb +91 -0
- data/test/haml/util_test.rb +25 -0
- data/test/sass/conversion_test.rb +23 -3
- data/test/sass/engine_test.rb +50 -7
- data/test/sass/extend_test.rb +1045 -0
- data/test/sass/results/complex.css +0 -1
- data/test/sass/results/script.css +1 -1
- data/test/sass/script_conversion_test.rb +16 -0
- data/test/sass/script_test.rb +37 -4
- data/test/sass/scss/css_test.rb +17 -3
- data/test/sass/scss/rx_test.rb +1 -1
- data/test/sass/scss/scss_test.rb +30 -0
- data/test/sass/templates/complex.sass +0 -2
- data/test/test_helper.rb +5 -0
- metadata +18 -4
data/lib/haml/root.rb
CHANGED
data/lib/haml/template.rb
CHANGED
data/lib/haml/util.rb
CHANGED
@@ -3,6 +3,7 @@ require 'set'
|
|
3
3
|
require 'enumerator'
|
4
4
|
require 'stringio'
|
5
5
|
require 'haml/root'
|
6
|
+
require 'haml/util/subset_map'
|
6
7
|
|
7
8
|
module Haml
|
8
9
|
# A module containing various useful functions.
|
@@ -10,6 +11,7 @@ module Haml
|
|
10
11
|
extend self
|
11
12
|
|
12
13
|
# An array of ints representing the Ruby version number.
|
14
|
+
# @api public
|
13
15
|
RUBY_VERSION = ::RUBY_VERSION.split(".").map {|s| s.to_i}
|
14
16
|
|
15
17
|
# Returns the path of a file relative to the Haml root directory.
|
@@ -135,6 +137,33 @@ module Haml
|
|
135
137
|
end
|
136
138
|
end
|
137
139
|
|
140
|
+
# Intersperses a value in an enumerable, as would be done with `Array#join`
|
141
|
+
# but without concatenating the array together afterwards.
|
142
|
+
#
|
143
|
+
# @param enum [Enumerable]
|
144
|
+
# @param val
|
145
|
+
# @return [Array]
|
146
|
+
def intersperse(enum, val)
|
147
|
+
enum.inject([]) {|a, e| a << e << val}[0...-1]
|
148
|
+
end
|
149
|
+
|
150
|
+
# Substitutes a sub-array of one array with another sub-array.
|
151
|
+
#
|
152
|
+
# @param ary [Array] The array in which to make the substitution
|
153
|
+
# @param from [Array] The sequence of elements to replace with `to`
|
154
|
+
# @param to [Array] The sequence of elements to replace `from` with
|
155
|
+
def substitute(ary, from, to)
|
156
|
+
res = ary.dup
|
157
|
+
i = 0
|
158
|
+
while i < res.size
|
159
|
+
if res[i...i+from.size] == from
|
160
|
+
res[i...i+from.size] = to
|
161
|
+
end
|
162
|
+
i += 1
|
163
|
+
end
|
164
|
+
res
|
165
|
+
end
|
166
|
+
|
138
167
|
# Destructively strips whitespace from the beginning and end
|
139
168
|
# of the first and last elements, respectively,
|
140
169
|
# in the array (if those elements are strings).
|
@@ -147,6 +176,23 @@ module Haml
|
|
147
176
|
arr
|
148
177
|
end
|
149
178
|
|
179
|
+
# Return an array of all possible paths through the given arrays.
|
180
|
+
#
|
181
|
+
# @param arrs [Array<Array>]
|
182
|
+
# @return [Array<Arrays>]
|
183
|
+
#
|
184
|
+
# @example
|
185
|
+
# paths([[1, 2], [3, 4], [5]]) #=>
|
186
|
+
# # [[1, 3, 5],
|
187
|
+
# # [2, 3, 5],
|
188
|
+
# # [1, 4, 5],
|
189
|
+
# # [2, 4, 5]]
|
190
|
+
def paths(arrs)
|
191
|
+
arrs.inject([[]]) do |paths, arr|
|
192
|
+
arr.map {|e| paths.map {|path| path + [e]}}.flatten(1)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
150
196
|
# Returns information about the caller of the previous method.
|
151
197
|
#
|
152
198
|
# @param entry [String] An entry in the `#caller` list, or a similarly formatted string
|
@@ -237,6 +283,30 @@ module Haml
|
|
237
283
|
ActionPack::VERSION::TINY == "0.beta")
|
238
284
|
end
|
239
285
|
|
286
|
+
# Returns whether this environment is using ActionPack
|
287
|
+
# version 3.0.0.beta.3 or greater.
|
288
|
+
#
|
289
|
+
# @return [Boolean]
|
290
|
+
def ap_geq_3_beta_3?
|
291
|
+
# The ActionPack module is always loaded automatically in Rails >= 3
|
292
|
+
return false unless defined?(ActionPack) && defined?(ActionPack::VERSION)
|
293
|
+
|
294
|
+
version =
|
295
|
+
if defined?(ActionPack::VERSION::MAJOR)
|
296
|
+
ActionPack::VERSION::MAJOR
|
297
|
+
else
|
298
|
+
# Rails 1.2
|
299
|
+
ActionPack::VERSION::Major
|
300
|
+
end
|
301
|
+
version >= 3 &&
|
302
|
+
((defined?(ActionPack::VERSION::TINY) &&
|
303
|
+
ActionPack::VERSION::TINY.is_a?(Fixnum) &&
|
304
|
+
ActionPack::VERSION::TINY >= 1) ||
|
305
|
+
(defined?(ActionPack::VERSION::BUILD) &&
|
306
|
+
ActionPack::VERSION::BUILD =~ /beta(\d+)/ &&
|
307
|
+
$1.to_i >= 3))
|
308
|
+
end
|
309
|
+
|
240
310
|
# Returns an ActionView::Template* class.
|
241
311
|
# In pre-3.0 versions of Rails, most of these classes
|
242
312
|
# were of the form `ActionView::TemplateFoo`,
|
@@ -282,6 +352,10 @@ module Haml
|
|
282
352
|
raise Haml::Error.new("Expected #{text.inspect} to be HTML-safe.")
|
283
353
|
end
|
284
354
|
|
355
|
+
# The class for the Rails SafeBuffer XSS protection class.
|
356
|
+
# This varies depending on Rails version.
|
357
|
+
#
|
358
|
+
# @return [Class]
|
285
359
|
def rails_safe_buffer_class
|
286
360
|
return ActionView::SafeBuffer if defined?(ActionView::SafeBuffer)
|
287
361
|
ActiveSupport::SafeBuffer
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Haml
|
4
|
+
module Util
|
5
|
+
# A map from sets to values.
|
6
|
+
# A value is \{#\[]= set} by providing a set (the "set-set") and a value,
|
7
|
+
# which is then recorded as corresponding to that set.
|
8
|
+
# Values are \{#\[] accessed} by providing a set (the "get-set")
|
9
|
+
# and returning all values that correspond to set-sets
|
10
|
+
# that are subsets of the get-set.
|
11
|
+
#
|
12
|
+
# SubsetMap preserves the order of values as they're inserted.
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# ssm = SubsetMap.new
|
16
|
+
# ssm[Set[1, 2]] = "Foo"
|
17
|
+
# ssm[Set[2, 3]] = "Bar"
|
18
|
+
# ssm[Set[1, 2, 3]] = "Baz"
|
19
|
+
#
|
20
|
+
# ssm[Set[1, 2, 3]] #=> ["Foo", "Bar", "Baz"]
|
21
|
+
class SubsetMap
|
22
|
+
# Creates a new, empty SubsetMap.
|
23
|
+
def initialize
|
24
|
+
@hash = {}
|
25
|
+
@vals = []
|
26
|
+
end
|
27
|
+
|
28
|
+
# Whether or not this SubsetMap has any key-value pairs.
|
29
|
+
#
|
30
|
+
# @return [Boolean]
|
31
|
+
def empty?
|
32
|
+
@hash.empty?
|
33
|
+
end
|
34
|
+
|
35
|
+
# Associates a value with a set.
|
36
|
+
# When `set` or any of its supersets is accessed,
|
37
|
+
# `value` will be among the values returned.
|
38
|
+
#
|
39
|
+
# Note that if the same `set` is passed to this method multiple times,
|
40
|
+
# all given `value`s will be associated with that `set`.
|
41
|
+
#
|
42
|
+
# This runs in `O(n)` time, where `n` is the size of `set`.
|
43
|
+
#
|
44
|
+
# @param set [#to_set] The set to use as the map key. May not be empty.
|
45
|
+
# @param value [Object] The value to associate with `set`.
|
46
|
+
# @raise [ArgumentError] If `set` is empty.
|
47
|
+
def []=(set, value)
|
48
|
+
raise ArgumentError.new("SubsetMap keys may not be empty.") if set.empty?
|
49
|
+
|
50
|
+
index = @vals.size
|
51
|
+
@vals << value
|
52
|
+
set.each do |k|
|
53
|
+
@hash[k] ||= []
|
54
|
+
@hash[k] << [set, set.to_set, index]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Returns all values associated with subsets of `set`.
|
59
|
+
#
|
60
|
+
# In the worst case, this runs in `O(m*max(n, log m))` time,
|
61
|
+
# where `n` is the size of `set`
|
62
|
+
# and `m` is the number of assocations in the map.
|
63
|
+
# However, unless many keys in the map overlap with `set`,
|
64
|
+
# `m` will typically be much smaller.
|
65
|
+
#
|
66
|
+
# @param set [Set] The set to use as the map key.
|
67
|
+
# @return [Array<(Object, #to_set)>] An array of pairs,
|
68
|
+
# where the first value is the value associated with a subset of `set`,
|
69
|
+
# and the second value is that subset of `set`
|
70
|
+
# (or whatever `#to_set` object was used to set the value)
|
71
|
+
# This array is in insertion order.
|
72
|
+
# @see #[]
|
73
|
+
def get(set)
|
74
|
+
res = set.map do |k|
|
75
|
+
next unless subsets = @hash[k]
|
76
|
+
subsets.map do |subenum, subset, index|
|
77
|
+
next unless subset.subset?(set)
|
78
|
+
[index, subenum]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
res.flatten!(1)
|
82
|
+
res.compact!
|
83
|
+
res.uniq!
|
84
|
+
res.sort!
|
85
|
+
res.map! {|i, s| [@vals[i], s]}
|
86
|
+
return res
|
87
|
+
end
|
88
|
+
|
89
|
+
# Same as \{#get}, but doesn't return the subsets of the argument
|
90
|
+
# for which values were found.
|
91
|
+
#
|
92
|
+
# @param set [Set] The set to use as the map key.
|
93
|
+
# @return [Array] The array of all values
|
94
|
+
# associated with subsets of `set`, in insertion order.
|
95
|
+
# @see #get
|
96
|
+
def [](set)
|
97
|
+
get(set).map {|v, _| v}
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/lib/sass.rb
CHANGED
data/lib/sass/engine.rb
CHANGED
@@ -9,12 +9,14 @@ require 'sass/tree/directive_node'
|
|
9
9
|
require 'sass/tree/variable_node'
|
10
10
|
require 'sass/tree/mixin_def_node'
|
11
11
|
require 'sass/tree/mixin_node'
|
12
|
+
require 'sass/tree/extend_node'
|
12
13
|
require 'sass/tree/if_node'
|
13
14
|
require 'sass/tree/while_node'
|
14
15
|
require 'sass/tree/for_node'
|
15
16
|
require 'sass/tree/debug_node'
|
16
17
|
require 'sass/tree/warn_node'
|
17
18
|
require 'sass/tree/import_node'
|
19
|
+
require 'sass/selector'
|
18
20
|
require 'sass/environment'
|
19
21
|
require 'sass/script'
|
20
22
|
require 'sass/scss'
|
@@ -79,60 +81,49 @@ module Sass
|
|
79
81
|
end
|
80
82
|
|
81
83
|
# The character that begins a CSS property.
|
82
|
-
# @private
|
83
84
|
PROPERTY_CHAR = ?:
|
84
85
|
|
85
86
|
# The character that designates that
|
86
87
|
# a property should be assigned to a SassScript expression.
|
87
|
-
# @private
|
88
88
|
SCRIPT_CHAR = ?=
|
89
89
|
|
90
90
|
# The character that designates the beginning of a comment,
|
91
91
|
# either Sass or CSS.
|
92
|
-
# @private
|
93
92
|
COMMENT_CHAR = ?/
|
94
93
|
|
95
94
|
# The character that follows the general COMMENT_CHAR and designates a Sass comment,
|
96
95
|
# which is not output as a CSS comment.
|
97
|
-
# @private
|
98
96
|
SASS_COMMENT_CHAR = ?/
|
99
97
|
|
100
98
|
# The character that follows the general COMMENT_CHAR and designates a CSS comment,
|
101
99
|
# which is embedded in the CSS document.
|
102
|
-
# @private
|
103
100
|
CSS_COMMENT_CHAR = ?*
|
104
101
|
|
105
102
|
# The character used to denote a compiler directive.
|
106
|
-
# @private
|
107
103
|
DIRECTIVE_CHAR = ?@
|
108
104
|
|
109
105
|
# Designates a non-parsed rule.
|
110
|
-
# @private
|
111
106
|
ESCAPE_CHAR = ?\\
|
112
107
|
|
113
108
|
# Designates block as mixin definition rather than CSS rules to output
|
114
|
-
# @private
|
115
109
|
MIXIN_DEFINITION_CHAR = ?=
|
116
110
|
|
117
111
|
# Includes named mixin declared using MIXIN_DEFINITION_CHAR
|
118
|
-
# @private
|
119
112
|
MIXIN_INCLUDE_CHAR = ?+
|
120
113
|
|
121
114
|
# The regex that matches properties of the form `name: prop`.
|
122
|
-
# @private
|
123
115
|
PROPERTY_NEW_MATCHER = /^[^\s:"\[]+\s*[=:](\s|$)/
|
124
116
|
|
125
117
|
# The regex that matches and extracts data from
|
126
118
|
# properties of the form `name: prop`.
|
127
|
-
# @private
|
128
119
|
PROPERTY_NEW = /^([^\s=:"]+)\s*(=|:)(?:\s+|$)(.*)/
|
129
120
|
|
130
121
|
# The regex that matches and extracts data from
|
131
122
|
# properties of the form `:name prop`.
|
132
|
-
# @private
|
133
123
|
PROPERTY_OLD = /^:([^\s=:"]+)\s*(=?)(?:\s+|$)(.*)/
|
134
124
|
|
135
125
|
# The default options for Sass::Engine.
|
126
|
+
# @api public
|
136
127
|
DEFAULT_OPTIONS = {
|
137
128
|
:style => :nested,
|
138
129
|
:load_paths => ['.'],
|
@@ -382,7 +373,10 @@ WARNING
|
|
382
373
|
# if we're using the new property syntax
|
383
374
|
Tree::RuleNode.new(parse_interp(line.text))
|
384
375
|
else
|
385
|
-
|
376
|
+
name, eq, value = line.text.scan(PROPERTY_OLD)[0]
|
377
|
+
raise SyntaxError.new("Invalid property: \"#{line.text}\".",
|
378
|
+
:line => @line) if name.nil? || value.nil?
|
379
|
+
parse_property(name, parse_interp(name), eq, value, :old, line)
|
386
380
|
end
|
387
381
|
when ?!, ?$
|
388
382
|
parse_variable(line)
|
@@ -401,20 +395,29 @@ WARNING
|
|
401
395
|
parse_mixin_include(line, root)
|
402
396
|
end
|
403
397
|
else
|
404
|
-
|
405
|
-
parse_property(line, PROPERTY_NEW)
|
406
|
-
else
|
407
|
-
Tree::RuleNode.new(parse_interp(line.text))
|
408
|
-
end
|
398
|
+
parse_property_or_rule(line)
|
409
399
|
end
|
410
400
|
end
|
411
401
|
|
412
|
-
def
|
413
|
-
|
402
|
+
def parse_property_or_rule(line)
|
403
|
+
scanner = StringScanner.new(line.text)
|
404
|
+
hack_char = scanner.scan(/[:\*\.]|\#(?!\{)/)
|
405
|
+
parser = Sass::SCSS::SassParser.new(scanner, @line)
|
414
406
|
|
415
|
-
|
416
|
-
|
407
|
+
unless res = parser.parse_interp_ident
|
408
|
+
return Tree::RuleNode.new(parse_interp(line.text))
|
409
|
+
end
|
410
|
+
res.unshift(hack_char) if hack_char
|
411
|
+
|
412
|
+
name = line.text[0...scanner.pos]
|
413
|
+
if scanner.scan(/\s*([:=])(?:\s|$)/)
|
414
|
+
parse_property(name, res, scanner[1], scanner.rest, :new, line)
|
415
|
+
else
|
416
|
+
Tree::RuleNode.new(res + parse_interp(scanner.rest))
|
417
|
+
end
|
418
|
+
end
|
417
419
|
|
420
|
+
def parse_property(name, parsed_name, eq, value, prop, line)
|
418
421
|
if value.strip.empty?
|
419
422
|
expr = Sass::Script::String.new("")
|
420
423
|
else
|
@@ -427,9 +430,7 @@ WARNING
|
|
427
430
|
@line, line.offset + 1, @options[:filename])
|
428
431
|
end
|
429
432
|
end
|
430
|
-
Tree::PropNode.new(
|
431
|
-
parse_interp(name), expr,
|
432
|
-
property_regx == PROPERTY_OLD ? :old : :new)
|
433
|
+
Tree::PropNode.new(parse_interp(name), expr, prop)
|
433
434
|
end
|
434
435
|
|
435
436
|
def parse_variable(line)
|
@@ -500,6 +501,12 @@ WARNING
|
|
500
501
|
:line => @line + 1) unless line.children.empty?
|
501
502
|
offset = line.offset + line.text.index(value).to_i
|
502
503
|
Tree::DebugNode.new(parse_script(value, :offset => offset))
|
504
|
+
elsif directive == "extend"
|
505
|
+
raise SyntaxError.new("Invalid extend directive '@extend': expected expression.") unless value
|
506
|
+
raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath extend directives.",
|
507
|
+
:line => @line + 1) unless line.children.empty?
|
508
|
+
offset = line.offset + line.text.index(value).to_i
|
509
|
+
Tree::ExtendNode.new(parse_interp(value, offset))
|
503
510
|
elsif directive == "warn"
|
504
511
|
raise SyntaxError.new("Invalid warn directive '@warn': expected expression.") unless value
|
505
512
|
raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath warn directives.",
|
@@ -552,7 +559,6 @@ WARNING
|
|
552
559
|
nil
|
553
560
|
end
|
554
561
|
|
555
|
-
# @private
|
556
562
|
MIXIN_DEF_RE = /^(?:=|@mixin)\s*(#{Sass::SCSS::RX::IDENT})(.*)$/
|
557
563
|
def parse_mixin_definition(line)
|
558
564
|
name, arg_string = line.text.scan(MIXIN_DEF_RE).first
|
@@ -565,7 +571,6 @@ WARNING
|
|
565
571
|
Tree::MixinDefNode.new(name, args)
|
566
572
|
end
|
567
573
|
|
568
|
-
# @private
|
569
574
|
MIXIN_INCLUDE_RE = /^(?:\+|@include)\s*(#{Sass::SCSS::RX::IDENT})(.*)$/
|
570
575
|
def parse_mixin_include(line, root)
|
571
576
|
name, arg_string = line.text.scan(MIXIN_INCLUDE_RE).first
|
@@ -605,15 +610,15 @@ WARNING
|
|
605
610
|
end
|
606
611
|
end
|
607
612
|
|
608
|
-
def parse_interp(text)
|
609
|
-
self.class.parse_interp(text, @line, :filename => @filename)
|
613
|
+
def parse_interp(text, offset = 0)
|
614
|
+
self.class.parse_interp(text, @line, offset, :filename => @filename)
|
610
615
|
end
|
611
616
|
|
612
617
|
# It's important that this have strings (at least)
|
613
618
|
# at the beginning, the end, and between each Script::Node.
|
614
619
|
#
|
615
620
|
# @private
|
616
|
-
def self.parse_interp(text, line, options)
|
621
|
+
def self.parse_interp(text, line, offset, options)
|
617
622
|
res = []
|
618
623
|
rest = Haml::Shared.handle_interpolation text do |scan|
|
619
624
|
escapes = scan[2].size
|
@@ -623,7 +628,7 @@ WARNING
|
|
623
628
|
else
|
624
629
|
res << "\\" * [0, escapes - 1].max
|
625
630
|
res << Script::Parser.new(
|
626
|
-
scan, line, scan.pos - scan.matched_size, options).
|
631
|
+
scan, line, offset + scan.pos - scan.matched_size, options).
|
627
632
|
parse_interpolated
|
628
633
|
end
|
629
634
|
end
|
data/lib/sass/files.rb
CHANGED
@@ -20,7 +20,7 @@ module Sass
|
|
20
20
|
options = Sass::Engine::DEFAULT_OPTIONS.merge(options)
|
21
21
|
text = File.read(filename)
|
22
22
|
|
23
|
-
if options[:cache]
|
23
|
+
if options[:cache] || options[:read_cache]
|
24
24
|
compiled_filename = sassc_filename(filename, options)
|
25
25
|
sha = Digest::SHA1.hexdigest(text)
|
26
26
|
|
data/lib/sass/plugin.rb
CHANGED
@@ -231,6 +231,27 @@ module Sass
|
|
231
231
|
end
|
232
232
|
end
|
233
233
|
|
234
|
+
# Updates all stylesheets, even those that aren't out-of-date.
|
235
|
+
# Ignores the cache.
|
236
|
+
#
|
237
|
+
# @param individual_files [Array<(String, String)>]
|
238
|
+
# A list of files to check for updates
|
239
|
+
# **in addition to those specified by the
|
240
|
+
# {file:SASS_REFERENCE.md#template_location-option `:template_location` option}.**
|
241
|
+
# The first string in each pair is the location of the Sass/SCSS file,
|
242
|
+
# the second is the location of the CSS file that it should be compiled to.
|
243
|
+
# @see #update_stylesheets
|
244
|
+
def force_update_stylesheets(individual_files = [])
|
245
|
+
old_options = options
|
246
|
+
self.options = options.dup
|
247
|
+
options[:never_update] = false
|
248
|
+
options[:always_update] = true
|
249
|
+
options[:cache] = false
|
250
|
+
update_stylesheets(individual_files)
|
251
|
+
ensure
|
252
|
+
self.options = old_options
|
253
|
+
end
|
254
|
+
|
234
255
|
# Watches the template directory (or directories)
|
235
256
|
# and updates the CSS files whenever the related Sass/SCSS files change.
|
236
257
|
# `watch` never returns.
|