sass-embedded 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/sass/embedded.rb CHANGED
@@ -1,14 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'base64'
4
- require 'json'
3
+ require_relative 'compile_error'
4
+ require_relative 'compile_result'
5
+ require_relative 'importer_result'
5
6
  require_relative 'embedded/channel'
6
7
  require_relative 'embedded/compile_context'
7
- require_relative 'embedded/error'
8
- require_relative 'embedded/result'
9
- require_relative 'embedded/util'
8
+ require_relative 'embedded/render'
9
+ require_relative 'embedded/url'
10
10
  require_relative 'embedded/version'
11
11
  require_relative 'embedded/version_context'
12
+ require_relative 'logger'
12
13
 
13
14
  module Sass
14
15
  # The {Embedded} host for using dart-sass-embedded. Each instance creates
@@ -16,241 +17,117 @@ module Sass
16
17
  #
17
18
  # @example
18
19
  # embedded = Sass::Embedded.new
19
- # result = embedded.render(data: 'h1 { font-size: 40px; }')
20
- # result = embedded.render(file: 'style.css')
20
+ # result = embedded.compile_string('h1 { font-size: 40px; }')
21
+ # result = embedded.compile('style.scss')
21
22
  # embedded.close
22
23
  class Embedded
23
- def self.include_paths
24
- @include_paths ||= if ENV['SASS_PATH']
25
- ENV['SASS_PATH'].split(File::PATH_SEPARATOR)
26
- else
27
- []
28
- end
29
- end
30
-
31
24
  def initialize
32
25
  @channel = Channel.new
33
26
  end
34
27
 
35
- # The {Embedded#info} method.
28
+ # The {Embedded#compile} method.
36
29
  #
30
+ # @return [CompileResult]
31
+ # @raise [CompileError]
37
32
  # @raise [ProtocolError]
38
- def info
39
- @info ||= VersionContext.new(@channel).receive_message
40
- end
33
+ def compile(path,
34
+ load_paths: [],
41
35
 
42
- # The {Embedded#render} method.
43
- #
44
- # See {file:README.md#options} for supported options.
45
- #
46
- # @return [RenderResult]
47
- # @raise [ProtocolError]
48
- # @raise [RenderError]
49
- def render(data: nil,
50
- file: nil,
51
- indented_syntax: false,
52
- include_paths: [],
53
- output_style: :expanded,
54
- indent_type: :space,
55
- indent_width: 2,
56
- linefeed: :lf,
57
- source_map: false,
58
- out_file: nil,
59
- omit_source_map_url: false,
60
- source_map_contents: false,
61
- source_map_embed: false,
62
- source_map_root: '',
63
- functions: {},
64
- importer: [])
65
- start = Util.now
36
+ source_map: false,
37
+ style: :expanded,
66
38
 
67
- indent_type = parse_indent_type(indent_type)
68
- indent_width = parse_indent_width(indent_width)
69
- linefeed = parse_linefeed(linefeed)
39
+ functions: {},
40
+ importers: [],
41
+
42
+ alert_ascii: false,
43
+ alert_color: $stderr.tty?,
44
+ logger: nil,
45
+ quiet_deps: false,
46
+ verbose: false)
47
+
48
+ raise ArgumentError, 'path must be set' if path.nil?
70
49
 
71
50
  message = CompileContext.new(@channel,
72
- data: data,
73
- file: file,
74
- indented_syntax: indented_syntax,
75
- include_paths: include_paths,
76
- output_style: output_style,
51
+ path: path,
52
+ source: nil,
53
+ importer: nil,
54
+ load_paths: load_paths,
55
+ syntax: nil,
56
+ url: nil,
77
57
  source_map: source_map,
78
- out_file: out_file,
58
+ style: style,
79
59
  functions: functions,
80
- importer: importer).receive_message
81
-
82
- if message.failure
83
- raise RenderError.new(
84
- message.failure.message,
85
- message.failure.formatted,
86
- if message.failure.span.nil?
87
- nil
88
- elsif message.failure.span.url == ''
89
- 'stdin'
90
- else
91
- Util.path_from_file_uri(message.failure.span.url)
92
- end,
93
- message.failure.span ? message.failure.span.start.line + 1 : nil,
94
- message.failure.span ? message.failure.span.start.column + 1 : nil,
95
- 1
96
- )
97
- end
60
+ importers: importers,
61
+ alert_color: alert_color,
62
+ alert_ascii: alert_ascii,
63
+ logger: logger,
64
+ quiet_deps: quiet_deps,
65
+ verbose: verbose).receive_message
98
66
 
