From 908fc1d89778bb91c16caca72a41e92c546a646c Mon Sep 17 00:00:00 2001 From: Oliver Steele Date: Mon, 10 Jul 2017 13:23:51 -0400 Subject: [PATCH] remove page.RenderContext --- collection/collection.go | 6 ++++-- collection/collection_test.go | 7 ++++--- collection/read.go | 2 +- frontmatter/read.go | 4 ++-- pages/drops.go | 28 ++++++++++++++++------------ pages/drops_test.go | 2 +- pages/file.go | 15 ++++++++------- pages/file_test.go | 32 +++++++++++++++++++++++--------- pages/interfaces.go | 16 ++++------------ pages/page.go | 20 ++++++++++---------- pages/page_test.go | 28 ++++++---------------------- pages/permalinks.go | 2 +- pages/permalinks_test.go | 10 +++++----- pages/static_file.go | 3 +-- plugins/feed.go | 3 +-- plugins/redirect_from.go | 2 +- site/drop.go | 2 +- site/read.go | 2 +- site/write.go | 2 +- 19 files changed, 91 insertions(+), 95 deletions(-) diff --git a/collection/collection.go b/collection/collection.go index e228e81..6b9c078 100644 --- a/collection/collection.go +++ b/collection/collection.go @@ -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 } diff --git a/collection/collection_test.go b/collection/collection_test.go index 147084f..b97db98 100644 --- a/collection/collection_test.go +++ b/collection/collection_test.go @@ -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()} diff --git a/collection/read.go b/collection/read.go index 1265107..a1166ae 100644 --- a/collection/read.go +++ b/collection/read.go @@ -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 diff --git a/frontmatter/read.go b/frontmatter/read.go index b817ad1..3d06b7a 100644 --- a/frontmatter/read.go +++ b/frontmatter/read.go @@ -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 diff --git a/pages/drops.go b/pages/drops.go index 67f3628..86b85ba 100644 --- a/pages/drops.go +++ b/pages/drops.go @@ -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) { diff --git a/pages/drops_test.go b/pages/drops_test.go index c294817..f8dc6bb 100644 --- a/pages/drops_test.go +++ b/pages/drops_test.go @@ -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"] diff --git a/pages/file.go b/pages/file.go index 2b1728a..84e56fd 100644 --- a/pages/file.go +++ b/pages/file.go @@ -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) diff --git a/pages/file_test.go b/pages/file_test.go index d143ab4..ac19e4a 100644 --- a/pages/file_test.go +++ b/pages/file_test.go @@ -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()) } diff --git a/pages/interfaces.go b/pages/interfaces.go index 7aca4fa..673e563 100644 --- a/pages/interfaces.go +++ b/pages/interfaces.go @@ -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 } diff --git a/pages/page.go b/pages/page.go index 90e71c5..b75638f 100644 --- a/pages/page.go +++ b/pages/page.go @@ -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 } diff --git a/pages/page_test.go b/pages/page_test.go index 4cc2d56..131bbf6 100644 --- a/pages/page_test.go +++ b/pages/page_test.go @@ -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)) } diff --git a/pages/permalinks.go b/pages/permalinks.go index 77e1c02..f106862 100644 --- a/pages/permalinks.go +++ b/pages/permalinks.go @@ -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 diff --git a/pages/permalinks_test.go b/pages/permalinks_test.go index 9bcec51..85f72ad 100644 --- a/pages/permalinks_test.go +++ b/pages/permalinks_test.go @@ -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) diff --git a/pages/static_file.go b/pages/static_file.go index d7bac17..5669206 100644 --- a/pages/static_file.go +++ b/pages/static_file.go @@ -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 diff --git a/plugins/feed.go b/plugins/feed.go index 4322801..571291f 100644 --- a/plugins/feed.go +++ b/plugins/feed.go @@ -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 } diff --git a/plugins/redirect_from.go b/plugins/redirect_from.go index 509b48d..28c447e 100644 --- a/plugins/redirect_from.go +++ b/plugins/redirect_from.go @@ -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) } diff --git a/site/drop.go b/site/drop.go index 45b15e5..9608c0c 100644 --- a/site/drop.go +++ b/site/drop.go @@ -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 } } diff --git a/site/read.go b/site/read.go index 0f966cc..fcb9b1c 100644 --- a/site/read.go +++ b/site/read.go @@ -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) } diff --git a/site/write.go b/site/write.go index fe33c69..6aef719 100644 --- a/site/write.go +++ b/site/write.go @@ -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()