-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit a558b46
Showing
15 changed files
with
258 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
.DS_Store | ||
*.swp | ||
*.swo | ||
tags | ||
trofaf |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package main | ||
|
||
import ( | ||
"html/template" | ||
"log" | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/eknkc/amber" | ||
"github.com/howeyc/fsnotify" | ||
"github.com/jessevdk/go-flags" | ||
) | ||
|
||
var ( | ||
postTpl *template.Template | ||
) | ||
|
||
func main() { | ||
_, err := flags.Parse(&Options) | ||
if err == nil { // err prints the usage automatically | ||
// Compile the template(s) | ||
compileTemplate() | ||
// Generate the site | ||
regeneratePosts() | ||
|
||
// Start the watcher | ||
w, err := fsnotify.NewWatcher() | ||
if err != nil { | ||
log.Fatal("FATAL ", err) | ||
} | ||
defer w.Close() | ||
go watch(w) | ||
if err = w.Watch(PostsDir); err != nil { | ||
log.Fatal("FATAL ", err) | ||
} | ||
|
||
// Start the web server | ||
run() | ||
} | ||
} | ||
|
||
func compileTemplate() { | ||
ap := filepath.Join(TemplatesDir, "post.amber") | ||
if _, err := os.Stat(ap); os.IsNotExist(err) { | ||
// Amber post template does not exist, compile the native Go templates | ||
postTpl, err = template.ParseGlob(filepath.Join(TemplatesDir, "*.html")) | ||
if err != nil { | ||
log.Fatal("FATAL ", err) | ||
} | ||
} else { | ||
c := amber.New() | ||
if err := c.ParseFile(ap); err != nil { | ||
log.Fatal("FATAL ", err) | ||
} | ||
if postTpl, err = c.Compile(); err != nil { | ||
log.Fatal("FATAL ", err) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package main | ||
|
||
import ( | ||
"log" | ||
"os" | ||
"path/filepath" | ||
) | ||
|
||
type options struct { | ||
Port int `short:"p" long:"port" description:"the port to use for the web server" default:"9000"` | ||
} | ||
|
||
var ( | ||
Options options | ||
PublicDir string | ||
PostsDir string | ||
TemplatesDir string | ||
) | ||
|
||
func init() { | ||
pwd, err := os.Getwd() | ||
if err != nil { | ||
log.Fatal("FATAL ", err) | ||
} | ||
PublicDir = filepath.Join(pwd, "public/") | ||
PostsDir = filepath.Join(pwd, "posts/") | ||
TemplatesDir = filepath.Join(pwd, "templates/") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# This is my first post! | ||
|
||
I'm so happy to write this right now! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# Test 2! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# Test 3! |
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"net/http" | ||
"path/filepath" | ||
"time" | ||
|
||
"github.com/PuerkitoBio/ghost/handlers" | ||
) | ||
|
||
var ( | ||
faviconPath = filepath.Join(PublicDir, "favicon.ico") | ||
faviconCache = 2 * 24 * time.Hour | ||
) | ||
|
||
func run() { | ||
h := handlers.FaviconHandler( | ||
handlers.PanicHandler( | ||
handlers.LogHandler( | ||
handlers.GZIPHandler( | ||
http.FileServer(http.Dir(PublicDir)), | ||
nil), | ||
handlers.NewLogOptions(nil, handlers.Lshort)), | ||
nil), | ||
faviconPath, | ||
faviconCache) | ||
|
||
// Assign the combined handler to the server. | ||
http.Handle("/", h) | ||
|
||
// Start it up. | ||
log.Printf("trofaf server listening on port %d", Options.Port) | ||
if err := http.ListenAndServe(fmt.Sprintf(":%d", Options.Port), nil); err != nil { | ||
log.Fatal("FATAL ", err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
!!! html | ||
// From HTML5 Boilerplate | ||
html.no-js | ||
head | ||
meta[charset="utf-8"] | ||
meta[http-equiv="X-UA-Compatible"][content="IE=edge"] | ||
title ${Title} | ||
meta[name="description"][content=Description] | ||
meta[name="viewport"][content="width=device-width, initial-scale=1"] | ||
link[rel="stylesheet"][href="/public/css/normalize.css"] | ||
link[rel="stylesheet"][href="/public/css/main.css"] | ||
body | ||
<!--[if lt IE 7]> | ||
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p> | ||
<![endif]--> | ||
|
||
block content | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
extends layout | ||
|
||
block content | ||
h1 My Post! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package main | ||
|
||
import ( | ||
"io/ioutil" | ||
"log" | ||
"os" | ||
"path/filepath" | ||
"sort" | ||
"strings" | ||
"time" | ||
|
||
"github.com/howeyc/fsnotify" | ||
) | ||
|
||
const ( | ||
// Sometimes many events can be triggered in succession for the same file | ||
// (i.e. Create followed by Modify, etc.). No need to rush to generate | ||
// the HTML, just wait for it to calm down before processing. | ||
watchEventDelay = 30 * time.Second | ||
) | ||
|
||
// Receive watcher events for the posts directory. All events require re-generating | ||
// the whole site (because the template may display the n most recent posts, the | ||
// next and previous post, etc.). It could be fine-tuned based on what data we give | ||
// to the templates, but for now, lazy approach. | ||
func watch(w *fsnotify.Watcher) { | ||
var delay <-chan time.Time | ||
for { | ||
select { | ||
case ev := <-w.Event: | ||
log.Print("watch event ", ev) | ||
// Regenerate the files after the delay, reset the delay if an event is triggered | ||
// in the meantime | ||
delay = time.After(watchEventDelay) | ||
|
||
case err := <-w.Error: | ||
log.Print("WATCH ERROR ", err) | ||
|
||
case <-delay: | ||
log.Print("trigger regeneration of site") | ||
regeneratePosts() | ||
} | ||
} | ||
} | ||
|
||
type sortableFileInfo []os.FileInfo | ||
|
||
func (s sortableFileInfo) Len() int { return len(s) } | ||
func (s sortableFileInfo) Less(i, j int) bool { return s[i].ModTime().Before(s[j].ModTime()) } | ||
func (s sortableFileInfo) Swap(i, j int) { s[i], s[j] = s[j], s[i] } | ||
|
||
func FilterDir(s sortableFileInfo) sortableFileInfo { | ||
for i := 0; i < len(s); { | ||
if s[i].IsDir() { | ||
s[i], s = s[len(s)-1], s[:len(s)-1] | ||
} else { | ||
i++ | ||
} | ||
} | ||
return s | ||
} | ||
|
||
func regeneratePosts() { | ||
fis, err := ioutil.ReadDir(PostsDir) | ||
if err != nil { | ||
log.Fatal("FATAL ", err) | ||
} | ||
sfi := sortableFileInfo(fis) | ||
sfi = FilterDir(sfi) | ||
sort.Sort(sfi) | ||
for _, fi := range sfi { | ||
regenerateFile(fi) | ||
} | ||
} | ||
|
||
// TODO : Should pass to the template: | ||
// Title : The first heading in the file, or the file name, or front matter? | ||
// Description : ? | ||
// ModTime | ||
// Parsed : The html-parsed markdown | ||
// Recent : A slice of n recent posts | ||
// Next : The next (more recent) post | ||
// Previous : The previous (older) post | ||
|
||
func regenerateFile(fi os.FileInfo) { | ||
f, err := os.Open(filepath.Join(PostsDir, fi.Name())) | ||
if err != nil { | ||
log.Fatal("FATAL ", err) | ||
} | ||
defer f.Close() | ||
// TODO : Blackfriday... | ||
|
||
nm := fi.Name() | ||
nm = strings.Replace(nm, filepath.Ext(nm), "", 1) | ||
fw, err := os.Create(filepath.Join(PublicDir, nm)) | ||
if err != nil { | ||
log.Fatal("FATAL ", err) | ||
} | ||
defer fw.Close() | ||
postTpl.ExecuteTemplate(fw, "post", nil) | ||
} |