sassc 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/sassc.rb +1 -0
- data/lib/sassc/engine.rb +12 -0
- data/lib/sassc/import_handler.rb +4 -0
- data/lib/sassc/importer.rb +57 -0
- data/lib/sassc/native.rb +6 -0
- data/lib/sassc/native/lib_c.rb +19 -0
- data/lib/sassc/native/native_context_api.rb +2 -1
- data/lib/sassc/native/native_functions_api.rb +41 -4
- data/lib/sassc/script.rb +1 -0
- data/lib/sassc/version.rb +1 -1
- data/test/custom_importer_test.rb +87 -0
- data/test/functions_test.rb +20 -4
- data/test/native_test.rb +39 -2
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 993be013b98cbdeb9f4a4bcb1839cbd5438e0812
|
4
|
+
data.tar.gz: 5bb1391019da6ae3c231116248d1fdfe8ab06c84
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9c516bab484b989c7c560ed4463ade3f4064ed3206a3eb58d43ae062a81778543b243c9f4531eb676b995fcd5062bf7d8ea44c9296afd2c6221040fbcf584cc7
|
7
|
+
data.tar.gz: 81a118cc6d8d05814a6a740666e1b3c968cb1ee654d9132655cf0a6a866a9626ef9f70b979afe461ef1144d687b5a556b55b83c1eb805a684423115b9bd61800
|
data/lib/sassc.rb
CHANGED
data/lib/sassc/engine.rb
CHANGED
@@ -16,6 +16,8 @@ module SassC
|
|
16
16
|
Native.option_set_input_path(options, filename) if filename
|
17
17
|
Native.option_set_include_path(options, load_paths)
|
18
18
|
|
19
|
+
importer.setup(options) if importer
|
20
|
+
|
19
21
|
status = Script.setup_custom_functions(options, @options) do
|
20
22
|
Native.compile_data_context(data_context)
|
21
23
|
end
|
@@ -53,6 +55,16 @@ module SassC
|
|
53
55
|
@options[:syntax] && @options[:syntax].to_sym == :sass
|
54
56
|
end
|
55
57
|
|
58
|
+
def importer
|
59
|
+
@importer ||= begin
|
60
|
+
if @options[:importer]
|
61
|
+
@options[:importer].new
|
62
|
+
else
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
56
68
|
def load_paths
|
57
69
|
paths = @options[:load_paths]
|
58
70
|
paths.join(":") if paths
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module SassC
|
2
|
+
class Importer
|
3
|
+
def imports(path)
|
4
|
+
# A custom importer must override this method.
|
5
|
+
raise NotImplementedError
|
6
|
+
end
|
7
|
+
|
8
|
+
def setup(native_options)
|
9
|
+
@function = FFI::Function.new(:pointer, [:string, :pointer, :pointer]) do |path, prev, cookie|
|
10
|
+
imports = [*imports(path)]
|
11
|
+
self.class.imports_to_native(imports)
|
12
|
+
end
|
13
|
+
|
14
|
+
callback = SassC::Native.make_importer(@function, nil)
|
15
|
+
SassC::Native.option_set_importer(native_options, callback)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.empty_imports
|
19
|
+
SassC::Native.make_import_list(0)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.imports_to_native(imports)
|
23
|
+
import_list = SassC::Native.make_import_list(imports.size)
|
24
|
+
|
25
|
+
imports.each_with_index do |import, i|
|
26
|
+
source = import.source ? native_string(import.source) : nil
|
27
|
+
source_map_path = nil
|
28
|
+
|
29
|
+
entry = SassC::Native.make_import_entry(import.path, source, source_map_path)
|
30
|
+
SassC::Native.import_set_list_entry(import_list, i, entry)
|
31
|
+
end
|
32
|
+
|
33
|
+
import_list
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.native_string(string)
|
37
|
+
string += "\0"
|
38
|
+
data = SassC::Native::LibC.malloc(string.size)
|
39
|
+
data.write_string(string)
|
40
|
+
data
|
41
|
+
end
|
42
|
+
|
43
|
+
class Import
|
44
|
+
attr_accessor :path, :source, :source_map_path
|
45
|
+
|
46
|
+
def initialize(path, source: nil, source_map_path: nil)
|
47
|
+
@path = path
|
48
|
+
@source = source
|
49
|
+
@source_map_path = source_map_path
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_s
|
53
|
+
"Import: #{path} #{source} #{source_map_path}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/sassc/native.rb
CHANGED
@@ -19,11 +19,17 @@ module SassC
|
|
19
19
|
typedef :pointer, :sass_c_function_callback_ptr
|
20
20
|
typedef :pointer, :sass_value_ptr
|
21
21
|
|
22
|
+
typedef :pointer, :sass_import_list_ptr
|
23
|
+
typedef :pointer, :sass_importer
|
24
|
+
typedef :pointer, :sass_import_ptr
|
25
|
+
|
22
26
|
callback :sass_c_function, [:pointer, :pointer], :pointer
|
27
|
+
callback :sass_c_import_function, [:pointer, :pointer, :pointer], :pointer
|
23
28
|
|
24
29
|
require_relative "native/sass_input_style"
|
25
30
|
require_relative "native/sass_output_style"
|
26
31
|
require_relative "native/string_list"
|
32
|
+
require_relative "native/lib_c"
|
27
33
|
|
28
34
|
# Remove the redundant "sass_" from the beginning of every method name
|
29
35
|
def self.attach_function(*args)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module SassC
|
2
|
+
module Native
|
3
|
+
module LibC
|
4
|
+
extend FFI::Library
|
5
|
+
ffi_lib FFI::Library::LIBC
|
6
|
+
|
7
|
+
# memory allocators
|
8
|
+
attach_function :malloc, [:size_t], :pointer
|
9
|
+
# attach_function :calloc, [:size_t], :pointer
|
10
|
+
# attach_function :valloc, [:size_t], :pointer
|
11
|
+
# attach_function :realloc, [:pointer, :size_t], :pointer
|
12
|
+
# attach_function :free, [:pointer], :void
|
13
|
+
|
14
|
+
# memory movers
|
15
|
+
# attach_function :memcpy, [:pointer, :pointer, :size_t], :pointer
|
16
|
+
# attach_function :bcopy, [:pointer, :pointer, :size_t], :void
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -98,6 +98,7 @@ module SassC
|
|
98
98
|
# ADDAPI void ADDCALL sass_option_set_include_path (struct Sass_Options* options, const char* include_path);
|
99
99
|
# ADDAPI void ADDCALL sass_option_set_source_map_file (struct Sass_Options* options, const char* source_map_file);
|
100
100
|
# ADDAPI void ADDCALL sass_option_set_c_functions (struct Sass_Options* options, Sass_C_Function_List c_functions);
|
101
|
+
# ADDAPI void ADDCALL sass_option_set_importer (struct Sass_Options* options, Sass_C_Import_Callback importer);
|
101
102
|
attach_function :sass_option_set_precision, [:sass_options_ptr, :int], :void
|
102
103
|
attach_function :sass_option_set_output_style, [:sass_options_ptr, SassOutputStyle], :void
|
103
104
|
attach_function :sass_option_set_source_comments, [:sass_options_ptr, :bool], :void
|
@@ -111,7 +112,7 @@ module SassC
|
|
111
112
|
attach_function :sass_option_set_include_path, [:sass_options_ptr, :string], :void
|
112
113
|
attach_function :sass_option_set_source_map_file, [:sass_options_ptr, :string], :void
|
113
114
|
attach_function :sass_option_set_c_functions, [:sass_options_ptr, :pointer], :void
|
114
|
-
|
115
|
+
attach_function :sass_option_set_importer, [:sass_options_ptr, :sass_importer], :void
|
115
116
|
|
116
117
|
# Getter for context
|
117
118
|
# ADDAPI const char* ADDCALL sass_context_get_output_string (struct Sass_Context* ctx);
|
@@ -36,10 +36,47 @@ module SassC
|
|
36
36
|
attach_function :sass_function_get_function, [:sass_c_function_callback_ptr], :sass_c_function
|
37
37
|
attach_function :sass_function_get_cookie, [:sass_c_function_callback_ptr], :pointer
|
38
38
|
|
39
|
+
# Creators for custom importer callback (with some additional pointer)
|
40
|
+
# The pointer is mostly used to store the callback into the actual binding
|
41
|
+
# ADDAPI Sass_C_Import_Callback ADDCALL sass_make_importer (Sass_C_Import_Fn, void* cookie);
|
42
|
+
attach_function :sass_make_importer, [:sass_c_import_function, :pointer], :sass_importer
|
39
43
|
|
40
|
-
#
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
+
# Getters for import function descriptors
|
45
|
+
# ADDAPI Sass_C_Import_Fn ADDCALL sass_import_get_function (Sass_C_Import_Callback fn);
|
46
|
+
# ADDAPI void* ADDCALL sass_import_get_cookie (Sass_C_Import_Callback fn);
|
47
|
+
|
48
|
+
# Deallocator for associated memory
|
49
|
+
# ADDAPI void ADDCALL sass_delete_importer (Sass_C_Import_Callback fn);
|
50
|
+
|
51
|
+
# Creator for sass custom importer return argument list
|
52
|
+
# ADDAPI struct Sass_Import** ADDCALL sass_make_import_list (size_t length);
|
53
|
+
attach_function :sass_make_import_list, [:size_t], :sass_import_list_ptr
|
54
|
+
|
55
|
+
# Creator for a single import entry returned by the custom importer inside the list
|
56
|
+
# ADDAPI struct Sass_Import* ADDCALL sass_make_import_entry (const char* path, char* source, char* srcmap);
|
57
|
+
# ADDAPI struct Sass_Import* ADDCALL sass_make_import (const char* path, const char* base, char* source, char* srcmap);
|
58
|
+
attach_function :sass_make_import_entry, [:string, :pointer, :pointer], :sass_import_ptr
|
59
|
+
|
60
|
+
# Setters to insert an entry into the import list (you may also use [] access directly)
|
61
|
+
# Since we are dealing with pointers they should have a guaranteed and fixed size
|
62
|
+
# ADDAPI void ADDCALL sass_import_set_list_entry (struct Sass_Import** list, size_t idx, struct Sass_Import* entry);
|
63
|
+
attach_function :sass_import_set_list_entry, [:sass_import_list_ptr, :size_t, :sass_import_ptr], :void
|
64
|
+
# ADDAPI struct Sass_Import* ADDCALL sass_import_get_list_entry (struct Sass_Import** list, size_t idx);
|
65
|
+
|
66
|
+
# Getters for import entry
|
67
|
+
# ADDAPI const char* ADDCALL sass_import_get_path (struct Sass_Import*);
|
68
|
+
# ADDAPI const char* ADDCALL sass_import_get_base (struct Sass_Import*);
|
69
|
+
# ADDAPI const char* ADDCALL sass_import_get_source (struct Sass_Import*);
|
70
|
+
attach_function :sass_import_get_source, [:sass_import_ptr], :string
|
71
|
+
# ADDAPI const char* ADDCALL sass_import_get_srcmap (struct Sass_Import*);
|
72
|
+
# Explicit functions to take ownership of these items
|
73
|
+
# The property on our struct will be reset to NULL
|
74
|
+
# ADDAPI char* ADDCALL sass_import_take_source (struct Sass_Import*);
|
75
|
+
# ADDAPI char* ADDCALL sass_import_take_srcmap (struct Sass_Import*);
|
76
|
+
|
77
|
+
# Deallocator for associated memory (incl. entries)
|
78
|
+
# ADDAPI void ADDCALL sass_delete_import_list (struct Sass_Import**);
|
79
|
+
# Just in case we have some stray import structs
|
80
|
+
# ADDAPI void ADDCALL sass_delete_import (struct Sass_Import*);
|
44
81
|
end
|
45
82
|
end
|
data/lib/sassc/script.rb
CHANGED
data/lib/sassc/version.rb
CHANGED
@@ -0,0 +1,87 @@
|
|
1
|
+
require_relative "test_helper"
|
2
|
+
|
3
|
+
class FunctionsTest < SassCTest
|
4
|
+
class CustomImporter < SassC::Importer
|
5
|
+
def imports(path)
|
6
|
+
if path =~ /styles/
|
7
|
+
[
|
8
|
+
Import.new("#{path}1.scss", source: "$var1: #000;"),
|
9
|
+
Import.new("#{path}2.scss")
|
10
|
+
]
|
11
|
+
else
|
12
|
+
Import.new(path)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class NoFilesImporter < SassC::Importer
|
18
|
+
def imports(path)
|
19
|
+
[]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def around
|
24
|
+
within_construct do |construct|
|
25
|
+
@construct = construct
|
26
|
+
yield
|
27
|
+
end
|
28
|
+
|
29
|
+
@construct = nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_custom_importer_works
|
33
|
+
@construct.file("styles2.scss", ".hi { color: $var1; }")
|
34
|
+
@construct.file("fonts.scss", ".font { color: $var1; }")
|
35
|
+
|
36
|
+
data = <<SCSS
|
37
|
+
@import "styles";
|
38
|
+
@import "fonts";
|
39
|
+
SCSS
|
40
|
+
|
41
|
+
engine = SassC::Engine.new(data, {
|
42
|
+
importer: CustomImporter
|
43
|
+
})
|
44
|
+
|
45
|
+
assert_equal <<CSS, engine.render
|
46
|
+
.hi {
|
47
|
+
color: #000; }
|
48
|
+
|
49
|
+
.font {
|
50
|
+
color: #000; }
|
51
|
+
CSS
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_dependency_list
|
55
|
+
@construct.file("styles2.scss", ".hi { color: $var1; }")
|
56
|
+
@construct.file("fonts.scss", ".font { color: $var1; }")
|
57
|
+
|
58
|
+
data = <<SCSS
|
59
|
+
@import "styles";
|
60
|
+
@import "fonts";
|
61
|
+
SCSS
|
62
|
+
|
63
|
+
engine = SassC::Engine.new(data, {
|
64
|
+
importer: CustomImporter
|
65
|
+
})
|
66
|
+
engine.render
|
67
|
+
|
68
|
+
dependencies = engine.dependencies.map(&:options).map { |o| o[:filename] }
|
69
|
+
|
70
|
+
# TODO: this behavior is kind of weird (styles1.scss is not included)
|
71
|
+
# not sure why.
|
72
|
+
|
73
|
+
assert_equal [
|
74
|
+
"fonts.scss",
|
75
|
+
"styles",
|
76
|
+
"styles2.scss"
|
77
|
+
], dependencies
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_custom_importer_works_with_no_files
|
81
|
+
engine = SassC::Engine.new("@import 'fake.scss';", {
|
82
|
+
importer: NoFilesImporter
|
83
|
+
})
|
84
|
+
|
85
|
+
assert_equal "", engine.render
|
86
|
+
end
|
87
|
+
end
|
data/test/functions_test.rb
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
require_relative "test_helper"
|
2
2
|
|
3
3
|
class FunctionsTest < SassCTest
|
4
|
+
SassString = Struct.new(:value, :type) do
|
5
|
+
def to_s
|
6
|
+
value
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
4
10
|
module ::SassC::Script::Functions
|
5
11
|
def javascript_path(path)
|
6
12
|
::SassC::Script::String.new("/js/#{path.value}", :string)
|
@@ -10,6 +16,10 @@ class FunctionsTest < SassCTest
|
|
10
16
|
nil
|
11
17
|
end
|
12
18
|
|
19
|
+
def sass_return_path(path)
|
20
|
+
return SassString.new("'#{path.value}'", :string)
|
21
|
+
end
|
22
|
+
|
13
23
|
module Compass
|
14
24
|
def stylesheet_path(path)
|
15
25
|
::SassC::Script::String.new("/css/#{path.value}", :identifier)
|
@@ -18,9 +28,18 @@ class FunctionsTest < SassCTest
|
|
18
28
|
include Compass
|
19
29
|
end
|
20
30
|
|
31
|
+
def test_functions_may_return_sass_string_type
|
32
|
+
engine = ::SassC::Engine.new("div {url: url(sass_return_path('foo.svg'));}")
|
33
|
+
|
34
|
+
assert_equal <<-EOS, engine.render
|
35
|
+
div {
|
36
|
+
url: url("foo.svg"); }
|
37
|
+
EOS
|
38
|
+
end
|
39
|
+
|
21
40
|
def test_functions_work
|
22
41
|
filename = fixture_path('paths.scss')
|
23
|
-
|
42
|
+
data = File.read(filename)
|
24
43
|
|
25
44
|
engine = ::SassC::Engine.new(data, {
|
26
45
|
filename: filename,
|
@@ -44,9 +63,6 @@ div {
|
|
44
63
|
end
|
45
64
|
|
46
65
|
def test_function_with_no_return_value
|
47
|
-
filename = fixture_path('paths.scss')
|
48
|
-
assert data = File.read(filename)
|
49
|
-
|
50
66
|
engine = ::SassC::Engine.new("div {url: url(no-return-path('foo.svg'));}")
|
51
67
|
|
52
68
|
assert_equal <<-EOS, engine.render
|
data/test/native_test.rb
CHANGED
@@ -57,9 +57,13 @@ module NativeTest
|
|
57
57
|
|
58
58
|
random_thing = FFI::MemoryPointer.from_string("hi")
|
59
59
|
|
60
|
+
funct = FFI::Function.new(:pointer, [:pointer, :pointer]) do |s_args, cookie|
|
61
|
+
SassC::Native.make_number(43, "px")
|
62
|
+
end
|
63
|
+
|
60
64
|
callback = SassC::Native.make_function(
|
61
65
|
"foo()",
|
62
|
-
|
66
|
+
funct,
|
63
67
|
random_thing
|
64
68
|
)
|
65
69
|
|
@@ -71,7 +75,7 @@ module NativeTest
|
|
71
75
|
|
72
76
|
first_list_entry = SassC::Native.function_get_list_entry(list, 0)
|
73
77
|
assert_equal SassC::Native.function_get_function(first_list_entry),
|
74
|
-
|
78
|
+
funct
|
75
79
|
assert_equal SassC::Native.function_get_signature(first_list_entry),
|
76
80
|
"foo()"
|
77
81
|
assert_equal SassC::Native.function_get_cookie(first_list_entry),
|
@@ -164,5 +168,38 @@ module NativeTest
|
|
164
168
|
assert_match /import_parent.scss/, included_files[1]
|
165
169
|
assert_match /styles.scss/, included_files[2]
|
166
170
|
end
|
171
|
+
|
172
|
+
def test_custom_importer
|
173
|
+
@construct.file("not_included.scss", "$size: $var + 25;")
|
174
|
+
@construct.file("styles.scss", "@import 'import.scss'; .hi { width: $size; }")
|
175
|
+
|
176
|
+
@file_context = SassC::Native.make_file_context("styles.scss")
|
177
|
+
context = SassC::Native.file_context_get_context(@file_context)
|
178
|
+
options = SassC::Native.context_get_options(context)
|
179
|
+
|
180
|
+
funct = FFI::Function.new(:pointer, [:pointer, :pointer, :pointer]) do |url, prev, cookie|
|
181
|
+
list = SassC::Native.make_import_list(2)
|
182
|
+
|
183
|
+
str = "$var: 5px;\0"
|
184
|
+
data = SassC::Native::LibC.malloc(str.size)
|
185
|
+
data.write_string(str)
|
186
|
+
|
187
|
+
entry0 = SassC::Native.make_import_entry("fake_includ.scss", data, nil)
|
188
|
+
entry1 = SassC::Native.make_import_entry("not_included.scss", nil, nil)
|
189
|
+
SassC::Native.import_set_list_entry(list, 0, entry0)
|
190
|
+
SassC::Native.import_set_list_entry(list, 1, entry1)
|
191
|
+
list
|
192
|
+
end
|
193
|
+
|
194
|
+
callback = SassC::Native.make_importer(funct, nil)
|
195
|
+
|
196
|
+
SassC::Native.option_set_importer(options, callback)
|
197
|
+
|
198
|
+
status = SassC::Native.compile_file_context(@file_context)
|
199
|
+
assert_equal 0, status
|
200
|
+
|
201
|
+
css = SassC::Native.context_get_output_string(context)
|
202
|
+
assert_equal SAMPLE_CSS_OUTPUT, css
|
203
|
+
end
|
167
204
|
end
|
168
205
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sassc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Boland
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -244,7 +244,10 @@ files:
|
|
244
244
|
- lib/sassc/dependency.rb
|
245
245
|
- lib/sassc/engine.rb
|
246
246
|
- lib/sassc/error.rb
|
247
|
+
- lib/sassc/import_handler.rb
|
248
|
+
- lib/sassc/importer.rb
|
247
249
|
- lib/sassc/native.rb
|
250
|
+
- lib/sassc/native/lib_c.rb
|
248
251
|
- lib/sassc/native/native_context_api.rb
|
249
252
|
- lib/sassc/native/native_functions_api.rb
|
250
253
|
- lib/sassc/native/sass_input_style.rb
|
@@ -256,6 +259,7 @@ files:
|
|
256
259
|
- lib/sassc/script/string.rb
|
257
260
|
- lib/sassc/version.rb
|
258
261
|
- sassc.gemspec
|
262
|
+
- test/custom_importer_test.rb
|
259
263
|
- test/engine_test.rb
|
260
264
|
- test/fixtures/paths.scss
|
261
265
|
- test/functions_test.rb
|
@@ -287,6 +291,7 @@ signing_key:
|
|
287
291
|
specification_version: 4
|
288
292
|
summary: Use libsass with Ruby!
|
289
293
|
test_files:
|
294
|
+
- test/custom_importer_test.rb
|
290
295
|
- test/engine_test.rb
|
291
296
|
- test/fixtures/paths.scss
|
292
297
|
- test/functions_test.rb
|