mirror of
https://github.com/facundoolano/jorge.git
synced 2025-01-13 20:03:26 +01:00
port liquid filters from gojekyll
This commit is contained in:
parent
bacc9d9052
commit
b788826423
3 changed files with 143 additions and 3 deletions
2
go.mod
2
go.mod
|
@ -6,12 +6,12 @@ require (
|
||||||
github.com/fsnotify/fsnotify v1.7.0
|
github.com/fsnotify/fsnotify v1.7.0
|
||||||
github.com/niklasfasching/go-org v1.7.0
|
github.com/niklasfasching/go-org v1.7.0
|
||||||
github.com/osteele/liquid v1.3.2
|
github.com/osteele/liquid v1.3.2
|
||||||
|
github.com/yuin/goldmark v1.7.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/osteele/tuesday v1.0.3 // indirect
|
github.com/osteele/tuesday v1.0.3 // indirect
|
||||||
github.com/yuin/goldmark v1.7.0 // indirect
|
|
||||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect
|
golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect
|
||||||
golang.org/x/sys v0.4.0 // indirect
|
golang.org/x/sys v0.4.0 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
|
123
templates/filters.go
Normal file
123
templates/filters.go
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
package templates
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/osteele/liquid/evaluator"
|
||||||
|
"github.com/osteele/liquid/expressions"
|
||||||
|
)
|
||||||
|
|
||||||
|
// copied from https://github.com/osteele/gojekyll/blob/main/filters/filters.go
|
||||||
|
|
||||||
|
func filter(values []map[string]interface{}, key string) []interface{} {
|
||||||
|
var result []interface{}
|
||||||
|
for _, value := range values {
|
||||||
|
if _, ok := value[key]; ok {
|
||||||
|
result = append(result, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func groupByExpFilter(array []map[string]interface{}, name string, expr expressions.Closure) ([]map[string]interface{}, error) {
|
||||||
|
rt := reflect.ValueOf(array)
|
||||||
|
if !(rt.Kind() != reflect.Array || rt.Kind() == reflect.Slice) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
groups := map[interface{}][]interface{}{}
|
||||||
|
for i := 0; i < rt.Len(); i++ {
|
||||||
|
item := rt.Index(i).Interface()
|
||||||
|
key, err := expr.Bind(name, item).Evaluate()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if group, found := groups[key]; found {
|
||||||
|
groups[key] = append(group, item)
|
||||||
|
} else {
|
||||||
|
groups[key] = []interface{}{item}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var result []map[string]interface{}
|
||||||
|
for k, v := range groups {
|
||||||
|
result = append(result, map[string]interface{}{"name": k, "items": v})
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func groupByFilter(array []map[string]interface{}, property string) []map[string]interface{} {
|
||||||
|
rt := reflect.ValueOf(array)
|
||||||
|
if !(rt.Kind() != reflect.Array || rt.Kind() == reflect.Slice) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
groups := map[interface{}][]interface{}{}
|
||||||
|
for i := 0; i < rt.Len(); i++ {
|
||||||
|
irt := rt.Index(i)
|
||||||
|
if irt.Kind() == reflect.Map && irt.Type().Key().Kind() == reflect.String {
|
||||||
|
krt := irt.MapIndex(reflect.ValueOf(property))
|
||||||
|
if krt.IsValid() && krt.CanInterface() {
|
||||||
|
key := krt.Interface()
|
||||||
|
if group, found := groups[key]; found {
|
||||||
|
groups[key] = append(group, irt.Interface())
|
||||||
|
} else {
|
||||||
|
groups[key] = []interface{}{irt.Interface()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var result []map[string]interface{}
|
||||||
|
for k, v := range groups {
|
||||||
|
result = append(result, map[string]interface{}{"name": k, "items": v})
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func sortFilter(array []interface{}, key interface{}, nilFirst func(bool) bool) []interface{} {
|
||||||
|
nf := nilFirst(true)
|
||||||
|
result := make([]interface{}, len(array))
|
||||||
|
copy(result, array)
|
||||||
|
if key == nil {
|
||||||
|
evaluator.Sort(result)
|
||||||
|
} else {
|
||||||
|
// TODO error if key is not a string
|
||||||
|
evaluator.SortByProperty(result, key.(string), nf)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func whereExpFilter(array []interface{}, name string, expr expressions.Closure) ([]interface{}, error) {
|
||||||
|
rt := reflect.ValueOf(array)
|
||||||
|
if rt.Kind() != reflect.Array && rt.Kind() != reflect.Slice {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
var result []interface{}
|
||||||
|
for i := 0; i < rt.Len(); i++ {
|
||||||
|
item := rt.Index(i).Interface()
|
||||||
|
value, err := expr.Bind(name, item).Evaluate()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if value != nil && value != false {
|
||||||
|
result = append(result, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func whereFilter(array []map[string]interface{}, key string, value interface{}) []interface{} {
|
||||||
|
rt := reflect.ValueOf(array)
|
||||||
|
if rt.Kind() != reflect.Array && rt.Kind() != reflect.Slice {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var result []interface{}
|
||||||
|
for i := 0; i < rt.Len(); i++ {
|
||||||
|
item := rt.Index(i)
|
||||||
|
if item.Kind() == reflect.Map && item.Type().Key().Kind() == reflect.String {
|
||||||
|
attr := item.MapIndex(reflect.ValueOf(key))
|
||||||
|
if attr.IsValid() && fmt.Sprint(attr) == value {
|
||||||
|
result = append(result, item.Interface())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
|
@ -1,4 +1,3 @@
|
||||||
// TODO consider making this another package
|
|
||||||
package templates
|
package templates
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -27,7 +26,25 @@ type Template struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEngine() *Engine {
|
func NewEngine() *Engine {
|
||||||
return liquid.NewEngine()
|
// a lot of the filters and tags available at jekyll aren't default liquid
|
||||||
|
// manually adding them here as in https://github.com/osteele/gojekyll/blob/main/filters/filters.go
|
||||||
|
|
||||||
|
e := liquid.NewEngine()
|
||||||
|
|
||||||
|
e.RegisterFilter("filter", filter)
|
||||||
|
e.RegisterFilter("group_by", groupByFilter)
|
||||||
|
e.RegisterFilter("group_by_exp", groupByExpFilter)
|
||||||
|
e.RegisterFilter("sort", sortFilter)
|
||||||
|
e.RegisterFilter("where", whereFilter)
|
||||||
|
e.RegisterFilter("where_exp", whereExpFilter)
|
||||||
|
|
||||||
|
e.RegisterFilter("absolute_url", func(s string) string {
|
||||||
|
// FIXME implement after adding a config struct, using the url
|
||||||
|
// return utils.URLJoin(c.AbsoluteURL, c.BaseURL, s)
|
||||||
|
return s
|
||||||
|
})
|
||||||
|
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
func Parse(engine *Engine, path string) (*Template, error) {
|
func Parse(engine *Engine, path string) (*Template, error) {
|
||||||
|
|
Loading…
Reference in a new issue