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:
parent
1d9dfa5e78
commit
d6bab69738
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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 }
|
||||
|
@ -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) }
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
26
site/site.go
26
site/site.go
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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})
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user