99
- map, source_map = post_process_map(map: message.success.source_map,
100
- data: data,
101
- file: file,
102
- out_file: out_file,
103
- source_map: source_map,
104
- source_map_contents: source_map_contents,
105
- source_map_root: source_map_root)
67
+ raise CompileError.from_proto(message.failure) if message.failure
106
68
 
107
- css = post_process_css(css: message.success.css,
108
- indent_type: indent_type,
109
- indent_width: indent_width,
110
- linefeed: linefeed,
111
- map: map,
112
- out_file: out_file,
113
- omit_source_map_url: omit_source_map_url,
114
- source_map: source_map,
115
- source_map_embed: source_map_embed)
116
-
117
- finish = Util.now
118
-
119
- stats = RenderResultStats.new(file.nil? ? 'data' : file, start, finish, finish - start)
120
-
121
- RenderResult.new(css, map, stats)
122
- end
123
-
124
- def close
125
- @channel.close
126
- end
127
-
128
- def closed?
129
- @channel.closed?
69
+ CompileResult.from_proto(message.success)
130
70
  end
131
71
 
132
- private
133
-
134
- def post_process_map(map:,
135
- data:,
136
- file:,
137
- out_file:,
138
- source_map:,
139
- source_map_contents:,
140
- source_map_root:)
141
- return if map.nil? || map.empty?
142
-
143
- map_data = JSON.parse(map)
144
-
145
- map_data['sourceRoot'] = source_map_root
146
-
147
- source_map_path = if source_map.is_a? String
148
- source_map
149
- else
150
- "#{out_file}.map"
151
- end
152
-
153
- source_map_dir = File.dirname(source_map_path)
154
-
155
- if out_file
156
- map_data['file'] = Util.relative_path(source_map_dir, out_file)
157
- elsif file
158
- ext = File.extname(file)
159
- map_data['file'] = "#{file[0..(ext.empty? ? -1 : -ext.length - 1)]}.css"
160
- else
161
- map_data['file'] = 'stdin.css'
162
- end
163
-
164
- map_data['sourcesContent'] = [] if source_map_contents
72
+ # The {Embedded#compile_string} method.
73
+ #
74
+ # @return [CompileResult]
75
+ # @raise [CompileError]
76
+ # @raise [ProtocolError]
77
+ def compile_string(source,
78
+ importer: nil,
79
+ load_paths: [],
80
+ syntax: :scss,
81
+ url: nil,
165
82
 
166
- file = File.absolute_path(file) unless file.nil?
83
+ source_map: false,
84
+ style: :expanded,
167
85
 
168
- map_data['sources'].map! do |source|
169
- if source.start_with? 'file://'
170
- path = Util.path_from_file_uri(source)
171
- content = if path == file && !data.nil?
172
- data
173
- else
174
- begin
175
- File.read(path)
176
- rescue StandardError
177
- nil
178
- end
179
- end
180
- map_data['sourcesContent'].push(content) if source_map_contents
181
- Util.relative_path(source_map_dir, path)
182
- else
183
- map_data['sourcesContent'].push(nil) if source_map_contents
184
- source
185
- end
186
- end
86
+ functions: {},
87
+ importers: [],
187
88
 
188
- [-JSON.generate(map_data), source_map_path]
189
- end
89
+ alert_ascii: false,
90
+ alert_color: $stderr.tty?,
91
+ logger: nil,
92
+ quiet_deps: false,
93
+ verbose: false)
94
+ raise ArgumentError, 'source must be set' if source.nil?
190
95
 
