generate details sites from fnRender
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Sebastian Frank 2019-02-28 10:43:30 +01:00
parent 650bdc2fd6
commit 39f1932cc3
Signed by: apairon
GPG Key ID: 7270D06DDA7FE8C3
10 changed files with 208 additions and 142 deletions

9
.gitmodules vendored
View File

@ -25,9 +25,6 @@
[submodule "vendor/github.com/davecgh/go-spew"]
path = vendor/github.com/davecgh/go-spew
url = https://github.com/davecgh/go-spew
[submodule "vendor/github.com/aymerick/raymond"]
path = vendor/github.com/aymerick/raymond
url = https://github.com/aymerick/raymond
[submodule "vendor/github.com/imdario/mergo"]
path = vendor/github.com/imdario/mergo
url = https://github.com/imdario/mergo
@ -40,12 +37,6 @@
[submodule "vendor/github.com/juju/errors"]
path = vendor/github.com/juju/errors
url = https://github.com/juju/errors
[submodule "vendor/github.com/gosimple/slug"]
path = vendor/github.com/gosimple/slug
url = https://github.com/gosimple/slug
[submodule "vendor/github.com/rainycape/unidecode"]
path = vendor/github.com/rainycape/unidecode
url = https://github.com/rainycape/unidecode
[submodule "vendor/github.com/flosch/pongo2-addons"]
path = vendor/github.com/flosch/pongo2-addons
url = https://github.com/flosch/pongo2-addons

92
config/tree.go Normal file
View File

@ -0,0 +1,92 @@
package config
import (
"reflect"
"github.com/imdario/mergo"
)
// ThisPathConfig is struct for This in paths yaml
type ThisPathConfig struct {
Navname *string `yaml:"Navname"`
GoTo *string `yaml:"GoTo"`
Data interface{} `yaml:"Data"`
}
// IndexConfig describes index input and output file
type IndexConfig struct {
InputFile *string `yaml:"InputFile"`
OutputFile *string `yaml:"OutputFile"`
}
// MetaData describes meta data for current site/tree node
type MetaData struct {
Title *string `yaml:"Title"`
Description *string `yaml:"Description"`
Keywords *string `yaml:"Keywords"`
}
// DirnameConfig describes how to handle directory names
type DirnameConfig struct {
Strip *string `yaml:"Strip"`
IgnoreForNav *string `yaml:"IgnoreForNav"`
}
// FilenameConfig describes how to handle filenames
type FilenameConfig struct {
Strip *string `yaml:"Strip"`
Ignore *string `yaml:"Ignore"`
OutputExtension *string `yaml:"OutputExtension"`
}
// MarkdownConfig describes markdown handling
type MarkdownConfig struct {
ChromaRenderer *bool `yaml:"ChromaRenderer"`
ChromaStyle *string `yaml:"ChromaStyle"`
}
// PathConfig of subdir
type PathConfig struct {
This ThisPathConfig `yaml:"This"`
Template *string `yaml:"Template"`
Index *IndexConfig `yaml:"Index"`
Meta *MetaData `yaml:"Meta"`
Path *DirnameConfig `yaml:"Path"`
Filename *FilenameConfig `yaml:"Filename"`
Markdown *MarkdownConfig `yaml:"Markdown"`
Data interface{} `yaml:"Data"`
}
// PathConfigTree is complete config tree of content dir
type PathConfigTree struct {
InputPath string
OutputPath string
InputFiles []string
OtherFiles []string
Config *PathConfig
Sub []*PathConfigTree
}
type ptrTransformer struct{}
func (t ptrTransformer) Transformer(typ reflect.Type) func(dst, src reflect.Value) error {
if typ.Kind() == reflect.Ptr {
return func(dst, src reflect.Value) error {
if dst.CanSet() {
if dst.IsNil() {
dst.Set(src)
}
}
return nil
}
}
return nil
}
// Merge merges 2 objects or maps
func Merge(dst, src interface{}) error {
return mergo.Merge(dst, src, mergo.WithTransformers(ptrTransformer{}))
}

