aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common.go134
-rw-r--r--compiled.go46
-rw-r--r--dynamic.go69
-rw-r--r--files.go106
-rw-r--r--interactive.go131
-rw-r--r--main.go60
6 files changed, 546 insertions, 0 deletions
diff --git a/common.go b/common.go
new file mode 100644
index 0000000..0cf2655
--- /dev/null
+++ b/common.go
@@ -0,0 +1,134 @@
1/*
2
3 This file is part of CompileTree (https://github.com/Pacien/CompileTree)
4
5 CompileTree is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Affero General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 CompileTree is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with CompileTree. If not, see <http://www.gnu.org/licenses/>.
17
18*/
19
20package main
21
22import (
23 "bytes"
24 "fmt"
25 "github.com/hoisie/mustache"
26 "github.com/russross/blackfriday"
27 "io/ioutil"
28 "path"
29 "strings"
30 "sync"
31)
32
33var wait sync.WaitGroup
34
35// Common templating
36
37func isParsable(fileName string) bool {
38 switch path.Ext(fileName) {
39 case ".md", ".html", ".txt":
40 return true
41 }
42 return false
43}
44
45func read(fileName string) ([]byte, error) {
46 fileBody, err := ioutil.ReadFile(fileName)
47 if err != nil {
48 return nil, err
49 }
50 if path.Ext(fileName) == ".md" {
51 fileBody = blackfriday.MarkdownCommon(fileBody)
52 }
53 return fileBody, nil
54}
55
56func merge(files map[string][]byte) (merged []byte) {
57 merged = files["index"]
58 for pass := 0; bytes.Contains(merged, []byte("{{> ")) && pass < 4000; pass++ {
59 for fileName, fileBody := range files {
60 merged = bytes.Replace(merged, []byte("{{> "+fileName+"}}"), fileBody, -1)
61 }
62 }
63 return
64}
65
66// COMPILED and INTERACTIVE modes
67
68// render and write everything inside
69
70func parse(dirPath string, elements map[string][]byte, overwrite bool) map[string][]byte {
71 _, filesList := ls(dirPath)
72 for _, fileName := range filesList {
73 if isParsable(fileName) && (overwrite || elements[fileName[:len(fileName)-len(path.Ext(fileName))]] == nil) {
74 var err error
75 elements[fileName[:len(fileName)-len(path.Ext(fileName))]], err = read(path.Join(dirPath, fileName))
76 if err != nil {
77 fmt.Println(err)
78 }
79 }
80 }
81 return elements
82}
83
84func compile(dirPath string, elements map[string][]byte, sourceDir, outputDir string, recursive bool) {
85 wait.Add(1)
86 defer wait.Done()
87
88 if strings.HasPrefix(dirPath, outputDir) {
89 return
90 }
91
92 elements = parse(dirPath, elements, true)
93
94 if recursive {
95 dirs, _ := ls(dirPath)
96 for _, dir := range dirs {
97 go compile(path.Join(dirPath, dir), elements, sourceDir, outputDir, recursive)
98 }
99 }
100
101 template := merge(elements)
102 page := mustache.Render(string(template), nil /* TODO: generate contextual variables */)
103
104 err := writeFile(path.Join(outputDir, strings.TrimPrefix(dirPath, sourceDir), "index.html"), []byte(page))
105 if err != nil {
106 fmt.Println(err)
107 return
108 }
109}
110
111func copyFiles(dirPath, sourceDir, outputDir string, recursive bool) {
112 wait.Add(1)
113 defer wait.Done()
114
115 if strings.HasPrefix(dirPath, outputDir) {
116 return
117 }
118
119 dirs, files := ls(dirPath)
120 for _, file := range files {
121 if !isParsable(file) {
122 err := cp(path.Join(dirPath, file), path.Join(outputDir, strings.TrimPrefix(dirPath, sourceDir), file))
123 if err != nil {
124 fmt.Println(err)
125 }
126 }
127 }
128
129 if recursive {
130 for _, dir := range dirs {
131 go copyFiles(path.Join(dirPath, dir), sourceDir, outputDir, recursive)
132 }
133 }
134}
diff --git a/compiled.go b/compiled.go
new file mode 100644
index 0000000..5b2c19b
--- /dev/null
+++ b/compiled.go
@@ -0,0 +1,46 @@
1/*
2
3 This file is part of CompileTree (https://github.com/Pacien/CompileTree)
4
5 CompileTree is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Affero General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 CompileTree is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with CompileTree. If not, see <http://www.gnu.org/licenses/>.
17
18*/
19
20package main
21
22import (
23 "fmt"
24 "os"
25 "time"
26)
27
28func compiled(sourceDir, outputDir string) {
29 // remove previously compiled site
30 err := os.RemoveAll(outputDir)
31 if err != nil {
32 fmt.Println(err)
33 return
34 }
35
36 // compile everything
37 go compile(sourceDir, make(map[string][]byte), sourceDir, outputDir, true)
38 go copyFiles(sourceDir, sourceDir, outputDir, true)
39
40 // sleep some milliseconds to prevent early exit
41 time.Sleep(time.Millisecond * 100)
42
43 // wait until all tasks are completed
44 wait.Wait()
45 fmt.Println("Compilation done.")
46}
diff --git a/dynamic.go b/dynamic.go
new file mode 100644
index 0000000..0307003
--- /dev/null
+++ b/dynamic.go
@@ -0,0 +1,69 @@
1/*
2
3 This file is part of CompileTree (https://github.com/Pacien/CompileTree)
4
5 CompileTree is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Affero General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 CompileTree is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with CompileTree. If not, see <http://www.gnu.org/licenses/>.
17
18*/
19
20package main
21
22import (
23 "fmt"
24 "github.com/hoisie/mustache"
25 "net/http"
26 "path"
27 "strings"
28)
29
30func handle(w http.ResponseWriter, r *http.Request) {
31 // serve static files
32 if !(path.Ext(r.URL.Path) == "" || isParsable(path.Ext(r.URL.Path))) {
33 http.ServeFile(w, r, path.Join(*settings.sourceDir, r.URL.Path))
34 return
35 }
36
37 // get the list of dirs to parse
38 request := strings.Trim(r.URL.Path, "/")
39 dirs := strings.Split(request, "/")
40 if request != "" {
41 dirs = append(dirs, "")
42 }
43
44 // parse these dirs
45 elements := make(map[string][]byte)
46 for _, dir := range dirs {
47 parse(path.Join(*settings.sourceDir, dir), elements, false)
48 }
49
50 // render the page
51 template := merge(elements)
52 page := mustache.Render(string(template), nil /* TODO: generate contextual variables */)
53
54 // serve the page
55 _, err := w.Write([]byte(page))
56 if err != nil {
57 fmt.Println(err)
58 return
59 }
60}
61
62func dynamic(port string) {
63 fmt.Println("Listening on: localhost:" + port)
64 http.HandleFunc("/", handle)
65 err := http.ListenAndServe(":"+port, nil)
66 if err != nil {
67 fmt.Println(err)
68 }
69}
diff --git a/files.go b/files.go
new file mode 100644
index 0000000..afdac86
--- /dev/null
+++ b/files.go
@@ -0,0 +1,106 @@
1/*
2
3 This file is part of CompileTree (https://github.com/Pacien/CompileTree)
4
5 CompileTree is free software: you can redistribute it and/or modify
6