-
Notifications
You must be signed in to change notification settings - Fork 464
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement custom importers #21
Comments
I also agree with the issue. It would be great to have some interface that implement custom importers. |
I have implemented this functionality in my fork: https://github.com/Igorbek/libsass/tree/SourceProvider |
Wow, that is fantastic |
@pistolero yep, I'll do it today after take some code cleaning. |
Is this feature still planned? I could need it too 😄 |
I believe this is already solved. Please let me know if it's still an issue. |
Hi @hcatlin, I've had a look through the source code and while I've found code to allow adding a vector of custom include paths, I haven't spotted the ability for tools that bind to libsass (e.g. node-sass) to provide a custom The use-case I'm thinking of is that binding libraries could provide hooks into that ecosystem's package manager. For instance node-sass could provide an Thanks. |
@BPScott that's exactly the use-case 👍 |
Hmm... yeah, we haven't written anything like that. I bet we could do it In your mind, would you expect the @import callback to act like a "last On Mon, Oct 6, 2014 at 10:36 AM, Johannes Ewald notifications@github.com
|
I think it would need to be the first thing to try. This functionality feels like an override rather than a fallback coping mechanism. I believe |
Hmm… I think I’d assume it did local resolution first. But, I can see your point. On Mon, Oct 6, 2014 at 11:38 AM, Ben Scott notifications@github.com
|
A quick nose around the rework importer and the npm docs suggests that npm dodges this problem by saying that imports are only considered to be relative if they start with So with npm-style importing rules Other package managers may treat these paths differently so I think this needs to solved by each binding library depending on their platform's package manager. |
Following the Node module resolver heuristic, In other terms Sass modules could be shipped and consumed as npm dependencies; thus making a very explicit graph of relationships between BEM blocks (for example). |
@hcatlin I'd assume that the callback provides the rewritten path. Basically I want to configure somewhere (e.g. using node-sass): ...
resolveImport: function (path) {
// do some magic rewrite or throw an error if the path is illegal
return path;
}
... |
@hcatlin, @jhnns – I want to be able to provide a callback to actually returns the SCSS code to be imported, not just to return a resolved path. So by providing this callback, I could ensure Sass never touches the disk at all. ...
importer: function (name, cb) {
// look up `name`, load it, and maybe do some custom preprocessing...
// then call back with the SCSS
cb(null, scssString);
} This would allow me to properly use libsass in a transform pipeline. Current applications of this are hacky and limited, due to the fact that libsass wants to access the disk directly when it needs to import something. Imagine I want an extra preprocessing step before rendering my SCSS. I can have But what if my SCSS contains This is why I want to be able to provide a callback that takes care of all file reading. Because it's not just about controlling disk access or resolving paths, but also about importing from a non-disk source, such as an in-memory pipeline. |
Agreed 👍 |
A source should always have a path/filename associated, since this is what we use to create source-map information. In regard to source-maps the whole thing becomes even more complex, as a preprocessor that alters the original data will make the mappings invalid. So IMO a proper implementation should be able to return:
Beside that case, an implementer may also want to add multiple files from one import!
IMO this would cover all possible use cases! Or did I miss anything? The |
Good point, I didn't think of sourcemaps. But I don't get why an importer would want to add multiple files from one import? |
I guess someone might want to implement a |
IMO this is not implemented yet, so re-opening. |
I have a working implementation in my local branch! It should implement what I propesed earlier in this thread. |
Awesome! I'm glad to see progress on this issue. 👍 |
I'm just wondering how node.js would be able to load the file asynchronously in the custom importer... |
Same here. I'd like to help test, but I don't know C. @mgreter can you explain how I would test your branch? Presumably I would make a custom sassc build using your libsass branch, but then I don't know how I would run that executable in such a way that I can respond to its requests to load imports... or even if that makes any sense |
To implement it someone definitely has to know C, there is no way around. struct Sass_Import** sass_importer(const char* url, void* cookie)
{
struct Sass_Import** includes = sass_make_import_list(1);
includes[0] = sass_make_import_entry("path", strdup("source"), 0);
return includes;
} This C function is then registered with the sass context: sass_option_set_importer(sass_options, sass_make_importer(sass_importer, *importer_sv)); Note that By the way, the most recent version you find in #635 |
Since commit mgreter@df5b7c3 this should be possible! |
@mgreter: that is fantastic. Thank you for your work and the time you put into this <3 |
\o/ |
Awesome, thx! 👍 |
Thank you! 👍 |
The Sass Importer abstraction is a well defined API. It doesn't require the sass file to be on disk. It allows you to load Sass files from a database or over HTTP. It allows you to construct a sass file on the fly (Eg. compass sprites) The resolution order is always relative to the current Sass file and then falling back to searching the load path from the beginning. Is this how this works? I'm having a hard time understanding this from the code and wiki. |
Unfortunately most information is scattered around in various issues. I'll try to explain the basics. You get called for every import statement libsass sees (and get passed the url). If you return
struct Sass_Import** sass_importer(const char* url, void* cookie)
{
struct Sass_Import** incs = sass_make_import_list(2);
incs[0] = sass_make_import_entry("virtual.scss", strdup(source), 0);
incs[1] = sass_make_import_entry("include.scss", 0, 0);
return incs;
} I hope this clears it up a little? But full ACK that the documentation could still need a lot of more examples and more detailed information, but I hope it's still better than what we had before ;) |
I don't see how this scheme handles relative import resolution. |
I don't think I understand the concerns correctly? If you pass back a relative path to libsass, it should take care of that, as it should still see that import within the context of the current file (or how is it different from normal relative import resolution libsass already does?). But maybe you mean that the implementor would have to know what the current file beeing processed is, so it can actually make the imports relative from there? Not sure if this is already possible ... |
So if a file imports "foo/bar/baz" and then that file imports "asdf" then the file that should be imported is "foo/bar/asdf" if such a file exists otherwise a file "asdf" on the import path should be looked for. With importers the concept of a file is abstract, so there's a relative resolution that is passed the import statement as well as the current filename. filenames and import statements are not necessarily filesystem paths, they can be any string that the importer understands. |
I would like to use libsass with user-generated SCSS templates, but exposing libsass to user creates security threat. By crafting @import directives users can read some, possibly sensitive files, for server filesystem.
I would be nice if libsass would have support for custom importers, and have control over access to filesystem.
The text was updated successfully, but these errors were encountered: