1
0
mirror of https://github.com/danog/gojekyll.git synced 2024-11-27 09:44:41 +01:00
gojekyll/page.go

140 lines
3.4 KiB
Go

package gojekyll
import (
"fmt"
"io"
"io/ioutil"
"os"
"path"
"path/filepath"
"reflect"
"regexp"
"time"
"github.com/osteele/gojekyll/helpers"
)
var (
frontMatterMatcher = regexp.MustCompile(`(?s)^---\n(.+?\n)---\n`)
emptyFontMatterMatcher = regexp.MustCompile(`(?s)^---\n+---\n`)
)
// Page is a Jekyll page.
type Page interface {
Path() string
Site() *Site
Source() string
Static() bool
Published() bool
Permalink() string
TemplateObject() VariableMap
Write(io.Writer) error
DebugVariables() VariableMap
initPermalink() error
}
type pageFields struct {
relpath string // relative to site source, e.g. "_post/base.ext"
permalink string // cached permalink
modTime time.Time
frontMatter VariableMap // page front matter, merged with defaults
collection *Collection
site *Site
}
func (p *pageFields) String() string {
return fmt.Sprintf("%s{Path=%v, Permalink=%v}", reflect.TypeOf(p).Name(), p.relpath, p.permalink)
}
func (p *pageFields) Path() string { return p.relpath }
func (p *pageFields) Permalink() string { return p.permalink }
func (p *pageFields) Published() bool { return p.frontMatter.Bool("published", true) }
func (p *pageFields) Site() *Site { return p.site }
// ReadPage reads a Page from a file, using defaults as the default front matter.
func ReadPage(site *Site, collection *Collection, relpath string, defaults VariableMap) (p Page, err error) {
abspath := filepath.Join(site.Source, relpath)
magic, err := helpers.ReadFileMagic(abspath)
if err != nil {
return
}
info, err := os.Stat(abspath)
if err != nil {
return
}
fields := pageFields{
site: site,
collection: collection,
modTime: info.ModTime(),
relpath: relpath,
frontMatter: defaults,
}
if string(magic) == "---\n" {
p, err = NewDynamicPage(fields)
if err != nil {
return
}
} else {
p = &StaticPage{fields}
}
// Compute this after creating the page, in order to pick up the front matter.
err = p.initPermalink()
if err != nil {
return
}
return
}
func (p *StaticPage) Write(w io.Writer) error {
source, err := ioutil.ReadFile(p.Source())
if err != nil {
return err
}
_, err = w.Write(source)
return err
}
// TemplateObject returns the attributes of the template page object.
// See https://jekyllrb.com/docs/variables/#page-variables
func (p *pageFields) TemplateObject() VariableMap {
var (
relpath = "/" + filepath.ToSlash(p.relpath)
base = path.Base(relpath)
ext = path.Ext(relpath)
)
return VariableMap{
"path": relpath,
"modified_time": p.modTime,
"name": base,
"basename": helpers.PathWithoutExtension(base),
"extname": ext,
}
}
// DebugVariables returns a map that's useful to present during diagnostics.
// For a static page, this is just the page's template object attributes.
func (p *pageFields) DebugVariables() VariableMap {
return p.TemplateObject()
}
// Source returns the file path of the page source.
func (p *pageFields) Source() string {
return filepath.Join(p.site.Source, p.relpath)
}
// StaticPage is a static page.
type StaticPage struct {
pageFields
}
// Static returns a bool indicating that the page is a static page.
func (p *StaticPage) Static() bool { return true }
// TemplateObject returns metadata for use in the representation of the page as a collection item
func (p *StaticPage) TemplateObject() VariableMap {
return MergeVariableMaps(p.frontMatter, p.pageFields.TemplateObject())
}