mirror of
https://github.com/danog/gojekyll.git
synced 2024-11-30 04:09:00 +01:00
Implement include_relative
This commit is contained in:
parent
197f6b0572
commit
956ca7bc3f
10
README.md
10
README.md
@ -45,7 +45,6 @@ gojekyll help build
|
||||
- themes, page tags, excerpts, plugins (except for a few listed below), pagination, math, warning mode.
|
||||
- Site variables: `pages`, `static_files`, `html_pages`, `html_files`, `documents`, and `tags`
|
||||
- Jekyll filters: `group_by_exp`, `pop`, `shift`, `cgi_escape`, `uri_escape`, `scssify`, and `smartify`.
|
||||
- Jekyll's `include_relative` tag
|
||||
- The Go Liquid engine is also missing some tags and a few filters. See its [README](https://github.com/osteele/gojekyll/#status) for status.
|
||||
- Data files must be YAML. CSV and JSON data files are not supported.
|
||||
- `{% highlight %}` uses Pygments. There's no way to tell it to use Rouge. Also, I don't know what will happen if Pygments isn't installed.
|
||||
@ -104,12 +103,11 @@ The cache is for calls to Pygments (via the `highlight` tag). For another site,
|
||||
- [ ] Jekyll filters
|
||||
- [ ] `group_by_exp` `pop` `shift` `cgi_escape` `uri_escape` `scssify` `smartify`
|
||||
- [x] everything else
|
||||
- [ ] Jekyll tags
|
||||
- [x] Jekyll tags
|
||||
- [x] `include`
|
||||
- [ ] `include_relative`
|
||||
- [x] `include_relative`
|
||||
- [x] `link`
|
||||
- [x] `post_url`
|
||||
- [ ] `gist`
|
||||
- [x] `highlight`
|
||||
- [x] Includes
|
||||
- [x] `include` parameters
|
||||
@ -130,7 +128,7 @@ The cache is for calls to Pygments (via the `highlight` tag). For another site,
|
||||
- [x] `build`
|
||||
- [x] `--source`, `--destination`, `--drafts`, `--future`, `--unpublished`
|
||||
- [ ] `--config`, `--baseurl`, `--lsi`, `--watch`, etc.
|
||||
- [ ] won't implement: `--force-polling`, `--limit-posts`, `--incremental`, `JEKYLL_ENV=production`
|
||||
- [ ] not planned: `--force-polling`, `--limit-posts`, `--incremental`, `JEKYLL_ENV=production`
|
||||
- [x] `clean`
|
||||
- [ ] `doctor`
|
||||
- [x] `help`
|
||||
@ -140,7 +138,7 @@ The cache is for calls to Pygments (via the `highlight` tag). For another site,
|
||||
- [x] `serve`
|
||||
- [x] `--open-uri`
|
||||
- [ ] `--detach`, `--host`, `--port`, `--baseurl`
|
||||
- [ ] won't implement: `--incremental`, `--ssl-*`
|
||||
- [ ] not planned: `--incremental`, `--ssl`-*
|
||||
- [ ] Windows
|
||||
|
||||
## Contributing
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
|
||||
"github.com/osteele/gojekyll/config"
|
||||
"github.com/osteele/liquid"
|
||||
"github.com/osteele/liquid/expressions"
|
||||
"github.com/osteele/liquid/expression"
|
||||
"github.com/osteele/liquid/generics"
|
||||
"github.com/russross/blackfriday"
|
||||
)
|
||||
@ -214,7 +214,7 @@ func sortFilter(array []interface{}, key interface{}, nilFirst interface{}) []in
|
||||
return out
|
||||
}
|
||||
|
||||
func whereExpFilter(array []interface{}, name string, expr expressions.Closure) ([]interface{}, error) {
|
||||
func whereExpFilter(array []interface{}, name string, expr expression.Closure) ([]interface{}, error) {
|
||||
rt := reflect.ValueOf(array)
|
||||
if rt.Kind() != reflect.Array && rt.Kind() != reflect.Slice {
|
||||
return nil, nil
|
||||
|
@ -78,8 +78,8 @@ func (p *page) Write(rc RenderingContext, w io.Writer) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
layout := templates.VariableMap(p.frontMatter).String("layout", "")
|
||||
if layout != "" {
|
||||
layout, ok := p.frontMatter["layout"].(string)
|
||||
if ok && layout != "" {
|
||||
b, err = rp.ApplyLayout(layout, b, p.TemplateContext(rc))
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -41,7 +41,12 @@ func (p *Pipeline) FindLayout(base string, fm *map[string]interface{}) (t liquid
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return p.liquidEngine.ParseTemplate(content)
|
||||
t, err = p.liquidEngine.ParseTemplate(content)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t.SetSourcePath(filename)
|
||||
return
|
||||
}
|
||||
|
||||
// LayoutsDir returns the path to the layouts directory.
|
||||
|
@ -73,8 +73,13 @@ func (p *Pipeline) Render(w io.Writer, b []byte, filename string, e map[string]i
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (p *Pipeline) renderTemplate(tpl []byte, b map[string]interface{}, filename string) ([]byte, error) {
|
||||
out, err := p.liquidEngine.ParseAndRender(tpl, b)
|
||||
func (p *Pipeline) renderTemplate(src []byte, b map[string]interface{}, filename string) ([]byte, error) {
|
||||
tpl, err := p.liquidEngine.ParseTemplate(src)
|
||||
if err != nil {
|
||||
return nil, helpers.PathError(err, "Liquid Error", filename)
|
||||
}
|
||||
tpl.SetSourcePath(filename)
|
||||
out, err := tpl.Render(b)
|
||||
if err != nil {
|
||||
return nil, helpers.PathError(err, "Liquid Error", filename)
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/osteele/gojekyll/tags"
|
||||
"github.com/osteele/liquid/chunks"
|
||||
"github.com/osteele/liquid/render"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -17,7 +17,7 @@ func init() {
|
||||
|
||||
const avatarTemplate = `<img class="avatar avatar-small" src="https://avatars3.githubusercontent.com/{user}?v=3&s=40" alt="{user}" srcset="https://avatars3.githubusercontent.com/{user}?v=3&s=40 1x, https://avatars3.githubusercontent.com/{user}?v=3&s=80 2x, https://avatars3.githubusercontent.com/{user}?v=3&s=120 3x, https://avatars3.githubusercontent.com/{user}?v=3&s=160 4x" width="40" height="40" data-proofer-ignore="true" />`
|
||||
|
||||
func avatarTag(ctx chunks.RenderContext) (string, error) {
|
||||
func avatarTag(ctx render.Context) (string, error) {
|
||||
var (
|
||||
user string
|
||||
size interface{} = 40
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/osteele/gojekyll/tags"
|
||||
"github.com/osteele/liquid/chunks"
|
||||
"github.com/osteele/liquid/render"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -14,7 +14,7 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
func gistTag(ctx chunks.RenderContext) (string, error) {
|
||||
func gistTag(ctx render.Context) (string, error) {
|
||||
argsline, err := ctx.ParseTagArgs()
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/osteele/liquid"
|
||||
"github.com/osteele/liquid/chunks"
|
||||
"github.com/osteele/liquid/render"
|
||||
)
|
||||
|
||||
// PluginContext is the context for plugin initialization.
|
||||
@ -22,7 +22,7 @@ type PluginContext interface {
|
||||
func Install(name string, ctx PluginContext) bool {
|
||||
p, found := plugins[name]
|
||||
if p != nil {
|
||||
if err := p(ctx, pluginHelper{name, ctx}); err != nil {
|
||||
if err := p(ctx, pluginHelper{ctx, name}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
@ -56,8 +56,8 @@ func init() {
|
||||
}
|
||||
|
||||
type pluginHelper struct {
|
||||
PluginContext
|
||||
name string
|
||||
ctx PluginContext
|
||||
}
|
||||
|
||||
func (h pluginHelper) stubbed() {
|
||||
@ -65,12 +65,12 @@ func (h pluginHelper) stubbed() {
|
||||
}
|
||||
|
||||
func (h pluginHelper) tag(name string, r liquid.Renderer) {
|
||||
h.ctx.TemplateEngine().RegisterTag(name, r)
|
||||
h.TemplateEngine().RegisterTag(name, r)
|
||||
}
|
||||
|
||||
func (h pluginHelper) makeUnimplementedTag() liquid.Renderer {
|
||||
warned := false
|
||||
return func(ctx chunks.RenderContext) (string, error) {
|
||||
return func(ctx render.Context) (string, error) {
|
||||
if !warned {
|
||||
fmt.Printf("The %q tag in the %q plugin has not been implemented.\n", ctx.TagName(), h.name)
|
||||
warned = true
|
||||
|
@ -46,13 +46,11 @@ func (s *Site) Clean(options BuildOptions) error {
|
||||
// Build cleans the destination and create files in it.
|
||||
// It attends to the global options.dry_run.
|
||||
func (s *Site) Build(options BuildOptions) (int, error) {
|
||||
count := 0
|
||||
if err := s.prepareRendering(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if err := s.Clean(options); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
n, err := s.WritePages(options)
|
||||
return count + n, err
|
||||
return s.WritePages(options)
|
||||
}
|
||||
|
@ -33,11 +33,8 @@ func (s *Site) WriteDocument(p pages.Document, w io.Writer) error {
|
||||
|
||||
// WritePages writes output files.
|
||||
// It attends to options.dry_run.
|
||||
func (s *Site) WritePages(options BuildOptions) (int, error) {
|
||||
count := 0
|
||||
var err error
|
||||
func (s *Site) WritePages(options BuildOptions) (count int, err error) {
|
||||
errs := make(chan error)
|
||||
|
||||
for _, p := range s.OutputPages() {
|
||||
count++
|
||||
go func(p pages.Document) {
|
||||
@ -46,6 +43,7 @@ func (s *Site) WritePages(options BuildOptions) (int, error) {
|
||||
}
|
||||
for i := 0; i < count; i++ {
|
||||
// might as well report the last error as the first
|
||||
// TODO return an aggregate
|
||||
if e := <-errs; e != nil {
|
||||
err = e
|
||||
}
|
||||
|
@ -7,10 +7,10 @@ import (
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/osteele/liquid/chunks"
|
||||
"github.com/osteele/liquid/render"
|
||||
)
|
||||
|
||||
func highlightTag(ctx chunks.RenderContext) (string, error) {
|
||||
func highlightTag(ctx render.Context) (string, error) {
|
||||
args, err := ctx.ParseTagArgs()
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -2,12 +2,23 @@ package tags
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/osteele/liquid/chunks"
|
||||
"github.com/osteele/liquid/render"
|
||||
)
|
||||
|
||||
func (tc tagContext) includeTag(ctx chunks.RenderContext) (string, error) {
|
||||
func (tc tagContext) includeTag(ctx render.Context) (string, error) {
|
||||
return includeFromDir(ctx, filepath.Join(tc.config.Source, tc.config.IncludesDir))
|
||||
}
|
||||
|
||||
func (tc tagContext) includeRelativeTag(ctx render.Context) (string, error) {
|
||||
fmt.Println("include relative", ctx.SourceFile())
|
||||
// TODO Note that you cannot use the ../ syntax
|
||||
return includeFromDir(ctx, path.Dir(ctx.SourceFile()))
|
||||
}
|
||||
|
||||
func includeFromDir(ctx render.Context, dirname string) (string, error) {
|
||||
argsline, err := ctx.ParseTagArgs()
|
||||
if err != nil {
|
||||
return "", err
|
||||
@ -23,8 +34,6 @@ func (tc tagContext) includeTag(ctx chunks.RenderContext) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
filename := filepath.Join(tc.config.Source, tc.config.IncludesDir, args.Args[0])
|
||||
ctx2 := ctx.Clone()
|
||||
ctx2.UpdateBindings(map[string]interface{}{"include": include})
|
||||
return ctx2.RenderFile(filename)
|
||||
filename := filepath.Join(dirname, args.Args[0])
|
||||
return ctx.RenderFile(filename, map[string]interface{}{"include": include})
|
||||
}
|
||||
|
46
tags/include_test.go
Normal file
46
tags/include_test.go
Normal file
@ -0,0 +1,46 @@
|
||||
package tags
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/osteele/gojekyll/config"
|
||||
"github.com/osteele/liquid"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
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")
|
||||
if s == "_posts/2017-07-04-test.md" {
|
||||
return "post.html", true
|
||||
}
|
||||
return "", false
|
||||
})
|
||||
bindings := map[string]interface{}{}
|
||||
|
||||
s, err := engine.ParseAndRenderString(`{% include include_target.html %}`, bindings)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "include target", strings.TrimSpace(s))
|
||||
|
||||
// TODO {% include {{ page.my_variable }} %}
|
||||
// TODO {% include note.html content="This is my sample note." %}
|
||||
}
|
||||
|
||||
func TestIncludeRelativeTag(t *testing.T) {
|
||||
engine := liquid.NewEngine()
|
||||
cfg := config.Default()
|
||||
AddJekyllTags(engine, cfg, func(s string) (string, bool) { return "", false })
|
||||
bindings := map[string]interface{}{}
|
||||
|
||||
tpl, err := engine.ParseTemplate([]byte(`{% include_relative subdir/include_relative.html %}`))
|
||||
require.NoError(t, err)
|
||||
tpl.SetSourcePath("testdata/dir/include_relative_source.md")
|
||||
s, err := tpl.Render(bindings)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "include_relative target", strings.TrimSpace(string(s)))
|
||||
}
|
@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/osteele/liquid/chunks"
|
||||
"github.com/osteele/liquid/render"
|
||||
)
|
||||
|
||||
// TODO string escapes
|
||||
@ -52,7 +52,7 @@ func ParseArgs(argsline string) (*ParsedArgs, error) {
|
||||
}
|
||||
|
||||
// EvalOptions evaluates unquoted options.
|
||||
func (r *ParsedArgs) EvalOptions(ctx chunks.RenderContext) (map[string]interface{}, error) {
|
||||
func (r *ParsedArgs) EvalOptions(ctx render.Context) (map[string]interface{}, error) {
|
||||
options := map[string]interface{}{}
|
||||
for k, v := range r.Options {
|
||||
if v.quoted {
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
|
||||
"github.com/osteele/gojekyll/config"
|
||||
"github.com/osteele/liquid"
|
||||
"github.com/osteele/liquid/chunks"
|
||||
"github.com/osteele/liquid/render"
|
||||
)
|
||||
|
||||
// A LinkTagHandler given an include tag file name returns a URL.
|
||||
@ -17,6 +17,7 @@ func AddJekyllTags(e liquid.Engine, c config.Config, lh LinkTagHandler) {
|
||||
tc := tagContext{c, lh}
|
||||
e.RegisterBlock("highlight", highlightTag)
|
||||
e.RegisterTag("include", tc.includeTag)
|
||||
e.RegisterTag("include_relative", tc.includeRelativeTag)
|
||||
e.RegisterTag("link", tc.linkTag)
|
||||
e.RegisterTag("post_url", tc.postURLTag)
|
||||
}
|
||||
@ -31,7 +32,7 @@ type tagContext struct {
|
||||
// time it's rendered, and otherwise does nothing.
|
||||
func CreateUnimplementedTag() liquid.Renderer {
|
||||
warned := false
|
||||
return func(ctx chunks.RenderContext) (string, error) {
|
||||
return func(ctx render.Context) (string, error) {
|
||||
if !warned {
|
||||
fmt.Printf("The %q tag has not been implemented. It is being ignored.\n", ctx.TagName())
|
||||
warned = true
|
||||
@ -40,7 +41,7 @@ func CreateUnimplementedTag() liquid.Renderer {
|
||||
}
|
||||
}
|
||||
|
||||
func (tc tagContext) linkTag(ctx chunks.RenderContext) (string, error) {
|
||||
func (tc tagContext) linkTag(ctx render.Context) (string, error) {
|
||||
filename := ctx.TagArgs()
|
||||
url, found := tc.lh(filename)
|
||||
if !found {
|
||||
@ -49,7 +50,7 @@ func (tc tagContext) linkTag(ctx chunks.RenderContext) (string, error) {
|
||||
return url, nil
|
||||
}
|
||||
|
||||
func (tc tagContext) postURLTag(ctx chunks.RenderContext) (string, error) {
|
||||
func (tc tagContext) postURLTag(ctx render.Context) (string, error) {
|
||||
var (
|
||||
filename = ctx.TagArgs()
|
||||
found = false
|
||||
|
1
tags/testdata/_includes/include_target.html
vendored
Normal file
1
tags/testdata/_includes/include_target.html
vendored
Normal file
@ -0,0 +1 @@
|
||||
include target
|
1
tags/testdata/dir/subdir/include_relative.html
vendored
Normal file
1
tags/testdata/dir/subdir/include_relative.html
vendored
Normal file
@ -0,0 +1 @@
|
||||
include_relative target
|
Loading…
Reference in New Issue
Block a user