mirror of
https://github.com/facundoolano/jorge.git
synced 2024-12-25 21:58:28 +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/niklasfasching/go-org v1.7.0
|
||||
github.com/osteele/liquid v1.3.2
|
||||
github.com/yuin/goldmark v1.7.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
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/sys v0.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
|
||||
|
||||
import (
|
||||
|
@ -27,7 +26,25 @@ type Template struct {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
|
Loading…
Reference in a new issue