diff options
Diffstat (limited to 'local/page.go')
| -rw-r--r-- | local/page.go | 139 |
1 files changed, 139 insertions, 0 deletions
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) +} |
