-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser.go
133 lines (119 loc) · 3.04 KB
/
parser.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
package main
import (
"bytes"
"encoding/base64"
"flag"
"io"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"github.com/russross/blackfriday"
"golang.org/x/crypto/sha3"
)
var (
from = flag.String("from", "", "Source directory with markdown and images.")
to = flag.String("to", "", "Destination for static content.")
)
func processImages(images []string) (map[string]string, error) {
mapping := make(map[string]string)
for _, image := range images {
file, err := os.Open(image)
if err != nil {
return nil, err
}
defer file.Close()
// Compute hash and destination filename.
shaker := sha3.New224()
if _, err := io.Copy(shaker, file); err != nil {
return nil, err
}
digest := make([]byte, 0, 28)
digest = shaker.Sum(digest)
hash := base64.RawURLEncoding.EncodeToString(digest)
destPath := filepath.Join(*to, hash+".jpg")
// Figure out mapping.
mKey, err := filepath.Rel(*from, image)
if err != nil {
return nil, err
}
mValue, err := filepath.Rel(*to, destPath)
if err != nil {
return nil, err
}
mapping[mKey] = mValue
log.Printf("Map image %q to %q in markdown.", mKey, mValue)
// Copy image.
if _, err := file.Seek(0, os.SEEK_SET); err != nil {
return nil, err
}
copy, err := os.Create(destPath)
if err != nil {
return nil, err
}
if _, err := io.Copy(copy, file); err != nil {
return nil, err
}
if err := copy.Close(); err != nil {
return nil, err
}
log.Printf("Image %q copied to %q.", image, destPath)
}
return mapping, nil
}
func processMarkdowns(markdowns []string, imapping map[string]string, output io.WriteCloser) error {
for _, markdown := range markdowns {
stream, err := ioutil.ReadFile(markdown)
if err != nil {
return err
}
for mKey, mValue := range imapping {
stream = bytes.Replace(stream, []byte(mKey), []byte(mValue), -1)
}
html := blackfriday.MarkdownCommon(stream)
if _, err := output.Write(html); err != nil {
return err
}
}
return output.Close()
}
func main() {
flag.Parse()
if _, err := os.Open(*to); err == nil {
log.Fatalf("Destination folder %q already exists.", *to)
}
if err := os.MkdirAll(*to, 0777); err != nil {
log.Fatalf("Failed to create destination directory %q: %s", *to, err)
}
var markdowns, images []string
walker := func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
switch strings.ToLower(filepath.Ext(path)) {
case ".md":
markdowns = append(markdowns, path)
case ".jpg", ".jpeg":
images = append(images, path)
default:
log.Printf("File or directory %q skipped.", path)
}
return nil
}
if err := filepath.Walk(*from, walker); err != nil {
log.Fatalf("Error while processing source files: %s", err)
}
imapping, err := processImages(images)
if err != nil {
log.Fatal(err)
}
outputPath := filepath.Join(*to, "index.html")
output, err := os.Create(outputPath)
if err != nil {
log.Fatalf("Failed to create destination HTML %q: %s", outputPath, err)
}
if err := processMarkdowns(markdowns, imapping, output); err != nil {
log.Fatal(err)
}
}