/
sass.go
102 lines (95 loc) · 2.51 KB
/
sass.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package renderers
import (
"bytes"
"crypto/md5" // nolint: gas
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/osteele/gojekyll/cache"
"github.com/osteele/gojekyll/utils"
"github.com/tdewolff/minify"
"github.com/tdewolff/minify/css"
libsass "github.com/wellington/go-libsass"
)
// CopySassFileIncludes copies sass partials into a temporary directory,
// removing initial underscores.
func (p *Manager) CopySassFileIncludes() error {
// TODO delete the temp directory when done?
// TODO use libsass.ImportsOption instead?
if p.sassTempDir == "" {
dir, err := ioutil.TempDir(os.TempDir(), "_sass")
if err != nil {
return err
}
p.sassTempDir = dir
}
h := md5.New() // nolint: gas, noncrypto
if p.ThemeDir != "" {
if err := copySassFiles(filepath.Join(p.ThemeDir, "_sass"), p.sassTempDir, h); err != nil {
return err
}
}
if err := copySassFiles(filepath.Join(p.sourceDir(), "_sass"), p.sassTempDir, h); err != nil {
return err
}
p.sassHash = fmt.Sprintf("%x", h.Sum(nil))
return nil
}
func copySassFiles(src, dst string, h io.Writer) error {
err := filepath.Walk(src, func(from string, info os.FileInfo, err error) error {
if err != nil || info.IsDir() {
return err
}
rel := utils.MustRel(src, from)
to := filepath.Join(dst, strings.TrimPrefix(rel, "_"))
in, err := os.Open(from)
if err != nil {
return err
}
defer in.Close() // nolint: errcheck
if _, err = io.Copy(h, in); err != nil {
return err
}
return utils.CopyFileContents(to, from, 0644)
})
if os.IsNotExist(err) {
return nil
}
return err
}
// SassIncludePaths returns an array of sass include directories.
func (p *Manager) SassIncludePaths() []string {
return []string{p.sassTempDir}
}
// WriteSass converts a SASS file and writes it to w.
func (p *Manager) WriteSass(w io.Writer, b []byte) error {
s, err := cache.WithFile(fmt.Sprintf("sass: %s", p.sassHash), string(b), func() (s string, err error) {
buf := new(bytes.Buffer)
comp, err := libsass.New(buf, bytes.NewBuffer(b))
if err != nil {
return "", err
}
err = comp.Option(libsass.IncludePaths(p.SassIncludePaths()))
if err != nil {
return "", err
}
if err = comp.Run(); err != nil {
return "", err
}
m := minify.New()
m.AddFunc("text/css", css.Minify)
min := bytes.NewBuffer(make([]byte, 0, buf.Len()))
if err := m.Minify("text/css", min, bytes.NewBuffer(buf.Bytes())); err != nil {
return "", err
}
return min.String(), nil
})
if err != nil {
return err
}
_, err = io.WriteString(w, s)
return err
}