diff --git a/.gitmodules b/.gitmodules index 2b75f67..b5122f9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -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 diff --git a/README.md b/README.md index 548f526..029876d 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/example/config.yml b/example/config.yml new file mode 100644 index 0000000..d7ba927 --- /dev/null +++ b/example/config.yml @@ -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 used diff --git a/example/content/config.yml b/example/content/config.yml new file mode 100644 index 0000000..85831d4 --- /dev/null +++ b/example/content/config.yml @@ -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: "^_" diff --git a/example/content/de/main/01_home/README.md b/example/content/de/main/01_home/README.md new file mode 100644 index 0000000..59914c1 --- /dev/null +++ b/example/content/de/main/01_home/README.md @@ -0,0 +1,8 @@ +--- +navname: Home + +--- + +# Home + +Lorem ipsum... \ No newline at end of file diff --git a/example/content/de/main/02_leistungen/README.md b/example/content/de/main/02_leistungen/README.md new file mode 100644 index 0000000..b782437 --- /dev/null +++ b/example/content/de/main/02_leistungen/README.md @@ -0,0 +1,8 @@ +--- +navname: Leistungen + +--- + +# Leistungen + +Lorem ipsum... \ No newline at end of file diff --git a/example/content/de/main/03_kontakt/01_adresse/README.md b/example/content/de/main/03_kontakt/01_adresse/README.md new file mode 100644 index 0000000..d64bab2 --- /dev/null +++ b/example/content/de/main/03_kontakt/01_adresse/README.md @@ -0,0 +1,8 @@ +--- +navname: Adresse + +--- + +# Adresse + +Lorem ipsum... \ No newline at end of file diff --git a/example/content/de/main/03_kontakt/02_anfahrt/README.md b/example/content/de/main/03_kontakt/02_anfahrt/README.md new file mode 100644 index 0000000..5d9a654 --- /dev/null +++ b/example/content/de/main/03_kontakt/02_anfahrt/README.md @@ -0,0 +1,8 @@ +--- +navname: Anfahrt + +--- + +# Anfahrt + +Lorem ipsum... \ No newline at end of file diff --git a/example/content/de/main/03_kontakt/config.yml b/example/content/de/main/03_kontakt/config.yml new file mode 100644 index 0000000..8d44797 --- /dev/null +++ b/example/content/de/main/03_kontakt/config.yml @@ -0,0 +1 @@ +goTo: adresse/ \ No newline at end of file diff --git a/example/content/de/main/04_impressum/config.yml b/example/content/de/main/04_impressum/config.yml new file mode 100644 index 0000000..aa58544 --- /dev/null +++ b/example/content/de/main/04_impressum/config.yml @@ -0,0 +1 @@ +goTo: /de/service/impressum/ \ No newline at end of file diff --git a/example/content/de/service/01_datenschutz/README.md b/example/content/de/service/01_datenschutz/README.md new file mode 100644 index 0000000..7dfae0a --- /dev/null +++ b/example/content/de/service/01_datenschutz/README.md @@ -0,0 +1,8 @@ +--- +navname: Datenschutz + +--- + +# Datenshutz + +Lorem ipsum... \ No newline at end of file diff --git a/example/content/de/service/02_agb/README.md b/example/content/de/service/02_agb/README.md new file mode 100644 index 0000000..c463439 --- /dev/null +++ b/example/content/de/service/02_agb/README.md @@ -0,0 +1,8 @@ +--- +navname: AGB's + +--- + +# AGB's + +Lorem ipsum... \ No newline at end of file diff --git a/example/content/de/service/03_impressum/README.md b/example/content/de/service/03_impressum/README.md new file mode 100644 index 0000000..8b11259 --- /dev/null +++ b/example/content/de/service/03_impressum/README.md @@ -0,0 +1,8 @@ +--- +navname: Impressum + +--- + +# Impressum + +Lorem ipsum... \ No newline at end of file diff --git a/example/content/en/main/01_home/README.md b/example/content/en/main/01_home/README.md new file mode 100644 index 0000000..59914c1 --- /dev/null +++ b/example/content/en/main/01_home/README.md @@ -0,0 +1,8 @@ +--- +navname: Home + +--- + +# Home + +Lorem ipsum... \ No newline at end of file diff --git a/example/content/en/main/02_services/README.md b/example/content/en/main/02_services/README.md new file mode 100644 index 0000000..5803efc --- /dev/null +++ b/example/content/en/main/02_services/README.md @@ -0,0 +1,8 @@ +--- +navname: Services + +--- + +# Services + +Lorem ipsum... \ No newline at end of file diff --git a/example/content/en/main/03_contact/README.md b/example/content/en/main/03_contact/README.md new file mode 100644 index 0000000..328e299 --- /dev/null +++ b/example/content/en/main/03_contact/README.md @@ -0,0 +1,8 @@ +--- +navname: Contact + +--- + +# Contact + +Lorem ipsum... \ No newline at end of file diff --git a/example/content/en/main/04_imprint/config.yml b/example/content/en/main/04_imprint/config.yml new file mode 100644 index 0000000..28d09f9 --- /dev/null +++ b/example/content/en/main/04_imprint/config.yml @@ -0,0 +1 @@ +goTo: /en/service/imprint/ \ No newline at end of file diff --git a/example/content/en/service/01_terms/README.md b/example/content/en/service/01_terms/README.md new file mode 100644 index 0000000..b758afd --- /dev/null +++ b/example/content/en/service/01_terms/README.md @@ -0,0 +1,8 @@ +--- +navname: Terms + +--- + +# Terms + +Lorem ipsum... \ No newline at end of file diff --git a/example/content/en/service/02_imprint/README.md b/example/content/en/service/02_imprint/README.md new file mode 100644 index 0000000..05bd9ec --- /dev/null +++ b/example/content/en/service/02_imprint/README.md @@ -0,0 +1,8 @@ +--- +navname: Imprint + +--- + +# Imprint + +Lorem ipsum... \ No newline at end of file diff --git a/main.go b/main.go index f5b2338..fa98638 100644 --- a/main.go +++ b/main.go @@ -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)) + */ } diff --git a/vendor/github.com/davecgh/go-spew b/vendor/github.com/davecgh/go-spew new file mode 160000 index 0000000..d8f796a --- /dev/null +++ b/vendor/github.com/davecgh/go-spew @@ -0,0 +1 @@ +Subproject commit d8f796af33cc11cb798c1aaeb27a4ebc5099927d diff --git a/vendor/github.com/op/go-logging b/vendor/github.com/op/go-logging new file mode 160000 index 0000000..970db52 --- /dev/null +++ b/vendor/github.com/op/go-logging @@ -0,0 +1 @@ +Subproject commit 970db520ece77730c7e4724c61121037378659d9 diff --git a/vendor/gopkg.in/yaml.v2 b/vendor/gopkg.in/yaml.v2 new file mode 160000 index 0000000..51d6538 --- /dev/null +++ b/vendor/gopkg.in/yaml.v2 @@ -0,0 +1 @@ +Subproject commit 51d6538a90f86fe93ac480b35f37b2be17fef232