This repository has been archived by the owner on Dec 22, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
util.go
171 lines (152 loc) · 3.95 KB
/
util.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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package main
import (
"bytes"
"io"
"os"
"os/exec"
"path/filepath"
"strings"
)
// Appends the extension to the specified file. If the file already has the
// desired extension no changes are made.
func appendExt(fn, ext string) string {
if strings.HasSuffix(fn, ext) {
return fn
}
return fn + ext
}
// Copies a file to the specified directory. It will also create any necessary
// sub directories.
//
// TODO use native Go code to copy file to enable Windows support
func copyTo(from, to string) error {
os.MkdirAll(filepath.Dir(to), 0755)
if err := exec.Command("cp", from, to).Run(); err != nil {
return err
}
return nil
}
// Returns True if a file has YAML front-end matter.
func hasMatter(fn string) bool {
sample, _ := sniff(strings.TrimLeft(fn, " \t\n"), 4)
return bytes.Equal(sample, []byte("---\n"))
}
// Returns True if the file is a temp file (starts with . or ends with ~).
func isHiddenOrTemp(fn string) bool {
base := filepath.Base(fn)
return strings.HasPrefix(base, ".") ||
strings.HasPrefix(fn, ".") ||
strings.HasPrefix(base, "#") ||
strings.HasSuffix(base, "~") ||
fn == "README.md"
}
// Returns True if the file is a template. This is determine by the files
// parent directory (_layout or _include) and the file type (markdown).
func isTemplate(fn string) bool {
switch {
case !isHtml(fn):
return false
case strings.HasPrefix(fn, "_layouts"):
return true
case strings.HasPrefix(fn, "_includes"):
return true
}
return false
}
// Return True if the markup is HTML.
// TODO change this to isMarkup and add .xml, .rss, .atom
func isHtml(fn string) bool {
switch filepath.Ext(fn) {
case ".html", ".htm", ".xml", ".rss", ".atom":
return true
}
return false
}
// Returns True if the markup is Markdown.
func isMarkdown(fn string) bool {
switch filepath.Ext(fn) {
case ".md", ".markdown":
return true
}
return false
}
// Returns True if the specified file is a Page.
func isPage(fn string) bool {
switch {
case strings.HasPrefix(fn, "_"):
return false
case !isMarkdown(fn) && !isHtml(fn):
return false
case !hasMatter(fn):
return false
}
return true
}
// Returns True if the specified file is a Post.
func isPost(fn string) bool {
switch {
case !strings.HasPrefix(fn, "_posts"):
return false
case !isMarkdown(fn):
return false
case !hasMatter(fn):
return false
}
return true
}
// Returns True if the specified file is Static Content, meaning it should
// be included in the site, but not compiled and processed by Jekyll.
//
// NOTE: this assumes that we've already established the file is not markdown
// and does not have yaml front matter.
func isStatic(fn string) bool {
return !strings.HasPrefix(fn, "_")
}
// Returns an recursive list of all child directories
func dirs(path string) (paths []string) {
site := filepath.Join(path, "_site")
filepath.Walk(path, func(fn string, fi os.FileInfo, err error) error {
switch {
case err != nil:
return nil
case fi.IsDir() && isHiddenOrTemp(fn):
return filepath.SkipDir
case fi.IsDir() == false:
return nil
case strings.HasPrefix(fn, site):
return nil
}
paths = append(paths, fn)
return nil
})
return
}
// Removes the files extension. If the file has no extension the string is
// returned without modification.
func removeExt(fn string) string {
if ext := filepath.Ext(fn); len(ext) > 0 {
return fn[:len(fn)-len(ext)]
}
return fn
}
// Replaces the files extension with the new extension.
func replaceExt(fn, ext string) string {
return removeExt(fn) + ext
}
// sniff will extract the first N bytes from a file and return the results.
//
// This is used, for example, by the hasMatter function to check and see
// if the file include YAML without having to read the entire contents of the
// file into memory.
func sniff(fn string, n int) ([]byte, error) {
f, err := os.Open(fn)
if err != nil {
return nil, err
}
defer f.Close()
b := make([]byte, n, n)
if _, err := io.ReadAtLeast(f, b, n); err != nil {
return nil, err
}
return b, nil
}