Skip to content

Commit

Permalink
Add Url to main entry + imports
Browse files Browse the repository at this point in the history
To get proper source references in source maps.

Also clean up the scheme logic.
  • Loading branch information
bep committed Dec 22, 2020
1 parent ba89b1c commit 39fcffb
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 12 deletions.
13 changes: 12 additions & 1 deletion options.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,14 @@ func (opts *Options) init() error {
}

// ImportResolver allows custom import resolution.
//
// CanonicalizeURL should create a canonical version of the given URL if it's
// able to resolve it, else return an empty string.
// Include scheme if relevant, e.g. 'file://foo/bar.scss'.
//
// A canonicalized URL should include a scheme, e.g. 'file:///foo/bar.scss',
// if applicable, see:
// https://en.wikipedia.org/wiki/File_URI_scheme
//
// Importers must ensure that the same canonical URL
// always refers to the same stylesheet.
//
Expand All @@ -49,6 +54,12 @@ type Args struct {
// The input source.
Source string

// The URL of the Source.
// Leave empty if it's unknown.
// Must include a scheme, e.g. 'file:///myproject/main.scss'
// See https://en.wikipedia.org/wiki/File_URI_scheme
URL string

// Defaults is SCSS.
SourceSyntax SourceSyntax

Expand Down
30 changes: 21 additions & 9 deletions transpiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import (
"io"
"os"
"os/exec"
"regexp"
"runtime"
"strings"
"sync"

"github.com/cli/safeexec"
Expand All @@ -21,9 +21,6 @@ import (
var defaultDartSassEmbeddedFilename = "dart-sass-embedded"

const (
// Dart Sass requires a schema of some sort, add this
// if the resolver does not.
dummyImportSchema = "godartimport:"

// There is only one, and this number is picked out of a hat.
importerID = 5679
Expand Down Expand Up @@ -113,6 +110,7 @@ func (t *Transpiler) Execute(args Args) (Result, error) {
String_: &embeddedsass.InboundMessage_CompileRequest_StringInput{
Syntax: args.sassSourceSyntax,
Source: args.Source,
Url: args.URL,
},
},
SourceMap: args.EnableSourceMap,
Expand Down Expand Up @@ -186,10 +184,6 @@ func (t *Transpiler) input() {
case *embeddedsass.OutboundMessage_CanonicalizeRequest_:
var url *embeddedsass.InboundMessage_CanonicalizeResponse_Url
if resolved := t.opts.ImportResolver.CanonicalizeURL(c.CanonicalizeRequest.GetUrl()); resolved != "" {
if !strings.Contains(resolved, ":") {
// Add a dummy schema.
resolved = dummyImportSchema + ":" + resolved
}
url = &embeddedsass.InboundMessage_CanonicalizeResponse_Url{
Url: resolved,
}
Expand All @@ -209,12 +203,24 @@ func (t *Transpiler) input() {
)

case *embeddedsass.OutboundMessage_ImportRequest_:
url := c.ImportRequest.GetUrl()
var sourceMapURL string
// Dart Sass expect a browser-accessible URL or an empty string.
// If no URL is supplied, a `data:` URL wil be generated
// automatically from `contents`
// The hasSchema function may be too coarse grained, but we
// need to test this in real life situations.
if hasSchema(url) {
sourceMapURL = url
}

response := &embeddedsass.InboundMessage_ImportResponse_{
ImportResponse: &embeddedsass.InboundMessage_ImportResponse{
Id: c.ImportRequest.GetId(),
Result: &embeddedsass.InboundMessage_ImportResponse_Success{
Success: &embeddedsass.InboundMessage_ImportResponse_ImportSuccess{
Contents: t.opts.ImportResolver.Load(strings.TrimPrefix(c.ImportRequest.GetUrl(), dummyImportSchema)),
Contents: t.opts.ImportResolver.Load(url),
SourceMapUrl: sourceMapURL,
},
},
},
Expand Down Expand Up @@ -319,3 +325,9 @@ func (call *call) done() {
func isWindows() bool {
return runtime.GOOS == "windows"
}

var hasSchemaRe = regexp.MustCompile("^[a-z]*:")

func hasSchema(s string) bool {
return hasSchemaRe.MatchString(s)
}
27 changes: 25 additions & 2 deletions transpiler_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package godartsass

import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
Expand Down Expand Up @@ -41,7 +42,7 @@ func (t testImportResolver) CanonicalizeURL(url string) string {
return ""
}

return url
return filepath.Clean("file:/myproject/scss/" + url + "_myfile.scss")
}

func (t testImportResolver) Load(url string) string {
Expand All @@ -66,7 +67,7 @@ func TestTranspilerVariants(t *testing.T) {
expect interface{}
}{
{"Output style compressed", Options{}, Args{Source: "div { color: #ccc; }", OutputStyle: OutputStyleCompressed}, Result{CSS: "div{color:#ccc}"}},
{"Enable Source Map", Options{}, Args{Source: "div{color:blue;}", OutputStyle: OutputStyleCompressed, EnableSourceMap: true}, Result{CSS: "div{color:blue}", SourceMap: "{\"version\":3,\"sourceRoot\":\"\",\"sources\":[\"data:;charset=utf-8,div%7Bcolor:blue;%7D\"],\"names\":[],\"mappings\":\"AAAA\"}"}},
{"Enable Source Map", Options{}, Args{Source: "div{color:blue;}", URL: "file://myproject/main.scss", OutputStyle: OutputStyleCompressed, EnableSourceMap: true}, Result{CSS: "div{color:blue}", SourceMap: "{\"version\":3,\"sourceRoot\":\"\",\"sources\":[\"file://myproject/main.scss\"],\"names\":[],\"mappings\":\"AAAA\"}"}},
{"Sass syntax", Options{}, Args{
Source: `$font-stack: Helvetica, sans-serif
$primary-color: #333
Expand All @@ -79,6 +80,7 @@ body
SourceSyntax: SourceSyntaxSASS,
}, Result{CSS: "body{font:100% Helvetica,sans-serif;color:#333}"}},
{"Import resolver", Options{ImportResolver: colorsResolver}, Args{Source: "@import \"colors\";\ndiv { p { color: $white; } }"}, Result{CSS: "div p {\n color: #ffff;\n}"}},
{"Import resolver with source map", Options{ImportResolver: colorsResolver}, Args{Source: "@import \"colors\";\ndiv { p { color: $white; } }", EnableSourceMap: true}, Result{CSS: "div p {\n color: #ffff;\n}", SourceMap: "{\"version\":3,\"sourceRoot\":\"\",\"sources\":[\"data:;charset=utf-8,@import%20%22colors%22;%0Adiv%20%7B%20p%20%7B%20color:%20$white;%20%7D%20%7D\",\"file:///myproject/scss/colors_myfile.scss\"],\"names\":[],\"mappings\":\"AACM;EAAI,OCDC\"}"}},

// Error cases
{"Invalid syntax", Options{}, Args{Source: "div { color: $white; }"}, false},
Expand All @@ -102,7 +104,9 @@ body
} else {
expectedResult := test.expect.(Result)
c.Assert(err, qt.IsNil)
//printJSON(result.SourceMap)
c.Assert(result, qt.Equals, expectedResult)

}
})

Expand Down Expand Up @@ -250,6 +254,16 @@ func BenchmarkTranspiler(b *testing.B) {
})
}

func TestHasSchema(t *testing.T) {
c := qt.New(t)

c.Assert(hasSchema("file:foo"), qt.Equals, true)
c.Assert(hasSchema("http:foo"), qt.Equals, true)
c.Assert(hasSchema("123:foo"), qt.Equals, false)
c.Assert(hasSchema("foo"), qt.Equals, false)

}

func newTestTranspiler(c *qt.C, opts Options) (*Transpiler, func()) {
opts.DartSassEmbeddedFilename = getSassEmbeddedFilename()
transpiler, err := Start(opts)
Expand All @@ -268,3 +282,12 @@ func getSassEmbeddedFilename() string {

return defaultDartSassEmbeddedFilename
}

// used for debugging
func printJSON(s string) {
m := make(map[string]interface{})
json.Unmarshal([]byte(s), &m)
b, _ := json.MarshalIndent(m, "", " ")
fmt.Printf("%s", b)

}

0 comments on commit 39fcffb

Please sign in to comment.