1
0
mirror of https://github.com/danog/gojekyll.git synced 2024-11-27 01:14:40 +01:00

Switch to osteele/liquid

This commit is contained in:
Oliver Steele 2017-06-27 22:59:53 -04:00
parent 9ae0eae4c1
commit 60ac92497e
4 changed files with 53 additions and 78 deletions

View File

@ -29,11 +29,12 @@ This project is missing more functionality than it implements. It may accidental
- [ ] Sass caching
- [ ] Customization
- [x] Templates
- [x] link tag
- [x] include tag
- [x] `link` tag
- [ ] Remaining Jekyll Liquid tags
- [ ] Jekyll Liquid filters
- [x] Includes
- [ ] parameters
- [ ] `include_relative`
- [x] Permalinks
- [ ] Pagination
- [ ] Themes
@ -55,16 +56,6 @@ Intentional differences from Jekyll:
go get -u osteele/gojekyll/cmd/gojekyll
```
You get slightly better Liquid template parsing from some unmerged pull requests to the **acstech/liquid** library. If you want to use [my fork](https://github.com/osteele/liquid) instead:
```bash
cd $(go env GOPATH)/src/github.com/acstech/liquid
git remote add osteele https://github.com/osteele/liquid.git
git pull -f osteele
```
(See articles by [Shlomi Noach](http://code.openark.org/blog/development/forking-golang-repositories-on-github-and-managing-the-import-path) and [Francesc Campoy](http://blog.campoy.cat/2014/03/github-and-go-forking-pull-requests-and.html) for how this works and why it is necessary.)
## Usage
```bash
@ -74,23 +65,6 @@ gojekyll help
gojekyll help build
```
### Liquid Template Server
The embedded Liquid server isn't very compliant with Shopfiy Liquid syntax.
You can run a "Liquid Template Server" on the same machine, and tell `gojekyll` to use this instead.
This is currently about 10x slower than using the embedded engine, but still 5x faster than Ruby `jekyll`.
1. Download and run (liquid-template-server)[https://github.com/osteele/liquid-template-server].
2. Invoke `gojekyll` with the `--use-liquid-server` option; e.g.:
```bash
gojekyll --use-liquid-server build
gojekyll --use-liquid-server serve
```
Neither the embedded Liquid server nor the Liquid Template Server implements very many Jekyll Liquid filters or tags. I'm adding to these as necessary to support my own sites.
## Contributing
Install package dependencies and development tools:
@ -121,8 +95,6 @@ go tool pprof gojekyll gojekyll.prof
## Credits
For rendering Liquid templates: ACS Technologies's fork [acstech/liquid](https://github.com/acstech/liquid) of Karl Seguin's [karlseguin/liquid](https://github.com/karlseguin/liquid) Go implementation; or, Jun Yang's JavaScript implementation [harttle/shopify-liquid](https://github.com/harttle/shopify-liquid/) via JSON-RPC.
Jascha Ephraim's [jaschaephraim/lrserver](https://github.com/jaschaephraim/lrserver) Live Reload server.
<https://github.com/pkg/browser> to open the URL in a browser.

View File

@ -19,6 +19,17 @@ func init() {
core.RegisterFilter("where_exp", whereExpFactory)
}
func AddStandardFilters(e *LocalWrapperEngine) {
e.engine.DefineFilter("date_to_rfc822", func(date time.Time) interface{} {
return date.Format(time.RFC822)
// Out: Mon, 07 Nov 2008 13:07:54 -0800
})
e.engine.DefineFilter("date_to_string", func(date time.Time) interface{} {
return date.Format("02 Jan 2005")
// Out: 07 Nov 2008
})
}
func arrayToSentenceStringFactory(parameters []core.Value) core.Filter {
conj := "and "
if len(parameters) > 0 {

View File

@ -25,7 +25,7 @@ var filterTestScope = map[string]interface{}{
}
func timeMustParse(s string) time.Time {
t, err := time.Parse(time.RFC3339, "2006-01-02T15:04:05Z")
t, err := time.Parse(time.RFC3339, s)
if err != nil {
panic(err)
}

View File

@ -1,74 +1,66 @@
package liquid
import (
"bytes"
"fmt"
"io"
"strings"
"github.com/acstech/liquid"
"github.com/acstech/liquid/core"
"github.com/osteele/liquid"
"github.com/osteele/liquid/chunks"
)
// LocalWrapperEngine is a wrapper around acstech/liquid.
// LocalWrapperEngine is a wrapper around osteele/liquid.
type LocalWrapperEngine struct {
config *core.Configuration
linkHandler LinkTagHandler
}
type localTemplate struct {
engine *LocalWrapperEngine
lt *liquid.Template
engine liquid.Engine
linkHandler LinkTagHandler
includeTagHandler IncludeTagHandler
}
// NewLocalWrapperEngine creates a LocalEngine.
func NewLocalWrapperEngine() LocalEngine {
return &LocalWrapperEngine{}
e := &LocalWrapperEngine{engine: liquid.NewEngine()}
AddStandardFilters(e)
e.engine.DefineTag("link", func(filename string) (func(io.Writer, chunks.Context) error, error) {
return func(w io.Writer, _ chunks.Context) error {
url, found := e.linkHandler(filename)
if !found {
return fmt.Errorf("missing link filename: %s", filename)
}
_, err := w.Write([]byte(url))
return err
}, nil
})
e.engine.DefineTag("include", func(filename string) (func(io.Writer, chunks.Context) error, error) {
return func(w io.Writer, ctx chunks.Context) error {
return e.includeTagHandler(filename, w, ctx.GetVariableMap())
}, nil
})
return e
}
// LinkTagHandler sets the link tag handler.
func (engine *LocalWrapperEngine) LinkTagHandler(h LinkTagHandler) {
engine.linkHandler = h
func (e *LocalWrapperEngine) LinkTagHandler(h LinkTagHandler) {
e.linkHandler = h
}
// IncludeHandler sets the include tag handler.
func (engine *LocalWrapperEngine) IncludeHandler(h IncludeTagHandler) {
engine.config = liquid.Configure().IncludeHandler(func(name string, w io.Writer, context map[string]interface{}) {
name = strings.TrimLeft(strings.TrimRight(name, "}}"), "{{")
err := h(name, w, context)
if err != nil {
panic(err)
}
})
func (e *LocalWrapperEngine) IncludeHandler(h IncludeTagHandler) {
e.includeTagHandler = h
}
// Parse is a wrapper for liquid.Parse.
func (engine *LocalWrapperEngine) Parse(text []byte) (Template, error) {
template, err := liquid.Parse(text, engine.config)
return &localTemplate{engine, template}, err
func (e *LocalWrapperEngine) Parse(source []byte) (Template, error) {
// fmt.Println("parse", string(source))
t, err := e.engine.ParseTemplate(source)
// return &localTemplate{t}, err
return t, err
}
// ParseAndRender parses and then renders the template.
func (engine *LocalWrapperEngine) ParseAndRender(text []byte, scope map[string]interface{}) ([]byte, error) {
template, err := engine.Parse(text)
func (e *LocalWrapperEngine) ParseAndRender(source []byte, scope map[string]interface{}) ([]byte, error) {
t, err := e.Parse(source)
if err != nil {
return nil, err
}
return template.Render(scope)
}
// Render is a wrapper around liquid's template.Render that turns panics into errors.
func (template *localTemplate) Render(scope map[string]interface{}) (out []byte, err error) {
defer func() {
if r := recover(); r != nil {
if e, ok := r.(error); ok {
err = e
} else {
panic(r)
}
}
}()
SetLinkHandler(template.engine.linkHandler)
writer := new(bytes.Buffer)
template.lt.Render(writer, scope)
return writer.Bytes(), nil
// fmt.Println("render", t)
return t.Render(scope)
}