sassc-embedded 1.64.2 → 1.68.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +41 -8
- data/lib/sassc/embedded/version.rb +1 -1
- data/lib/sassc/embedded.rb +11 -9
- data/vendor/github.com/sass/sassc-ruby/LICENSE.txt +22 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/dependency.rb +17 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/engine.rb +141 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/error.rb +37 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/functions_handler.rb +73 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/import_handler.rb +50 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/importer.rb +31 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/native/native_context_api.rb +147 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/native/native_functions_api.rb +159 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/native/sass2scss_api.rb +10 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/native/sass_input_style.rb +13 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/native/sass_output_style.rb +12 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/native/sass_value.rb +97 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/native/string_list.rb +10 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/native.rb +64 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/sass_2_scss.rb +9 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/functions.rb +8 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value/bool.rb +32 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value/color.rb +95 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value/list.rb +136 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value/map.rb +69 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value/number.rb +389 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value/string.rb +96 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value.rb +137 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value_conversion/base.rb +13 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value_conversion/bool.rb +13 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value_conversion/color.rb +18 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value_conversion/list.rb +25 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value_conversion/map.rb +21 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value_conversion/number.rb +13 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value_conversion/string.rb +17 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value_conversion.rb +69 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script.rb +17 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/util/normalized_map.rb +117 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/util.rb +231 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/version.rb +5 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc.rb +64 -0
- metadata +44 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c1bae171b142e9c93398da7fd657e968c0804ce760bd7c05e04dc59a1d6c408
|
4
|
+
data.tar.gz: e45f9276e88a116aa2f83f592187b3705a6b2989b7837e90ca6917fbc418a51e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f36c1fd78fbebbb9af4bf20126b0024aa0ca15a1900ed258390c449d1de36294c96160c0e9c76777d1a2ff053564b650b0b048038ceb03f7a2c64f3c9f8d88f
|
7
|
+
data.tar.gz: fc2bf82ab1c39773ea130bea388028c649dab02e71e35c9f31a2cbbb4f9a30be4718a535b628f5dbeef5fac1b43009e6c3776765c3d10b2399d0aba8019bd9ab
|
data/README.md
CHANGED
@@ -14,12 +14,51 @@ It has been tested with:
|
|
14
14
|
- [`sprockets`](https://github.com/rails/sprockets)
|
15
15
|
- [`sprockets-rails`](https://github.com/rails/sprockets-rails)
|
16
16
|
|
17
|
-
##
|
17
|
+
## Uninstall `sassc`
|
18
18
|
|
19
|
-
|
19
|
+
Execute:
|
20
|
+
|
21
|
+
``` sh
|
22
|
+
bundle remove sassc
|
23
|
+
```
|
24
|
+
|
25
|
+
Or uninstall it yourself as:
|
26
|
+
|
27
|
+
``` sh
|
28
|
+
gem uninstall sassc
|
29
|
+
```
|
30
|
+
|
31
|
+
**If your application has a transitive dependency on `sassc` that cannot be removed, you can use any of the following workarounds.**
|
32
|
+
|
33
|
+
### Workaround One
|
34
|
+
|
35
|
+
Add this line to your application's Gemfile:
|
20
36
|
|
21
37
|
``` ruby
|
22
38
|
gem 'sassc', github: 'sass/sassc-ruby', ref: 'refs/pull/233/head'
|
39
|
+
```
|
40
|
+
|
41
|
+
And then execute:
|
42
|
+
|
43
|
+
``` sh
|
44
|
+
bundle
|
45
|
+
```
|
46
|
+
|
47
|
+
The fork of `sassc` at https://github.com/sass/sassc-ruby/pull/233 will load the shim automatically when `require 'sassc'` is invoked, meaning no other code changes needed in your application.
|
48
|
+
|
49
|
+
### Workaround Two
|
50
|
+
|
51
|
+
Add this line to your application's code:
|
52
|
+
|
53
|
+
``` ruby
|
54
|
+
require 'sassc-embedded'
|
55
|
+
```
|
56
|
+
|
57
|
+
## Install `sassc-embedded`
|
58
|
+
|
59
|
+
Add this line to your application's Gemfile:
|
60
|
+
|
61
|
+
``` ruby
|
23
62
|
gem 'sassc-embedded'
|
24
63
|
```
|
25
64
|
|
@@ -35,12 +74,6 @@ Or install it yourself as:
|
|
35
74
|
gem install sassc-embedded
|
36
75
|
```
|
37
76
|
|
38
|
-
---
|
39
|
-
|
40
|
-
The fork of `sassc` at https://github.com/sass/sassc-ruby/pull/233 removes the libsass extension and loads the shim when `require 'sassc'` is invoked.
|
41
|
-
|
42
|
-
Alternatively, the original `sassc` gem can be used, but you must explictly call `require 'sassc-embedded'` to load the shim.
|
43
|
-
|
44
77
|
## Usage
|
45
78
|
|
46
79
|
This shim utilizes `sass-embedded` to allow you to compile SCSS or SASS syntax to CSS. To compile, use a `SassC::Engine`, e.g.:
|
data/lib/sassc/embedded.rb
CHANGED
@@ -49,7 +49,7 @@ module SassC
|
|
49
49
|
source_mapping_url = if source_map_embed?
|
50
50
|
"data:application/json;base64,#{[@source_map].pack('m0')}"
|
51
51
|
else
|
52
|
-
URL.parse(source_map_file_url).route_from(url).to_s
|
52
|
+
URL.unescape(URL.parse(source_map_file_url).route_from(url).to_s)
|
53
53
|
end
|
54
54
|
css += "\n/*# sourceMappingURL=#{source_mapping_url} */"
|
55
55
|
end
|
@@ -60,7 +60,9 @@ module SassC
|
|
60
60
|
line = e.span&.start&.line
|
61
61
|
line += 1 unless line.nil?
|
62
62
|
url = e.span&.url
|
63
|
-
path =
|
63
|
+
path = if url&.start_with?(Protocol::FILE)
|
64
|
+
URL.unescape(URL.parse(url).route_from(URL.path_to_file_url("#{Dir.pwd}/")).to_s)
|
65
|
+
end
|
64
66
|
raise SyntaxError.new(e.full_message, filename: path, line: line)
|
65
67
|
end
|
66
68
|
|
@@ -77,10 +79,10 @@ module SassC
|
|
77
79
|
|
78
80
|
url = URL.parse(source_map_file_url || file_url)
|
79
81
|
data = JSON.parse(@source_map)
|
80
|
-
data['file'] = URL.parse(output_url).route_from(url).to_s if output_url
|
82
|
+
data['file'] = URL.unescape(URL.parse(output_url).route_from(url).to_s) if output_url
|
81
83
|
data['sources'].map! do |source|
|
82
84
|
if source.start_with?(Protocol::FILE)
|
83
|
-
URL.parse(source).route_from(url).to_s
|
85
|
+
URL.unescape(URL.parse(source).route_from(url).to_s)
|
84
86
|
else
|
85
87
|
source
|
86
88
|
end
|
@@ -298,16 +300,16 @@ module SassC
|
|
298
300
|
@parent_urls = [URL.path_to_file_url(File.absolute_path(@importer.options[:filename] || 'stdin'))]
|
299
301
|
end
|
300
302
|
|
301
|
-
def canonicalize(url,
|
303
|
+
def canonicalize(url, context)
|
302
304
|
if url.start_with?(Protocol::IMPORT)
|
303
305
|
canonical_url = @canonical_urls.delete(url.delete_prefix(Protocol::IMPORT))
|
304
306
|
unless @importer_results.key?(canonical_url)
|
305
|
-
canonical_url = resolve_file_url(canonical_url, @parent_urls.last, from_import)
|
307
|
+
canonical_url = resolve_file_url(canonical_url, @parent_urls.last, context.from_import)
|
306
308
|
end
|
307
309
|
@parent_urls.push(canonical_url)
|
308
310
|
canonical_url
|
309
311
|
elsif url.start_with?(Protocol::FILE)
|
310
|
-
path = URL.parse(url).route_from(@parent_urls.last).to_s
|
312
|
+
path = URL.unescape(URL.parse(url).route_from(@parent_urls.last).to_s)
|
311
313
|
parent_path = URL.file_url_to_path(@parent_urls.last)
|
312
314
|
|
313
315
|
imports = @importer.imports(path, parent_path)
|
@@ -318,7 +320,7 @@ module SassC
|
|
318
320
|
end
|
319
321
|
|
320
322
|
canonical_url = "#{Protocol::IMPORT}#{next_id}"
|
321
|
-
@importer_results[canonical_url] = imports_to_native(imports, from_import)
|
323
|
+
@importer_results[canonical_url] = imports_to_native(imports, context.from_import)
|
322
324
|
canonical_url
|
323
325
|
elsif url.start_with?(Protocol::LOADED)
|
324
326
|
canonical_url = Protocol::LOADED
|
@@ -352,7 +354,7 @@ module SassC
|
|
352
354
|
end
|
353
355
|
|
354
356
|
def resolve_file_url(url, parent_url, from_import)
|
355
|
-
path = URL.parse(url).route_from(parent_url).to_s
|
357
|
+
path = URL.unescape(URL.parse(url).route_from(parent_url).to_s)
|
356
358
|
parent_path = URL.file_url_to_path(parent_url)
|
357
359
|
[File.dirname(parent_path)].concat(load_paths).each do |load_path|
|
358
360
|
resolved = FileImporter.resolve_path(File.absolute_path(path, load_path), from_import)
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) Ryan Boland & Contributors
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SassC
|
4
|
+
class Dependency
|
5
|
+
attr_reader :filename
|
6
|
+
attr_reader :options
|
7
|
+
|
8
|
+
def initialize(filename)
|
9
|
+
@filename = filename
|
10
|
+
@options = { filename: @filename }
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.from_filenames(filenames)
|
14
|
+
filenames.map { |f| new(f) }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "error"
|
4
|
+
|
5
|
+
module SassC
|
6
|
+
class Engine
|
7
|
+
OUTPUT_STYLES = %i[
|
8
|
+
sass_style_nested
|
9
|
+
sass_style_expanded
|
10
|
+
sass_style_compact
|
11
|
+
sass_style_compressed
|
12
|
+
]
|
13
|
+
|
14
|
+
attr_reader :template, :options
|
15
|
+
|
16
|
+
def initialize(template, options = {})
|
17
|
+
@template = template
|
18
|
+
@options = options
|
19
|
+
@functions = options.fetch(:functions, Script::Functions)
|
20
|
+
end
|
21
|
+
|
22
|
+
def render
|
23
|
+
return @template.dup if @template.empty?
|
24
|
+
|
25
|
+
data_context = Native.make_data_context(@template)
|
26
|
+
context = Native.data_context_get_context(data_context)
|
27
|
+
native_options = Native.context_get_options(context)
|
28
|
+
|
29
|
+
Native.option_set_is_indented_syntax_src(native_options, true) if sass?
|
30
|
+
Native.option_set_input_path(native_options, filename) if filename
|
31
|
+
Native.option_set_precision(native_options, precision) if precision
|
32
|
+
Native.option_set_include_path(native_options, load_paths)
|
33
|
+
Native.option_set_output_style(native_options, output_style_enum)
|
34
|
+
Native.option_set_source_comments(native_options, true) if line_comments?
|
35
|
+
Native.option_set_source_map_file(native_options, source_map_file) if source_map_file
|
36
|
+
Native.option_set_source_map_embed(native_options, true) if source_map_embed?
|
37
|
+
Native.option_set_source_map_contents(native_options, true) if source_map_contents?
|
38
|
+
Native.option_set_omit_source_map_url(native_options, true) if omit_source_map_url?
|
39
|
+
|
40
|
+
import_handler.setup(native_options)
|
41
|
+
functions_handler.setup(native_options, functions: @functions)
|
42
|
+
|
43
|
+
status = Native.compile_data_context(data_context)
|
44
|
+
|
45
|
+
if status != 0
|
46
|
+
message = Native.context_get_error_message(context)
|
47
|
+
filename = Native.context_get_error_file(context)
|
48
|
+
line = Native.context_get_error_line(context)
|
49
|
+
|
50
|
+
raise SyntaxError.new(message, filename: filename, line: line)
|
51
|
+
end
|
52
|
+
|
53
|
+
css = Native.context_get_output_string(context)
|
54
|
+
|
55
|
+
@dependencies = Native.context_get_included_files(context)
|
56
|
+
@source_map = Native.context_get_source_map_string(context)
|
57
|
+
|
58
|
+
css.force_encoding(@template.encoding)
|
59
|
+
@source_map.force_encoding(@template.encoding) if @source_map.is_a?(String)
|
60
|
+
|
61
|
+
return css unless quiet?
|
62
|
+
ensure
|
63
|
+
Native.delete_data_context(data_context) if data_context
|
64
|
+
end
|
65
|
+
|
66
|
+
def dependencies
|
67
|
+
raise NotRenderedError unless @dependencies
|
68
|
+
Dependency.from_filenames(@dependencies)
|
69
|
+
end
|
70
|
+
|
71
|
+
def source_map
|
72
|
+
raise NotRenderedError unless @source_map
|
73
|
+
@source_map
|
74
|
+
end
|
75
|
+
|
76
|
+
def filename
|
77
|
+
@options[:filename]
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def quiet?
|
83
|
+
@options[:quiet]
|
84
|
+
end
|
85
|
+
|
86
|
+
def precision
|
87
|
+
@options[:precision]
|
88
|
+
end
|
89
|
+
|
90
|
+
def sass?
|
91
|
+
@options[:syntax] && @options[:syntax].to_sym == :sass
|
92
|
+
end
|
93
|
+
|
94
|
+
def line_comments?
|
95
|
+
@options[:line_comments]
|
96
|
+
end
|
97
|
+
|
98
|
+
def source_map_embed?
|
99
|
+
@options[:source_map_embed]
|
100
|
+
end
|
101
|
+
|
102
|
+
def source_map_contents?
|
103
|
+
@options[:source_map_contents]
|
104
|
+
end
|
105
|
+
|
106
|
+
def omit_source_map_url?
|
107
|
+
@options[:omit_source_map_url]
|
108
|
+
end
|
109
|
+
|
110
|
+
def source_map_file
|
111
|
+
@options[:source_map_file]
|
112
|
+
end
|
113
|
+
|
114
|
+
def import_handler
|
115
|
+
@import_handler ||= ImportHandler.new(@options)
|
116
|
+
end
|
117
|
+
|
118
|
+
def functions_handler
|
119
|
+
@functions_handler = FunctionsHandler.new(@options)
|
120
|
+
end
|
121
|
+
|
122
|
+
def output_style_enum
|
123
|
+
@output_style_enum ||= Native::SassOutputStyle[output_style]
|
124
|
+
end
|
125
|
+
|
126
|
+
def output_style
|
127
|
+
@output_style ||= begin
|
128
|
+
style = @options.fetch(:style, :sass_style_nested).to_s
|
129
|
+
style = "sass_style_#{style}" unless style.include?("sass_style_")
|
130
|
+
style = style.to_sym
|
131
|
+
raise InvalidStyleError unless Native::SassOutputStyle.symbols.include?(style)
|
132
|
+
style
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def load_paths
|
137
|
+
paths = (@options[:load_paths] || []) + SassC.load_paths
|
138
|
+
paths.join(File::PATH_SEPARATOR) unless paths.empty?
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pathname"
|
4
|
+
|
5
|
+
module SassC
|
6
|
+
|
7
|
+
class BaseError < StandardError; end
|
8
|
+
class NotRenderedError < BaseError; end
|
9
|
+
class InvalidStyleError < BaseError; end
|
10
|
+
class UnsupportedValue < BaseError; end
|
11
|
+
|
12
|
+
# When dealing with SyntaxErrors,
|
13
|
+
# it's important to provide filename and line number information.
|
14
|
+
# This will be used in various error reports to users, including backtraces.
|
15
|
+
|
16
|
+
class SyntaxError < BaseError
|
17
|
+
|
18
|
+
def initialize(message, filename: nil, line: nil)
|
19
|
+
@filename = filename
|
20
|
+
@line = line
|
21
|
+
super(message)
|
22
|
+
end
|
23
|
+
|
24
|
+
def backtrace
|
25
|
+
return nil if super.nil?
|
26
|
+
sass_backtrace + super
|
27
|
+
end
|
28
|
+
|
29
|
+
# The backtrace of the error within Sass files.
|
30
|
+
def sass_backtrace
|
31
|
+
return [] unless @filename && @line
|
32
|
+
["#{@filename}:#{@line}"]
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SassC
|
4
|
+
class FunctionsHandler
|
5
|
+
def initialize(options)
|
6
|
+
@options = options
|
7
|
+
end
|
8
|
+
|
9
|
+
def setup(native_options, functions: Script::Functions)
|
10
|
+
@callbacks = {}
|
11
|
+
@function_names = {}
|
12
|
+
|
13
|
+
list = Native.make_function_list(Script.custom_functions(functions: functions).count)
|
14
|
+
|
15
|
+
# use an anonymous class wrapper to avoid mutations in a threaded environment
|
16
|
+
functions_wrapper = Class.new do
|
17
|
+
attr_accessor :options
|
18
|
+
include functions
|
19
|
+
end.new
|
20
|
+
functions_wrapper.options = @options
|
21
|
+
|
22
|
+
Script.custom_functions(functions: functions).each_with_index do |custom_function, i|
|
23
|
+
@callbacks[custom_function] = FFI::Function.new(:pointer, [:pointer, :pointer]) do |native_argument_list, cookie|
|
24
|
+
begin
|
25
|
+
function_arguments = arguments_from_native_list(native_argument_list)
|
26
|
+
result = functions_wrapper.send(custom_function, *function_arguments)
|
27
|
+
to_native_value(result)
|
28
|
+
rescue StandardError => exception
|
29
|
+
# This rescues any exceptions that occur either in value conversion
|
30
|
+
# or during the execution of a custom function.
|
31
|
+
error(exception.message)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
@function_names[custom_function] = Script.formatted_function_name(custom_function, functions: functions)
|
36
|
+
|
37
|
+
callback = Native.make_function(
|
38
|
+
@function_names[custom_function],
|
39
|
+
@callbacks[custom_function],
|
40
|
+
nil
|
41
|
+
)
|
42
|
+
|
43
|
+
Native::function_set_list_entry(list, i, callback)
|
44
|
+
end
|
45
|
+
|
46
|
+
Native::option_set_c_functions(native_options, list)
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def arguments_from_native_list(native_argument_list)
|
52
|
+
native_argument_list_length = Native.list_get_length(native_argument_list)
|
53
|
+
|
54
|
+
(0...native_argument_list_length).map do |i|
|
55
|
+
native_value = Native.list_get_value(native_argument_list, i)
|
56
|
+
Script::ValueConversion.from_native(native_value, @options)
|
57
|
+
end.compact
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_native_value(sass_value)
|
61
|
+
# if the custom function returns nil, we provide a "default" return
|
62
|
+
# value of an empty string
|
63
|
+
sass_value ||= SassC::Script::Value::String.new("")
|
64
|
+
sass_value.options = @options
|
65
|
+
Script::ValueConversion.to_native(sass_value)
|
66
|
+
end
|
67
|
+
|
68
|
+
def error(message)
|
69
|
+
$stderr.puts "[SassC::FunctionsHandler] #{message}"
|
70
|
+
Native.make_error(message)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SassC
|
4
|
+
class ImportHandler
|
5
|
+
def initialize(options)
|
6
|
+
@importer = if options[:importer]
|
7
|
+
options[:importer].new(options)
|
8
|
+
else
|
9
|
+
nil
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def setup(native_options)
|
14
|
+
return unless @importer
|
15
|
+
|
16
|
+
importer_callback = Native.make_importer(import_function, nil)
|
17
|
+
|
18
|
+
list = Native.make_function_list(1)
|
19
|
+
Native::function_set_list_entry(list, 0, importer_callback)
|
20
|
+
|
21
|
+
Native.option_set_c_importers(native_options, list)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def import_function
|
27
|
+
@import_function ||= FFI::Function.new(:pointer, [:string, :pointer, :pointer]) do |path, importer_entry, compiler|
|
28
|
+
last_import = Native::compiler_get_last_import(compiler)
|
29
|
+
parent_path = Native::import_get_abs_path(last_import)
|
30
|
+
|
31
|
+
imports = [*@importer.imports(path, parent_path)]
|
32
|
+
imports_to_native(imports)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def imports_to_native(imports)
|
37
|
+
import_list = Native.make_import_list(imports.size)
|
38
|
+
|
39
|
+
imports.each_with_index do |import, i|
|
40
|
+
source = import.source ? Native.native_string(import.source) : nil
|
41
|
+
source_map_path = nil
|
42
|
+
|
43
|
+
entry = Native.make_import_entry(import.path, source, source_map_path)
|
44
|
+
Native.import_set_list_entry(import_list, i, entry)
|
45
|
+
end
|
46
|
+
|
47
|
+
import_list
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SassC
|
4
|
+
class Importer
|
5
|
+
attr_reader :options
|
6
|
+
|
7
|
+
def initialize(options)
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def imports(path, parent_path)
|
12
|
+
# A custom importer must override this method.
|
13
|
+
# Custom importer may return an Import, or an array of Imports.
|
14
|
+
raise NotImplementedError
|
15
|
+
end
|
16
|
+
|
17
|
+
class Import
|
18
|
+
attr_accessor :path, :source, :source_map_path
|
19
|
+
|
20
|
+
def initialize(path, source: nil, source_map_path: nil)
|
21
|
+
@path = path
|
22
|
+
@source = source
|
23
|
+
@source_map_path = source_map_path
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_s
|
27
|
+
"Import: #{path} #{source} #{source_map_path}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SassC
|
4
|
+
module Native
|
5
|
+
attach_function :version, :libsass_version, [], :string
|
6
|
+
|
7
|
+
# Create and initialize an option struct
|
8
|
+
# ADDAPI struct Sass_Options* ADDCALL sass_make_options (void);
|
9
|
+
attach_function :sass_make_options, [], :sass_options_ptr
|
10
|
+
|
11
|
+
# Create and initialize a specific context
|
12
|
+
# ADDAPI struct Sass_File_Context* ADDCALL sass_make_file_context (const char* input_path);
|
13
|
+
# ADDAPI struct Sass_Data_Context* ADDCALL sass_make_data_context (char* source_string);
|
14
|
+
attach_function :sass_make_file_context, [:string], :sass_file_context_ptr
|
15
|
+
attach_function :_make_data_context, :sass_make_data_context, [:pointer], :sass_data_context_ptr
|
16
|
+
|
17
|
+
def self.make_data_context(data)
|
18
|
+
_make_data_context(Native.native_string(data))
|
19
|
+
end
|
20
|
+
|
21
|
+
# Call the compilation step for the specific context
|
22
|
+
# ADDAPI int ADDCALL sass_compile_file_context (struct Sass_File_Context* ctx);
|
23
|
+
# ADDAPI int ADDCALL sass_compile_data_context (struct Sass_Data_Context* ctx);
|
24
|
+
attach_function :sass_compile_file_context, [:sass_file_context_ptr], :int
|
25
|
+
attach_function :sass_compile_data_context, [:sass_data_context_ptr], :int
|
26
|
+
|
27
|
+
# Create a sass compiler instance for more control
|
28
|
+
# ADDAPI struct Sass_Compiler* ADDCALL sass_make_file_compiler (struct Sass_File_Context* file_ctx);
|
29
|
+
# ADDAPI struct Sass_Compiler* ADDCALL sass_make_data_compiler (struct Sass_Data_Context* data_ctx);
|
30
|
+
|
31
|
+
# Execute the different compilation steps individually
|
32
|
+
# Usefull if you only want to query the included files
|
33
|
+
# ADDAPI int ADDCALL sass_compiler_parse(struct Sass_Compiler* compiler);
|
34
|
+
# ADDAPI int ADDCALL sass_compiler_execute(struct Sass_Compiler* compiler);
|
35
|
+
|
36
|
+
# Release all memory allocated with the compiler
|
37
|
+
# This does _not_ include any contexts or options
|
38
|
+
# ADDAPI void ADDCALL sass_delete_compiler(struct Sass_Compiler* compiler);
|
39
|
+
|
40
|
+
# Release all memory allocated and also ourself
|
41
|
+
# ADDAPI void ADDCALL sass_delete_file_context (struct Sass_File_Context* ctx);
|
42
|
+
# ADDAPI void ADDCALL sass_delete_data_context (struct Sass_Data_Context* ctx);
|
43
|
+
attach_function :sass_delete_file_context, [:sass_file_context_ptr], :void
|
44
|
+
attach_function :sass_delete_data_context, [:sass_data_context_ptr], :void
|
45
|
+
|
46
|
+
# Getters for context from specific implementation
|
47
|
+
# ADDAPI struct Sass_Context* ADDCALL sass_file_context_get_context (struct Sass_File_Context* file_ctx);
|
48
|
+
# ADDAPI struct Sass_Context* ADDCALL sass_data_context_get_context (struct Sass_Data_Context* data_ctx);
|
49
|
+
attach_function :sass_file_context_get_context, [:sass_file_context_ptr], :sass_context_ptr
|
50
|
+
attach_function :sass_data_context_get_context, [:sass_data_context_ptr], :sass_context_ptr
|
51
|
+
|
52
|
+
# Getters for context options from Sass_Context
|
53
|
+
# ADDAPI struct Sass_Options* ADDCALL sass_context_get_options (struct Sass_Context* ctx);
|
54
|
+
# ADDAPI struct Sass_Options* ADDCALL sass_file_context_get_options (struct Sass_File_Context* file_ctx);
|
55
|
+
# ADDAPI struct Sass_Options* ADDCALL sass_data_context_get_options (struct Sass_Data_Context* data_ctx);
|
56
|
+
# ADDAPI void ADDCALL sass_file_context_set_options (struct Sass_File_Context* file_ctx, struct Sass_Options* opt);
|
57
|
+
# ADDAPI void ADDCALL sass_data_context_set_options (struct Sass_Data_Context* data_ctx, struct Sass_Options* opt);
|
58
|
+
attach_function :sass_context_get_options, [:sass_context_ptr], :sass_options_ptr
|
59
|
+
attach_function :sass_file_context_get_options, [:sass_file_context_ptr], :sass_options_ptr
|
60
|
+
attach_function :sass_data_context_get_options, [:sass_data_context_ptr], :sass_options_ptr
|
61
|
+
attach_function :sass_file_context_set_options, [:sass_file_context_ptr, :sass_options_ptr], :void
|
62
|
+
attach_function :sass_data_context_set_options, [:sass_data_context_ptr, :sass_options_ptr], :void
|
63
|
+
|
64
|
+
# Getters for options
|
65
|
+
# ADDAPI int ADDCALL sass_option_get_precision (struct Sass_Options* options);
|
66
|
+
# ADDAPI enum Sass_Output_Style ADDCALL sass_option_get_output_style (struct Sass_Options* options);
|
67
|
+
# ADDAPI bool ADDCALL sass_option_get_source_comments (struct Sass_Options* options);
|
68
|
+
# ADDAPI bool ADDCALL sass_option_get_source_map_embed (struct Sass_Options* options);
|
69
|
+
# ADDAPI bool ADDCALL sass_option_get_source_map_contents (struct Sass_Options* options);
|
70
|
+
# ADDAPI bool ADDCALL sass_option_get_omit_source_map_url (struct Sass_Options* options);
|
71
|
+
# ADDAPI bool ADDCALL sass_option_get_is_indented_syntax_src (struct Sass_Options* options);
|
72
|
+
# ADDAPI const char* ADDCALL sass_option_get_input_path (struct Sass_Options* options);
|
73
|
+
# ADDAPI const char* ADDCALL sass_option_get_output_path (struct Sass_Options* options);
|
74
|
+
# ADDAPI const char* ADDCALL sass_option_get_include_path (struct Sass_Options* options);
|
75
|
+
# ADDAPI const char* ADDCALL sass_option_get_source_map_file (struct Sass_Options* options);
|
76
|
+
# ADDAPI Sass_C_Function_List ADDCALL sass_option_get_c_functions (struct Sass_Options* options);
|
77
|
+
attach_function :sass_option_get_precision, [:sass_options_ptr], :int
|
78
|
+
attach_function :sass_option_get_output_style, [:sass_options_ptr], SassOutputStyle
|
79
|
+
attach_function :sass_option_get_source_comments, [:sass_options_ptr], :bool
|
80
|
+
attach_function :sass_option_get_source_map_embed, [:sass_options_ptr], :bool
|
81
|
+
attach_function :sass_option_get_source_map_contents, [:sass_options_ptr], :bool
|
82
|
+
attach_function :sass_option_get_omit_source_map_url, [:sass_options_ptr], :bool
|
83
|
+
attach_function :sass_option_get_is_indented_syntax_src, [:sass_options_ptr], :bool
|
84
|
+
attach_function :sass_option_get_input_path, [:sass_options_ptr], :string
|
85
|
+
attach_function :sass_option_get_output_path, [:sass_options_ptr], :string
|
86
|
+
attach_function :sass_option_get_include_path, [:sass_options_ptr], :string
|
87
|
+
attach_function :sass_option_get_source_map_file, [:sass_options_ptr], :string
|
88
|
+
attach_function :sass_option_get_c_functions, [:sass_options_ptr], :sass_c_function_list_ptr
|
89
|
+
# ADDAPI Sass_C_Import_Callback ADDCALL sass_option_get_importer (struct Sass_Options* options);
|
90
|
+
|
91
|
+
# Setters for options
|
92
|
+
# ADDAPI void ADDCALL sass_option_set_precision (struct Sass_Options* options, int precision);
|
93
|
+
# ADDAPI void ADDCALL sass_option_set_output_style (struct Sass_Options* options, enum Sass_Output_Style output_style);
|
94
|
+
# ADDAPI void ADDCALL sass_option_set_source_comments (struct Sass_Options* options, bool source_comments);
|
95
|
+
# ADDAPI void ADDCALL sass_option_set_source_map_embed (struct Sass_Options* options, bool source_map_embed);
|
96
|
+
# ADDAPI void ADDCALL sass_option_set_source_map_contents (struct Sass_Options* options, bool source_map_contents);
|
97
|
+
# ADDAPI void ADDCALL sass_option_set_omit_source_map_url (struct Sass_Options* options, bool omit_source_map_url);
|
98
|
+
# ADDAPI void ADDCALL sass_option_set_is_indented_syntax_src (struct Sass_Options* options, bool is_indented_syntax_src);
|
99
|
+
# ADDAPI void ADDCALL sass_option_set_input_path (struct Sass_Options* options, const char* input_path);
|
100
|
+
# ADDAPI void ADDCALL sass_option_set_output_path (struct Sass_Options* options, const char* output_path);
|
101
|
+
# ADDAPI void ADDCALL sass_option_set_include_path (struct Sass_Options* options, const char* include_path);
|
102
|
+
# ADDAPI void ADDCALL sass_option_set_source_map_file (struct Sass_Options* options, const char* source_map_file);
|
103
|
+
# ADDAPI void ADDCALL sass_option_set_c_functions (struct Sass_Options* options, Sass_C_Function_List c_functions);
|
104
|
+
# ADDAPI void ADDCALL sass_option_set_c_importers (struct Sass_Options* options, Sass_Importer_List c_importers);
|
105
|
+
attach_function :sass_option_set_precision, [:sass_options_ptr, :int], :void
|
106
|
+
attach_function :sass_option_set_output_style, [:sass_options_ptr, SassOutputStyle], :void
|
107
|
+
attach_function :sass_option_set_source_comments, [:sass_options_ptr, :bool], :void
|
108
|
+
attach_function :sass_option_set_source_map_embed, [:sass_options_ptr, :bool], :void
|
109
|
+
attach_function :sass_option_set_source_map_contents, [:sass_options_ptr, :bool], :void
|
110
|
+
attach_function :sass_option_set_omit_source_map_url, [:sass_options_ptr, :bool], :void
|
111
|
+
attach_function :sass_option_set_is_indented_syntax_src, [:sass_options_ptr, :bool], :void
|
112
|
+
attach_function :sass_option_set_input_path, [:sass_options_ptr, :string], :void
|
113
|
+
attach_function :sass_option_set_output_path, [:sass_options_ptr, :string], :void
|
114
|
+
attach_function :sass_option_set_include_path, [:sass_options_ptr, :string], :void
|
115
|
+
attach_function :sass_option_set_source_map_file, [:sass_options_ptr, :string], :void
|
116
|
+
attach_function :sass_option_set_c_functions, [:sass_options_ptr, :pointer], :void
|
117
|
+
attach_function :sass_option_set_c_importers, [:sass_options_ptr, :pointer], :void
|
118
|
+
#attach_function :sass_option_set_c_importers, [:sass_options_ptr, :sass_importer], :void
|
119
|
+
|
120
|
+
# Getter for context
|
121
|
+
# ADDAPI const char* ADDCALL sass_context_get_output_string (struct Sass_Context* ctx);
|
122
|
+
# ADDAPI int ADDCALL sass_context_get_error_status (struct Sass_Context* ctx);
|
123
|
+
# ADDAPI const char* ADDCALL sass_context_get_error_json (struct Sass_Context* ctx);
|
124
|
+
# ADDAPI const char* ADDCALL sass_context_get_error_message (struct Sass_Context* ctx);
|
125
|
+
# ADDAPI const char* ADDCALL sass_context_get_error_file (struct Sass_Context* ctx);
|
126
|
+
# ADDAPI size_t ADDCALL sass_context_get_error_line (struct Sass_Context* ctx);
|
127
|
+
# ADDAPI size_t ADDCALL sass_context_get_error_column (struct Sass_Context* ctx);
|
128
|
+
# ADDAPI const char* ADDCALL sass_context_get_source_map_string (struct Sass_Context* ctx);
|
129
|
+
# ADDAPI char** ADDCALL sass_context_get_included_files (struct Sass_Context* ctx);
|
130
|
+
attach_function :sass_context_get_output_string, [:sass_context_ptr], :string
|
131
|
+
attach_function :sass_context_get_error_status, [:sass_context_ptr], :int
|
132
|
+
attach_function :sass_context_get_error_json, [:sass_context_ptr], :string
|
133
|
+
attach_function :sass_context_get_error_message, [:sass_context_ptr], :string
|
134
|
+
attach_function :sass_context_get_error_file, [:sass_context_ptr], :string
|
135
|
+
attach_function :sass_context_get_error_line, [:sass_context_ptr], :size_t
|
136
|
+
attach_function :sass_context_get_error_column, [:sass_context_ptr], :size_t
|
137
|
+
attach_function :sass_context_get_source_map_string, [:sass_context_ptr], :string
|
138
|
+
attach_function :_context_get_included_files, :sass_context_get_included_files, [:sass_context_ptr], :pointer
|
139
|
+
|
140
|
+
def self.context_get_included_files(*args)
|
141
|
+
return_string_array _context_get_included_files(*args)
|
142
|
+
end
|
143
|
+
|
144
|
+
# ADDAPI Sass_Import_Entry ADDCALL sass_compiler_get_last_import(struct Sass_Compiler* compiler);
|
145
|
+
attach_function :sass_compiler_get_last_import, [:pointer], :pointer
|
146
|
+
end
|
147
|
+
end
|