collections as one navigation level
This commit is contained in:
parent
e3dfbcb591
commit
38820e6baf
@ -8,10 +8,16 @@ import (
|
||||
|
||||
// CollectionConfig describes a collection
|
||||
type CollectionConfig struct {
|
||||
Name *string `yaml:"Name"`
|
||||
URL *string `yaml:"URL"`
|
||||
GoToTemplate *string `yaml:"GoToTemplate"`
|
||||
RegisterNav *bool `yaml:"RegisterNav"`
|
||||
Name *string `yaml:"Name"`
|
||||
EntriesJSON *string `yaml:"EntriesJSON"`
|
||||
NavTemplate *struct {
|
||||
GoTo string `yaml:"GoTo"`
|
||||
Navname string `yaml:"Navname"`
|
||||
Body string `yaml:"Body"`
|
||||
DataKey string `yaml:"DataKey"`
|
||||
Hidden bool `yaml:"Hidden"`
|
||||
Template string `yaml:"Template"`
|
||||
} `yaml:"NavTemplate"`
|
||||
}
|
||||
|
||||
// ThisPathConfig is struct for This in paths yaml
|
||||
|
@ -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)
|
||||
|
@ -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(
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -1,9 +1,21 @@
|
||||
This:
|
||||
Collections:
|
||||
- Name: blog1st
|
||||
URL: https://mark2web.basiscms.de/api/collections/get/mark2webBlog?token=89ff216524093123bf7a0a10f7b273&filter[published]=true&sort[date]=-1&skip=0&limit=1
|
||||
GoToTemplate: '{{ date|add:"-"|add:title|slugify }}'
|
||||
EntriesJSON: '{{ fnRequest("https://mark2web.basiscms.de/api/collections/get/mark2webBlog?token=89ff216524093123bf7a0a10f7b273&filter[published]=true&sort[date]=-1&skip=0&limit=1").entries|json }}'
|
||||
NavTemplate:
|
||||
GoTo: '{{ date|add:"-"|add:title|slugify }}'
|
||||
Navname: '{{ title }}'
|
||||
Body: '{{ body }}'
|
||||
Template: base_blog_details.html
|
||||
DataKey: details
|
||||
Hidden: true # hide from nav, but use this feature for rendering detail sites
|
||||
|
||||
- Name: blog1skip
|
||||
URL: https://mark2web.basiscms.de/api/collections/get/mark2webBlog?token=89ff216524093123bf7a0a10f7b273&filter[published]=true&sort[date]=-1&skip=1&limit=100
|
||||
GoToTemplate: '{{ date|add:"-"|add:title|slugify }}'
|
||||
EntriesJSON: '{{ fnRequest("https://mark2web.basiscms.de/api/collections/get/mark2webBlog?token=89ff216524093123bf7a0a10f7b273&filter[published]=true&sort[date]=-1&skip=1&limit=100").entries|json }}'
|
||||
NavTemplate:
|
||||
GoTo: '{{ date|add:"-"|add:title|slugify }}'
|
||||
Navname: '{{ title }}'
|
||||
Body: '{{ body }}'
|
||||
Template: base_blog_details.html
|
||||
DataKey: details
|
||||
Hidden: true
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
{% block part0 %}
|
||||
{{ Body }}
|
||||
{% for e in NavElement.ColMap.blog1st.entries %}
|
||||
{% for e in NavElement.ColMap.blog1st %}
|
||||
<h2>
|
||||
{{ e.title }}
|
||||
<div class="datum">{{ e.date|datum }}</div>
|
||||
@ -10,7 +10,6 @@
|
||||
{{ e.teaser|markdown }}
|
||||
{% if e.body %}
|
||||
<a href="{{ e.date|add:"-"|add:e.title|slugify }}" class="btn">mehr lesen »</a>
|
||||
{{ fnRender("base_blog_details.html", e.date|add:"-"|add:e.title, e, "details", e.body) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endblock part0 %}
|
||||
@ -19,7 +18,7 @@
|
||||
{% comment %}
|
||||
limit wird für skip in Query gebraucht
|
||||
{% endcomment %}
|
||||
{% for e in NavElement.ColMap.blog1skip.entries %}
|
||||
{% for e in NavElement.ColMap.blog1skip %}
|
||||
<h2>
|
||||
{{ e.title }}
|
||||
<div class="datum">{{ e.date|datum }}</div>
|
||||
@ -27,7 +26,6 @@
|
||||
{{ e.teaser|markdown }}
|
||||
{% if e.body %}
|
||||
<a href="{{ e.date|add:"-"|add:e.title|slugify }}" class="btn">mehr lesen »</a>
|
||||
{{ fnRender("base_blog_details.html", e.date|add:"-"|add:e.title, e, "details", e.body) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endblock part1 %}
|
||||
|
Loading…
Reference in New Issue
Block a user