sass-embedded 0.2.1 → 0.4.0
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.
- checksums.yaml +4 -4
- data/.github/workflows/build.yml +2 -2
- data/.rubocop.yml +14 -0
- data/README.md +3 -3
- data/Rakefile +11 -4
- data/ext/{sass_embedded/.gitignore → .gitignore} +0 -0
- data/ext/Makefile +51 -0
- data/ext/extconf.rb +160 -0
- data/lib/sass.rb +11 -3
- data/lib/sass/embedded.rb +374 -174
- data/lib/sass/error.rb +4 -9
- data/lib/sass/transport.rb +76 -64
- data/lib/sass/util.rb +22 -3
- data/lib/sass/version.rb +1 -1
- data/sass-embedded.gemspec +4 -2
- data/test/concurrency_test.rb +34 -0
- data/test/functions_test.rb +149 -157
- data/test/{custom_importer_test.rb → importer_test.rb} +24 -31
- data/test/include_paths_test.rb +81 -0
- data/test/indented_syntax_test.rb +61 -0
- data/test/input_test.rb +56 -0
- data/test/output_test.rb +136 -0
- data/test/render_error_test.rb +44 -0
- data/test/render_test.rb +19 -0
- data/test/source_maps_test.rb +178 -0
- data/test/test_helper.rb +1 -0
- metadata +54 -17
- data/ext/sass_embedded/Makefile +0 -35
- data/ext/sass_embedded/extconf.rb +0 -124
- data/test/compiler_test.rb +0 -276
- data/test/error_test.rb +0 -31
- data/test/output_style_test.rb +0 -93
- data/test/sass_test.rb +0 -22
data/lib/sass/error.rb
CHANGED
@@ -1,17 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Sass
|
4
|
-
class
|
4
|
+
class SassError < StandardError; end
|
5
5
|
|
6
|
-
class ProtocolError <
|
6
|
+
class ProtocolError < SassError; end
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
class InvalidStyleError < BaseError; end
|
11
|
-
|
12
|
-
class UnsupportedValue < BaseError; end
|
13
|
-
|
14
|
-
class CompilationError < BaseError
|
8
|
+
# The error returned by {Sass.render}
|
9
|
+
class RenderError < SassError
|
15
10
|
attr_accessor :formatted, :file, :line, :column, :status
|
16
11
|
|
17
12
|
def initialize(message, formatted, file, line, column, status)
|
data/lib/sass/transport.rb
CHANGED
@@ -2,68 +2,36 @@
|
|
2
2
|
|
3
3
|
require 'open3'
|
4
4
|
require 'observer'
|
5
|
-
require_relative '../../ext/
|
5
|
+
require_relative '../../ext/embedded_sass_pb'
|
6
6
|
|
7
7
|
module Sass
|
8
|
+
# The interface for communicating with dart-sass-embedded.
|
9
|
+
# It handles message serialization and deserialization as well as
|
10
|
+
# tracking concurrent request and response
|
8
11
|
class Transport
|
9
12
|
include Observable
|
10
13
|
|
11
14
|
DART_SASS_EMBEDDED = File.absolute_path(
|
12
|
-
"../../ext/sass_embedded/
|
15
|
+
"../../ext/sass_embedded/dart-sass-embedded#{Platform::OS == 'windows' ? '.bat' : ''}", __dir__
|
13
16
|
)
|
14
17
|
|
15
18
|
PROTOCOL_ERROR_ID = 4_294_967_295
|
16
19
|
|
17
20
|
def initialize
|
18
|
-
@stdin, @stdout, @stderr, @wait_thread = Open3.popen3(DART_SASS_EMBEDDED)
|
19
21
|
@stdin_semaphore = Mutex.new
|
20
22
|
@observerable_semaphore = Mutex.new
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
bits = length = 0
|
25
|
-
loop do
|
26
|
-
byte = @stdout.readbyte
|
27
|
-
length += (byte & 0x7f) << bits
|
28
|
-
bits += 7
|
29
|
-
break if byte <= 0x7f
|
30
|
-
end
|
31
|
-
changed
|
32
|
-
payload = @stdout.read length
|
33
|
-
@observerable_semaphore.synchronize do
|
34
|
-
notify_observers nil, Sass::EmbeddedProtocol::OutboundMessage.decode(payload)
|
35
|
-
end
|
36
|
-
rescue Interrupt
|
37
|
-
break
|
38
|
-
rescue IOError => e
|
39
|
-
notify_observers e, nil
|
40
|
-
close
|
41
|
-
break
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
Thread.new do
|
46
|
-
loop do
|
47
|
-
warn @stderr.read
|
48
|
-
rescue Interrupt
|
49
|
-
break
|
50
|
-
rescue IOError => e
|
51
|
-
@observerable_semaphore.synchronize do
|
52
|
-
notify_observers e, nil
|
53
|
-
end
|
54
|
-
close
|
55
|
-
break
|
56
|
-
end
|
57
|
-
end
|
23
|
+
@stdin, @stdout, @stderr, @wait_thread = Open3.popen3(DART_SASS_EMBEDDED)
|
24
|
+
pipe @stderr, $stderr
|
25
|
+
receive
|
58
26
|
end
|
59
27
|
|
60
28
|
def send(req, id)
|
61
29
|
mutex = Mutex.new
|
62
30
|
resource = ConditionVariable.new
|
63
31
|
|
64
|
-
|
32
|
+
req_kind = req.class.name.split('::').last.gsub(/\B(?=[A-Z])/, '_').downcase
|
65
33
|
|
66
|
-
message =
|
34
|
+
message = EmbeddedProtocol::InboundMessage.new(req_kind => req)
|
67
35
|
|
68
36
|
error = nil
|
69
37
|
res = nil
|
@@ -95,42 +63,86 @@ module Sass
|
|
95
63
|
@stdin.close unless @stdin.closed?
|
96
64
|
@stdout.close unless @stdout.closed?
|
97
65
|
@stderr.close unless @stderr.closed?
|
66
|
+
nil
|
98
67
|
end
|
99
68
|
|
100
69
|
private
|
101
70
|
|
102
|
-
def
|
71
|
+
def receive
|
72
|
+
Thread.new do
|
73
|
+
loop do
|
74
|
+
bits = length = 0
|
75
|
+
loop do
|
76
|
+
byte = @stdout.readbyte
|
77
|
+
length += (byte & 0x7f) << bits
|
78
|
+
bits += 7
|
79
|
+
break if byte <= 0x7f
|
80
|
+
end
|
81
|
+
changed
|
82
|
+
payload = @stdout.read length
|
83
|
+
@observerable_semaphore.synchronize do
|
84
|
+
notify_observers nil, EmbeddedProtocol::OutboundMessage.decode(payload)
|
85
|
+
end
|
86
|
+
rescue Interrupt
|
87
|
+
break
|
88
|
+
rescue IOError => e
|
89
|
+
notify_observers e, nil
|
90
|
+
close
|
91
|
+
break
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def pipe(readable, writeable)
|
97
|
+
Thread.new do
|
98
|
+
loop do
|
99
|
+
writeable.write readable.read
|
100
|
+
rescue Interrupt
|
101
|
+
break
|
102
|
+
rescue IOError => e
|
103
|
+
@observerable_semaphore.synchronize do
|
104
|
+
notify_observers e, nil
|
105
|
+
end
|
106
|
+
close
|
107
|
+
break
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def write(payload)
|
103
113
|
@stdin_semaphore.synchronize do
|
104
|
-
length =
|
114
|
+
length = payload.length
|
105
115
|
while length.positive?
|
106
116
|
@stdin.write ((length > 0x7f ? 0x80 : 0) | (length & 0x7f)).chr
|
107
117
|
length >>= 7
|
108
118
|
end
|
109
|
-
@stdin.write
|
119
|
+
@stdin.write payload
|
110
120
|
end
|
111
121
|
end
|
112
|
-
end
|
113
122
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
123
|
+
# The observer used to listen on messages from stdout, check if id
|
124
|
+
# matches the given request id, and yield back to the given block.
|
125
|
+
class MessageObserver
|
126
|
+
def initialize(obs, id, &block)
|
127
|
+
@obs = obs
|
128
|
+
@id = id
|
129
|
+
@block = block
|
130
|
+
@obs.add_observer self
|
131
|
+
end
|
121
132
|
|
122
|
-
|
123
|
-
|
124
|
-
@obs.delete_observer self
|
125
|
-
@block.call error, nil
|
126
|
-
elsif message.error&.id == Sass::Transport::PROTOCOL_ERROR_ID
|
127
|
-
@obs.delete_observer self
|
128
|
-
@block.call Sass::ProtocolError.new(message.error.message), nil
|
129
|
-
else
|
130
|
-
res = message[message.message.to_s]
|
131
|
-
if (res['compilation_id'] || res['id']) == @id
|
133
|
+
def update(error, message)
|
134
|
+
if error
|
132
135
|
@obs.delete_observer self
|
133
|
-
@block.call error,
|
136
|
+
@block.call error, nil
|
137
|
+
elsif message.error&.id == Transport::PROTOCOL_ERROR_ID
|
138
|
+
@obs.delete_observer self
|
139
|
+
@block.call ProtocolError.new(message.error.message), nil
|
140
|
+
else
|
141
|
+
res = message[message.message.to_s]
|
142
|
+
if (res['compilation_id'] || res['id']) == @id
|
143
|
+
@obs.delete_observer self
|
144
|
+
@block.call error, res
|
145
|
+
end
|
134
146
|
end
|
135
147
|
end
|
136
148
|
end
|
data/lib/sass/util.rb
CHANGED
@@ -1,19 +1,38 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Sass
|
4
|
+
# Utilities functions
|
4
5
|
module Util
|
5
6
|
module_function
|
6
7
|
|
8
|
+
FILE_PROTOCOL = 'file://'
|
9
|
+
|
7
10
|
def file_uri(path)
|
8
11
|
absolute_path = File.absolute_path(path)
|
9
12
|
|
10
|
-
unless absolute_path.start_with?
|
13
|
+
unless absolute_path.start_with? File::SEPARATOR
|
14
|
+
components = absolute_path.split File::SEPARATOR
|
15
|
+
components[0] = components[0][0].downcase
|
16
|
+
absolute_path = components.join File::SEPARATOR
|
17
|
+
end
|
18
|
+
|
19
|
+
"#{FILE_PROTOCOL}#{absolute_path}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def path(file_uri)
|
23
|
+
absolute_path = file_uri[FILE_PROTOCOL.length..]
|
24
|
+
|
25
|
+
unless absolute_path.start_with? File::SEPARATOR
|
11
26
|
components = absolute_path.split File::SEPARATOR
|
12
|
-
components[0] = components[0].
|
27
|
+
components[0] = "#{components[0].upcase}:"
|
13
28
|
absolute_path = components.join File::SEPARATOR
|
14
29
|
end
|
15
30
|
|
16
|
-
|
31
|
+
absolute_path
|
32
|
+
end
|
33
|
+
|
34
|
+
def relative(from, to)
|
35
|
+
Pathname.new(File.absolute_path(to)).relative_path_from(Pathname.new(File.absolute_path(from))).to_s
|
17
36
|
end
|
18
37
|
|
19
38
|
def now
|
data/lib/sass/version.rb
CHANGED
data/sass-embedded.gemspec
CHANGED
@@ -15,11 +15,11 @@ Gem::Specification.new do |spec|
|
|
15
15
|
spec.license = 'MIT'
|
16
16
|
|
17
17
|
spec.files = `git ls-files -z`.split("\x0")
|
18
|
-
spec.extensions = ['ext/
|
18
|
+
spec.extensions = ['ext/extconf.rb']
|
19
19
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
20
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
21
|
|
22
|
-
spec.required_ruby_version = '>= 2.
|
22
|
+
spec.required_ruby_version = '>= 2.6'
|
23
23
|
|
24
24
|
spec.require_paths = ['lib']
|
25
25
|
|
@@ -33,4 +33,6 @@ Gem::Specification.new do |spec|
|
|
33
33
|
spec.add_development_dependency 'rake'
|
34
34
|
spec.add_development_dependency 'rake-compiler'
|
35
35
|
spec.add_development_dependency 'rubocop'
|
36
|
+
spec.add_development_dependency 'rubocop-minitest'
|
37
|
+
spec.add_development_dependency 'rubocop-rake'
|
36
38
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'test_helper'
|
4
|
+
|
5
|
+
module Sass
|
6
|
+
class ConcurrencyTest < MiniTest::Test
|
7
|
+
include TempFileTest
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@embedded = Embedded.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def teardown
|
14
|
+
@embedded.close
|
15
|
+
end
|
16
|
+
|
17
|
+
def render(data)
|
18
|
+
@embedded.render(data: data)[:css]
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_concurrency
|
22
|
+
10.times do
|
23
|
+
threads = []
|
24
|
+
10.times do |i|
|
25
|
+
threads << Thread.new(i) do |id|
|
26
|
+
output = @embedded.render(data: "div { width: #{id} }")[:css]
|
27
|
+
assert_match(/#{id}/, output)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
threads.each(&:join)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/test/functions_test.rb
CHANGED
@@ -13,155 +13,153 @@ module Sass
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def render(sass)
|
16
|
-
@embedded.render(
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
path
|
29
|
-
},
|
30
|
-
'no_return_path($path)': lambda { |_path|
|
31
|
-
Sass::EmbeddedProtocol::Value.new(
|
32
|
-
singleton: Sass::EmbeddedProtocol::SingletonValue::NULL
|
33
|
-
)
|
16
|
+
@embedded.render(data: sass,
|
17
|
+
functions: {
|
18
|
+
'javascript_path($path)': lambda { |path|
|
19
|
+
path.string.text = "/js/#{path.string.text}"
|
20
|
+
path
|
21
|
+
},
|
22
|
+
'stylesheet_path($path)': lambda { |path|
|
23
|
+
path.string.text = "/css/#{path.string.text}"
|
24
|
+
path
|
25
|
+
},
|
26
|
+
'sass_return_path($path)': lambda { |path|
|
27
|
+
path
|
34
28
|
},
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
29
|
+
'no_return_path($path)': lambda { |_path|
|
30
|
+
EmbeddedProtocol::Value.new(
|
31
|
+
singleton: EmbeddedProtocol::SingletonValue::NULL
|
32
|
+
)
|
33
|
+
},
|
34
|
+
'optional_arguments($path, $optional: null)': lambda { |path, optional|
|
35
|
+
EmbeddedProtocol::Value.new(
|
36
|
+
string: EmbeddedProtocol::Value::String.new(
|
37
|
+
text: "#{path.string.text}/#{optional.singleton == :NULL ? 'bar' : optional.string.text}",
|
38
|
+
quoted: true
|
41
39
|
)
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
'nice_color_argument($color)': lambda { |color|
|
48
|
-
color
|
40
|
+
)
|
41
|
+
},
|
42
|
+
'function_that_raises_errors()': lambda {
|
43
|
+
raise StandardError,
|
44
|
+
'Intentional wrong thing happened somewhere inside the custom function'
|
49
45
|
},
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
46
|
+
'nice_color_argument($color)': lambda { |color|
|
47
|
+
color
|
48
|
+
},
|
49
|
+
'returns_a_color()': lambda {
|
50
|
+
EmbeddedProtocol::Value.new(
|
51
|
+
rgb_color: EmbeddedProtocol::Value::RgbColor.new(
|
52
|
+
red: 0,
|
53
|
+
green: 0,
|
54
|
+
blue: 0,
|
55
|
+
alpha: 1
|
58
56
|
)
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
57
|
+
)
|
58
|
+
},
|
59
|
+
'returns_a_number()': lambda {
|
60
|
+
EmbeddedProtocol::Value.new(
|
61
|
+
number: EmbeddedProtocol::Value::Number.new(
|
62
|
+
value: -312,
|
63
|
+
numerators: ['rem']
|
66
64
|
)
|
67
|
-
},
|
68
|
-
'returns_a_bool()': lambda {
|
69
|
-
Sass::EmbeddedProtocol::Value.new(
|
70
|
-
singleton: Sass::EmbeddedProtocol::SingletonValue::TRUE
|
71
65
|
)
|
72
66
|
},
|
73
|
-
|
74
|
-
|
67
|
+
'returns_a_bool()': lambda {
|
68
|
+
EmbeddedProtocol::Value.new(
|
69
|
+
singleton: EmbeddedProtocol::SingletonValue::TRUE
|
70
|
+
)
|
71
|
+
},
|
72
|
+
'inspect_bool($argument)': lambda { |argument|
|
73
|
+
unless argument&.singleton == :TRUE || argument.singleton == :FALSE
|
74
|
+
raise StandardError,
|
75
|
+
'passed value is not a EmbeddedProtocol::SingletonValue::TRUE or EmbeddedProtocol::SingletonValue::FALSE'
|
76
|
+
end
|
77
|
+
|
78
|
+
argument
|
79
|
+
},
|
80
|
+
'inspect_number($argument)': lambda { |argument|
|
81
|
+
unless argument&.number.is_a? EmbeddedProtocol::Value::Number
|
75
82
|
raise StandardError,
|
76
|
-
'passed value is not a
|
83
|
+
'passed value is not a EmbeddedProtocol::Value::Number'
|
77
84
|
end
|
78
85
|
|
79
86
|
argument
|
80
87
|
},
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
argument
|
88
|
-
},
|
89
|
-
'inspect_map($argument)': lambda { |argument|
|
90
|
-
unless argument&.map.is_a? Sass::EmbeddedProtocol::Value::Map
|
91
|
-
raise StandardError,
|
92
|
-
'passed value is not a Sass::EmbeddedProtocol::Value::Map'
|
93
|
-
end
|
88
|
+
'inspect_map($argument)': lambda { |argument|
|
89
|
+
unless argument&.map.is_a? EmbeddedProtocol::Value::Map
|
90
|
+
raise StandardError,
|
91
|
+
'passed value is not a EmbeddedProtocol::Value::Map'
|
92
|
+
end
|
94
93
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
94
|
+
argument
|
95
|
+
},
|
96
|
+
'inspect_list($argument)': lambda { |argument|
|
97
|
+
unless argument&.list.is_a? EmbeddedProtocol::Value::List
|
98
|
+
raise StandardError,
|
99
|
+
'passed value is not a EmbeddedProtocol::Value::List'
|
100
|
+
end
|
102
101
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
)
|
102
|
+
argument
|
103
|
+
},
|
104
|
+
'returns_sass_value()': lambda {
|
105
|
+
EmbeddedProtocol::Value.new(
|
106
|
+
rgb_color: EmbeddedProtocol::Value::RgbColor.new(
|
107
|
+
red: 0,
|
108
|
+
green: 0,
|
109
|
+
blue: 0,
|
110
|
+
alpha: 1
|
113
111
|
)
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
)
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
112
|
+
)
|
113
|
+
},
|
114
|
+
'returns_sass_map()': lambda {
|
115
|
+
EmbeddedProtocol::Value.new(
|
116
|
+
map: EmbeddedProtocol::Value::Map.new(
|
117
|
+
entries: [
|
118
|
+
EmbeddedProtocol::Value::Map::Entry.new(
|
119
|
+
key: EmbeddedProtocol::Value.new(
|
120
|
+
string: EmbeddedProtocol::Value::String.new(
|
121
|
+
text: 'color',
|
122
|
+
quoted: true
|
123
|
+
)
|
124
|
+
),
|
125
|
+
value: EmbeddedProtocol::Value.new(
|
126
|
+
rgb_color: EmbeddedProtocol::Value::RgbColor.new(
|
127
|
+
red: 0,
|
128
|
+
green: 0,
|
129
|
+
blue: 0,
|
130
|
+
alpha: 1
|
133
131
|
)
|
134
132
|
)
|
135
|
-
|
136
|
-
|
133
|
+
)
|
134
|
+
]
|
137
135
|
)
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
),
|
150
|
-
Sass::EmbeddedProtocol::Value.new(
|
151
|
-
number: Sass::EmbeddedProtocol::Value::Number.new(
|
152
|
-
value: 20
|
153
|
-
)
|
154
|
-
),
|
155
|
-
Sass::EmbeddedProtocol::Value.new(
|
156
|
-
number: Sass::EmbeddedProtocol::Value::Number.new(
|
157
|
-
value: 30
|
158
|
-
)
|
136
|
+
)
|
137
|
+
},
|
138
|
+
'returns_sass_list()': lambda {
|
139
|
+
EmbeddedProtocol::Value.new(
|
140
|
+
list: EmbeddedProtocol::Value::List.new(
|
141
|
+
separator: EmbeddedProtocol::ListSeparator::COMMA,
|
142
|
+
has_brackets: true,
|
143
|
+
contents: [
|
144
|
+
EmbeddedProtocol::Value.new(
|
145
|
+
number: EmbeddedProtocol::Value::Number.new(
|
146
|
+
value: 10
|
159
147
|
)
|
160
|
-
|
161
|
-
|
148
|
+
),
|
149
|
+
EmbeddedProtocol::Value.new(
|
150
|
+
number: EmbeddedProtocol::Value::Number.new(
|
151
|
+
value: 20
|
152
|
+
)
|
153
|
+
),
|
154
|
+
EmbeddedProtocol::Value.new(
|
155
|
+
number: EmbeddedProtocol::Value::Number.new(
|
156
|
+
value: 30
|
157
|
+
)
|
158
|
+
)
|
159
|
+
]
|
162
160
|
)
|
163
|
-
|
164
|
-
|
161
|
+
)
|
162
|
+
}
|
165
163
|
})[:css]
|
166
164
|
end
|
167
165
|
|
@@ -270,7 +268,7 @@ module Sass
|
|
270
268
|
end
|
271
269
|
|
272
270
|
def test_function_with_error
|
273
|
-
assert_raises(
|
271
|
+
assert_raises(RenderError) do
|
274
272
|
render('div {url: function_that_raises_errors();}')
|
275
273
|
end
|
276
274
|
end
|
@@ -322,17 +320,15 @@ module Sass
|
|
322
320
|
threads = []
|
323
321
|
10.times do |i|
|
324
322
|
threads << Thread.new(i) do |id|
|
325
|
-
output = @embedded.render({
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
quoted: true
|
333
|
-
)
|
323
|
+
output = @embedded.render(data: 'div { url: test-function() }',
|
324
|
+
functions: {
|
325
|
+
'test_function()': lambda {
|
326
|
+
EmbeddedProtocol::Value.new(
|
327
|
+
string: EmbeddedProtocol::Value::String.new(
|
328
|
+
text: "{test_key1: 'test_value', test_key2: #{id}}",
|
329
|
+
quoted: true
|
334
330
|
)
|
335
|
-
|
331
|
+
)
|
336
332
|
}
|
337
333
|
})[:css]
|
338
334
|
assert_match(/test_key1/, output)
|
@@ -346,17 +342,15 @@ module Sass
|
|
346
342
|
end
|
347
343
|
|
348
344
|
def test_pass_custom_functions_as_a_parameter
|
349
|
-
output = @embedded.render({
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
quoted: true
|
357
|
-
)
|
345
|
+
output = @embedded.render(data: 'div { url: test-function(); }',
|
346
|
+
functions: {
|
347
|
+
'test_function()': lambda {
|
348
|
+
EmbeddedProtocol::Value.new(
|
349
|
+
string: EmbeddedProtocol::Value::String.new(
|
350
|
+
text: 'custom_function',
|
351
|
+
quoted: true
|
358
352
|
)
|
359
|
-
|
353
|
+
)
|
360
354
|
}
|
361
355
|
})[:css]
|
362
356
|
|
@@ -364,13 +358,11 @@ module Sass
|
|
364
358
|
end
|
365
359
|
|
366
360
|
def test_pass_incompatible_type_to_custom_functions
|
367
|
-
assert_raises(
|
368
|
-
@embedded.render({
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
Class.new
|
373
|
-
}
|
361
|
+
assert_raises(RenderError) do
|
362
|
+
@embedded.render(data: 'div { url: test-function(); }',
|
363
|
+
functions: {
|
364
|
+
'test_function()': lambda {
|
365
|
+
Class.new
|
374
366
|
}
|
375
367
|
})[:css]
|
376
368
|
end
|