diff options
Diffstat (limited to 'site')
-rw-r--r-- | site/init.go | 164 | ||||
-rw-r--r-- | site/site.go | 135 |
2 files changed, 299 insertions, 0 deletions
diff --git a/site/init.go b/site/init.go new file mode 100644 index 0000000..dc17cfa --- /dev/null +++ b/site/init.go @@ -0,0 +1,164 @@ +package site + +import ( + "path" + "snkt/render" + "snkt/config" + "os" + "log" + "gopkg.in/yaml.v2" +) + +type skeleton struct { + Dir string + Filename string + Content []byte +} + +var skeletons = []skeleton { + { + Dir: "tmpl", + Filename: "base", + Content: []byte( +`{{define "base"}} +<!DOCTYPE html> +<html> + <head> + <title>{{template "title" .}}</title> + </head> + <body> + <h1>{{template "title"}}</h1> + {{template "content" .}} + <hr /> + <p><a href="{{.Site.URL}}/index.html">Home</a></p> + <p><a href="{{.Site.URL}}/archive.html">Archive</a></p> + </body> +</html> +{{end}} +{{define "title"}}{{end}} +{{define "content"}}{{end}} +`)}, + { + Dir: "tmpl", + Filename: "home", + Content: []byte( +`{{define "title"}}{{.Site.Title}}{{end}} +{{define "content"}} +<h1>{{.Site.Title}}</h1> +{{range .Posts.Limit 15}} +<h2><a href="{{.Permalink}}">{{.Title}}</a></h2> +{{.Content}} +{{end}} +{{end}} +`)}, + { + Dir: "tmpl", + Filename: "post", + Content: []byte( +`{{define "title"}}{{ .Post.Title }}{{end}} +{{define "content"}} +<h2>{{ .Post.Title }}</h2> +{{.Post.Content}} +{{if .Post.Next.Title}} +<p><a href="{{.Post.Next.Permalink}}">{{.Post.Next.Title}}</a></p> +{{end}} + {{if .Post.Prev.Title}} +<p><a href="{{.Post.Prev.Permalink}}">{{.Post.Prev.Title}}</a></p> +{{end}} +{{end}} +`)}, + { + Dir: "tmpl", + Filename: "archive", + Content: []byte( +`{{define "title"}}{{.Site.Title}} Archives{{end}} +{{define "content"}} +<h1>{{ .Site.Title }}</h1> +{{range .Posts}} +{{if .}}<h2><a href="{{.Permalink}}">{{.Title}}</a></h2>{{end}} +{{end}} +{{end}} +`)}, + { + Dir: "tmpl", + Filename: "rss", + Content: []byte( +`{{define "base"}} +<?xml version="1.0" encoding="UTF-8" ?> +<rss version="2.0"> +<channel> + <title>{{ .Site.Title }}</title> + <link>{{ .Site.URL }}</link> + <description></description> + {{ range .Posts.Limit 15 }} + <item> + <link>{{ .Permalink }}</link> + <title><![CDATA[{{ .Title }}]]></title> + <pubDate>{{ .RssDate }}</pubDate> + <description><![CDATA[ + {{ .AbsoluteContent }} + ]]> + </description> + </item> + {{ end }} +</channel> +</rss> +{{end}} +`)}} + +/* +Init initializes a new site in `directory` This includes: create `directory` and populate with: +config.json with sane defaults +txt, html directories for input/output +tmpl directory with barebones [base,post,archive,rss] templates +*/ +var init_dir = "" +func Init(directory string) { + init_dir = directory + + if init_dir[0] != '/' { + wd, err := os.Getwd() + if err == nil { + init_dir = path.Join(wd, init_dir) + } + } + + var cfg = config.Settings{ + TxtDir: path.Join(init_dir, "txt"), + HtmlDir: path.Join(init_dir, "html"), + TmplDir: path.Join(init_dir, "tmpl"), + } + + cyaml, err := yaml.Marshal(cfg) + if err != nil { + log.Fatal("marshalling yaml error: ", err) + } + + c := skeleton{ + Dir: "", + Filename: "config.yml", + Content: cyaml, + } + skeletons = append(skeletons, c) + + os.MkdirAll( cfg.TxtDir , 0755) + os.MkdirAll( cfg.HtmlDir , 0755) + os.MkdirAll( cfg.TmplDir , 0755) + + writeSkeletons() +} + + +func (s skeleton) Render() []byte { + return s.Content +} + +func (s skeleton) Target() string { + return path.Join(init_dir, s.Dir, s.Filename) +} + +func writeSkeletons() { + for _,skeleton := range skeletons { + render.Write(skeleton) + } +} diff --git a/site/site.go b/site/site.go new file mode 100644 index 0000000..87aa7fc --- /dev/null +++ b/site/site.go @@ -0,0 +1,135 @@ +package site + +import ( + "snkt/archive" + "snkt/config" + "snkt/post" + "snkt/render" + "io/ioutil" + "log" + "path" + "sort" +) + +type Site struct { + Title string + URL string + + Posts post.Posts + + // all archives are optional based on presence of template + Archive *archive.ListArchive + Home *archive.ListArchive + Rss *archive.ListArchive + Paged *archive.PagedArchives +} + +/* +Read reads post data from the filesystem and populates posts and archives +*/ +func (s *Site) Read() { + s.Title = config.Config.SiteTitle + s.URL = config.Config.SiteURL + s.ReadPosts() + + if render.TmplExists("archive") { + s.Archive = archive.NewListArchive(s.Posts) + s.Archive.Site = *s + sort.Sort(sort.Reverse(s.Archive.Posts)) + } + if render.TmplExists("rss") { + s.Rss = archive.NewRssArchive(s.Posts) + s.Rss.Site = *s + } + if render.TmplExists("paged") { + s.Paged = archive.CreatePaged(15, s.Posts) + } + if render.TmplExists("home") { + s.Home = archive.NewListArchive(s.Posts) + s.Home.Tgt = path.Join(config.Config.HtmlDir, "index.html") + s.Home.Template = "home" + s.Home.Site = s + } +} + +/* +ReadPosts reads all files from the Config.TxtDir, parses them and stores in s.Posts +*/ +func (s *Site) ReadPosts() { + // TODO: filter this as needed + files, err := ioutil.ReadDir(config.Config.TxtDir) + if err != nil { + log.Fatal(err) + } + + for _, file := range files { + p := post.NewPost(s) + p.Read(file) + + // Ignore post-dated posts unless overriden in config + if !config.Config.ShowFuture && p.InFuture { + log.Printf("Skipping future dated post: %s\n", p.SourceFile) + } else { + s.Posts = append(s.Posts, p) + } + } + + // Sort the posts by date, earliest first + sort.Sort(s.Posts) + + // Add next/previous to each post. + // An allocated but empty post is set at start/end + // This prevents templates from failing at start/end if nil checks are not made properly + for i, p := range s.Posts { + if i > 0 { + p.Prev = s.Posts[i-1] + } else { + p.Prev = new(post.Post) + } + if i+1 < len(s.Posts) { + p.Next = s.Posts[i+1] + } else { + p.Next = new(post.Post) + } + } +} + +/* +Write writes posts and archives to the filesystem +*/ +func (s *Site) Write() { + s.WritePosts() + s.WriteArchives() +} + +func (s *Site) WriteArchives() { + if render.TmplExists("archive") { + render.Write(s.Archive) + } + if render.TmplExists("rss") { + render.Write(s.Rss) + } + if render.TmplExists("home") { + render.Write(s.Home) + } + if render.TmplExists("paged") { + for _, p := range *s.Paged { + p.Site = s + render.Write(p) + } + } +} + +func (s *Site) WritePosts() { + for _, p := range s.Posts { + render.Write(p) + } +} + +func (s Site) GetTitle() string { + return s.Title +} + +func (s Site) GetURL() string { + return s.URL +} |