mirror of
https://github.com/danog/gojekyll.git
synced 2024-11-30 08:08:59 +01:00
remove page.RenderContext
This commit is contained in:
parent
c6f33c91c3
commit
908fc1d897
@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/osteele/gojekyll/config"
|
||||
"github.com/osteele/gojekyll/pages"
|
||||
"github.com/osteele/gojekyll/pipelines"
|
||||
"github.com/osteele/gojekyll/templates"
|
||||
)
|
||||
|
||||
@ -21,6 +22,7 @@ type Collection struct {
|
||||
// Site is the interface a site provides to collections it contains.
|
||||
type Site interface {
|
||||
Config() *config.Config
|
||||
RenderingPipeline() pipelines.PipelineInterface
|
||||
OutputExt(pathname string) string
|
||||
}
|
||||
|
||||
@ -65,9 +67,9 @@ func (c *Collection) Pages() []pages.Page {
|
||||
}
|
||||
|
||||
// SetPageContent sets up the collection's pages' "content".
|
||||
func (c *Collection) SetPageContent(ctx pages.RenderingContext) error {
|
||||
func (c *Collection) SetPageContent() error {
|
||||
for _, p := range c.Pages() {
|
||||
_, err := p.Content(ctx)
|
||||
_, err := p.Content()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -4,14 +4,15 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/osteele/gojekyll/config"
|
||||
"github.com/osteele/gojekyll/pipelines"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type siteMock struct{ c config.Config }
|
||||
|
||||
func (c siteMock) Config() *config.Config { return &c.c }
|
||||
func (c siteMock) OutputExt(s string) string { return "" }
|
||||
func (c siteMock) Site() interface{} { return c }
|
||||
func (c siteMock) Config() *config.Config { return &c.c }
|
||||
func (c siteMock) OutputExt(s string) string { return "" }
|
||||
func (c siteMock) RenderingPipeline() pipelines.PipelineInterface { panic("unimplemented") }
|
||||
|
||||
func TestNewCollection(t *testing.T) {
|
||||
site := siteMock{config.Default()}
|
||||
|
@ -69,7 +69,7 @@ func (c *Collection) readFile(abs string, rel string, fm map[string]interface{})
|
||||
default:
|
||||
strategy.addDate(rel, fm)
|
||||
}
|
||||
f, err := pages.NewFile(abs, c, filepath.ToSlash(rel), fm)
|
||||
f, err := pages.NewFile(c.site, abs, filepath.ToSlash(rel), fm)
|
||||
switch {
|
||||
case err != nil:
|
||||
return err
|
||||
|
@ -10,8 +10,8 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
frontMatterMatcher = regexp.MustCompile(`(?s)^---\n(.+?\n)---\n`)
|
||||
emptyFontMatterMatcher = regexp.MustCompile(`(?s)^---\n+---\n`)
|
||||
frontMatterMatcher = regexp.MustCompile(`(?s)^---\n(.+?\n)---\n+`)
|
||||
emptyFontMatterMatcher = regexp.MustCompile(`(?s)^---\n+---\n+`)
|
||||
)
|
||||
|
||||
// Read reads the frontmatter from a document. It modifies srcPtr to point to the
|
||||
|
@ -43,24 +43,13 @@ func (p *page) ToLiquid() interface{} {
|
||||
root = utils.TrimExt(p.relpath)
|
||||
base = filepath.Base(root)
|
||||
content = p.raw
|
||||
excerpt string
|
||||
)
|
||||
if p.content != nil {
|
||||
content = *p.content
|
||||
}
|
||||
content = bytes.TrimSpace(content)
|
||||
if ei, ok := p.frontMatter["excerpt"]; ok {
|
||||
excerpt = fmt.Sprint(ei)
|
||||
} else {
|
||||
pos := bytes.Index(content, []byte(p.container.Config().ExcerptSeparator))
|
||||
if pos < 0 {
|
||||
pos = len(content)
|
||||
}
|
||||
excerpt = string(content[:pos])
|
||||
}
|
||||
data := map[string]interface{}{
|
||||
"content": string(content),
|
||||
"excerpt": excerpt,
|
||||
"excerpt": p.excerpt(),
|
||||
"path": relpath,
|
||||
"url": p.Permalink(),
|
||||
// TODO output
|
||||
@ -101,6 +90,21 @@ func (p *page) ToLiquid() interface{} {
|
||||
return data
|
||||
}
|
||||
|
||||
func (p *page) excerpt() string {
|
||||
if ei, ok := p.frontMatter["excerpt"]; ok {
|
||||
return fmt.Sprint(ei)
|
||||
}
|
||||
content := p.raw
|
||||
if p.content != nil {
|
||||
content = *p.content
|
||||
}
|
||||
pos := bytes.Index(content, []byte(p.site.Config().ExcerptSeparator))
|
||||
if pos >= 0 {
|
||||
return string(content[:pos])
|
||||
}
|
||||
return string(content)
|
||||
}
|
||||
|
||||
// MarshalYAML is part of the yaml.Marshaler interface
|
||||
// The variables subcommand uses this.
|
||||
func (f *file) MarshalYAML() (interface{}, error) {
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
|
||||
func TestPage_ToLiquid(t *testing.T) {
|
||||
cfg := config.Default()
|
||||
page, err := NewFile("testdata/excerpt.md", containerFake{cfg, ""}, "excerpt.md", map[string]interface{}{})
|
||||
page, err := NewFile(siteFake{t, cfg}, "testdata/excerpt.md", "excerpt.md", map[string]interface{}{})
|
||||
require.NoError(t, err)
|
||||
drop := page.(liquid.Drop).ToLiquid()
|
||||
excerpt := drop.(map[string]interface{})["excerpt"]
|
||||
|
@ -3,7 +3,6 @@ package pages
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/osteele/gojekyll/frontmatter"
|
||||
@ -12,7 +11,7 @@ import (
|
||||
|
||||
// file is embedded in StaticFile and page
|
||||
type file struct {
|
||||
container Container
|
||||
site Site
|
||||
filename string // target os filepath
|
||||
relpath string // slash-separated path relative to site or container source
|
||||
outputExt string
|
||||
@ -22,7 +21,7 @@ type file struct {
|
||||
}
|
||||
|
||||
func (f *file) String() string {
|
||||
return fmt.Sprintf("%s{Path=%v, Permalink=%v}", reflect.TypeOf(f).Name(), f.relpath, f.permalink)
|
||||
return fmt.Sprintf("%T{Path=%v, Permalink=%v}", f.relpath, f.permalink)
|
||||
}
|
||||
|
||||
func (f *file) OutputExt() string { return f.outputExt }
|
||||
@ -31,8 +30,10 @@ func (f *file) Permalink() string { return f.permalink }
|
||||
func (f *file) Published() bool { return templates.VariableMap(f.frontMatter).Bool("published", true) }
|
||||
func (f *file) SourcePath() string { return f.relpath }
|
||||
|
||||
// NewFile creates a Post or StaticFile.
|
||||
func NewFile(filename string, c Container, relpath string, defaults map[string]interface{}) (Document, error) {
|
||||
// NewFile creates a Page or StaticFile.
|
||||
//
|
||||
// filename is the absolute filename. relpath is the path relative to the site or collection directory.
|
||||
func NewFile(s Site, filename string, relpath string, defaults map[string]interface{}) (Document, error) {
|
||||
fm, err := frontmatter.FileHasFrontMatter(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -43,12 +44,12 @@ func NewFile(filename string, c Container, relpath string, defaults map[string]i
|
||||
}
|
||||
|
||||
fields := file{
|
||||
container: c,
|
||||
site: s,
|
||||
filename: filename,
|
||||
frontMatter: defaults,
|
||||
fileModTime: info.ModTime(),
|
||||
relpath: relpath,
|
||||
outputExt: c.OutputExt(relpath),
|
||||
outputExt: s.OutputExt(relpath),
|
||||
}
|
||||
if fm {
|
||||
return makePage(filename, fields)
|
||||
|
@ -1,25 +1,39 @@
|
||||
package pages
|
||||
|
||||
import (
|
||||
"io"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/osteele/gojekyll/config"
|
||||
"github.com/osteele/gojekyll/pipelines"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type containerFake struct {
|
||||
cfg config.Config
|
||||
prefix string
|
||||
type siteFake struct {
|
||||
t *testing.T
|
||||
cfg config.Config
|
||||
}
|
||||
|
||||
func (c containerFake) Config() *config.Config { return &c.cfg }
|
||||
func (c containerFake) PathPrefix() string { return c.prefix }
|
||||
func (c containerFake) OutputExt(p string) string { return filepath.Ext(p) }
|
||||
func (s siteFake) Config() *config.Config { return &s.cfg }
|
||||
func (s siteFake) RenderingPipeline() pipelines.PipelineInterface { return &pipelineFake{s.t} }
|
||||
func (s siteFake) OutputExt(p string) string { return filepath.Ext(p) }
|
||||
|
||||
func TestPageCategories(t *testing.T) {
|
||||
c := containerFake{config.Default(), ""}
|
||||
type pipelineFake struct{ t *testing.T }
|
||||
|
||||
func (p pipelineFake) OutputExt(string) string { return ".html" }
|
||||
func (p pipelineFake) ApplyLayout(layout string, src []byte, vars map[string]interface{}) ([]byte, error) {
|
||||
require.Equal(p.t, "layout1", layout)
|
||||
return nil, nil
|
||||
}
|
||||
func (p pipelineFake) Render(w io.Writer, src []byte, filename string, lineNo int, vars map[string]interface{}) ([]byte, error) {
|
||||
require.Equal(p.t, "testdata/page_with_layout.md", filename)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func TestFile_Categories(t *testing.T) {
|
||||
s := siteFake{t, config.Default()}
|
||||
fm := map[string]interface{}{"categories": "b a"}
|
||||
f := file{container: c, frontMatter: fm}
|
||||
f := file{site: s, frontMatter: fm}
|
||||
require.Equal(t, []string{"a", "b"}, f.Categories())
|
||||
}
|
||||
|
@ -17,23 +17,15 @@ type Document interface {
|
||||
// Output
|
||||
Published() bool
|
||||
Static() bool
|
||||
Write(io.Writer, RenderingContext) error
|
||||
Write(io.Writer) error
|
||||
|
||||
Categories() []string
|
||||
Tags() []string
|
||||
}
|
||||
|
||||
// RenderingContext provides context information for rendering.
|
||||
type RenderingContext interface {
|
||||
RenderingPipeline() pipelines.PipelineInterface
|
||||
// Site is the value of the "site" template variable.
|
||||
Site() interface{} // used as a drop in the rendering context
|
||||
}
|
||||
|
||||
// Container is the document container.
|
||||
// It's either the Site or Collection that immediately contains the document.
|
||||
type Container interface {
|
||||
// Site is the interface that the site provides to a page.
|
||||
type Site interface {
|
||||
Config() *config.Config
|
||||
RenderingPipeline() pipelines.PipelineInterface
|
||||
OutputExt(pathname string) string
|
||||
PathPrefix() string // PathPrefix is the relative prefix, "" for the site and "_coll/" for a collection
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ type Page interface {
|
||||
Document
|
||||
// Content asks a page to compute its content.
|
||||
// This has the side effect of causing the content to subsequently appear in the drop.
|
||||
Content(rc RenderingContext) ([]byte, error)
|
||||
Content() ([]byte, error)
|
||||
SetContent(content []byte)
|
||||
FrontMatter() map[string]interface{}
|
||||
// PostDate returns the date computed from the filename or frontmatter.
|
||||
@ -59,10 +59,10 @@ func makePage(filename string, f file) (*page, error) {
|
||||
}
|
||||
|
||||
// TemplateContext returns the local variables for template evaluation
|
||||
func (p *page) TemplateContext(rc RenderingContext) map[string]interface{} {
|
||||
func (p *page) TemplateContext() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"page": p,
|
||||
"site": rc.Site(),
|
||||
"site": p.site,
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,15 +87,15 @@ func (p *page) PostDate() time.Time {
|
||||
}
|
||||
|
||||
// Write applies Liquid and Markdown, as appropriate.
|
||||
func (p *page) Write(w io.Writer, rc RenderingContext) error {
|
||||
content, err := p.Content(rc)
|
||||
func (p *page) Write(w io.Writer) error {
|
||||
content, err := p.Content()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
layout, ok := p.frontMatter["layout"].(string)
|
||||
if ok && layout != "" {
|
||||
rp := rc.RenderingPipeline()
|
||||
content, err = rp.ApplyLayout(layout, content, p.TemplateContext(rc))
|
||||
rp := p.site.RenderingPipeline()
|
||||
content, err = rp.ApplyLayout(layout, content, p.TemplateContext())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -105,13 +105,13 @@ func (p *page) Write(w io.Writer, rc RenderingContext) error {
|
||||
}
|
||||
|
||||
// Content computes the page content.
|
||||
func (p *page) Content(rc RenderingContext) ([]byte, error) {
|
||||
func (p *page) Content() ([]byte, error) {
|
||||
if p.content != nil {
|
||||
return *p.content, nil
|
||||
}
|
||||
rp := rc.RenderingPipeline()
|
||||
pipe := p.site.RenderingPipeline()
|
||||
buf := new(bytes.Buffer)
|
||||
b, err := rp.Render(buf, p.raw, p.filename, p.firstLine, p.TemplateContext(rc))
|
||||
b, err := pipe.Render(buf, p.raw, p.filename, p.firstLine, p.TemplateContext())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -2,38 +2,22 @@ package pages
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/osteele/gojekyll/config"
|
||||
"github.com/osteele/gojekyll/pipelines"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type renderingContextFake struct {
|
||||
t *testing.T
|
||||
cfg config.Config
|
||||
}
|
||||
|
||||
func (c renderingContextFake) RenderingPipeline() pipelines.PipelineInterface { return c }
|
||||
func (c renderingContextFake) Config() config.Config { return c.cfg }
|
||||
func (c renderingContextFake) PathPrefix() string { return "." }
|
||||
func (c renderingContextFake) OutputExt(string) string { return ".html" }
|
||||
func (c renderingContextFake) Site() interface{} { return nil }
|
||||
func (c renderingContextFake) ApplyLayout(layout string, src []byte, vars map[string]interface{}) ([]byte, error) {
|
||||
require.Equal(c.t, "layout1", layout)
|
||||
return nil, nil
|
||||
}
|
||||
func (c renderingContextFake) Render(w io.Writer, src []byte, filename string, lineNo int, vars map[string]interface{}) ([]byte, error) {
|
||||
require.Equal(c.t, "testdata/page_with_layout.md", filename)
|
||||
return nil, nil
|
||||
}
|
||||
// func (c pipelineFake) RenderingPipeline() pipelines.PipelineInterface { return c }
|
||||
// func (c pipelineFake) Config() config.Config { return c.cfg }
|
||||
// func (c pipelineFake) PathPrefix() string { return "." }
|
||||
// func (c pipelineFake) Site() interface{} { return nil }
|
||||
|
||||
func TestPageWrite(t *testing.T) {
|
||||
cfg := config.Default()
|
||||
p, err := NewFile("testdata/page_with_layout.md", containerFake{cfg, ""}, "page_with_layout.md", map[string]interface{}{})
|
||||
p, err := NewFile(siteFake{t, cfg}, "testdata/page_with_layout.md", "page_with_layout.md", map[string]interface{}{})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, p)
|
||||
buf := new(bytes.Buffer)
|
||||
require.NoError(t, p.Write(buf, renderingContextFake{t, cfg}))
|
||||
require.NoError(t, p.Write(buf))
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ var templateVariableMatcher = regexp.MustCompile(`:\w+\b`)
|
||||
// See https://jekyllrb.com/docs/permalinks/#template-variables
|
||||
func (f *file) permalinkVariables() map[string]string {
|
||||
var (
|
||||
relpath = strings.TrimPrefix(f.relpath, f.container.PathPrefix())
|
||||
relpath = f.relpath
|
||||
root = utils.TrimExt(relpath)
|
||||
name = filepath.Base(root)
|
||||
fm = f.frontMatter
|
||||
|
@ -30,13 +30,13 @@ var tests = []pathTest{
|
||||
}
|
||||
|
||||
var collectionTests = []pathTest{
|
||||
{"_c/a/b/c.d", "/prefix/:collection/post", "/prefix/c/post"},
|
||||
{"_c/a/b/c.d", "/prefix:path/post", "/prefix/a/b/c/post"},
|
||||
{"/a/b/c.d", "/prefix/:collection/post", "/prefix/c/post"},
|
||||
{"/a/b/c.d", "/prefix:path/post", "/prefix/a/b/c/post"},
|
||||
}
|
||||
|
||||
func TestExpandPermalinkPattern(t *testing.T) {
|
||||
var (
|
||||
c = containerFake{config.Default(), ""}
|
||||
s = siteFake{t, config.Default()}
|
||||
d = map[string]interface{}{
|
||||
"categories": "b a",
|
||||
}
|
||||
@ -49,7 +49,7 @@ func TestExpandPermalinkPattern(t *testing.T) {
|
||||
case ".md", ".markdown":
|
||||
ext = ".html"
|
||||
}
|
||||
p := file{container: c, relpath: path, frontMatter: fm, outputExt: ext}
|
||||
p := file{site: s, relpath: path, frontMatter: fm, outputExt: ext}
|
||||
t0, err := time.Parse(time.RFC3339, "2006-02-03T15:04:05Z")
|
||||
require.NoError(t, err)
|
||||
p.fileModTime = t0
|
||||
@ -68,7 +68,7 @@ func TestExpandPermalinkPattern(t *testing.T) {
|
||||
|
||||
runTests(tests)
|
||||
|
||||
c = containerFake{config.Default(), "_c/"}
|
||||
s = siteFake{t, config.Default()}
|
||||
d["collection"] = "c"
|
||||
runTests(collectionTests)
|
||||
|
||||
|
@ -13,8 +13,7 @@ type StaticFile struct {
|
||||
// Static is in the File interface.
|
||||
func (p *StaticFile) Static() bool { return true }
|
||||
|
||||
// Write returns a bool indicating that the page is a static page.
|
||||
func (p *StaticFile) Write(w io.Writer, _ RenderingContext) error {
|
||||
func (p *StaticFile) Write(w io.Writer) error {
|
||||
in, err := os.Open(p.filename)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"html"
|
||||
"io"
|
||||
|
||||
"github.com/osteele/gojekyll/pages"
|
||||
"github.com/osteele/liquid"
|
||||
"github.com/osteele/liquid/render"
|
||||
)
|
||||
@ -79,7 +78,7 @@ func (d *feedDoc) Content() []byte {
|
||||
return b
|
||||
}
|
||||
|
||||
func (d *feedDoc) Write(w io.Writer, c pages.RenderingContext) error {
|
||||
func (d *feedDoc) Write(w io.Writer) error {
|
||||
_, err := w.Write(d.Content())
|
||||
return err
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ func (d *redirectionDoc) Content() []byte {
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func (d *redirectionDoc) Write(w io.Writer, c pages.RenderingContext) error {
|
||||
func (d *redirectionDoc) Write(w io.Writer) error {
|
||||
return redirectTemplate.Execute(w, d)
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ func (s *Site) initializeDrop() {
|
||||
|
||||
func (s *Site) setPageContent() error {
|
||||
for _, c := range s.Collections {
|
||||
if err := c.SetPageContent(s); err != nil {
|
||||
if err := c.SetPageContent(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ func (s *Site) readFiles() error {
|
||||
return nil
|
||||
}
|
||||
defaultFrontmatter := s.config.GetFrontMatterDefaults("", relname)
|
||||
p, err := pages.NewFile(filename, s, filepath.ToSlash(relname), defaultFrontmatter)
|
||||
p, err := pages.NewFile(s, filename, filepath.ToSlash(relname), defaultFrontmatter)
|
||||
if err != nil {
|
||||
return utils.PathError(err, "read", filename)
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ func (s *Site) WriteDocument(w io.Writer, p pages.Document) error {
|
||||
return err
|
||||
}
|
||||
buf := new(bytes.Buffer)
|
||||
if err := p.Write(buf, s); err != nil {
|
||||
if err := p.Write(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
c := buf.Bytes()
|
||||
|
Loading…
Reference in New Issue
Block a user