1
0
mirror of https://github.com/danog/gojekyll.git synced 2024-11-30 08:39:01 +01:00

include tag looks in $theme/_includes

This commit is contained in:
Oliver Steele 2017-07-24 09:32:57 -04:00
parent 1d9dfa5e78
commit d6bab69738
14 changed files with 60 additions and 36 deletions

View File

@ -14,8 +14,6 @@ Gojekyll is a partially-compatible clone of the [Jekyll](https://jekyllrb.com) s
| Runs on Windows | | ✓ | ✓ |
| Implementation language | Go | Ruby | Go |
<!-- TOC -->
- [Gojekyll](#gojekyll)
@ -140,7 +138,7 @@ Muzukashii:
- [x] Permalinks
- [ ] Pagination
- [ ] Plugins partial; see [here](./docs/plugins.md)
- [ ] Themes
- [x] Themes
- [x] Layouts
- [x] Server
- [x] Directory watch

View File

@ -23,6 +23,7 @@ type Collection struct {
type Site interface {
Config() *config.Config
Exclude(string) bool
RelativePath(string) string
RenderingPipeline() pipelines.PipelineInterface
OutputExt(pathname string) string
}

View File

@ -8,15 +8,16 @@ import (
"github.com/stretchr/testify/require"
)
type siteMock struct{ c config.Config }
type siteFake struct{ c config.Config }
func (c siteMock) Config() *config.Config { return &c.c }
func (c siteMock) Exclude(string) bool { return false }
func (c siteMock) OutputExt(s string) string { return "" }
func (c siteMock) RenderingPipeline() pipelines.PipelineInterface { panic("unimplemented") }
func (s siteFake) Config() *config.Config { return &s.c }
func (s siteFake) Exclude(string) bool { return false }
func (s siteFake) OutputExt(string) string { return "" }
func (s siteFake) RelativePath(string) string { panic("unimplemented") }
func (s siteFake) RenderingPipeline() pipelines.PipelineInterface { panic("unimplemented") }
func TestNewCollection(t *testing.T) {
site := siteMock{config.Default()}
site := siteFake{config.Default()}
c1 := New(site, "c", map[string]interface{}{"output": true})
require.Equal(t, true, c1.Output())
@ -27,7 +28,7 @@ func TestNewCollection(t *testing.T) {
}
func TestPermalinkPattern(t *testing.T) {
site := siteMock{config.Default()}
site := siteFake{config.Default()}
c1 := New(site, "c", map[string]interface{}{})
require.Contains(t, c1.PermalinkPattern(), ":collection")
@ -40,17 +41,17 @@ func TestPermalinkPattern(t *testing.T) {
}
func TestReadPosts(t *testing.T) {
site := siteMock{config.FromString("source: testdata")}
site := siteFake{config.FromString("source: testdata")}
c := New(site, "posts", map[string]interface{}{})
require.NoError(t, c.ReadPages())
require.Len(t, c.Pages(), 1)
site = siteMock{config.FromString("source: testdata\nunpublished: true")}
site = siteFake{config.FromString("source: testdata\nunpublished: true")}
c = New(site, "posts", map[string]interface{}{})
require.NoError(t, c.ReadPages())
require.Len(t, c.Pages(), 2)
site = siteMock{config.FromString("source: testdata\nfuture: true")}
site = siteFake{config.FromString("source: testdata\nfuture: true")}
c = New(site, "posts", map[string]interface{}{})
require.NoError(t, c.ReadPages())
require.Len(t, c.Pages(), 2)

View File

@ -70,7 +70,7 @@ func (p *page) ToLiquid() interface{} {
"tags": p.Tags(),
// TODO Only present in collection pages https://jekyllrb.com/docs/collections/#documents
"relative_path": p.Path(),
"relative_path": filepath.ToSlash(p.site.RelativePath(p.filename)),
// TODO collection(name)
// TODO undocumented; only present in collection pages:

View File

@ -7,7 +7,6 @@ import (
"github.com/osteele/gojekyll/frontmatter"
"github.com/osteele/gojekyll/templates"
"github.com/osteele/gojekyll/utils"
)
// file is embedded in StaticFile and page
@ -26,7 +25,6 @@ func (f *file) String() string {
}
func (f *file) OutputExt() string { return f.outputExt }
func (f *file) Path() string { return utils.MustRel(f.site.Config().Source, f.filename) }
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.filename }

View File

@ -16,6 +16,7 @@ type siteFake struct {
}
func (s siteFake) Config() *config.Config { return &s.cfg }
func (s siteFake) RelativePath(p string) string { return p }
func (s siteFake) RenderingPipeline() pipelines.PipelineInterface { return &pipelineFake{s.t} }
func (s siteFake) OutputExt(p string) string { return filepath.Ext(p) }

View File

@ -23,6 +23,7 @@ type Document interface {
// Site is the interface that the site provides to a page.
type Site interface {
Config() *config.Config
RelativePath(string) string
RenderingPipeline() pipelines.PipelineInterface
OutputExt(pathname string) string
}

View File

@ -3,6 +3,7 @@ package pipelines
import (
"bytes"
"io"
"path/filepath"
"github.com/osteele/gojekyll/config"
"github.com/osteele/gojekyll/filters"
@ -91,8 +92,12 @@ func (p *Pipeline) renderTemplate(src []byte, b map[string]interface{}, filename
}
func (p *Pipeline) makeLiquidEngine() *liquid.Engine {
dirs := []string{filepath.Join(p.cfg.Source, p.cfg.IncludesDir)}
if p.ThemeDir != "" {
dirs = append(dirs, filepath.Join(p.ThemeDir, "_includes"))
}
engine := liquid.NewEngine()
filters.AddJekyllFilters(engine, &p.cfg)
tags.AddJekyllTags(engine, &p.cfg, p.RelativeFilenameToURL)
tags.AddJekyllTags(engine, &p.cfg, dirs, p.RelativeFilenameToURL)
return engine
}

View File

@ -131,8 +131,12 @@ func (s *Site) KeepFile(filename string) bool {
func (s *Site) FilePathPage(rel string) (pages.Document, bool) {
// This looks wasteful. If it shows up as a hotspot, you know what to do.
for _, p := range s.Routes {
if p.SourcePath() != "" && rel == utils.MustRel(s.SourceDir(), p.SourcePath()) {
return p, true
if p.SourcePath() != "" {
if r, err := filepath.Rel(s.SourceDir(), p.SourcePath()); err == nil {
if r == rel {
return p, true
}
}
}
}
return nil, false
@ -163,7 +167,7 @@ func (s *Site) TemplateEngine() *liquid.Engine {
func (s *Site) initializeRenderingPipeline() (err error) {
options := pipelines.PipelineOptions{
RelativeFilenameToURL: s.FilenameURLPath,
ThemeDir: s.themeDir,
ThemeDir: s.themeDir,
}
s.pipeline, err = pipelines.NewPipeline(s.config, options)
if err != nil {
@ -175,9 +179,19 @@ func (s *Site) initializeRenderingPipeline() (err error) {
})
}
// RelativePath is in the page.Container interface.
func (s *Site) RelativePath(path string) string {
if s.themeDir != "" {
if rel, err := filepath.Rel(s.themeDir, path); err == nil {
return rel
}
}
return utils.MustRel(s.config.Source, path)
}
// OutputExt is in the page.Container interface.
func (s *Site) OutputExt(pathname string) string {
return s.config.OutputExt(pathname)
func (s *Site) OutputExt(path string) string {
return s.config.OutputExt(path)
}
// URLPage returns the page that will be served at URL
@ -192,7 +206,7 @@ func (s *Site) URLPage(urlpath string) (p pages.Document, found bool) {
return
}
// Exclude returns a boolean indicating that the site excludes a file.
// Exclude returns a boolean indicating that the site excludes a file or directory.
func (s *Site) Exclude(path string) bool {
base := filepath.Base(path)
switch {

View File

@ -28,7 +28,7 @@ func TestHighlightTag(t *testing.T) {
cache.Disable()
engine := liquid.NewEngine()
cfg := config.Default()
AddJekyllTags(engine, &cfg, func(string) (string, bool) { return "", false })
AddJekyllTags(engine, &cfg, []string{}, func(string) (string, bool) { return "", false })
for i, test := range highlightTagTests {
t.Run(fmt.Sprintf("%d", i+1), func(t *testing.T) {

View File

@ -8,16 +8,22 @@ import (
"github.com/osteele/liquid/render"
)
func (tc tagContext) includeTag(rc render.Context) (string, error) {
return includeFromDir(rc, filepath.Join(tc.cfg.Source, tc.cfg.IncludesDir))
func (tc tagContext) includeTag(rc render.Context) (s string, err error) {
for _, dir := range tc.includeDirs {
s, err = includeFromDir(dir, rc)
if err == nil {
return
}
}
return
}
func (tc tagContext) includeRelativeTag(rc render.Context) (string, error) {
// TODO "Note that you cannot use the ../ syntax"
return includeFromDir(rc, path.Dir(rc.SourceFile()))
return includeFromDir(path.Dir(rc.SourceFile()), rc)
}
func includeFromDir(rc render.Context, dirname string) (string, error) {
func includeFromDir(dir string, rc render.Context) (string, error) {
argsline, err := rc.ExpandTagArg()
if err != nil {
return "", err
@ -33,6 +39,6 @@ func includeFromDir(rc render.Context, dirname string) (string, error) {
if err != nil {
return "", err
}
filename := filepath.Join(dirname, args.Args[0])
filename := filepath.Join(dir, args.Args[0])
return rc.RenderFile(filename, map[string]interface{}{"include": include})
}

View File

@ -1,7 +1,6 @@
package tags
import (
"fmt"
"strings"
"testing"
@ -14,8 +13,7 @@ func TestIncludeTag(t *testing.T) {
engine := liquid.NewEngine()
cfg := config.Default()
cfg.Source = "testdata"
AddJekyllTags(engine, &cfg, func(s string) (string, bool) {
fmt.Println("ok")
AddJekyllTags(engine, &cfg, []string{"testdata/_includes"}, func(s string) (string, bool) {
if s == "_posts/2017-07-04-test.md" {
return "post.html", true
}
@ -34,7 +32,7 @@ func TestIncludeTag(t *testing.T) {
func TestIncludeRelativeTag(t *testing.T) {
engine := liquid.NewEngine()
cfg := config.Default()
AddJekyllTags(engine, &cfg, func(s string) (string, bool) { return "", false })
AddJekyllTags(engine, &cfg, []string{}, func(s string) (string, bool) { return "", false })
bindings := map[string]interface{}{}
path := "testdata/dir/include_relative_source.md"

View File

@ -13,8 +13,8 @@ import (
type LinkTagHandler func(string) (string, bool)
// AddJekyllTags adds the Jekyll tags to the Liquid engine.
func AddJekyllTags(e *liquid.Engine, c *config.Config, lh LinkTagHandler) {
tc := tagContext{c, lh}
func AddJekyllTags(e *liquid.Engine, c *config.Config, includeDirs []string, lh LinkTagHandler) {
tc := tagContext{c, includeDirs, lh}
e.RegisterBlock("highlight", highlightTag)
e.RegisterTag("include", tc.includeTag)
e.RegisterTag("include_relative", tc.includeRelativeTag)
@ -25,6 +25,7 @@ func AddJekyllTags(e *liquid.Engine, c *config.Config, lh LinkTagHandler) {
// tagContext provides the context to a tag renderer.
type tagContext struct {
cfg *config.Config
includeDirs []string
lh LinkTagHandler
}

View File

@ -11,7 +11,7 @@ import (
func TestTags(t *testing.T) {
engine := liquid.NewEngine()
cfg := config.Default()
AddJekyllTags(engine, &cfg, func(s string) (string, bool) {
AddJekyllTags(engine, &cfg, []string{}, func(s string) (string, bool) {
if s == "_posts/2017-07-04-test.md" {
return "post.html", true
}