pagr

A 'static site generator', built using dati.
Log | Files | Refs | Atom

page.go (3686B)


      1 package main
      2 
      3 import (
      4 	"bytes"
      5 	"io/ioutil"
      6 	"os"
      7 	"path/filepath"
      8 	"strings"
      9 	"time"
     10 
     11 	"notabug.org/gearsix/suti"
     12 )
     13 
     14 const timefmt = "2006-01-02"
     15 
     16 func titleFromPath(path string) (title string) {
     17 	if title = filepath.Base(path); title == "/" {
     18 		title = "Home"
     19 	}
     20 	title = strings.TrimSuffix(title, filepath.Ext(title))
     21 	title = strings.ReplaceAll(title, "-", " ")
     22 	title = strings.Title(title)
     23 	return
     24 }
     25 
     26 func pagePath(root, path string) string {
     27 	path = strings.TrimPrefix(path, root)
     28 	if len(path) == 0 {
     29 		path = "/"
     30 	} else {
     31 		path = filepath.ToSlash(strings.TrimSuffix(path, filepath.Ext(path)))
     32 	}
     33 	return path
     34 }
     35 
     36 // Page is the data structure loaded from Content files/folders that
     37 // gets passed to templates for execution after Content has been loaded.
     38 // This is the data structure to reference when writing a template!
     39 type Page struct {
     40 	Slug     string
     41 	Path     string
     42 	Nav      Nav
     43 	Meta     Meta
     44 	Contents []Content
     45 	Assets   Assets
     46 	Updated  string
     47 }
     48 
     49 type Assets struct {
     50 	All   []string
     51 	Audio []*string
     52 	Image []*string
     53 	Video []*string
     54 	Misc  []*string
     55 }
     56 
     57 // Nav is a struct that provides a set of pointers for navigating a
     58 // across a set of pages. All values are initialised to nil and will only
     59 // be populated manually or by calling `BuildSitemap`.
     60 type Nav struct {
     61 	All      []*Page
     62 	Root     *Page
     63 	Parent   *Page
     64 	Children []*Page
     65 	Crumbs   []*Page
     66 }
     67 
     68 // Meta is the structure any metadata is parsed into (_.toml_, _.json_, etc)
     69 type Meta map[string]interface{}
     70 
     71 // MergeMeta merges `meta` into `m`. When there are matching keys in both,
     72 // `overwrite` determines whether the existing value in `m` is overwritten.
     73 func (m Meta) MergeMeta(meta Meta, overwrite bool) {
     74 	for k, v := range meta {
     75 		if _, ok := m[k]; ok && overwrite {
     76 			m[k] = v
     77 		} else if !ok {
     78 			m[k] = v
     79 		}
     80 	}
     81 }
     82 
     83 // NewPage returns a Page with init values. `.Path` will be set to `path`.
     84 // Updated is set to time.Now(). Any other values will simply be initialised.
     85 func NewPage(path string, updated time.Time) Page {
     86 	return Page{
     87 		Slug:     filepath.Base(path),
     88 		Path:     path,
     89 		Nav:      Nav{},
     90 		Meta:     Meta{"Title": titleFromPath(path)},
     91 		Contents: make([]Content, 0),
     92 		Assets:   Assets{},
     93 		Updated:  updated.Format(timefmt),
     94 	}
     95 }
     96 
     97 // GetTemplate will check if `p.Meta` has the key `template` or `Template`
     98 // (in the order) and return the value of the first existing key as a string.
     99 // If `.Meta` neither has the key `template` or `Template`, then it will
    100 // return `DefaultTemplateName` from [./template.go].
    101 func (p *Page) TemplateName(defaultName string) string {
    102 	if v, ok := p.Meta["template"]; ok {
    103 		return v.(string)
    104 	} else if v, ok = p.Meta["Template"]; ok {
    105 		return v.(string)
    106 	} else {
    107 		return defaultName
    108 	}
    109 }
    110 
    111 // Build will run `t.Execute(p)` and write the result to
    112 // `outDir/p.Path/index.html`.
    113 func (p *Page) Build(outDir string, t suti.Template) (out string, err error) {
    114 	var buf bytes.Buffer
    115 	if buf, err = t.Execute(p); err == nil {
    116 		out = filepath.Join(outDir, p.Path, "index.html")
    117 		if err = os.MkdirAll(filepath.Dir(out), 0755); err == nil {
    118 			err = ioutil.WriteFile(out, buf.Bytes(), 0644)
    119 		}
    120 	}
    121 	return out, err
    122 }
    123 
    124 // call `NewContentFromFile` and append it to `p.Contents`
    125 func (p *Page) NewContentFromFile(fpath string) (err error) {
    126 	var c Content
    127 	if c, err = NewContentFromFile(fpath); err == nil {
    128 		p.Contents = append(p.Contents, c)
    129 	}
    130 	return
    131 }
    132 
    133 func (page *Page) applyDefaults(defaultMetas map[string]Meta) {
    134 	for i, p := range page.Path {
    135 		if p != '/' {
    136 			continue
    137 		}
    138 		path := page.Path[:i]
    139 		if len(path) == 0 {
    140 			path = "/"
    141 		}
    142 		if meta, ok := defaultMetas[path]; ok {
    143 			page.Meta.MergeMeta(meta, false)
    144 		}
    145 	}
    146 }