-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcompile.go
128 lines (107 loc) · 2.67 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
package precompiler
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"github.com/tdewolff/minify/v2"
"github.com/tdewolff/minify/v2/css"
"github.com/tdewolff/minify/v2/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 {
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))
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))
if err := os.MkdirAll(dir, 0755); err != nil {
return nil, err
}
destFile := filepath.Join(dir, config.FilePrefix+ret[key].Hash+ext)
if err := ioutil.WriteFile(destFile, bytes, 0644); err != nil {
return nil, err
}
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)
}