diff options
Diffstat (limited to 'local')
| -rw-r--r-- | local/index.go | 69 | ||||
| -rw-r--r-- | local/page.go | 139 | ||||
| -rw-r--r-- | local/pagelist.go | 22 | ||||
| -rw-r--r-- | local/time.go | 21 |
4 files changed, 251 insertions, 0 deletions
diff --git a/local/index.go b/local/index.go new file mode 100644 index 0000000..a90276e --- /dev/null +++ b/local/index.go @@ -0,0 +1,69 @@ +package local + +import ( + "fmt" + "os" + "path/filepath" + "strings" + "time" +) + +var pageIndex map[string]PageList + +func (p *Page) RebuildIndex() error { + pageIndex = nil + _, err := p.Index() + return err +} + +// Index returns a map of all pages below the current Page's Path seperated +// into their respective tags If a Page has multiple tags it will be listed +// under each +func (p *Page) Index() (map[string]PageList, error) { + if pageIndex != nil { + return pageIndex, nil + } + fmt.Fprintln(os.Stderr, "Rebuilding index...") + + out := make(map[string]PageList) + + var pageErr error + + filepath.Walk(filepath.Dir(p.Path), + func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + if !info.IsDir() && strings.HasSuffix(info.Name(), ".md") { + + p2 := &Page{Path: strings.ReplaceAll(path, ".md", "")} + err = p2.Read() + + if err != nil { + pageErr = err + fmt.Fprintln(os.Stderr, "Error encountered: ", err) + return err + } + + for tag, _ := range p2.Tags { + if _, ok := out[tag]; !ok { + out[tag] = []*Page{p2} + } else { + out[tag] = append(out[tag], p2) + } + } + + } + + return nil + }) + + pageIndex = out + + return out, nil +} + +func (p *Page) Time() time.Time { + return p.Date.Time +} diff --git a/local/page.go b/local/page.go new file mode 100644 index 0000000..f514b4a --- /dev/null +++ b/local/page.go @@ -0,0 +1,139 @@ +package local + +import ( + "bufio" + "bytes" + "fmt" + "io" + "os" + "text/template" + + "github.com/russross/blackfriday" + "gopkg.in/yaml.v3" +) + +type Page struct { + Path string + Title string + Head string + Description string + Tags map[string]interface{} + Date *PageTime + Published bool + Vars map[string]interface{} + Markdown []byte +} + +// Can be adjusted to change the base template used in rendering +var BaseTemplate = "inc/base.html" + +// Used to split the .md files into yaml and markdown +var DocumentSplit = "|---\n" + +// Allow for the creation of a new page from the page +func (p Page) NewPage(pth string) *Page { + return &Page{Path: pth} +} + +// Renders a page +func (p *Page) Render(wr io.Writer) error { + if err := p.Read(); err != nil { + return err + } + + t, err := template.ParseFiles(BaseTemplate) + if err != nil { + return err + } + + // Automatically pull from the yml file if applicable + if p.Head != "" { + t, err = t.Parse(` + {{define "head"}} + {{.RenderHead}} + {{end}} + `) + if err != nil { + return err + } + } + + return t.Execute(wr, p) +} + +func (p *Page) RenderHead() (string, error) { + buf := &bytes.Buffer{} + t, err := template.New("Head").Parse(p.Head) + if err != nil { + return "", err + } + err = t.Execute(buf, p) + if err != nil { + return "", err + } + return string(buf.Bytes()), nil +} + +// Reads in the special markdown file format for the website off of the disk +func (p *Page) Read() error { + yamlBuf := bytes.NewBuffer(nil) + markdownBuf := bytes.NewBuffer(nil) + + fh, err := os.Open(p.Path + ".md") + if err != nil { + return err + } + defer fh.Close() + rdr := bufio.NewReader(fh) + + // Read in the file and split between markdown and yaml buffers + yamlDone := false + for { + + bytes, err := rdr.ReadBytes('\n') + if err == io.EOF { + break + } else if err != nil { + return err + } + + // Is this the line where we stop reading the yaml and start reading markdown? + if DocumentSplit == string(bytes) && !yamlDone { + yamlDone = true + continue + } + + if !yamlDone { + yamlBuf.Write(bytes) + } else { + markdownBuf.Write(bytes) + } + } + + err = yaml.Unmarshal(yamlBuf.Bytes(), p) + if err != nil { + return err + } + + p.Markdown = markdownBuf.Bytes() + return nil +} + +func (p *Page) RenderBody() (string, error) { + buf := &bytes.Buffer{} + t, err := template.New("Body").Parse(string(p.Markdown)) + if err != nil { + return "", err + } + + err = t.Execute(buf, p) + if err != nil { + return "", err + } + + return string(blackfriday.Run(buf.Bytes())), nil +} + +func (p Page) String() string { + return fmt.Sprintf("Page: %s", p.Path) +} diff --git a/local/pagelist.go b/local/pagelist.go new file mode 100644 index 0000000..75106f1 --- /dev/null +++ b/local/pagelist.go @@ -0,0 +1,22 @@ +package local + +import ( + "sort" + // "git.riedstra.dev/mitch/go-website/page" +) + +type PageList []*Page + +func (p PageList) SortDate() PageList { + sort.Slice(p, func(i, j int) bool { + return p[i].Time().After(p[j].Time()) + }) + return p +} + +func (p PageList) SortDateReverse() PageList { + sort.Slice(p, func(i, j int) bool { + return p[i].Time().Before(p[j].Time()) + }) + return p +} diff --git a/local/time.go b/local/time.go new file mode 100644 index 0000000..72ff3c6 --- /dev/null +++ b/local/time.go @@ -0,0 +1,21 @@ +package local + +import ( + "gopkg.in/yaml.v3" + "time" +) + +type PageTime struct { + time.Time +} + +var TimeFormat = "01.02.2006 15:04:05 MST" + +func (pt *PageTime) UnmarshalYAML(n *yaml.Node) error { + t, err := time.Parse(TimeFormat, n.Value) + if err != nil { + return err + } + pt.Time = t + return nil +} |
