collections as one navigation level

This commit is contained in:
Sebastian Frank
2019-03-10 16:02:53 +01:00
parent e3dfbcb591
commit 38820e6baf
6 changed files with 157 additions and 47 deletions

View File

@@ -2,6 +2,7 @@ package helper
import (
"bytes"
"encoding/json"
"io/ioutil"
"os"
"path"
@@ -18,6 +19,15 @@ import (
"gopkg.in/yaml.v2"
)
func newContext() map[string]interface{} {
return map[string]interface{}{
"fnRequest": RequestFn,
"fnRender": RenderFn,
"AssetsPath": config.Config.Assets.ToPath,
}
}
func fillNodeConfig(node *config.PathConfigTree, inBase, outBase, dir string, conf *config.PathConfig) {
inPath := inBase
if dir != "" {
@@ -90,15 +100,81 @@ func fillNodeConfig(node *config.PathConfigTree, inBase, outBase, dir string, co
if colConfig.Name == nil || *colConfig.Name == "" {
Log.Panicf("missing Name in collection config in '%s'", inPath)
}
if colConfig.URL == nil || *colConfig.URL == "" {
Log.Panicf("missing URL in collection config in '%s'", inPath)
if colConfig.EntriesJSON == nil || *colConfig.EntriesJSON == "" {
Log.Panicf("missing EntriesJSON in collection config in '%s'", inPath)
}
}
if node.ColMap == nil {
node.ColMap = make(map[string]interface{})
}
node.ColMap[*colConfig.Name] = jsonWebRequest(*colConfig.URL)
ctx := newContext()
jsonStr, err := pongo2.RenderTemplateString(*colConfig.EntriesJSON, ctx)
if err != nil {
Log.Panicf("invalid template string in '%s': %s", inPath, err)
}
var colSlice []map[string]interface{}
err = json.Unmarshal([]byte(jsonStr), &colSlice)
if err != nil {
Log.Panicf("invalid JSON in EntriesJSON in '%s': %s", inPath, err)
}
node.ColMap[*colConfig.Name] = colSlice
//node.ColMap[*colConfig.Name] = jsonWebRequest(*colConfig.URL)
if navT := colConfig.NavTemplate; navT != nil {
tpl := navT.Template
if tpl == "" {
tpl = *newConfig.Template
}
// build navigation with detail sites
for _, colEl := range colSlice {
ctxE := make(map[string]interface{})
err := config.Merge(&ctxE, ctx)
if err != nil {
Log.Panicf("could not merge context in '%s': %s", inPath, err)
}
err = config.Merge(&ctxE, colEl)
if err != nil {
Log.Panicf("could not merge context in '%s': %s", inPath, err)
}
goTo, err := pongo2.RenderTemplateString(navT.GoTo, ctxE)
if err != nil {
Log.Panicf("invalid template string for NavTemplate.GoTo in '%s': %s", inPath, err)
}
goTo = strings.Trim(goTo, "/")
goTo = path.Clean(goTo)
if strings.Contains(goTo, "..") {
Log.Panicf("going back via .. in NavTemplate.GoTo forbidden in collection config in '%s': %s", inPath, goTo)
}
if goTo == "." {
Log.Panicf("invalid config '.' for NavTemplate.GoTo in collection config in '%s'", inPath)
}
if goTo == "" {
Log.Panicf("missing NavTemplate.GoTo in collection config in '%s'", inPath)
}
navname := ""
if navT.Navname != "" {
navname, err = pongo2.RenderTemplateString(navT.Navname, ctxE)
if err != nil {
Log.Panicf("invalid template string for NavTemplate.Navname in '%s': %s", inPath, err)
}
}
body := ""
if navT.Body != "" {
body, err = pongo2.RenderTemplateString(navT.Body, ctxE)
if err != nil {
Log.Panicf("invalid template string for NavTemplate.Body in '%s': %s", inPath, err)
}
}
add2Nav(node, node.Config, tpl, goTo, navname, colEl, navT.DataKey, body, navT.Hidden)
}
}
}
}
@@ -304,7 +380,7 @@ RewriteRule ^$ %{REQUEST_URI}`+goToFixed+`/ [R,L]
BuildNavigation(rootConf, &navMap, &navSlice, &navActive, curNavPath)
// read yaml header as data for template
ctx := make(map[string]interface{})
ctx := newContext()
ctx["This"] = newConfig.This
ctx["Meta"] = newConfig.Meta
ctx["Data"] = newConfig.Data
@@ -314,7 +390,6 @@ RewriteRule ^$ %{REQUEST_URI}`+goToFixed+`/ [R,L]
ctx["NavActive"] = navActive
ctx["Body"] = pongo2.AsSafeValue(string(renderMarkdown(input, newConfig.Markdown)))
ctx["BodyParts"] = htmlParts
ctx["AssetsPath"] = config.Config.Assets.ToPath
ctx["CurrentPath"] = curNavPath
// set active nav element
if len(navActive) > 0 {
@@ -332,10 +407,6 @@ RewriteRule ^$ %{REQUEST_URI}`+goToFixed+`/ [R,L]
}
}
// register functions
ctx["fnRequest"] = RequestFn
ctx["fnRender"] = RenderFn
Log.Debugf("rendering template '%s' for '%s'", *newConfig.Template, outFile)
templateFilename := *newConfig.Template
result, err := RenderTemplate(*newConfig.Template, conf, newConfig, &ctx)

View File

@@ -2,6 +2,7 @@ package helper
import (
"crypto/md5"
"encoding/json"
"errors"
"fmt"
"image"
@@ -30,6 +31,7 @@ func init() {
newFilters := map[string]pongo2.FilterFunction{
"image_process": ImageProcessFilter,
"relative_path": RelativePathFilter,
"json": JSONFilter,
}
for name, fn := range newFilters {
err := pongo2.RegisterFilter(name, fn)
@@ -39,6 +41,19 @@ func init() {
}
}
// JSONFilter is a pongo2 filter, which returns a json string of the input
func JSONFilter(in *pongo2.Value, param *pongo2.Value) (*pongo2.Value, *pongo2.Error) {
jsonString, err := json.Marshal(in.Interface())
if err != nil {
return nil, &pongo2.Error{
Sender: "filter:json",
OrigError: err,
}
}
return pongo2.AsSafeValue(string(jsonString)), nil
}
// MarkdownFilter is a pongo2 filter, which converts markdown to html
func MarkdownFilter(in *pongo2.Value, param *pongo2.Value) (*pongo2.Value, *pongo2.Error) {
return pongo2.AsSafeValue(

View File

@@ -53,39 +53,30 @@ func RequestFn(url *pongo2.Value, args ...*pongo2.Value) *pongo2.Value {
return pongo2.AsValue(jsonWebRequest(u))
}
// RenderFn renders a pongo2 template with additional context
func RenderFn(templateFilename, outDir, ctx *pongo2.Value, param ...*pongo2.Value) *pongo2.Value {
ctxMapKey := ""
body := ""
for i, p := range param {
switch i {
case 0:
ctxMapKey = p.String()
case 1:
body = p.String()
}
}
func add2Nav(currentNode *config.PathConfigTree, pathConfig *config.PathConfig, tplFilename, outDir string, navname string, ctx interface{}, dataMapKey string, body string, hidden bool) {
newNodeConfig := new(config.PathConfigTree)
fillNodeConfig(
newNodeConfig,
currentTreeNodeConfig.InputPath,
currentTreeNodeConfig.OutputPath,
outDir.String(),
currentPathConfig,
currentNode.InputPath,
currentNode.OutputPath,
outDir,
pathConfig,
)
if newNodeConfig.Config.Data == nil {
newNodeConfig.Config.Data = make(map[string]interface{})
if navname != "" {
newNodeConfig.Config.This = config.ThisPathConfig{
Navname: &navname,
}
}
if ctxMapKey != "" {
if dataMapKey != "" {
if newNodeConfig.Config.Data == nil {
newNodeConfig.Config.Data = make(map[string]interface{})
}
// as submap in Data
newNodeConfig.Config.Data[ctxMapKey] = ctx.Interface()
} else if m, ok := ctx.Interface().(map[string]interface{}); ok {
newNodeConfig.Config.Data[dataMapKey] = ctx
} else if m, ok := ctx.(map[string]interface{}); ok {
// direct set data
newNodeConfig.Config.Data = m
}
tplFilename := templateFilename.String()
// fake via normal file behavior
newNodeConfig.Config.Template = &tplFilename
@@ -102,9 +93,26 @@ func RenderFn(templateFilename, outDir, ctx *pongo2.Value, param ...*pongo2.Valu
OutputFile: &indexOutFile,
InputString: &body,
}
newNodeConfig.Hidden = true
newNodeConfig.Hidden = hidden
currentTreeNodeConfig.Sub = append(currentTreeNodeConfig.Sub, newNodeConfig)
currentNode.Sub = append(currentNode.Sub, newNodeConfig)
}
// RenderFn renders a pongo2 template with additional context
func RenderFn(templateFilename, outDir, ctx *pongo2.Value, param ...*pongo2.Value) *pongo2.Value {
dataMapKey := ""
body := ""
for i, p := range param {
switch i {
case 0:
dataMapKey = p.String()
case 1:
body = p.String()
}
}
add2Nav(currentTreeNodeConfig, currentPathConfig, templateFilename.String(), outDir.String(), "", ctx.Interface(), dataMapKey, body, true)
return pongo2.AsValue(nil)
}