sass-embedded 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e03d2c1775fdd10b7f9d2b21898ac0a6e31e0be96157139742384c7be9b4275a
4
- data.tar.gz: dacdc9589a8da93246b791794f97be2c8818f8a492d77e473c9fa543fd49db9e
3
+ metadata.gz: c9afb73da6288ecf0360685cc9ddb4c072eb8840da50acaa8a52b67f09998e6c
4
+ data.tar.gz: 1a20d885e2e9f55ffd861f9428499f4c3bdea64a4aea81e44f356af8be69eccc
5
5
  SHA512:
6
- metadata.gz: 3be32cd37a7078fceabd16c661cf985fdfc1aa31fbf8b88e6c768cb8edd57749a30e28a77f367d6cc8c6c505710f402e1970ae6c12210b3f46fc10a42cf8d81d
7
- data.tar.gz: 5a122cd7c2e883f28b9401ce70d8fb43fcfcf39e1ff64484f5bf036c6978ca1a01cf8d69b1ebbf22f0fde81f98272127cf5a96d381b0279028d316d90775ebfb
6
+ metadata.gz: 679cfc5b502de2fdc5b33c8117b7e1d68f94acd62c7afbe04ebb17f9bceacdc677e8b35197cf239f92fed4e3d523468d71798d899c360d8402be127bdb50ac48
7
+ data.tar.gz: e1d698b3980914299ee2ce570bd1f109a875859c147f8930366df8e2dabcae94f0e0795339f6614f3f7828e365c191ba24554e30869e4bd106f565f1cbbb9af2
data/lib/sass/embedded.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'json'
4
+ require 'base64'
5
+
3
6
  module Sass
4
7
  # The interface for using dart-sass-embedded
5
8
  class Embedded
@@ -9,30 +12,36 @@ module Sass
9
12
  @id = 0
10
13
  end
11
14
 
12
- # rubocop:disable Lint/UnusedMethodArgument
15
+ def info
16
+ @transport.send EmbeddedProtocol::InboundMessage::VersionRequest.new(
17
+ id: next_id
18
+ )
19
+ end
13
20
 
14
21
  def render(data: nil,
15
22
  file: nil,
16
23
  indented_syntax: false,
17
24
  include_paths: [],
18
25
  output_style: :expanded,
19
- precision: 5,
26
+ # precision: 5,
20
27
  indent_type: :space,
21
28
  indent_width: 2,
22
29
  linefeed: :lf,
23
- source_comments: false,
30
+ # source_comments: false,
24
31
  source_map: false,
25
32
  out_file: nil,
26
33
  omit_source_map_url: false,
27
- source_map_contents: false,
34
+ # source_map_contents: false,
28
35
  source_map_embed: false,
29
36
  source_map_root: '',
30
37
  functions: {},
31
38
  importer: [])
32
- # rubocop:enable Lint/UnusedMethodArgument
33
-
34
39
  start = Util.now
35
40
 
41
+ indent_type = parse_indent_type(indent_type)
42
+ indent_width = parse_indent_width(indent_width)
43
+ linefeed = parse_linefeed(linefeed)
44
+
36
45
  compilation_id = next_id
37
46
 