24
helper/dir.go Normal file
View File

@ -0,0 +1,24 @@
package helper
import "os"
// CreateDirectory creates direcory with all missing parents and panic if error
func CreateDirectory(dir string) {
Log.Debugf("trying to create output directory: %s", dir)
if dirH, err := os.Stat(dir); os.IsNotExist(err) {
err := os.MkdirAll(dir, 0755)
if err != nil {
Log.Panicf("could not create output directory '%s': %s", dir, err)
}
Log.Noticef("created output directory: %s", dir)
} else if dirH != nil {
if dirH.IsDir() {
Log.Noticef("output directory '%s' already exists", dir)
} else {
Log.Panicf("output directory '%s' is no directory", dir)
}
} else {
Log.Panicf("unknown error for output directory '%s': %s", dir, err)
}
}

View File

@ -11,9 +11,12 @@ import (
)
var templateCache = make(map[string]*pongo2.Template)
var currentContext map[string]interface{}
var currentContext *map[string]interface{}
var currentTreeNodeConfig *config.PathConfigTree
var currentPathConfig *config.PathConfig
var templateDir string
// BackToRoot builds ../../ string
func BackToRoot(curNavPath string) string {
tmpPath := ""
if curNavPath != "" {
@ -30,8 +33,10 @@ func SetTemplateDir(dir string) {
}
// RenderTemplate renders a pongo2 template with context
func RenderTemplate(filename string, ctx map[string]interface{}) (string, error) {
func RenderTemplate(filename string, treeNodeConfig *config.PathConfigTree, pathConfig *config.PathConfig, ctx *map[string]interface{}) (string, error) {
currentContext = ctx
currentTreeNodeConfig = treeNodeConfig
currentPathConfig = pathConfig
templateFile := templateDir + "/" + filename
template := templateCache[templateFile]
if template == nil {
@ -43,9 +48,10 @@ func RenderTemplate(filename string, ctx map[string]interface{}) (string, error)
}
}
return template.Execute(ctx)
return template.Execute(*ctx)
}
// FixAssetsPath replaces assets path based on current path
func FixAssetsPath(str, curNavPath string) string {
if find := config.Config.Assets.FixTemplate.Find; find != "" {
Log.Debugf("fixing assets paths for path '%s'", curNavPath)

View File

@ -4,10 +4,14 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"path"
"strings"
"gitbase.de/apairon/mark2web/config"
"github.com/davecgh/go-spew/spew"
"github.com/extemporalgenome/slug"
"github.com/flosch/pongo2"
)
@ -52,16 +56,65 @@ func RequestFn(url *pongo2.Value, args ...*pongo2.Value) *pongo2.Value {
// RenderFn renders a pongo2 template with additional context
func RenderFn(templateFilename, outDir, subCtxName, ctx *pongo2.Value) *pongo2.Value {
currentContext[subCtxName.String()] = ctx
result, err := RenderTemplate(templateFilename.String(), currentContext)
oDirSlug := slug.Slug(outDir.String())
navPath := path.Clean((*currentContext)["CurrentPath"].(string) + "/" + oDirSlug)
outputPath := path.Clean(currentTreeNodeConfig.OutputPath + "/" + oDirSlug)
CreateDirectory(outputPath)
newContext := make(map[string]interface{})
if err := config.Merge(&newContext, *currentContext); err != nil {
Log.Panicf("unable to merge context")
}
newContext[subCtxName.String()] = ctx
newContext["CurrentPath"] = navPath
newNodeConfig := new(config.PathConfigTree)
if err := config.Merge(newNodeConfig, currentTreeNodeConfig); err != nil {
Log.Panicf("unable to merge tree node config")
}
newNodeConfig.OutputPath = outputPath
// remember old to set after recursion
oldContext := currentContext
oldNodeConfig := currentTreeNodeConfig
result, err := RenderTemplate(
templateFilename.String(),
newNodeConfig,
currentPathConfig,
&newContext,
)
if err != nil {
panic(err)
}
currentContext = oldContext
currentTreeNodeConfig = oldNodeConfig
result = FixAssetsPath(
result,
currentContext["CurrentPath"].(string),
navPath,
)
spew.Dump(result)
//spew.Dump(result)
// build output filename
outputFilename := "index.html"
var indexOutputFile *string
if i := currentPathConfig.Index; i != nil {
indexOutputFile = i.OutputFile
}
if indexOutputFile != nil && *indexOutputFile != "" {
outputFilename = *indexOutputFile
}
outFile := outputPath + "/" + outputFilename
Log.Debugf("using '%s' as output file", outFile)
Log.Noticef("writing to output file: %s", outFile)
err = ioutil.WriteFile(outFile, []byte(result), 0644)
if err != nil {
log.Panicf("could not write to output file '%s': %s", outFile, err)
}
return pongo2.AsValue(nil)
}

144
main.go
View File

@ -7,18 +7,15 @@ import (
"io/ioutil"
"os"
"path"
"reflect"
"regexp"
"strings"
"github.com/imdario/mergo"
"gitbase.de/apairon/mark2web/config"
"gitbase.de/apairon/mark2web/helper"
"github.com/Depado/bfchroma"
"github.com/davecgh/go-spew/spew"
"github.com/extemporalgenome/slug"
"github.com/flosch/pongo2"
"github.com/gosimple/slug"
cpy "github.com/otiai10/copy"
"gopkg.in/russross/blackfriday.v2"
"gopkg.in/yaml.v2"
@ -38,88 +35,9 @@ var log = helper.Log
var inDir *string
var outDir *string
// ThisPathConfig is struct for This in paths yaml
type ThisPathConfig struct {
Navname *string `yaml:"Navname"`
GoTo *string `yaml:"GoTo"`
Data interface{} `yaml:"Data"`
}
var contentConfig = new(config.PathConfigTree)
type indexStruct struct {
InputFile *string `yaml:"InputFile"`
OutputFile *string `yaml:"OutputFile"`
}
type metaStruct struct {
Title *string `yaml:"Title"`
Description *string `yaml:"Description"`
Keywords *string `yaml:"Keywords"`
}
type pathStruct struct {
Strip *string `yaml:"Strip"`
IgnoreForNav *string `yaml:"IgnoreForNav"`
}
type filenameStruct struct {
Strip *string `yaml:"Strip"`
Ignore *string `yaml:"Ignore"`
OutputExtension *string `yaml:"OutputExtension"`
}
type markdownStruct struct {
ChromaRenderer *bool `yaml:"ChromaRenderer"`
ChromaStyle *string `yaml:"ChromaStyle"`
}
// PathConfig of subdir
type PathConfig struct {
This ThisPathConfig `yaml:"This"`
Template *string `yaml:"Template"`
Index *indexStruct `yaml:"Index"`
Meta *metaStruct `yaml:"Meta"`
Path *pathStruct `yaml:"Path"`
Filename *filenameStruct `yaml:"Filename"`
Markdown *markdownStruct `yaml:"Markdown"`
Data interface{} `yaml:"Data"`
}
// PathConfigTree is complete config tree of content dir
type PathConfigTree struct {
InputPath string
OutputPath string
InputFiles []string
OtherFiles []string
Config *PathConfig
Sub []*PathConfigTree
}
var contentConfig = new(PathConfigTree)
type ptrTransformer struct{}
func (t ptrTransformer) Transformer(typ reflect.Type) func(dst, src reflect.Value) error {
if typ.Kind() == reflect.Ptr {
return func(dst, src reflect.Value) error {
if dst.CanSet() {
if dst.IsNil() {
dst.Set(src)
}
}
return nil
}
}
return nil
}
func merge(dst, src interface{}) error {
return mergo.Merge(dst, src, mergo.WithTransformers(ptrTransformer{}))
}
func readContentDir(inBase string, outBase string, dir string, conf *PathConfig, tree *PathConfigTree) {
func readContentDir(inBase string, outBase string, dir string, conf *config.PathConfig, tree *config.PathConfigTree) {
inPath := inBase
if dir != "" {
inPath += "/" + dir
@ -135,14 +53,14 @@ func readContentDir(inBase string, outBase string, dir string, conf *PathConfig,
tree.InputPath = inPath
// read config
newConfig := new(PathConfig)
newConfig := new(config.PathConfig)
log.Debug("looking for config.yml ...")
configFile := inPath + "/config.yml"
if _, err = os.Stat(configFile); os.IsNotExist(err) {
log.Debug("no config.yml found in this directory, using upper configs")
merge(newConfig, conf)
config.Merge(newConfig, conf)
// remove this
newConfig.This = ThisPathConfig{}
newConfig.This = config.ThisPathConfig{}
} else {
log.Debug("reading config...")
data, err := ioutil.ReadFile(configFile)
@ -156,7 +74,7 @@ func readContentDir(inBase string, outBase string, dir string, conf *PathConfig,
log.Debug("merging config with upper config")
oldThis := newConfig.This
merge(newConfig, conf)
config.Merge(newConfig, conf)
newConfig.This = oldThis
log.Debug(spew.Sdump(newConfig))
@ -183,7 +101,7 @@ func readContentDir(inBase string, outBase string, dir string, conf *PathConfig,
tree.Config.This.Navname = &navname
}
stripedDir = slug.Make(stripedDir)
stripedDir = slug.Slug(stripedDir)
outPath := outBase + "/" + stripedDir
outPath = path.Clean(outPath)
@ -217,9 +135,9 @@ func readContentDir(inBase string, outBase string, dir string, conf *PathConfig,
p := inPath + "/" + f.Name()
if f.IsDir() {
log.Debugf("DIR %s", p)
newTree := new(PathConfigTree)
newTree := new(config.PathConfigTree)
if tree.Sub == nil {
tree.Sub = make([]*PathConfigTree, 0)
tree.Sub = make([]*config.PathConfigTree, 0)
}
tree.Sub = append(tree.Sub, newTree)
readContentDir(inPath, outPath, f.Name(), newConfig, newTree)
@ -234,13 +152,13 @@ type navElement struct {
Data interface{}
This ThisPathConfig
This config.ThisPathConfig
SubMap *map[string]*navElement
SubSlice *[]*navElement
}
func buildNavigation(conf *PathConfigTree, curNavMap *map[string]*navElement, curNavSlice *[]*navElement, navActive *[]*navElement, activeNav string) {
func buildNavigation(conf *config.PathConfigTree, curNavMap *map[string]*navElement, curNavSlice *[]*navElement, navActive *[]*navElement, activeNav string) {
for _, el := range conf.Sub {
var ignNav *string
if p := el.Config.Path; p != nil {
@ -312,24 +230,8 @@ func buildNavigation(conf *PathConfigTree, curNavMap *map[string]*navElement, cu
}
}
func processContent(conf *PathConfigTree) {
log.Debugf("trying to create output directory: %s", conf.OutputPath)
if dirH, err := os.Stat(conf.OutputPath); os.IsNotExist(err) {
err := os.MkdirAll(conf.OutputPath, 0755)
if err != nil {
log.Panicf("could not create output directory '%s': %s", conf.OutputPath, err)
}
log.Noticef("created output directory: %s", conf.OutputPath)
} else if dirH != nil {
if dirH.IsDir() {
log.Noticef("output directory '%s' already exists", conf.OutputPath)
} else {
log.Panicf("output directory '%s' is no directory", conf.OutputPath)
}
} else {
log.Panicf("unknown error for output directory '%s': %s", conf.OutputPath, err)
}
func processContent(conf *config.PathConfigTree) {
helper.CreateDirectory(conf.OutputPath)
curNavPath := strings.TrimPrefix(conf.OutputPath, *outDir)
curNavPath = strings.TrimPrefix(curNavPath, "/")
@ -370,7 +272,7 @@ RewriteRule ^$ %{REQUEST_URI}`+goToFixed+`/ [R,L]
}
log.Infof("processing input file '%s'", inFile)
newConfig := new(PathConfig)
newConfig := new(config.PathConfig)
regex := regexp.MustCompile("(?s)^---(.*?)\\r?\\n\\r?---\\r?\\n\\r?")
yamlData := regex.Find(input)
@ -383,14 +285,14 @@ RewriteRule ^$ %{REQUEST_URI}`+goToFixed+`/ [R,L]
log.Debug("merging config with upper config")
oldThis := newConfig.This
merge(newConfig, conf.Config)
config.Merge(newConfig, conf.Config)
newConfig.This = oldThis
log.Debug(spew.Sdump(newConfig))
input = regex.ReplaceAll(input, []byte(""))
} else {
merge(newConfig, conf.Config)
config.Merge(newConfig, conf.Config)
}
// ignore ???
@ -484,7 +386,7 @@ RewriteRule ^$ %{REQUEST_URI}`+goToFixed+`/ [R,L]
buildNavigation(contentConfig, &navMap, &navSlice, &navActive, curNavPath)
// read yaml header as data for template
ctx := make(pongo2.Context)
ctx := make(map[string]interface{})
ctx["This"] = newConfig.This
ctx["Meta"] = newConfig.Meta
ctx["Data"] = newConfig.Data
@ -502,7 +404,7 @@ RewriteRule ^$ %{REQUEST_URI}`+goToFixed+`/ [R,L]
log.Debugf("rendering template '%s' for '%s'", *newConfig.Template, outFile)
templateFilename := *newConfig.Template
result, err := helper.RenderTemplate(*newConfig.Template, ctx)
result, err := helper.RenderTemplate(*newConfig.Template, conf, newConfig, &ctx)
if err != nil {
log.Panicf("could not execute template '%s' for input file '%s': %s", templateFilename, inFile, err)
}
@ -632,17 +534,17 @@ func main() {
defaultFilenameIgnore := "^_"
defaultFilenameOutputExtension := "html"
defaultPathConfig := new(PathConfig)
defaultPathConfig := new(config.PathConfig)
defaultPathConfig.Template = &defaultTemplate
defaultPathConfig.Index = &indexStruct{
defaultPathConfig.Index = &config.IndexConfig{
InputFile: &defaultInputFile,
OutputFile: &defaultOutputFile,
}
defaultPathConfig.Path = &pathStruct{
defaultPathConfig.Path = &config.DirnameConfig{
Strip: &defaultPathStrip,
IgnoreForNav: &defaultPathIgnoreForNav,
}
defaultPathConfig.Filename = &filenameStruct{
defaultPathConfig.Filename = &config.FilenameConfig{
Strip: &defaultFilenameStrip,
Ignore: &defaultFilenameIgnore,
OutputExtension: &defaultFilenameOutputExtension,

1
vendor/github.com/aymerick/raymond generated vendored

@ -1 +0,0 @@
Subproject commit b565731e1464263de0bda75f2e45d97b54b60110

1
vendor/github.com/gosimple/slug generated vendored

@ -1 +0,0 @@
Subproject commit 42ac18c34c2c6f4843fa48167317dcaa9416d1e2

@ -1 +0,0 @@
Subproject commit cb7f23ec59bec0d61b19c56cd88cee3d0cc1870c

View File

@ -1,9 +1,10 @@
{% extends 'base.html' %}
{% block part0 %}
<h1>{{ details.title }}</h1>
<h1>{{ details.title }}</h1>
{{ details.teaser|markdown }}
{% endblock part0 %}
{% block part1 %}
{{ details.body|markdown }}
{% endblock part1 %}