-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcompile.go
131 lines (109 loc) · 2.74 KB
/
compile.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package precompiler
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"github.com/tdewolff/minify"
"github.com/tdewolff/minify/css"
"github.com/tdewolff/minify/js"
)
// FileType represents a supported file extension (without the .)
type FileType string
// supported file types
const (
CSS FileType = "css"
JS FileType = "js"
)
func initMinify() *minify.M {
minifier := minify.New()
minifier.AddFunc(string(CSS), css.Minify)
minifier.AddFunc(string(JS), js.Minify)
return minifier
}
func supportedFileType(t FileType) bool {
switch t {
case CSS, JS:
return true
}
return false
}
func getBytes(config Config, minifier *minify.M) (map[FileType]*bytes.Buffer, error) {
buf := make(map[FileType]*bytes.Buffer)
for _, pattern := range config.Files {
// Get all files matching wildcard
files, _ := filepath.Glob(pattern)
for _, file := range files {
if file, err := os.Open(file); err == nil {
ext := FileType(filepath.Ext(file.Name())[1:])
if !supportedFileType(ext) {
fmt.Println("Unsupported file type:", file.Name())
continue
}
if buf[ext] == nil {
buf[ext] = &bytes.Buffer{}
}
if config.Minify {
if err = minifier.Minify(string(ext), buf[ext], file); err != nil {
return nil, err
}
} else {
if _, err = buf[ext].ReadFrom(file); err != nil {
return nil, err
}
}
} else {
return nil, err
}
}
}
return buf, nil
}
// CompileResult holds the results of compilation
type CompileResult struct {
Bytes []byte
Hash string
OutputPath string
}
func finalize(config Config, buf map[FileType]*bytes.Buffer) (map[FileType]*CompileResult, error) {
ret := make(map[FileType]*CompileResult, len(buf))
// Delete old assets
oldFiles, _ := filepath.Glob(config.OutputDir + "/**/*.min.*")
for _, oldFile := range oldFiles {
os.RemoveAll(oldFile)
}
for key, b := range buf {
if b.Len() > 0 {
bytes := b.Bytes()
hash := sha256.Sum256(bytes)
ret[key] = &CompileResult{
Bytes: bytes,
Hash: hex.EncodeToString(hash[:]),
}
if len(config.OutputDir) > 0 {
ext := "." + string(key)
if config.Minify {
ext = ".min" + ext
}
dir := filepath.Join(config.OutputDir, string(key))
os.MkdirAll(dir, 0777)
destFile := filepath.Join(dir, "app-"+ret[key].Hash+ext)
ioutil.WriteFile(destFile, bytes, 0644)
ret[key].OutputPath = destFile
}
}
}
return ret, nil
}
// Compile compiles files indicated by the config into a single file per type
func Compile(config Config) (map[FileType]*CompileResult, error) {
var buf map[FileType]*bytes.Buffer
var err error
if buf, err = getBytes(config, initMinify()); err != nil {
return nil, err
}
return finalize(config, buf)
}