read config

This commit is contained in:
Sebastian Frank 2019-02-11 15:00:27 +01:00
parent 291c1315ef
commit 3bce29a384
Signed by: apairon
GPG Key ID: 7270D06DDA7FE8C3
23 changed files with 408 additions and 31 deletions

9
.gitmodules vendored
View File

@ -16,3 +16,12 @@
[submodule "vendor/github.com/danwakefield/fnmatch"]
path = vendor/github.com/danwakefield/fnmatch
url = https://github.com/danwakefield/fnmatch
[submodule "vendor/github.com/op/go-logging"]
path = vendor/github.com/op/go-logging
url = https://github.com/op/go-logging
[submodule "vendor/gopkg.in/yaml.v2"]
path = vendor/gopkg.in/yaml.v2
url = https://gopkg.in/yaml.v2
[submodule "vendor/github.com/davecgh/go-spew"]
path = vendor/github.com/davecgh/go-spew
url = https://github.com/davecgh/go-spew

View File

@ -11,7 +11,7 @@ DIR content
DIR de (Sprache)
DIR main (Navigationsbaum)
DIR 01_Home (1. Ebene)
FIL config.toml
FIL config.yml
FIL README.md
DIR 02_Download
FIL README.md
@ -34,17 +34,18 @@ DIR media
DIR Referenzbilder
DIR Mitarbeiterfotos
DIR assets
DIR js
DIR img
DIR css
DIR templates
DIR assets
DIR js
DIR img
DIR css
FIL home.tmpl
FIL site.tmpl
FIL TOP.tmpl
FIL BOTTOM.tmpl
FIL config.toml
FIL config.yml
```
### content
@ -53,12 +54,13 @@ FIL config.toml
- voranestellte Nummer mit Unterstrich wie z.B. `01_` dienen nur der Sortierung und gehen nicht in den eigentlichen Navigationspfad mit ein
- zur Bildung des Navigationspfades werden die Verzeichnisnamen in Kleinschreibung konvertiert
- Navigationsnamen für die Website werden aus dem Pfad gebildet, wobei `_`(Unterstriche) in Leerzeichen umgewandelt werden
- Navigationsnamen können durch die `config.toml` überschrieben werden
- Navigationsnamen können durch die `config.yml` überschrieben werden
### media
- enthält alle Bilder, Videos und andere Medien-Dateien, die via Markdown in die jeweiligen Websites eingebunden werden
- Bilder die im Template benötigt werden liegen in `templates/assets`
- außerdem können die Mediendateien auch neben den Inhalten in `content` liegen und müssen demensprechend relativ verlinkt werden
- Bilder die im Template benötigt werden liegen in `assets`
### templates
@ -89,25 +91,25 @@ Weiterer Absatz, usw...
## zusätzliche Konfiguration
In jedem Ordner kann sich eine `config.toml` befinden.
In jedem Ordner kann sich eine `config.yml` befinden.
- z.B. Verküpfung eines Eintrags eines Navigations-Baums zu einem anderen
```toml
goto=/de/main/service/impressum
navname=Impressum
```yml
goto: /de/main/service/impressum
navname: Impressum
```
- außerdem kann sich im Header der Markdown-Datei die Konfig im YAML-Format befinden
- die Konfig in der Markdown-Datei überschreibt die Konfig aus der config.yml
## Haupt-Konfiguration im Root
```toml
[global]
default_file=README.md
[meta]
title=meine Website
description=Standard-Meta-Beschreibung, die verwendet wird, wenn keine pro Seite definiert ist
keywords=Standard-Keywords, welche in den einzelnen Seiten überschrieben werden kann
```yml
meta:
title: meine Website
description: Standard-Meta-Beschreibung, die verwendet wird, wenn keine pro Seite definiert ist
keywords: Standard-Keywords, welche in den einzelnen Seiten überschrieben werden kann
```
## Templates

7
example/config.yml Normal file
View File

@ -0,0 +1,7 @@
webserver:
type: "apache" # generates .htaccess
assets:
path: "/assets"
deployType: "symlink" # symlink, copy or move
fixTemplate: True # change path in html templates, no <base> used

View File

@ -0,0 +1,13 @@
title: "Example Website"
goTo: "/de/main/home"
inputFile: "README.md"
outputFile: "index.html"
meta:
title: "global title"
description: "global description of example website"
keywords: "global keywords"
path:
strip: "^[0-9]+_"
ignoreForNav: "^_"

View File

@ -0,0 +1,8 @@
---
navname: Home
---
# Home
Lorem ipsum...

View File

@ -0,0 +1,8 @@
---
navname: Leistungen
---
# Leistungen
Lorem ipsum...

View File

@ -0,0 +1,8 @@
---
navname: Adresse
---
# Adresse
Lorem ipsum...

View File

@ -0,0 +1,8 @@
---
navname: Anfahrt
---
# Anfahrt
Lorem ipsum...

View File

@ -0,0 +1 @@
goTo: adresse/

View File

@ -0,0 +1 @@
goTo: /de/service/impressum/

View File

@ -0,0 +1,8 @@
---
navname: Datenschutz
---
# Datenshutz
Lorem ipsum...

View File

@ -0,0 +1,8 @@
---
navname: AGB's
---
# AGB's
Lorem ipsum...

View File

@ -0,0 +1,8 @@
---
navname: Impressum
---
# Impressum
Lorem ipsum...

View File

@ -0,0 +1,8 @@
---
navname: Home
---
# Home
Lorem ipsum...

View File

@ -0,0 +1,8 @@
---
navname: Services
---
# Services
Lorem ipsum...

View File

@ -0,0 +1,8 @@
---
navname: Contact
---
# Contact
Lorem ipsum...

View File

@ -0,0 +1 @@
goTo: /en/service/imprint/

View File

@ -0,0 +1,8 @@
---
navname: Terms
---
# Terms
Lorem ipsum...

View File

@ -0,0 +1,8 @@
---
navname: Imprint
---
# Imprint
Lorem ipsum...

266
main.go
View File

@ -1,19 +1,263 @@
package main
import (
"fmt"
"flag"
"io/ioutil"
"os"
"strings"
"github.com/Depado/bfchroma"
"gopkg.in/russross/blackfriday.v2"
"github.com/davecgh/go-spew/spew"
"github.com/op/go-logging"
"gopkg.in/yaml.v2"
)
func main() {
input, err := ioutil.ReadFile("README.md")
if err != nil {
panic(err)
}
html := blackfriday.Run(input, blackfriday.WithRenderer(bfchroma.NewRenderer()))
fmt.Println(string(html))
var log = logging.MustGetLogger("myLogger")
var inDir *string
var outDir *string
// GlobalConfig is config which is used only once in root dir
type GlobalConfig struct {
Webserver struct {
Type *string `yaml:"type"`
} `yaml:"webserver"`
Assets struct {
Path *string `yaml:"path"`
DeployType *string `yaml:"deployType"`
FixTemplate *bool `yaml:"fixTemplate"`
} `yaml:"assets"`
}
var globalConfig = new(GlobalConfig)
// PathConfig of subdir
type PathConfig struct {
Title *string `yaml:"title"`
Navname *string `yaml:"navname"`
GoTo *string `yaml:"goTo"`
InputFile *string `yaml:"inputFile"`
OutputFile *string `yaml:"outputFile"`
Meta struct {
Title *string `yaml:"title"`
Description *string `yaml:"description"`
Keywords *string `yaml:"keywords"`
} `yaml:"meta"`
Path struct {
Strip *string `yaml:"strip"`
IgnoreForNav *string `yaml:"ignoreForNav"`
} `yaml:"path"`
}
// PathConfigTree is complete config tree of content dir
type PathConfigTree struct {
InputPath string
OutputPath string
Config *PathConfig
Sub []*PathConfigTree
}
func mergeConfig(mergeInto *PathConfig, mergeFrom *PathConfig) {
if mergeInto.InputFile == nil {
mergeInto.InputFile = mergeFrom.InputFile
}
if mergeInto.OutputFile == nil {
mergeInto.OutputFile = mergeFrom.OutputFile
}
if mergeInto.Meta.Title == nil {
mergeInto.Meta.Title = mergeFrom.Meta.Title
}
if mergeInto.Meta.Description == nil {
mergeInto.Meta.Description = mergeFrom.Meta.Description
}
if mergeInto.Meta.Keywords == nil {
mergeInto.Meta.Keywords = mergeFrom.Meta.Keywords
}
if mergeInto.Path.IgnoreForNav == nil {
mergeInto.Path.IgnoreForNav = mergeFrom.Path.IgnoreForNav
}
if mergeInto.Path.Strip == nil {
mergeInto.Path.Strip = mergeFrom.Path.Strip
}
}
var contentConfig = new(PathConfigTree)
func readContentDir(d string, conf *PathConfig, tree *PathConfigTree) {
files, err := ioutil.ReadDir(d)
if err != nil {
log.Panic(err)
}
tree.InputPath = d
// read config
var newConfig *PathConfig
log.Debug("looking for config.yml ...")
p := d + "/config.yml"
if _, err = os.Stat(p); os.IsNotExist(err) {
log.Debug("no config.yml found in this directory, using upper configs")
newConfig = conf
} else {
log.Debug("reading config...")
data, err := ioutil.ReadFile(p)
if err != nil {
log.Panicf("could not read file '%s': %s", p, err)
}
newConfig = new(PathConfig)
err = yaml.Unmarshal(data, newConfig)
if err != nil {
log.Panicf("could not parse YAML file '%s': %s", p, err)
}
log.Debug("merging config with upper config")
mergeConfig(newConfig, conf)
log.Debug(spew.Sdump(newConfig))
}
tree.Config = newConfig
// create outDir
oDir := *outDir + "/" + strings.TrimPrefix(d, *inDir+"/content")
oDir = strings.Replace(oDir, "//", "/", -1)
oDir = strings.TrimSuffix(oDir, "/")
log.Noticef("creating output directory: %s", oDir)
tree.OutputPath = oDir
// first only files
for _, f := range files {
p := d + "/" + f.Name()
if strings.HasSuffix(f.Name(), ".md") {
log.Debugf(".MD %s", p)
}
}
// only directorys, needed config before
for _, f := range files {
p := d + "/" + f.Name()
if f.IsDir() {
log.Debugf("DIR %s", p)
newTree := new(PathConfigTree)
if tree.Sub == nil {
tree.Sub = make([]*PathConfigTree, 0, 0)
}
tree.Sub = append(tree.Sub, newTree)
readContentDir(p, newConfig, newTree)
}
}
}
func main() {
spew.Config.DisablePointerAddresses = true
spew.Config.DisableCapacities = true
spew.Config.DisableMethods = true
spew.Config.DisablePointerMethods = true
inDir = flag.String("in", "./", "input directory")
outDir = flag.String("out", "html", "output directory")
createOutDir := flag.Bool("create", false, "create output directory if not existing")
//clearOutDir := flag.Bool("clear", false, "clear output directory before generating website")
logLevel := flag.String("logLevel", "info", "log level: debug, info, warning, error")
flag.Parse()
logBackend := logging.NewLogBackend(os.Stderr, "", 0)
logBackendFormatter := logging.NewBackendFormatter(logBackend, logging.MustStringFormatter(
`%{color}%{time:15:04:05.000} %{shortfunc} ▶ %{level:.4s} %{id:03x}%{color:reset} %{message}`,
))
logBackendLeveled := logging.AddModuleLevel(logBackendFormatter)
logBackendLevel := logging.INFO
if logLevel != nil {
switch *logLevel {
case "debug":
logBackendLevel = logging.DEBUG
break
case "info":
logBackendLevel = logging.INFO
break
case "warning":
logBackendLevel = logging.WARNING
break
case "error":
logBackendLevel = logging.ERROR
break
}
}
logBackendLeveled.SetLevel(logBackendLevel, "")
logging.SetBackend(logBackendLeveled)
if inDir == nil || *inDir == "" {
log.Panic("input directory not specified")
}
log.Noticef("input directory: %s", *inDir)
if outDir == nil || *outDir == "" {
log.Panic("output directory not specified")
}
log.Noticef("output directory: %s", *outDir)
if createOutDir != nil && *createOutDir {
if _, err := os.Stat(*outDir); os.IsNotExist(err) {
log.Debugf("output directory '%s' does not exist", *outDir)
log.Debugf("trying to create output directory: %s", *outDir)
err := os.MkdirAll(*outDir, 0755)
if err != nil {
log.Panic(err)
}
log.Noticef("created output directory: %s", *outDir)
} else {
log.Noticef("output directory '%s' already exists", *outDir)
}
}
if fD, err := os.Stat(*outDir); os.IsNotExist(err) {
log.Panicf("output directory '%s' does not exist, try -create parameter or create manually", *outDir)
} else {
if fD == nil {
log.Panicf("something went wrong, could not get file handle for output dir %s", *outDir)
} else if !fD.IsDir() {
log.Panicf("output directory '%s' is not a directory", *outDir)
}
}
log.Debug("reading global config...")
p := *inDir + "/config.yml"
data, err := ioutil.ReadFile(p)
if err != nil {
log.Panicf("could not read file '%s': %s", p, err)
}
err = yaml.Unmarshal(data, globalConfig)
if err != nil {
log.Panicf("could not parse YAML file '%s': %s", p, err)
}
log.Debug(spew.Sdump(globalConfig))
log.Debugf("reading input directory %s", *inDir)
readContentDir(*inDir+"/content", nil, contentConfig)
// log.Debug(spew.Sdump(contentConfig))
/*
input, err := ioutil.ReadFile("README.md")
if err != nil {
panic(err)
}
//html := blackfriday.Run(input, blackfriday.WithRenderer(bfchroma.NewRenderer()))
html := blackfriday.Run(input)
fmt.Println(string(html))
*/
}

1
vendor/github.com/davecgh/go-spew generated vendored Submodule

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

1
vendor/github.com/op/go-logging generated vendored Submodule

@ -0,0 +1 @@
Subproject commit 970db520ece77730c7e4724c61121037378659d9

1
vendor/gopkg.in/yaml.v2 generated vendored Submodule

@ -0,0 +1 @@
Subproject commit 51d6538a90f86fe93ac480b35f37b2be17fef232