38
47
  renderer = Renderer.new(
@@ -70,8 +79,10 @@ module Sass
70
79
  raise RenderError.new(
71
80
  response.failure.message,
72
81
  response.failure.formatted,
73
- if response.failure.span
74
- response.failure.span.url == '' ? 'stdin' : URI.parse(response.failure.span.url).path
82
+ if response.failure.span&.url == ''
83
+ 'stdin'
84
+ else
85
+ Util.path(response.failure.span.url)
75
86
  end,
76
87
  response.failure.span ? response.failure.span.start.line + 1 : nil,
77
88
  response.failure.span ? response.failure.span.start.column + 1 : nil,
@@ -79,11 +90,27 @@ module Sass
79
90
  )
80
91
  end
81
92
 
93
+ map, source_map = post_process_map(map: response.success.source_map,
94
+ file: file,
95
+ out_file: out_file,
96
+ source_map: source_map,
97
+ source_map_root: source_map_root)
98
+
99
+ css = post_process_css(css: response.success.css,
100
+ indent_type: indent_type,
101
+ indent_width: indent_width,
102
+ linefeed: linefeed,
103
+ map: map,
104
+ out_file: out_file,
105
+ omit_source_map_url: omit_source_map_url,
106
+ source_map: source_map,
107
+ source_map_embed: source_map_embed)
108
+
82
109
  finish = Util.now
83
110
 
84
111
  {
85
- css: response.success.css,
86
- map: response.success.source_map,
112
+ css: css,
113
+ map: map,
87
114
  stats: {
88
115
  entry: file.nil? ? 'data' : file,
89
116
  start: start,
@@ -100,16 +127,108 @@ module Sass
100
127
 
101
128
  private
102
129
 
103
- def info
104
- version_response = @transport.send EmbeddedProtocol::InboundMessage::VersionRequest.new(
105
- id: next_id
106
- )
107
- {
108
- compiler_version: version_response.compiler_version,
109
- protocol_version: version_response.protocol_version,
110
- implementation_name: version_response.implementation_name,
111
- implementation_version: version_response.implementation_version
112
- }
130
+ def post_process_map(map:,
131
+ file:,
132
+ out_file:,
133
+ source_map:,
134
+ source_map_root:)
135
+ return if map.nil? || map.empty?
136
+
137
+ map_data = JSON.parse(map)
138
+
139
+ map_data['sourceRoot'] = source_map_root
140
+
141
+ source_map_path = if source_map.is_a? String
142
+ source_map
143
+ else
144
+ "#{out_file}.map"
145
+ end
146
+
147
+ source_map_dir = File.dirname(source_map_path)
148
+
149
+ if out_file
150
+ map_data['file'] = Util.relative(source_map_dir, out_file)
151
+ elsif file
152
+ ext = File.extname(file)
153
+ map_data['file'] = "#{file[0..(ext.empty? ? -1 : -ext.length - 1)]}.css"
154
+ else
155
+ map_data['file'] = 'stdin.css'
156
+ end
157
+
158
+ map_data['sources'].map! do |source|
159
+ if source.start_with? Util::FILE_PROTOCOL
160
+ Util.relative(source_map_dir, Util.path(source))
161
+ else
162
+ source
163
+ end
164
+ end
165
+
166
+ [-JSON.generate(map_data), source_map_path]
167
+ end
168
+
169
+ def post_process_css(css:,
170
+ indent_type:,
171
+ indent_width:,
172
+ linefeed:,
173
+ map:,
174
+ omit_source_map_url:,
175
+ out_file:,
176
+ source_map:,
177
+ source_map_embed:)
178
+ css = +css
179
+ if indent_width != 2 || indent_type.to_sym != :space
180
+ indent = indent_type * indent_width
181
+ css.gsub!(/^ +/) do |space|
182
+ indent * (space.length / 2)
183
+ end
184
+ end
185
+ css.gsub!("\n", linefeed) if linefeed != "\n"
186
+
187
+ unless map.nil? || omit_source_map_url == true
188
+ url = if source_map_embed
189
+ "data:application/json;base64,#{Base64.strict_encode64(map)}"
190
+ elsif out_file
191
+ Util.relative(File.dirname(out_file), source_map)
192
+ else
193
+ source_map
194
+ end
195
+ css += "#{linefeed}/*# sourceMappingURL=#{url} */"
196
+ end
197
+
198
+ -css
199
+ end
200
+
201
+ def parse_indent_type(indent_type)
202
+ case indent_type.to_sym
203
+ when :space
204
+ ' '
205
+ when :tab
206
+ "\t"
207
+ else
208
+ raise ArgumentError, 'indent_type must be :space or :tab'
209
+ end
210
+ end
211
+
212
+ def parse_indent_width(indent_width)
213
+ raise ArgumentError, 'indent_width must be an integer' unless indent_width.is_a? Integer
214
+ raise RangeError, 'indent_width must be in between 0 and 10 (inclusive)' unless indent_width.between? 0, 10
215
+
216
+ indent_width
217
+ end
218
+
219
+ def parse_linefeed(linefeed)
220
+ case linefeed.to_sym
221
+ when :lf
222
+ "\n"
223
+ when :lfcr
224
+ "\n\r"
225
+ when :cr
226
+ "\r"
227
+ when :crlf
228
+ "\r\n"
229
+ else
230
+ raise ArgumentError, 'linefeed must be one of :lf, :lfcr, :cr, :crlf'
231
+ end
113
232
  end
114
233
 
115
234
  def next_id
@@ -131,7 +250,7 @@ module Sass
131
250
  out_file:,
132
251
  functions:,
133
252
  importer:)
134
- raise ArgumentError, 'Either :data or :file must be set.' if file.nil? && data.nil?
253
+ raise ArgumentError, 'either data or file must be set' if file.nil? && data.nil?
135
254
 
136
255
  @data = data
137
256
  @file = file
@@ -253,7 +372,7 @@ module Sass
253
372
  def url
254
373
  return if @file.nil?
255
374
 
256
- Util.file_uri(@file)
375
+ Util.file_uri @file
257
376
  end
258
377
 
259
378
  def string
@@ -271,7 +390,7 @@ module Sass
271
390
  end
272
391
 
273
392
  def style
274
- case @output_style.to_sym
393
+ case @output_style&.to_sym
275
394
  when :expanded
276
395
  EmbeddedProtocol::OutputStyle::EXPANDED
277
396
  when :compressed
@@ -25,7 +25,7 @@ module Sass
25
25
  receive
26
26
  end
27
27
 
28
- def send(req, res_id)
28
+ def send(req, id)
29
29
  mutex = Mutex.new
30
30
  resource = ConditionVariable.new
31
31
 
@@ -37,7 +37,7 @@ module Sass
37
37
  res = nil
38
38
 
39
39
  @observerable_semaphore.synchronize do
40
- MessageObserver.new self, res_id do |e, r|
40
+ MessageObserver.new self, id do |e, r|
41
41
  mutex.synchronize do
42
42
  error = e
43
43
  res = r
data/lib/sass/util.rb CHANGED
@@ -5,16 +5,34 @@ module Sass
5
5
  module Util
6
6
  module_function
7
7
 
8
+ FILE_PROTOCOL = 'file://'
9
+
8
10
  def file_uri(path)
9
11
  absolute_path = File.absolute_path(path)
10
12
 
11
- 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
12
26
  components = absolute_path.split File::SEPARATOR
13
- components[0] = components[0].split(':').first.downcase
27
+ components[0] = "#{components[0].upcase}:"
14
28
  absolute_path = components.join File::SEPARATOR
15
29
  end
16
30
 
17
- "file://#{absolute_path}"
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
18
36
  end
19
37
 
20
38
  def now
data/lib/sass/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sass
4
- VERSION = '0.3.0'
4
+ VERSION = '0.4.0'
5
5
  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
@@ -3,7 +3,7 @@
3
3
  require_relative 'test_helper'
4
4
 
5
5
  module Sass
6
- class CustomImporterTest < MiniTest::Test
6
+ class ImporterTest < MiniTest::Test
7
7
  include TempFileTest
8
8
 
9
9
  def setup
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'test_helper'
4
+
5
+ module Sass
6
+ class IncludePathsTest < 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 test_include_paths
18
+ temp_dir('included_1')
19
+ temp_dir('included_2')
20
+
21
+ temp_file('included_1/import_parent.scss', '$s: 30px;')
22
+ temp_file('included_2/import.scss', "@use 'import_parent' as *; $size: $s;")
23
+ temp_file('styles.scss', "@use 'import.scss' as *; .hi { width: $size; }")
24
+
25
+ css = <<~CSS.chomp
26
+ .hi {
27
+ width: 30px;
28
+ }
29
+ CSS
30
+
31
+ assert_equal css, @embedded.render(file: 'styles.scss',
32
+ include_paths: %w[
33
+ included_1 included_2
34
+ ])[:css]
35
+ end
36
+
37
+ def test_global_include_paths
38
+ temp_dir('included_1')
39
+ temp_dir('included_2')
40
+
41
+ temp_file('included_1/import_parent.scss', '$s: 30px;')
42
+ temp_file('included_2/import.scss', "@use 'import_parent' as *; $size: $s;")
43
+ temp_file('styles.scss', "@use 'import.scss' as *; .hi { width: $size; }")
44
+
45
+ ::Sass.include_paths << 'included_1'
46
+ ::Sass.include_paths << 'included_2'
47
+
48
+ css = <<~CSS.chomp
49
+ .hi {
50
+ width: 30px;
51
+ }
52
+ CSS
53
+
54
+ assert_equal css, @embedded.render(file: 'styles.scss')[:css]
55
+ end
56
+
57
+ def test_include_paths_from_env
58
+ expected_include_paths = %w[included_3 included_4]
59
+
60
+ ::Sass.instance_eval { @include_paths = nil }
61
+
62
+ ENV['SASS_PATH'] = expected_include_paths.join(File::PATH_SEPARATOR)
63
+
64
+ assert_equal expected_include_paths, ::Sass.include_paths
65
+
66
+ ::Sass.include_paths.clear
67
+ end
68
+
69
+ def test_include_paths_not_configured
70
+ temp_dir('included_5')
71
+ temp_dir('included_6')
72
+ temp_file('included_5/import_parent.scss', '$s: 30px;')
73
+ temp_file('included_6/import.scss', "@use 'import_parent' as *; $size: $s;")
74
+ temp_file('styles.scss', "@use 'import.scss' as *; .hi { width: $size; }")
75
+
76
+ assert_raises(RenderError) do
77
+ @embedded.render(file: 'styles.scss')
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'test_helper'
4
+
5
+ module Sass
6
+ class IndentedSyntaxTest < 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 test_input_data_with_indented_syntax
18
+ sass = <<~SASS
19
+ $size: 30px
20
+ .foo
21
+ width: $size
22
+ SASS
23
+
24
+ css = <<~CSS.chomp
25
+ .foo {
26
+ width: 30px;
27
+ }
28
+ CSS
29
+
30
+ assert_raises(RenderError) do
31
+ @embedded.render(data: sass)
32
+ end
33
+
34
+ assert_raises(RenderError) do
35
+ @embedded.render(data: sass, indented_syntax: false)
36
+ end
37
+
38
+ assert_equal css, @embedded.render(data: sass, indented_syntax: true)[:css]
39
+ end
40
+
41
+ def test_input_file_with_indented_syntax
42
+ sass = <<~SASS
43
+ $size: 30px
44
+ .foo
45
+ width: $size
46
+ SASS
47
+
48
+ css = <<~CSS.chomp
49
+ .foo {
50
+ width: 30px;
51
+ }
52
+ CSS
53
+
54
+ temp_file('style.sass', sass)
55
+
56
+ assert_equal css, @embedded.render(file: 'style.sass')[:css]
57
+ assert_equal css, @embedded.render(file: 'style.sass', indented_syntax: true)[:css]
58
+ assert_equal css, @embedded.render(file: 'style.sass', indented_syntax: false)[:css]
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'test_helper'
4
+
5
+ module Sass
6
+ class InputTest < 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 test_input_data
18
+ scss = <<~SCSS
19
+ $var: bang;
20
+
21
+ .foo {
22
+ baz: $var;
23
+ }
24
+ SCSS
25
+
26
+ css = <<~CSS.chomp
27
+ .foo {
28
+ baz: bang;
29
+ }
30
+ CSS
31
+
32
+ result = @embedded.render(data: scss)
33
+ assert_equal css, result[:css]
34
+ end
35
+
36
+ def test_input_file
37
+ scss = <<~SCSS
38
+ $var: bang;
39
+
40
+ .foo {
41
+ baz: $var;
42
+ }
43
+ SCSS
44
+
45
+ css = <<~CSS.chomp
46
+ .foo {
47
+ baz: bang;
48
+ }
49
+ CSS
50
+
51
+ temp_file('style.scss', scss)
52
+ result = @embedded.render(file: 'style.scss')
53
+ assert_equal css, result[:css]
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,136 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'test_helper'
4
+
5
+ module Sass
6
+ class OutputTest < 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 test_output_output_style
18
+ data = <<~SCSS
19
+ $var: bang;
20
+
21
+ .foo {
22
+ baz: $var;
23
+ }
24
+ SCSS
25
+
26
+ assert_equal <<~CSS.chomp, @embedded.render(data: data, output_style: :expanded)[:css]
27
+ .foo {
28
+ baz: bang;
29
+ }
30
+ CSS
31
+
32
+ assert_equal <<~CSS.chomp, @embedded.render(data: data, output_style: :compressed)[:css]
33
+ .foo{baz:bang}
34
+ CSS
35
+
36
+ assert_raises(ArgumentError) do
37
+ @embedded.render(data: data, output_style: :nested)[:css]
38
+ end
39
+
40
+ assert_raises(ArgumentError) do
41
+ @embedded.render(data: data, output_style: :compact)[:css]
42
+ end
43
+
44
+ assert_raises(ArgumentError) do
45
+ @embedded.render(data: data, output_style: nil)[:css]
46
+ end
47
+ end
48
+
49
+ DATA_INDENT_TEST = <<~SCSS
50
+ @media all {
51
+ .foo {
52
+ baz: bang;
53
+ }
54
+ }
55
+ SCSS
56
+
57
+ def test_output_indent_width
58
+ assert_equal <<~CSS.chomp, @embedded.render(data: DATA_INDENT_TEST, indent_width: 0)[:css]
59
+ @media all {
60
+ .foo {
61
+ baz: bang;
62
+ }
63
+ }
64
+ CSS
65
+
66
+ assert_equal <<~CSS.chomp, @embedded.render(data: DATA_INDENT_TEST, indent_width: 1)[:css]
67
+ @media all {
68
+ .foo {
69
+ baz: bang;
70
+ }
71
+ }
72
+ CSS
73
+
74
+ assert_equal <<~CSS.chomp, @embedded.render(data: DATA_INDENT_TEST, indent_width: 4)[:css]
75
+ @media all {
76
+ .foo {
77
+ baz: bang;
78
+ }
79
+ }
80
+ CSS
81
+
82
+ assert_equal <<~CSS.chomp, @embedded.render(data: DATA_INDENT_TEST, indent_width: 10)[:css]
83
+ @media all {
84
+ .foo {
85
+ baz: bang;
86
+ }
87
+ }
88
+ CSS
89
+
90
+ assert_raises(RangeError) do
91
+ @embedded.render(data: DATA_INDENT_TEST, indent_width: -1)[:css]
92
+ end
93
+
94
+ assert_raises(RangeError) do
95
+ @embedded.render(data: DATA_INDENT_TEST, indent_width: 11)[:css]
96
+ end
97
+
98
+ assert_raises(ArgumentError) do
99
+ @embedded.render(data: DATA_INDENT_TEST, indent_width: 3.14)[:css]
100
+ end
101
+ end
102
+
103
+ def test_output_indent_type
104
+ assert_equal <<~CSS.chomp, @embedded.render(data: DATA_INDENT_TEST, indent_type: :tab)[:css]
105
+ @media all {
106
+ \t\t.foo {
107
+ \t\t\t\tbaz: bang;
108
+ \t\t}
109
+ }
110
+ CSS
111
+
112
+ assert_equal <<~CSS.chomp, @embedded.render(data: DATA_INDENT_TEST, indent_width: 1, indent_type: 'tab')[:css]
113
+ @media all {
114
+ \t.foo {
115
+ \t\tbaz: bang;
116
+ \t}
117
+ }
118
+ CSS
119
+ end
120
+
121
+ def test_output_linefeed
122
+ data = <<~SCSS
123
+ $var: bang;
124
+
125
+ .foo {
126
+ baz: $var;
127
+ }
128
+ SCSS
129
+
130
+ assert_equal ".foo {\n baz: bang;\n}", @embedded.render(data: data, linefeed: :lf)[:css]
131
+ assert_equal ".foo {\n\r baz: bang;\n\r}", @embedded.render(data: data, linefeed: :lfcr)[:css]
132
+ assert_equal ".foo {\r baz: bang;\r}", @embedded.render(data: data, linefeed: :cr)[:css]
133
+ assert_equal ".foo {\r\n baz: bang;\r\n}", @embedded.render(data: data, linefeed: :crlf)[:css]
134
+ end
135
+ end
136
+ end
@@ -3,7 +3,9 @@
3
3
  require_relative 'test_helper'
4
4
 
5
5
  module Sass
6
- class ErrorTest < MiniTest::Test
6
+ class RenderErrorTest < MiniTest::Test
7
+ include TempFileTest
8
+
7
9
  def setup
8
10
  @embedded = Embedded.new
9
11
  end
@@ -12,7 +14,7 @@ module Sass
12
14
  @embedded.close
13
15
  end
14
16
 
15
- def test_first_backtrace_is_sass
17
+ def test_first_backtrace_is_stdin
16
18
  template = <<~SCSS
17
19
  .foo {
18
20
  baz: bang;
@@ -25,5 +27,18 @@ module Sass
25
27
  expected = 'stdin:3:20'
26
28
  assert_equal expected, e.backtrace.first
27
29
  end
30
+
31
+ def test_first_backtrace_is_file
32
+ temp_file('style.scss', <<~SCSS)
33
+ .foo {
34
+ baz: bang;
35
+ padding top: 10px;
36
+ }
37
+ SCSS
38
+
39
+ @embedded.render(file: 'style.scss')
40
+ rescue RenderError => e
41
+ assert e.backtrace.first.end_with? '/style.scss:3:20'
42
+ end
28
43
  end
29
44
  end
@@ -3,8 +3,8 @@
3
3
  require_relative 'test_helper'
4
4
 
5
5
  module Sass
6
- class SassTest < MiniTest::Test
7
- def test_sass_works
6
+ class RenderTest < MiniTest::Test
7
+ def test_sass_render
8
8
  assert_equal '', ::Sass.render(data: '')[:css]
9
9
 
10
10
  css = <<~CSS.chomp
@@ -12,6 +12,7 @@ module Sass
12
12
  font-size: 2rem;
13
13
  }
14
14
  CSS
15
+
15
16
  assert_equal css, ::Sass.render(data: 'h1 { font-size: 2rem; }')[:css]
16
17
  end
17
18
  end
@@ -0,0 +1,178 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'test_helper'
4
+
5
+ module Sass
6
+ class SourceMapsTest < 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 test_no_source_map
18
+ scss = <<~SCSS
19
+ $size: 40px;
20
+ h1 {
21
+ font-size: $size;
22
+ }
23
+ SCSS
24
+
25
+ css = <<~CSS.chomp
26
+ h1 {
27
+ font-size: 40px;
28
+ }
29
+ CSS
30
+
31
+ temp_file('style.scss', scss)
32
+
33
+ result = @embedded.render(file: 'style.scss')
34
+ assert_equal css, result[:css]
35
+ assert_nil result[:map]
36
+ end
37
+
38
+ def test_source_map_file_as_string
39
+ scss = <<~SCSS
40
+ $size: 40px;
41
+ h1 {
42
+ font-size: $size;
43
+ }
44
+ SCSS
45
+
46
+ css = <<~CSS.chomp
47
+ h1 {
48
+ font-size: 40px;
49
+ }
50
+ /*# sourceMappingURL=out.map */
51
+ CSS
52
+
53
+ temp_file('style.scss', scss)
54
+
55
+ result = @embedded.render(file: 'style.scss',
56
+ source_map: 'out.map')
57
+ assert_equal css, result[:css]
58
+ JSON.parse(result[:map])
59
+ end
60
+
61
+ def test_source_map_true_without_out_file_has_no_effect
62
+ scss = <<~SCSS
63
+ $size: 40px;
64
+ h1 {
65
+ font-size: $size;
66
+ }
67
+ SCSS
68
+
69
+ css = <<~CSS.chomp
70
+ h1 {
71
+ font-size: 40px;
72
+ }
73
+ CSS
74
+
75
+ temp_file('style.scss', scss)
76
+
77
+ result = @embedded.render(file: 'style.scss',
78
+ source_map: true)
79
+ assert_equal css, result[:css]
80
+ assert_nil result[:map]
81
+ end
82
+
83
+ def test_source_map_true_with_out_file
84
+ scss = <<~SCSS
85
+ $size: 40px;
86
+ h1 {
87
+ font-size: $size;
88
+ }
89
+ SCSS
90
+
91
+ css = <<~CSS.chomp
92
+ h1 {
93
+ font-size: 40px;
94
+ }
95
+ /*# sourceMappingURL=out.css.map */
96
+ CSS
97
+
98
+ temp_file('style.scss', scss)
99
+
100
+ result = @embedded.render(file: 'style.scss',
101
+ source_map: true,
102
+ out_file: 'out.css')
103
+ assert_equal css, result[:css]
104
+ JSON.parse(result[:map])
105
+ end
106
+
107
+ def test_omit_source_map_url
108
+ scss = <<~SCSS
109
+ $size: 40px;
110
+ h1 {
111
+ font-size: $size;
112
+ }
113
+ SCSS
114
+
115
+ css = <<~CSS.chomp
116
+ h1 {
117
+ font-size: 40px;
118
+ }
119
+ CSS
120
+
121
+ temp_file('style.scss', scss)
122
+
123
+ result = @embedded.render(file: 'style.scss',
124
+ source_map: 'out.map',
125
+ omit_source_map_url: true)
126
+ assert_equal css, result[:css]
127
+ JSON.parse(result[:map])
128
+ end
129
+
130
+ def test_source_map_embedded
131
+ scss = <<~SCSS
132
+ $size: 40px;
133
+ h1 {
134
+ font-size: $size;
135
+ }
136
+ SCSS
137
+
138
+ css = <<~CSS.chomp
139
+ h1 {
140
+ font-size: 40px;
141
+ }
142
+ /*# sourceMappingURL=data:application/json;base64,
143
+ CSS
144
+
145
+ temp_file('style.scss', scss)
146
+
147
+ result = @embedded.render(file: 'style.scss',
148
+ source_map: 'out.map',
149
+ source_map_embed: true)
150
+ assert result[:css].start_with? css
151
+ JSON.parse(result[:map])
152
+ end
153
+
154
+ def test_source_map_root
155
+ scss = <<~SCSS
156
+ $size: 40px;
157
+ h1 {
158
+ font-size: $size;
159
+ }
160
+ SCSS
161
+
162
+ css = <<~CSS.chomp
163
+ h1 {
164
+ font-size: 40px;
165
+ }
166
+ /*# sourceMappingURL=out.map */
167
+ CSS
168
+
169
+ temp_file('style.scss', scss)
170
+
171
+ result = @embedded.render(file: 'style.scss',
172
+ source_map: 'out.map',
173
+ source_map_root: 'assets')
174
+ assert_equal css, result[:css]
175
+ assert_equal 'assets', JSON.parse(result[:map])['sourceRoot']
176
+ end
177
+ end
178
+ end
data/test/test_helper.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'json'
3
4
  require 'fileutils'
4
5
  require 'minitest/autorun'
5
6
  require 'minitest/pride'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sass-embedded
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - なつき
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-26 00:00:00.000000000 Z
11
+ date: 2021-05-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: google-protobuf
@@ -162,12 +162,16 @@ files:
162
162
  - lib/sass/util.rb
163
163
  - lib/sass/version.rb
164
164
  - sass-embedded.gemspec
165
- - test/compiler_test.rb
166
- - test/custom_importer_test.rb
167
- - test/error_test.rb
165
+ - test/concurrency_test.rb
168
166
  - test/functions_test.rb
169
- - test/output_style_test.rb
170
- - test/sass_test.rb
167
+ - test/importer_test.rb
168
+ - test/include_paths_test.rb
169
+ - test/indented_syntax_test.rb
170
+ - test/input_test.rb
171
+ - test/output_test.rb
172
+ - test/render_error_test.rb
173
+ - test/render_test.rb
174
+ - test/source_maps_test.rb
171
175
  - test/test_helper.rb
172
176
  homepage: https://github.com/ntkme/embedded-host-ruby
173
177
  licenses:
@@ -193,10 +197,14 @@ signing_key:
193
197
  specification_version: 4
194
198
  summary: Use dart-sass with Ruby!
195
199
  test_files:
196
- - test/compiler_test.rb
197
- - test/custom_importer_test.rb
198
- - test/error_test.rb
200
+ - test/concurrency_test.rb
199
201
  - test/functions_test.rb
200
- - test/output_style_test.rb
201
- - test/sass_test.rb
202
+ - test/importer_test.rb
203
+ - test/include_paths_test.rb
204
+ - test/indented_syntax_test.rb
205
+ - test/input_test.rb
206
+ - test/output_test.rb
207
+ - test/render_error_test.rb
208
+ - test/render_test.rb
209
+ - test/source_maps_test.rb
202
210
  - test/test_helper.rb
@@ -1,262 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'test_helper'
4
-
5
- module Sass
6
- class EmbeddedTest < 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_line_comments
22
- skip 'not supported'
23
-
24
- template = <<~SCSS
25
- .foo {
26
- baz: bang; }
27
- SCSS
28
- expected_output = <<~CSS
29
- /* line 1, stdin */
30
- .foo {
31
- baz: bang;
32
- }
33
- CSS
34
- output = @embedded.render(data: template,
35
- source_comments: true)
36
- assert_equal expected_output, output[:css]
37
- end
38
-
39
- def test_one_line_comments
40
- assert_equal <<~CSS.chomp, render(<<~SCSS)
41
- .foo {
42
- baz: bang;
43
- }
44
- CSS
45
- .foo {// bar: baz;}
46
- baz: bang; //}
47
- }
48
- SCSS
49
- assert_equal <<~CSS.chomp, render(<<~SCSS)
50
- .foo bar[val="//"] {
51
- baz: bang;
52
- }
53
- CSS
54
- .foo bar[val="//"] {
55
- baz: bang; //}
56
- }
57
- SCSS
58
- end
59
-
60
- def test_variables
61
- assert_equal <<~CSS.chomp, render(<<~SCSS)
62
- blat {
63
- a: foo;
64
- }
65
- CSS
66
- $var: foo;
67
- #{' '}
68
- blat {a: $var}
69
- SCSS
70
-
71
- assert_equal <<~CSS.chomp, render(<<~SCSS)
72
- foo {
73
- a: 2;
74
- b: 6;
75
- }
76
- CSS
77
- foo {
78
- $var: 2;
79
- $another-var: 4;
80
- a: $var;
81
- b: $var + $another-var;}
82
- SCSS
83
- end
84
-
85
- def test_precision
86
- skip 'not supported'
87
-
88
- template = <<~SCSS
89
- $var: 1;
90
- .foo {
91
- baz: $var / 3; }
92
- SCSS
93
- expected_output = <<~CSS.chomp
94
- .foo {
95
- baz: 0.33333333;
96
- }
97
- CSS
98
- output = @embedded.render(data: template,
99
- precision: 8)
100
- assert_equal expected_output, output
101
- end
102
-
103
- def test_precision_not_specified
104
- template = <<~SCSS
105
- $var: 1;
106
- .foo {
107
- baz: $var / 3; }
108
- SCSS
109
- expected_output = <<~CSS.chomp
110
- .foo {
111
- baz: 0.3333333333;
112
- }
113
- CSS
114
- output = render(template)
115
- assert_equal expected_output, output
116
- end
117
-
118
- def test_source_map
119
- temp_dir('admin')
120
-
121
- temp_file('admin/text-color.scss', <<~SCSS)
122
- p {
123
- color: red;
124
- }
125
- SCSS
126
- temp_file('style.scss', <<~SCSS)
127
- @use 'admin/text-color';
128
- #{' '}
129
- p {
130
- padding: 20px;
131
- }
132
- SCSS
133
- output = @embedded.render(data: File.read('style.scss'),
134
- source_map: 'style.scss.map')
135
-
136
- assert output[:map].start_with? '{"version":3,'
137
- end
138
-
139
- def test_no_source_map
140
- output = @embedded.render(data: '$size: 30px;')
141
- assert_equal '', output[:map]
142
- end
143
-
144
- def test_include_paths
145
- temp_dir('included_1')
146
- temp_dir('included_2')
147
-
148
- temp_file('included_1/import_parent.scss', '$s: 30px;')
149
- temp_file('included_2/import.scss', "@use 'import_parent' as *; $size: $s;")
150
- temp_file('styles.scss', "@use 'import.scss' as *; .hi { width: $size; }")
151
-
152
- assert_equal ".hi {\n width: 30px;\n}", @embedded.render(data: File.read('styles.scss'),
153
- include_paths: %w[
154
- included_1 included_2
155
- ])[:css]
156
- end
157
-
158
- def test_global_include_paths
159
- temp_dir('included_1')
160
- temp_dir('included_2')
161
-
162
- temp_file('included_1/import_parent.scss', '$s: 30px;')
163
- temp_file('included_2/import.scss', "@use 'import_parent' as *; $size: $s;")
164
- temp_file('styles.scss', "@use 'import.scss' as *; .hi { width: $size; }")
165
-
166
- ::Sass.include_paths << 'included_1'
167
- ::Sass.include_paths << 'included_2'
168
-
169
- assert_equal ".hi {\n width: 30px;\n}", render(File.read('styles.scss'))
170
- end
171
-
172
- def test_env_include_paths
173
- expected_include_paths = %w[included_3 included_4]
174
-
175
- ::Sass.instance_eval { @include_paths = nil }
176
-
177
- ENV['SASS_PATH'] = expected_include_paths.join(File::PATH_SEPARATOR)
178
-
179
- assert_equal expected_include_paths, ::Sass.include_paths
180
-
181
- ::Sass.include_paths.clear
182
- end
183
-
184
- def test_include_paths_not_configured
185
- temp_dir('included_5')
186
- temp_dir('included_6')
187
- temp_file('included_5/import_parent.scss', '$s: 30px;')
188
- temp_file('included_6/import.scss', "@use 'import_parent' as *; $size: $s;")
189
- temp_file('styles.scss', "@use 'import.scss' as *; .hi { width: $size; }")
190
-
191
- assert_raises(RenderError) do
192
- render(File.read('styles.scss'))
193
- end
194
- end
195
-
196
- def test_sass_variation
197
- sass = <<~SASS
198
- $size: 30px
199
- .foo
200
- width: $size
201
- SASS
202
-
203
- css = <<~CSS.chomp
204
- .foo {
205
- width: 30px;
206
- }
207
- CSS
208
-
209
- assert_equal css, @embedded.render(data: sass, indented_syntax: true)[:css]
210
- assert_raises(RenderError) do
211
- @embedded.render(data: sass, indented_syntax: false)
212
- end
213
- end
214
-
215
- def test_inline_source_maps
216
- skip 'not supported'
217
-
218
- template = <<~SCSS
219
- .foo {
220
- baz: bang; }
221
- SCSS
222
-
223
- output = @embedded.render(data: template,
224
- source_map: '.',
225
- source_map_embed: true,
226
- source_map_contents: true)[:css]
227
-
228
- assert_match(/sourceMappingURL/, output)
229
- assert_match(/.foo/, output)
230
- end
231
-
232
- def test_empty_template
233
- output = render('')
234
- assert_equal '', output
235
- end
236
-
237
- def test_import_plain_css
238
- temp_file('test.css', '.something{color: red}')
239
- expected_output = <<~CSS.chomp
240
- .something {
241
- color: red;
242
- }
243
- CSS
244
-
245
- output = render("@use 'test';")
246
- assert_equal expected_output, output
247
- end
248
-
249
- def test_concurrency
250
- 10.times do
251
- threads = []
252
- 10.times do |i|
253
- threads << Thread.new(i) do |id|
254
- output = @embedded.render(data: "div { width: #{id} }")[:css]
255
- assert_match(/#{id}/, output)
256
- end
257
- end
258
- threads.each(&:join)
259
- end
260
- end
261
- end
262
- end
@@ -1,93 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'test_helper'
4
-
5
- module Sass
6
- class OutputStyleTest < MiniTest::Test
7
- def setup
8
- @embedded = Embedded.new
9
- end
10
-
11
- def teardown
12
- @embedded.close
13
- end
14
-
15
- def input_scss
16
- <<~CSS
17
- $color: #fff;
18
-
19
- #main {
20
- color: $color;
21
- background-color: #000;
22
- p {
23
- width: 10em;
24
- }
25
- }
26
-
27
- .huge {
28
- font-size: 10em;
29
- font-weight: bold;
30
- text-decoration: underline;
31
- }
32
- CSS
33
- end
34
-
35
- def expected_expanded_output
36
- <<~CSS.chomp
37
- #main {
38
- color: #fff;
39
- background-color: #000;
40
- }
41
- #main p {
42
- width: 10em;
43
- }
44
-
45
- .huge {
46
- font-size: 10em;
47
- font-weight: bold;
48
- text-decoration: underline;
49
- }
50
- CSS
51
- end
52
-
53
- def test_expanded_output_is_default
54
- output = @embedded.render(data: input_scss)[:css]
55
- assert_equal expected_expanded_output, output
56
- end
57
-
58
- def test_output_style_accepts_strings
59
- output = @embedded.render(data: input_scss, output_style: :expanded)[:css]
60
- assert_equal expected_expanded_output, output
61
- end
62
-
63
- def test_invalid_output_style
64
- assert_raises(ArgumentError) do
65
- @embedded.render(data: input_scss, output_style: :totally_wrong)[:css]
66
- end
67
- end
68
-
69
- def test_unsupported_output_style
70
- assert_raises(ArgumentError) do
71
- @embedded.render(data: input_scss, output_style: :nested)[:css]
72
- end
73
-
74
- assert_raises(ArgumentError) do
75
- @embedded.render(data: input_scss, output_style: :compact)[:css]
76
- end
77
- end
78
-
79
- def test_compressed_output
80
- output = @embedded.render(data: input_scss, output_style: :compressed)[:css]
81
- assert_equal <<~CSS.chomp, output
82
- #main{color:#fff;background-color:#000}#main p{width:10em}.huge{font-size:10em;font-weight:bold;text-decoration:underline}
83
- CSS
84
- end
85
-
86
- def test_string_output_style_names
87
- output = @embedded.render(data: input_scss, output_style: 'compressed')[:css]
88
- assert_equal <<~CSS.chomp, output
89
- #main{color:#fff;background-color:#000}#main p{width:10em}.huge{font-size:10em;font-weight:bold;text-decoration:underline}
90
- CSS
91
- end
92
- end
93
- end