wellington / go-libsass

Go wrapper for libsass, the only Sass 3.5 compiler for Go
http://godoc.org/github.com/wellington/go-libsass
Apache License 2.0
206 stars 28 forks source link

Using imports #45

Closed japettyjohn closed 7 years ago

japettyjohn commented 7 years ago

I'm trying to provide Imports to my compiler and have not been able to see a way to do this through the API.

Is this possible through the high level API?

drewwells commented 7 years ago

Not sure I understand the question. If you're looking to use sass imports @import 'file' the syntax is the same, just build it via libsass or use wellington to run it with a nicer cli. Maybe you are referring to headers, file included automatically on every build? https://github.com/sass/libsass/blob/master/docs/api-importer-example.md

japettyjohn commented 7 years ago

I've got import @import 'file' as you noted, but I'm trying to load these imports from memory, not from disk.

I thought to use NewImports() and add them there, but I didn't see a way to overwrite the one on the context as there is no "option" for it.

drewwells commented 7 years ago

That sounds like the job of a custom function or header. I have no option in the Compiler to pass in your own Buffers to be read as files. It would make logging problematic, what file would be logged out?

As a workaround, you can use RegisterHeader https://github.com/wellington/go-libsass/blob/master/mixins.go#L5

Here's another example of adding a preamble to output https://github.com/wellington/go-libsass/blob/master/examples/custompreamble/main.go#L13-L18

It's basically a magic import, an import without actually declaring in code what is being used. Some of the Sass contributors believe this is a bad practice and for good reason. As you have found, working with non-files is problematic with SASS. One of the reasons is the continued support of SASS vs SCSS standard. Wellington, however, makes compromises to support both and supports non-files like HTTP streams with this code SCSS and SASS.

japettyjohn commented 7 years ago

I get what you're saying, in my case it was all being done on disk but I'm trying to get the cgo dependencies out of the project so I've opted to use RPC (the pure implementations don't appear to be quite ready yet).

So I still have standard imports being used with paths etc., but I don't have files on the disk available to the process. So I'm streaming everything over and back. Sounded a little ridiculous but it hardly adds any time and it will be cached in the main.

I got it to work with this mod, tell me what you think: https://github.com/japettyjohn/go-libsass/commit/5da79f88d0488f0162546af7fc9e5cd39751ac18

With that option exposed I could use:

imports := libsass.NewImports() imports.Init() imports.Add("", fileName, importBuff.Bytes()) sass.Option(libsass.Importers(imports))

I'm not sure if the map generation can somehow be still be utilized, a comment I saw somewhere said it could be inlined but it didn't say how.

drewwells commented 7 years ago

I think I see what you're getting at now. Perhaps instead of modifying the internal compiler structure, it would be better to pass in an interface for resolving imports.

type MemImporter interface {
  Get(pathName string) ([]byte)
}

This way, you can just implement an interface{} and not beholden to the internal structure of go-libsass. I need to dig into C libsass to get more info to see if this can be done on demand as described.

drewwells commented 7 years ago

Silly me, custom importers are already available https://github.com/wellington/go-libsass/blob/master/libs/importer.go#L37 and in use by go-libsass.

The quickest way to unblock this is what you've done. Let's go with that and I'll see if I like this interface{} idea enough to rewrite the underlying c bindings to use it. Please comment the option and rename it removing the 'er'. er implies it is an interface, but it's just dealing with structs. Imports() or something similar would work. Submit a PR and I can merge it.

Thanks!