191
- def post_process_css(css:,
192
- indent_type:,
193
- indent_width:,
194
- linefeed:,
195
- map:,
196
- omit_source_map_url:,
197
- out_file:,
198
- source_map:,
199
- source_map_embed:)
200
- css = +css
201
- if indent_width != 2 || indent_type.to_sym != :space
202
- indent = indent_type * indent_width
203
- css.gsub!(/^ +/) do |space|
204
- indent * (space.length / 2)
205
- end
206
- end
207
- css.gsub!("\n", linefeed) if linefeed != "\n"
96
+ message = CompileContext.new(@channel,
97
+ path: nil,
98
+ source: source,
99
+ importer: importer,
100
+ load_paths: load_paths,
101
+ syntax: syntax,
102
+ url: url,
103
+ source_map: source_map,
104
+ style: style,
105
+ functions: functions,
106
+ importers: importers,
107
+ alert_color: alert_color,
108
+ alert_ascii: alert_ascii,
109
+ logger: logger,
110
+ quiet_deps: quiet_deps,
111
+ verbose: verbose).receive_message
208
112
 
209
- unless map.nil? || omit_source_map_url == true
210
- url = if source_map_embed
211
- "data:application/json;base64,#{Base64.strict_encode64(map)}"
212
- elsif out_file
213
- Util.relative_path(File.dirname(out_file), source_map)
214
- else
215
- source_map
216
- end
217
- css += "#{linefeed}#{linefeed}/*# sourceMappingURL=#{url} */"
218
- end
113
+ raise CompileError.from_proto(message.failure) if message.failure
219
114
 
220
- -css
115
+ CompileResult.from_proto(message.success)
221
116
  end
222
117
 
223
- def parse_indent_type(indent_type)
224
- case indent_type.to_sym
225
- when :space
226
- ' '
227
- when :tab
228
- "\t"
229
- else
230
- raise ArgumentError, 'indent_type must be one of :space, :tab'
231
- end
118
+ # The {Embedded#info} method.
119
+ #
120
+ # @raise [ProtocolError]
121
+ def info
122
+ @info ||= VersionContext.new(@channel).receive_message
232
123
  end
233
124
 
234
- def parse_indent_width(indent_width)
235
- raise ArgumentError, 'indent_width must be an integer' unless indent_width.is_a? Integer
236
- raise RangeError, 'indent_width must be in between 0 and 10 (inclusive)' unless indent_width.between? 0, 10
237
-
238
- indent_width
125
+ def close
126
+ @channel.close
239
127
  end
240
128
 
241
- def parse_linefeed(linefeed)
242
- case linefeed.to_sym
243
- when :lf
244
- "\n"
245
- when :lfcr
246
- "\n\r"
247
- when :cr
248
- "\r"
249
- when :crlf
250
- "\r\n"
251
- else
252
- raise ArgumentError, 'linefeed must be one of :lf, :lfcr, :cr, :crlf'
253
- end
129
+ def closed?
130
+ @channel.closed?
254
131
  end
255
132
  end
256
133
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ # The {FileImporter} interface.
5
+ class FileImporter
6
+ def find_file_url(url, from_import:) # rubocop:disable Lint/UnusedMethodArgument
7
+ raise NotImplementedError, 'FileImporter#find_file_url must be implemented'
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ # The {Importer} interface.
5
+ class Importer
6
+ def canonicalize(url) # rubocop:disable Lint/UnusedMethodArgument
7
+ raise NotImplementedError, 'Importer#canonicalize must be implemented'
8
+ end
9
+
10
+ def load(canonical_url) # rubocop:disable Lint/UnusedMethodArgument
11
+ raise NotImplementedError, 'Importer#load must be implemented'
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ # The {ImporterResult} of {Importer#load}.
5
+ class ImporterResult
6
+ attr_reader :contents, :syntax, :source_map_url
7
+
8
+ def initialize(contents, syntax, source_map_url = nil)
9
+ @contents = contents
10
+ @syntax = syntax
11
+ @source_map_url = source_map_url
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ module Logger
5
+ # The {SourceLocation} in {SourceSpan}.
6
+ class SourceLocation
7
+ attr_reader :offset, :line, :column
8
+
9
+ def initialize(offset, line, column)
10
+ @offset = offset
11
+ @line = line
12
+ @column = column
13
+ end
14
+
15
+ def self.from_proto(source_location)
16
+ return nil if source_location.nil?
17
+
18
+ SourceLocation.new(source_location.offset,
19
+ source_location.line,
20
+ source_location.column)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'source_location'
4
+
5
+ module Sass
6
+ module Logger
7
+ # The {SourceSpan} in {CompileError}.
8
+ class SourceSpan
9
+ attr_reader :start, :end, :text, :url, :context
10
+
11
+ def initialize(start, end_, text, url, context)
12
+ @start = start
13
+ @end = end_
14
+ @text = text
15
+ @url = url == '' ? nil : url
16
+ @context = context == '' ? nil : context
17
+ end
18
+
19
+ def self.from_proto(source_span)
20
+ return nil if source_span.nil?
21
+
22
+ SourceSpan.new(SourceLocation.from_proto(source_span.start),
23
+ SourceLocation.from_proto(source_span.end),
24
+ source_span.text,
25
+ source_span.url,
26
+ source_span.context)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ # The {Logger} module.
5
+ module Logger
6
+ # The instance of a slient {Logger}.
7
+ def self.slient
8
+ @slient ||= Slient.new
9
+ end
10
+
11
+ # The slient {Logger}.
12
+ class Slient
13
+ def warn(message, deprecation: false, span: nil, stack: nil); end
14
+
15
+ def debug(message, span: nil); end
16
+ end
17
+
18
+ private_constant :Slient
19
+ end
20
+ end
data/lib/sass.rb CHANGED
@@ -6,6 +6,35 @@ require_relative 'sass/embedded'
6
6
  # the Embedded Sass protocol.
7
7
  module Sass
8
8
  class << self
9
+ # The global {.compile} method. This instantiates a global {Embedded} instance
10
+ # and calls {Embedded#compile}.
11
+ #
12
+ # See {Embedded#compile} for supported options.
13
+ #
14
+ # @example
15
+ # Sass.compile('style.scss')
16
+ # @return [CompileResult]
17
+ # @raise [CompileError]
18
+ # @raise [ProtocolError]
19
+ def compile(path, **kwargs)
20
+ instance.compile(path, **kwargs)
21
+ end
22
+
23
+ # The global {.compile_string} method. This instantiates a global {Embedded} instance
24
+ # and calls {Embedded#compile_string}.
25
+ #
26
+ # See {Embedded#compile_string} for supported options.
27
+ #
28
+ # @example
29
+ # Sass.compile_string('h1 { font-size: 40px; }')
30
+ # @return [CompileResult]
31
+ # @raise [CompileError]
32
+ # @raise [ProtocolError]
33
+ def compile_string(source, **kwargs)
34
+ instance.compile_string(source, **kwargs)
35
+ end
36
+
37
+ # @deprecated
9
38
  # The global {.include_paths} for Sass files. This is meant for plugins and
10
39
  # libraries to register the paths to their Sass stylesheets to that they may
11
40
  # be included via `@import` or `@use`. This include path is used by every
@@ -32,10 +61,11 @@ module Sass
32
61
  instance.info
33
62
  end
34
63
 
64
+ # @deprecated
35
65
  # The global {.render} method. This instantiates a global {Embedded} instance
36
66
  # and calls {Embedded#render}.
37
67
  #
38
- # See {file:README.md#options} for supported options.
68
+ # See {Embedded#render} for supported options.
39
69
  #
40
70
  # @example
41
71
  # Sass.render(data: 'h1 { font-size: 40px; }')
@@ -51,9 +81,15 @@ module Sass
51
81
  private
52
82
 
53
83
  def instance
54
- return @instance if defined?(@instance) && !@instance.closed?
55
-
56
- @instance = Embedded.new
84
+ if @instance.nil?
85
+ @instance = Embedded.new
86
+ at_exit do
87
+ @instance.close
88
+ end
89
+ elsif @instance.closed?
90
+ @instance = Embedded.new
91
+ end
92
+ @instance
57
93
  end
58
94
  end
59
95
  end
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.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - なつき
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-28 00:00:00.000000000 Z
11
+ date: 2022-01-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: google-protobuf
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 3.18.0
19
+ version: 3.19.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 3.18.0
26
+ version: 3.19.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: minitest
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 5.14.4
33
+ version: 5.15.0
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 5.14.4
40
+ version: 5.15.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: minitest-around
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -72,42 +72,42 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 1.21.0
75
+ version: 1.24.0
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 1.21.0
82
+ version: 1.24.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rubocop-minitest
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 0.15.0
89
+ version: 0.17.0
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 0.15.0
96
+ version: 0.17.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rubocop-performance
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: 1.11.5
103
+ version: 1.13.0
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: 1.11.5
110
+ version: 1.13.0
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: rubocop-rake
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -138,27 +138,34 @@ files:
138
138
  - ext/sass/unzip.vbs
139
139
  - lib/sass-embedded.rb
140
140
  - lib/sass.rb
141
+ - lib/sass/compile_error.rb
142
+ - lib/sass/compile_result.rb
141
143
  - lib/sass/embedded.rb
142
144
  - lib/sass/embedded/channel.rb
143
145
  - lib/sass/embedded/compile_context.rb
144
146
  - lib/sass/embedded/compiler.rb
145
147
  - lib/sass/embedded/compiler/path.rb
146
148
  - lib/sass/embedded/compiler/requirements.rb
147
- - lib/sass/embedded/error.rb
148
149
  - lib/sass/embedded/observer.rb
149
150
  - lib/sass/embedded/platform.rb
150
- - lib/sass/embedded/result.rb
151
- - lib/sass/embedded/struct.rb
152
- - lib/sass/embedded/util.rb
151
+ - lib/sass/embedded/protocol_error.rb
152
+ - lib/sass/embedded/render.rb
153
+ - lib/sass/embedded/url.rb
153
154
  - lib/sass/embedded/version.rb
154
155
  - lib/sass/embedded/version_context.rb
155
156
  - lib/sass/embedded_protocol.rb
157
+ - lib/sass/file_importer.rb
158
+ - lib/sass/importer.rb
159
+ - lib/sass/importer_result.rb
160
+ - lib/sass/logger.rb
161
+ - lib/sass/logger/source_location.rb
162
+ - lib/sass/logger/source_span.rb
156
163
  homepage: https://github.com/ntkme/sass-embedded-host-ruby
157
164
  licenses:
158
165
  - MIT
159
166
  metadata:
160
- documentation_uri: https://www.rubydoc.info/gems/sass-embedded/0.9.0
161
- source_code_uri: https://github.com/ntkme/sass-embedded-host-ruby/tree/v0.9.0
167
+ documentation_uri: https://www.rubydoc.info/gems/sass-embedded/0.10.0
168
+ source_code_uri: https://github.com/ntkme/sass-embedded-host-ruby/tree/v0.10.0
162
169
  funding_uri: https://github.com/sponsors/ntkme
163
170
  post_install_message:
164
171
  rdoc_options: []
@@ -175,7 +182,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
175
182
  - !ruby/object:Gem::Version
176
183
  version: '0'
177
184
  requirements: []
178
- rubygems_version: 3.2.22
185
+ rubygems_version: 3.2.32
179
186
  signing_key:
180
187
  specification_version: 4
181
188
  summary: Use dart-sass with Ruby!