-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
site.go
147 lines (121 loc) · 3.58 KB
/
site.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
// Package ephemeris holds some minimal code to create a blog.
//
// A blog is largely made up of blog-posts, which are parsed from
// a series of text-files.
//
// Each post will have a small header to include tags, date, title,
// and will be transformed into a simple site.
//
package ephemeris
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"sort"
"strings"
)
// Ephemeris holds our site structure.
//
// There are only a few settings for the blog, which are the obvious
// ones - a path pointing to the blog-posts, a URL-prefix for use in
// generation of the output files, and a list of comment files.
type Ephemeris struct {
// Root is the source of our posts.
Root string
// BlogEntries holds the entries we've found
BlogEntries []BlogEntry
// CommentFiles holds the filenames of comments we've found.
CommentFiles []string
// Prefix is the absolute URL prefix for the blog
Prefix string
}
// New creates a new site object.
func New(directory string, commentPath string, prefix string) (*Ephemeris, error) {
// Create object
x := &Ephemeris{Root: directory, Prefix: prefix}
// If the comment-path is set we'll load comments
if commentPath != "" {
// Now we can find comments - by reading the given
// directory and adding each of them.
comments, err := ioutil.ReadDir(commentPath)
if err != nil {
return x, err
}
// Sort the comments, since we want to show them upon
// entries in the oldest->newest order.
sort.Slice(comments, func(i, j int) bool {
return comments[i].ModTime().Before(comments[j].ModTime())
})
// Save the (complete) path to each comment-file in our
// object, now they're sorted.
for _, f := range comments {
// By appending
x.CommentFiles = append(x.CommentFiles, filepath.Join(commentPath, f.Name()))
}
}
var err error
//
// Find the blog-posts, recursively.
//
if directory != "" {
err = filepath.Walk(directory,
func(path string, info os.FileInfo, err error) error {
// Error? Then we're done.
if err != nil {
return err
}
// Ignore non-text files.
if !strings.HasSuffix(path, ".txt") {
return nil
}
// Parse the blog-post from the file.
out, err := NewBlogEntry(path, x)
if err != nil {
return fmt.Errorf("failed to parse %s - %s", path, err.Error())
}
// Store the result.
x.BlogEntries = append(x.BlogEntries, out)
// Continue walking.
return nil
})
}
// Return the entries we found.
return x, err
}
// Entries returns the blog-entries contained within a site. Note that
// the input directory is searched recursively for files matching the
// pattern "*.txt" - this allows you to create entries in sub-directories
// if you wish.
//
// The entries are returned in a random-order, and contain a complete
// copy of all the text in the entries. This means that there is a reasonable
// amount of memory overhead here.
func (e *Ephemeris) Entries() []BlogEntry {
return e.BlogEntries
}
// Recent returns the data about the most recent N entries from the
// site
func (e *Ephemeris) Recent(count int) []BlogEntry {
// The return-value
var recent []BlogEntry
// Sort the list of posts by date.
sort.Slice(e.BlogEntries, func(i, j int) bool {
a := e.BlogEntries[i].Date
b := e.BlogEntries[j].Date
return a.Before(b)
})
// We want to include at-max `count` posts.
//
// But of course if this is a new blog there might
// be fewer than that present. Terminate early in
// that case.
c := 0
for c < len(e.BlogEntries) && c < count {
ent := e.BlogEntries[len(e.BlogEntries)-1-c]
recent = append(recent, ent)
c++
}
// All done
return recent
}