Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
node-sass
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
楚学文
node-sass
Commits
4bea0703
Commit
4bea0703
authored
Dec 18, 2014
by
Adeel Mujahid
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #576 from am11/importer
Feature: Custom importer (#530)
parents
7c354bf6
5a6bd67f
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
212 additions
and
51 deletions
+212
-51
index.js
lib/index.js
+12
-0
binding.cpp
src/binding.cpp
+162
-34
libsass
src/libsass
+1
-1
sass_context_wrapper.cpp
src/sass_context_wrapper.cpp
+18
-5
sass_context_wrapper.h
src/sass_context_wrapper.h
+18
-10
spec
test/fixtures/spec
+1
-1
No files found.
lib/index.js
View file @
4bea0703
...
...
@@ -150,6 +150,7 @@ function getOptions(options) {
var
error
=
options
.
error
;
var
success
=
options
.
success
;
var
importer
=
options
.
importer
;
options
.
error
=
function
(
err
,
code
)
{
try
{
...
...
@@ -173,6 +174,17 @@ function getOptions(options) {
}
};
if
(
importer
)
{
options
.
importer
=
function
(
file
,
prev
,
key
)
{
importer
(
file
,
prev
,
function
(
data
)
{
binding
.
importedCallback
({
index
:
key
,
objectLiteral
:
data
});
});
};
}
delete
options
.
image_path
;
delete
options
.
include_paths
;
delete
options
.
includePaths
;
...
...
src/binding.cpp
View file @
4bea0703
#include <nan.h>
#include <vector>
#include "sass_context_wrapper.h"
char
*
CreateString
(
Local
<
Value
>
value
)
{
if
(
value
->
IsNull
()
||
!
value
->
IsString
())
{
if
(
value
->
IsNull
()
||
!
value
->
IsString
())
{
return
const_cast
<
char
*>
(
""
);
// return empty string.
}
String
::
Utf8Value
string
(
value
);
char
*
str
=
(
char
*
)
malloc
(
string
.
length
()
+
1
);
char
*
str
=
(
char
*
)
malloc
(
string
.
length
()
+
1
);
strcpy
(
str
,
*
string
);
return
str
;
}
void
ExtractOptions
(
Local
<
Object
>
options
,
void
*
cptr
,
sass_context_wrapper
*
ctx_w
,
bool
isFile
)
{
if
(
ctx_w
)
{
NanAssignPersistent
(
ctx_w
->
stats
,
options
->
Get
(
NanNew
(
"stats"
))
->
ToObject
());
std
::
vector
<
sass_context_wrapper
*>
imports_collection
;
// async (callback) style
Local
<
Function
>
callback
=
Local
<
Function
>::
Cast
(
options
->
Get
(
NanNew
(
"success"
)));
Local
<
Function
>
errorCallback
=
Local
<
Function
>::
Cast
(
options
->
Get
(
NanNew
(
"error"
)));
if
(
isFile
)
{
ctx_w
->
fctx
=
(
struct
Sass_File_Context
*
)
cptr
;
}
else
{
ctx_w
->
dctx
=
(
struct
Sass_Data_Context
*
)
cptr
;
void
dispatched_async_uv_callback
(
uv_async_t
*
req
){
NanScope
();
sass_context_wrapper
*
ctx_w
=
static_cast
<
sass_context_wrapper
*>
(
req
->
data
);
TryCatch
try_catch
;
imports_collection
.
push_back
(
ctx_w
);
Handle
<
Value
>
argv
[]
=
{
NanNew
<
String
>
(
strdup
(
ctx_w
->
file
)),
NanNew
<
String
>
(
strdup
(
ctx_w
->
prev
)),
NanNew
<
Number
>
(
imports_collection
.
size
()
-
1
)
};
NanNew
<
Value
>
(
ctx_w
->
importer_callback
->
Call
(
3
,
argv
));
if
(
try_catch
.
HasCaught
())
{
node
::
FatalException
(
try_catch
);
}
ctx_w
->
request
.
data
=
ctx_w
;
ctx_w
->
callback
=
new
NanCallback
(
callback
);
ctx_w
->
errorCallback
=
new
NanCallback
(
errorCallback
);
}
struct
Sass_Import
**
sass_importer
(
const
char
*
file
,
const
char
*
prev
,
void
*
cookie
)
{
sass_context_wrapper
*
ctx_w
=
static_cast
<
sass_context_wrapper
*>
(
cookie
);
ctx_w
->
file
=
strdup
(
file
);
ctx_w
->
prev
=
strdup
(
prev
);
ctx_w
->
async
.
data
=
(
void
*
)
ctx_w
;
uv_async_send
(
&
ctx_w
->
async
);
if
(
ctx_w
->
success_callback
)
{
/* that is async: Render() or RenderFile(),
* the default even loop is unblocked so it
* can run uv_async_send without a push.
*/
uv_cond_wait
(
&
ctx_w
->
importer_condition_variable
,
&
ctx_w
->
importer_mutex
);
}
else
{
/* that is sync: RenderSync() or RenderFileSync,
* we need to explicitly uv_run as the event loop
* is blocked; waiting down the chain.
*/
uv_run
(
ctx_w
->
async
.
loop
,
UV_RUN_DEFAULT
);
}
return
ctx_w
->
imports
;
}
void
ExtractOptions
(
Local
<
Object
>
options
,
void
*
cptr
,
sass_context_wrapper
*
ctx_w
,
bool
isFile
,
bool
isSync
)
{
struct
Sass_Context
*
ctx
;
if
(
isFile
)
{
ctx
=
sass_file_context_get_context
((
struct
Sass_File_Context
*
)
cptr
);
}
else
{
ctx_w
->
fctx
=
(
struct
Sass_File_Context
*
)
cptr
;
}
else
{
ctx
=
sass_data_context_get_context
((
struct
Sass_Data_Context
*
)
cptr
);
ctx_w
->
dctx
=
(
struct
Sass_Data_Context
*
)
cptr
;
}
struct
Sass_Options
*
sass_options
=
sass_context_get_options
(
ctx
);
if
(
!
isSync
)
{
NanAssignPersistent
(
ctx_w
->
stats
,
options
->
Get
(
NanNew
(
"stats"
))
->
ToObject
());
ctx_w
->
request
.
data
=
ctx_w
;
// async (callback) style
Local
<
Function
>
success_callback
=
Local
<
Function
>::
Cast
(
options
->
Get
(
NanNew
(
"success"
)));
Local
<
Function
>
error_callback
=
Local
<
Function
>::
Cast
(
options
->
Get
(
NanNew
(
"error"
)));
ctx_w
->
success_callback
=
new
NanCallback
(
success_callback
);
ctx_w
->
error_callback
=
new
NanCallback
(
error_callback
);
}
Local
<
Function
>
importer_callback
=
Local
<
Function
>::
Cast
(
options
->
Get
(
NanNew
(
"importer"
)));
ctx_w
->
importer_callback
=
new
NanCallback
(
importer_callback
);
if
(
!
importer_callback
->
IsUndefined
())
{
uv_async_init
(
uv_default_loop
(),
&
ctx_w
->
async
,
(
uv_async_cb
)
dispatched_async_uv_callback
);
sass_option_set_importer
(
sass_options
,
sass_make_importer
(
sass_importer
,
ctx_w
));
}
sass_option_set_output_path
(
sass_options
,
CreateString
(
options
->
Get
(
NanNew
(
"outFile"
))));
sass_option_set_image_path
(
sass_options
,
CreateString
(
options
->
Get
(
NanNew
(
"imagePath"
))));
sass_option_set_output_style
(
sass_options
,
(
Sass_Output_Style
)
options
->
Get
(
NanNew
(
"style"
))
->
Int32Value
());
...
...
@@ -56,7 +116,7 @@ void FillStatsObj(Handle<Object> stats, Sass_Context* ctx) {
char
**
included_files
=
sass_context_get_included_files
(
ctx
);
Handle
<
Array
>
arr
=
NanNew
<
Array
>
();
if
(
included_files
)
{
if
(
included_files
)
{
for
(
int
i
=
0
;
included_files
[
i
]
!=
nullptr
;
++
i
)
{
arr
->
Set
(
i
,
NanNew
<
String
>
(
included_files
[
i
]));
}
...
...
@@ -72,14 +132,15 @@ void FillStatsObj(Handle<Object> stats, Sass_Context* ctx) {
if
(
sass_context_get_source_map_string
(
ctx
))
{
source_map
=
NanNew
<
String
>
(
sass_context_get_source_map_string
(
ctx
));
}
else
{
}
else
{
source_map
=
NanNew
<
String
>
(
"{}"
);
}
(
*
stats
)
->
Set
(
NanNew
(
"sourceMap"
),
source_map
);
}
void
MakeC
allback
(
uv_work_t
*
req
)
{
void
make_c
allback
(
uv_work_t
*
req
)
{
NanScope
();
TryCatch
try_catch
;
...
...
@@ -91,7 +152,8 @@ void MakeCallback(uv_work_t* req) {
ctx
=
sass_data_context_get_context
(
ctx_w
->
dctx
);
FillStatsObj
(
NanNew
(
ctx_w
->
stats
),
ctx
);
error_status
=
sass_context_get_error_status
(
ctx
);
}
else
{
}
else
{
ctx
=
sass_file_context_get_context
(
ctx_w
->
fctx
);
FillStatsObj
(
NanNew
(
ctx_w
->
stats
),
ctx
);
error_status
=
sass_context_get_error_status
(
ctx
);
...
...
@@ -104,15 +166,16 @@ void MakeCallback(uv_work_t* req) {
NanNew
<
String
>
(
val
),
NanNew
(
ctx_w
->
stats
)
->
Get
(
NanNew
(
"sourceMap"
))
};
ctx_w
->
callback
->
Call
(
2
,
argv
);
}
else
{
ctx_w
->
success_callback
->
Call
(
2
,
argv
);
}
else
{
// if error, do callback(error)
const
char
*
err
=
sass_context_get_error_json
(
ctx
);
Local
<
Value
>
argv
[]
=
{
NanNew
<
String
>
(
err
),
NanNew
<
Integer
>
(
error_status
)
};
ctx_w
->
error
C
allback
->
Call
(
2
,
argv
);
ctx_w
->
error
_c
allback
->
Call
(
2
,
argv
);
}
if
(
try_catch
.
HasCaught
())
{
node
::
FatalException
(
try_catch
);
...
...
@@ -129,11 +192,9 @@ NAN_METHOD(Render) {
struct
Sass_Data_Context
*
dctx
=
sass_make_data_context
(
source_string
);
sass_context_wrapper
*
ctx_w
=
sass_make_context_wrapper
();
ctx_w
->
dctx
=
dctx
;
ExtractOptions
(
options
,
dctx
,
ctx_w
,
false
);
ExtractOptions
(
options
,
dctx
,
ctx_w
,
false
,
false
);
int
status
=
uv_queue_work
(
uv_default_loop
(),
&
ctx_w
->
request
,
compile_it
,
(
uv_after_work_cb
)
MakeC
allback
);
int
status
=
uv_queue_work
(
uv_default_loop
(),
&
ctx_w
->
request
,
compile_it
,
(
uv_after_work_cb
)
make_c
allback
);
assert
(
status
==
0
);
...
...
@@ -147,8 +208,9 @@ NAN_METHOD(RenderSync) {
char
*
source_string
=
CreateString
(
options
->
Get
(
NanNew
(
"data"
)));
struct
Sass_Data_Context
*
dctx
=
sass_make_data_context
(
source_string
);
struct
Sass_Context
*
ctx
=
sass_data_context_get_context
(
dctx
);
sass_context_wrapper
*
ctx_w
=
sass_make_context_wrapper
();
ExtractOptions
(
options
,
dctx
,
NULL
,
fals
e
);
ExtractOptions
(
options
,
dctx
,
ctx_w
,
false
,
tru
e
);
compile_data
(
dctx
);
FillStatsObj
(
options
->
Get
(
NanNew
(
"stats"
))
->
ToObject
(),
ctx
);
...
...
@@ -161,7 +223,7 @@ NAN_METHOD(RenderSync) {
Local
<
String
>
error
=
NanNew
<
String
>
(
sass_context_get_error_json
(
ctx
));
sass_
delete_data_context
(
dctx
);
sass_
free_context_wrapper
(
ctx_w
);
NanThrowError
(
error
);
NanReturnUndefined
();
...
...
@@ -175,10 +237,9 @@ NAN_METHOD(RenderFile) {
struct
Sass_File_Context
*
fctx
=
sass_make_file_context
(
input_path
);
sass_context_wrapper
*
ctx_w
=
sass_make_context_wrapper
();
ctx_w
->
fctx
=
fctx
;
ExtractOptions
(
options
,
fctx
,
ctx_w
,
true
);
ExtractOptions
(
options
,
fctx
,
ctx_w
,
true
,
false
);
int
status
=
uv_queue_work
(
uv_default_loop
(),
&
ctx_w
->
request
,
compile_it
,
(
uv_after_work_cb
)
MakeC
allback
);
int
status
=
uv_queue_work
(
uv_default_loop
(),
&
ctx_w
->
request
,
compile_it
,
(
uv_after_work_cb
)
make_c
allback
);
assert
(
status
==
0
);
free
(
input_path
);
...
...
@@ -193,8 +254,9 @@ NAN_METHOD(RenderFileSync) {
char
*
input_path
=
CreateString
(
options
->
Get
(
NanNew
(
"file"
)));
struct
Sass_File_Context
*
fctx
=
sass_make_file_context
(
input_path
);
struct
Sass_Context
*
ctx
=
sass_file_context_get_context
(
fctx
);
sass_context_wrapper
*
ctx_w
=
sass_make_context_wrapper
();
ExtractOptions
(
options
,
fctx
,
NULL
,
true
);
ExtractOptions
(
options
,
fctx
,
ctx_w
,
true
,
true
);
compile_file
(
fctx
);
FillStatsObj
(
options
->
Get
(
NanNew
(
"stats"
))
->
ToObject
(),
ctx
);
free
(
input_path
);
...
...
@@ -208,17 +270,83 @@ NAN_METHOD(RenderFileSync) {
Local
<
String
>
error
=
NanNew
<
String
>
(
sass_context_get_error_json
(
ctx
));
sass_
delete_file_context
(
fctx
);
sass_
free_context_wrapper
(
ctx_w
);
NanThrowError
(
error
);
NanReturnUndefined
();
}
NAN_METHOD
(
ImportedCallback
)
{
NanScope
();
TryCatch
try_catch
;
Local
<
Object
>
options
=
args
[
0
]
->
ToObject
();
char
*
source_string
=
CreateString
(
options
->
Get
(
NanNew
(
"index"
)));
Local
<
Value
>
returned_value
=
options
->
Get
(
NanNew
(
"objectLiteral"
));
size_t
index
=
options
->
Get
(
NanNew
(
"index"
))
->
Int32Value
();
if
(
index
>=
imports_collection
.
size
())
{
NanReturnUndefined
();
}
sass_context_wrapper
*
ctx_w
=
imports_collection
[
index
];
if
(
returned_value
->
IsArray
())
{
Handle
<
Array
>
array
=
Handle
<
Array
>::
Cast
(
returned_value
);
ctx_w
->
imports
=
sass_make_import_list
(
array
->
Length
());
for
(
size_t
i
=
0
;
i
<
array
->
Length
();
++
i
)
{
Local
<
Value
>
value
=
array
->
Get
(
i
);
if
(
!
value
->
IsObject
())
continue
;
Local
<
Object
>
object
=
Local
<
Object
>::
Cast
(
value
);
char
*
path
=
CreateString
(
object
->
Get
(
String
::
New
(
"file"
)));
char
*
contents
=
CreateString
(
object
->
Get
(
String
::
New
(
"contents"
)));
ctx_w
->
imports
[
i
]
=
sass_make_import_entry
(
path
,
(
!
contents
||
contents
[
0
]
==
'\0'
)
?
0
:
strdup
(
contents
),
0
);
}
}
else
if
(
returned_value
->
IsObject
())
{
ctx_w
->
imports
=
sass_make_import_list
(
1
);
Local
<
Object
>
object
=
Local
<
Object
>::
Cast
(
returned_value
);
char
*
path
=
CreateString
(
object
->
Get
(
String
::
New
(
"file"
)));
char
*
contents
=
CreateString
(
object
->
Get
(
String
::
New
(
"contents"
)));
ctx_w
->
imports
[
0
]
=
sass_make_import_entry
(
path
,
(
!
contents
||
contents
[
0
]
==
'\0'
)
?
0
:
strdup
(
contents
),
0
);
}
else
{
ctx_w
->
imports
=
sass_make_import_list
(
1
);
ctx_w
->
imports
[
0
]
=
sass_make_import_entry
(
ctx_w
->
file
,
0
,
0
);
}
uv_cond_signal
(
&
ctx_w
->
importer_condition_variable
);
if
(
try_catch
.
HasCaught
())
{
node
::
FatalException
(
try_catch
);
}
if
(
!
ctx_w
->
success_callback
)
{
/*
* that is sync: RenderSync() or RenderFileSync,
* we ran it explictly, so we stop it similarly.
*/
uv_stop
(
ctx_w
->
async
.
loop
);
}
NanReturnValue
(
NanNew
<
Number
>
(
0
));
}
void
RegisterModule
(
v8
::
Handle
<
v8
::
Object
>
target
)
{
NODE_SET_METHOD
(
target
,
"render"
,
Render
);
NODE_SET_METHOD
(
target
,
"renderSync"
,
RenderSync
);
NODE_SET_METHOD
(
target
,
"renderFile"
,
RenderFile
);
NODE_SET_METHOD
(
target
,
"renderFileSync"
,
RenderFileSync
);
NODE_SET_METHOD
(
target
,
"importedCallback"
,
ImportedCallback
);
}
NODE_MODULE
(
binding
,
RegisterModule
);
libsass
@
7aaa45a9
Subproject commit
5f3558d7ce36bb61202f1585ed8e32a52209e940
Subproject commit
7aaa45a979ce65d50b3158ff50bf9409f8955063
src/sass_context_wrapper.cpp
View file @
4bea0703
...
...
@@ -8,7 +8,8 @@ extern "C" {
if
(
ctx_w
->
dctx
)
{
compile_data
(
ctx_w
->
dctx
);
}
else
if
(
ctx_w
->
fctx
)
{
}
else
if
(
ctx_w
->
fctx
)
{
compile_file
(
ctx_w
->
fctx
);
}
}
...
...
@@ -22,19 +23,31 @@ extern "C" {
}
sass_context_wrapper
*
sass_make_context_wrapper
()
{
return
(
sass_context_wrapper
*
)
calloc
(
1
,
sizeof
(
sass_context_wrapper
));
auto
ctx_w
=
(
sass_context_wrapper
*
)
calloc
(
1
,
sizeof
(
sass_context_wrapper
));
uv_mutex_init
(
&
ctx_w
->
importer_mutex
);
uv_cond_init
(
&
ctx_w
->
importer_condition_variable
);
return
ctx_w
;
}
void
sass_free_context_wrapper
(
sass_context_wrapper
*
ctx_w
)
{
if
(
ctx_w
->
dctx
)
{
sass_delete_data_context
(
ctx_w
->
dctx
);
}
else
if
(
ctx_w
->
fctx
)
{
}
else
if
(
ctx_w
->
fctx
)
{
sass_delete_file_context
(
ctx_w
->
fctx
);
}
NanDisposePersistent
(
ctx_w
->
stats
);
delete
ctx_w
->
callback
;
delete
ctx_w
->
errorCallback
;
delete
ctx_w
->
success_callback
;
delete
ctx_w
->
error_callback
;
delete
ctx_w
->
importer_callback
;
delete
ctx_w
->
file
;
delete
ctx_w
->
prev
;
delete
ctx_w
->
cookie
;
uv_mutex_destroy
(
&
ctx_w
->
importer_mutex
);
uv_cond_destroy
(
&
ctx_w
->
importer_condition_variable
);
free
(
ctx_w
);
}
...
...
src/sass_context_wrapper.h
View file @
4bea0703
...
...
@@ -5,23 +5,31 @@
extern
"C"
{
#endif
using
namespace
v8
;
using
namespace
v8
;
void
compile_data
(
struct
Sass_Data_Context
*
dctx
);
void
compile_file
(
struct
Sass_File_Context
*
fctx
);
void
compile_it
(
uv_work_t
*
req
);
void
compile_data
(
struct
Sass_Data_Context
*
dctx
);
void
compile_file
(
struct
Sass_File_Context
*
fctx
);
void
compile_it
(
uv_work_t
*
req
);
struct
sass_context_wrapper
{
struct
sass_context_wrapper
{
Sass_Data_Context
*
dctx
;
Sass_File_Context
*
fctx
;
Persistent
<
Object
>
stats
;
uv_work_t
request
;
NanCallback
*
callback
;
NanCallback
*
errorCallback
;
};
uv_mutex_t
importer_mutex
;
uv_cond_t
importer_condition_variable
;
uv_async_t
async
;
const
char
*
file
;
const
char
*
prev
;
void
*
cookie
;
Sass_Import
**
imports
;
NanCallback
*
success_callback
;
NanCallback
*
error_callback
;
NanCallback
*
importer_callback
;
};
struct
sass_context_wrapper
*
sass_make_context_wrapper
(
void
);
void
sass_free_context_wrapper
(
struct
sass_context_wrapper
*
ctx_w
);
struct
sass_context_wrapper
*
sass_make_context_wrapper
(
void
);
void
sass_free_context_wrapper
(
struct
sass_context_wrapper
*
ctx_w
);
#ifdef __cplusplus
}
...
...
spec
@
074ae3b2
Subproject commit
b85c617a0e7e5367dd347b0b301ad1c15b6d5087
Subproject commit
074ae3b24bfc3ff19a98efdec02415ed6fd5759a
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment