sass-embedded 0.3.0 → 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 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