func TestFontURLFail(t *testing.T) { r, w, _ := os.Pipe() old := os.Stdout defer func() { os.Stdout = old }() os.Stdout = w in := bytes.NewBufferString(`@font-face { src: font-url("arial.eot"); }`) var out bytes.Buffer ctx := libsass.Context{} err := ctx.Compile(in, &out) if err != nil { t.Error(err) } outC := make(chan string) go func(r *os.File) { var buf bytes.Buffer io.Copy(&buf, r) outC <- buf.String() }(r) w.Close() stdout := <-outC if e := "font-url: font path not set\n"; e != stdout { t.Errorf("got:\n%s\nwanted:\n%s\n", stdout, e) } }
// ImageURL handles calls to resolve a local image from the // built css file path. func ImageURL(ctx *libsass.Context, csv libsass.UnionSassValue) libsass.UnionSassValue { var path []string err := libsass.Unmarshal(csv, &path) // This should create and throw a sass error if err != nil { return libsass.Error(err) } url := filepath.Join(ctx.RelativeImage(), path[0]) res, err := libsass.Marshal(fmt.Sprintf("url('%s')", url)) if err != nil { return libsass.Error(err) } return res }
// HTTPHandler starts a CORS enabled web server that takes as input // Sass and outputs CSS. func HTTPHandler(ctx *libsass.Context) func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) { var ( pout bytes.Buffer buf bytes.Buffer ) start := time.Now() // Set headers if origin := r.Header.Get("Origin"); origin != "" { w.Header().Set("Access-Control-Allow-Origin", origin) } w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE") w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token") w.Header().Set("Access-Control-Allow-Credentials", "true") _, err := StartParser(ctx, r.Body, &pout, NewPartialMap()) if err != nil { enc := json.NewEncoder(w) enc.Encode(Response{ Start: start, Elapsed: strconv.FormatFloat(float64( time.Since(start).Nanoseconds())/float64(time.Millisecond), 'f', 3, 32) + "ms", Contents: "", Error: fmt.Sprintf("%s", err), }) return } err = ctx.Compile(&pout, &buf) defer func() { enc := json.NewEncoder(w) errString := "" if err != nil { errString = err.Error() } enc.Encode(Response{ Start: start, Elapsed: strconv.FormatFloat(float64( time.Since(start).Nanoseconds())/(1000*1000), 'f', 3, 32) + "ms", Contents: buf.String(), Error: errString, }) }() } }
// LoadAndBuild kicks off parser and compiling // TODO: make this function testable func LoadAndBuild(sassFile string, gba *BuildArgs, partialMap *SafePartialMap) error { if gba == nil { return fmt.Errorf("build args are nil") } // If no imagedir specified, assume relative to the input file if gba.Dir == "" { gba.Dir = filepath.Dir(sassFile) } var ( out io.WriteCloser fout string ) if gba.BuildDir != "" { // Build output file based off build directory and input filename rel, _ := filepath.Rel(gba.Includes, filepath.Dir(sassFile)) filename := updateFileOutputType(filepath.Base(sassFile)) fout = filepath.Join(gba.BuildDir, rel, filename) } else { out = os.Stdout } ctx := libsass.Context{ Sprites: gba.Sprites, Imgs: gba.Imgs, OutputStyle: gba.Style, ImageDir: gba.Dir, FontDir: gba.Font, // Assumption that output is a file BuildDir: filepath.Dir(fout), GenImgDir: gba.Gen, MainFile: sassFile, Comments: gba.Comments, IncludePaths: []string{filepath.Dir(sassFile)}, } ctx.Imports.Init() if gba.Includes != "" { ctx.IncludePaths = append(ctx.IncludePaths, strings.Split(gba.Includes, ",")...) } fRead, err := os.Open(sassFile) if err != nil { return err } defer fRead.Close() if fout != "" { dir := filepath.Dir(fout) err := os.MkdirAll(dir, 0755) if err != nil { return fmt.Errorf("Failed to create directory: %s", dir) } out, err = os.Create(fout) defer out.Close() if err != nil { return fmt.Errorf("Failed to create file: %s", sassFile) } // log.Println("Created:", fout) } err = ctx.FileCompile(sassFile, out) if err != nil { log.Println(sassFile) return err } for _, inc := range ctx.ResolvedImports { partialMap.AddRelation(ctx.MainFile, inc) } fmt.Printf("Rebuilt: %s\n", sassFile) return nil }