fixed merge of ptr
All checks were successful
the build was successful

This commit is contained in:
Sebastian Frank 2019-02-19 18:18:40 +01:00
parent 5b5b5d8c3a
commit 12dbfd43bb
Signed by: apairon
GPG Key ID: 7270D06DDA7FE8C3
5 changed files with 300 additions and 187 deletions

160
main.go
View File

@ -6,6 +6,7 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path" "path"
"reflect"
"regexp" "regexp"
"strings" "strings"
@ -67,37 +68,42 @@ type ThisPathConfig struct {
Data interface{} `yaml:"Data"` Data interface{} `yaml:"Data"`
} }
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 // PathConfig of subdir
type PathConfig struct { type PathConfig struct {
This ThisPathConfig `yaml:"This"` This ThisPathConfig `yaml:"This"`
Template *string `yaml:"Template"`
Template *string `yaml:"Template"` Index *indexStruct `yaml:"Index"`
Meta *metaStruct `yaml:"Meta"`
Index struct { Path *pathStruct `yaml:"Path"`
InputFile *string `yaml:"InputFile"` Filename *filenameStruct `yaml:"Filename"`
OutputFile *string `yaml:"OutputFile"` Markdown *markdownStruct `yaml:"Markdown"`
} `yaml:"Index"`
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"`
Filename struct {
Strip *string `yaml:"Strip"`
Ignore *string `yaml:"Ignore"`
OutputExtension *string `yaml:"OutputExtension"`
} `yaml:"Filename"`
Markdown struct {
SyntaxHighlight *bool `yaml:"SyntaxHighlight"`
} `yaml:"Markdown"`
Data interface{} `yaml:"Data"` Data interface{} `yaml:"Data"`
} }
@ -116,6 +122,26 @@ type PathConfigTree struct {
var contentConfig = new(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 backToRoot(curNavPath string) string { func backToRoot(curNavPath string) string {
tmpPath := "" tmpPath := ""
if curNavPath != "" { if curNavPath != "" {
@ -147,7 +173,7 @@ func readContentDir(inBase string, outBase string, dir string, conf *PathConfig,
configFile := inPath + "/config.yml" configFile := inPath + "/config.yml"
if _, err = os.Stat(configFile); os.IsNotExist(err) { if _, err = os.Stat(configFile); os.IsNotExist(err) {
log.Debug("no config.yml found in this directory, using upper configs") log.Debug("no config.yml found in this directory, using upper configs")
mergo.Merge(newConfig, conf) merge(newConfig, conf)
// remove this // remove this
newConfig.This = ThisPathConfig{} newConfig.This = ThisPathConfig{}
} else { } else {
@ -163,7 +189,7 @@ func readContentDir(inBase string, outBase string, dir string, conf *PathConfig,
log.Debug("merging config with upper config") log.Debug("merging config with upper config")
oldThis := newConfig.This oldThis := newConfig.This
mergo.Merge(newConfig, conf) merge(newConfig, conf)
newConfig.This = oldThis newConfig.This = oldThis
log.Debug(spew.Sdump(newConfig)) log.Debug(spew.Sdump(newConfig))
@ -173,7 +199,10 @@ func readContentDir(inBase string, outBase string, dir string, conf *PathConfig,
// calc outDir // calc outDir
stripedDir := dir stripedDir := dir
regexStr := newConfig.Path.Strip var regexStr *string
if newConfig.Path != nil {
regexStr = newConfig.Path.Strip
}
if regexStr != nil && *regexStr != "" { if regexStr != nil && *regexStr != "" {
if regex, err := regexp.Compile(*regexStr); err != nil { if regex, err := regexp.Compile(*regexStr); err != nil {
log.Panicf("error compiling path.strip regex '%s' from '%s': %s", *regexStr, inBase+"/"+dir, err) log.Panicf("error compiling path.strip regex '%s' from '%s': %s", *regexStr, inBase+"/"+dir, err)
@ -246,7 +275,10 @@ type navElement struct {
func buildNavigation(conf *PathConfigTree, curNavMap *map[string]*navElement, curNavSlice *[]*navElement, navActive *[]*navElement, activeNav string) { func buildNavigation(conf *PathConfigTree, curNavMap *map[string]*navElement, curNavSlice *[]*navElement, navActive *[]*navElement, activeNav string) {
for _, el := range conf.Sub { for _, el := range conf.Sub {
ignNav := el.Config.Path.IgnoreForNav var ignNav *string
if p := el.Config.Path; p != nil {
ignNav = p.IgnoreForNav
}
if ignNav != nil && *ignNav != "" { if ignNav != nil && *ignNav != "" {
regex, err := regexp.Compile(*ignNav) regex, err := regexp.Compile(*ignNav)
if err != nil { if err != nil {
@ -384,19 +416,26 @@ RewriteRule ^$ %{REQUEST_URI}`+goToFixed+`/ [R,L]
log.Debug("merging config with upper config") log.Debug("merging config with upper config")
oldThis := newConfig.This oldThis := newConfig.This
mergo.Merge(newConfig, conf.Config) merge(newConfig, conf.Config)
newConfig.This = oldThis newConfig.This = oldThis
log.Debug(spew.Sdump(newConfig)) log.Debug(spew.Sdump(newConfig))
input = regex.ReplaceAll(input, []byte("")) input = regex.ReplaceAll(input, []byte(""))
} else { } else {
mergo.Merge(newConfig, conf.Config) merge(newConfig, conf.Config)
} }
// ignore ??? // ignore ???
ignoreFile := false ignoreFile := false
ignoreRegex := newConfig.Filename.Ignore var ignoreRegex *string
var stripRegex *string
var outputExt *string
if f := newConfig.Filename; f != nil {
ignoreRegex = f.Ignore
stripRegex = f.Strip
outputExt = f.OutputExtension
}
if ignoreRegex != nil && *ignoreRegex != "" { if ignoreRegex != nil && *ignoreRegex != "" {
regex, err := regexp.Compile(*ignoreRegex) regex, err := regexp.Compile(*ignoreRegex)
if err != nil { if err != nil {
@ -412,13 +451,16 @@ RewriteRule ^$ %{REQUEST_URI}`+goToFixed+`/ [R,L]
// build output filename // build output filename
outputFilename := file outputFilename := file
indexInputFile := conf.Config.Index.InputFile var indexInputFile *string
indexOutputFile := conf.Config.Index.OutputFile var indexOutputFile *string
if i := newConfig.Index; i != nil {
indexInputFile = i.InputFile
indexOutputFile = i.OutputFile
}
if indexInputFile != nil && *indexInputFile == file && indexOutputFile != nil && *indexOutputFile != "" { if indexInputFile != nil && *indexInputFile == file && indexOutputFile != nil && *indexOutputFile != "" {
outputFilename = *indexOutputFile outputFilename = *indexOutputFile
} else { } else {
stripRegex := newConfig.Filename.Strip
if stripRegex != nil && *stripRegex != "" { if stripRegex != nil && *stripRegex != "" {
regex, err := regexp.Compile(*stripRegex) regex, err := regexp.Compile(*stripRegex)
if err != nil { if err != nil {
@ -426,7 +468,6 @@ RewriteRule ^$ %{REQUEST_URI}`+goToFixed+`/ [R,L]
} }
outputFilename = regex.ReplaceAllString(outputFilename, "$1") outputFilename = regex.ReplaceAllString(outputFilename, "$1")
} }
outputExt := newConfig.Filename.OutputExtension
if outputExt != nil && *outputExt != "" { if outputExt != nil && *outputExt != "" {
outputFilename += "." + *outputExt outputFilename += "." + *outputExt
} }
@ -437,10 +478,23 @@ RewriteRule ^$ %{REQUEST_URI}`+goToFixed+`/ [R,L]
var options []blackfriday.Option var options []blackfriday.Option
synH := conf.Config.Markdown.SyntaxHighlight var chromaRenderer *bool
if synH != nil && *synH { var chromaStyle *string
if m := newConfig.Markdown; m != nil {
chromaRenderer = m.ChromaRenderer
chromaStyle = m.ChromaStyle
}
if chromaStyle == nil {
style := "monokai"
chromaStyle = &style
}
if chromaRenderer != nil && *chromaRenderer {
options = []blackfriday.Option{ options = []blackfriday.Option{
blackfriday.WithRenderer(bfchroma.NewRenderer()), blackfriday.WithRenderer(
bfchroma.NewRenderer(
bfchroma.Style(*chromaStyle),
),
),
} }
} }
@ -665,13 +719,19 @@ func main() {
defaultPathConfig := new(PathConfig) defaultPathConfig := new(PathConfig)
defaultPathConfig.Template = &defaultTemplate defaultPathConfig.Template = &defaultTemplate
defaultPathConfig.Index.InputFile = &defaultInputFile defaultPathConfig.Index = &indexStruct{
defaultPathConfig.Index.OutputFile = &defaultOutputFile InputFile: &defaultInputFile,
defaultPathConfig.Path.Strip = &defaultPathStrip OutputFile: &defaultOutputFile,
defaultPathConfig.Path.IgnoreForNav = &defaultPathIgnoreForNav }
defaultPathConfig.Filename.Strip = &defaultFilenameStrip defaultPathConfig.Path = &pathStruct{
defaultPathConfig.Filename.Ignore = &defaultFilenameIgnore Strip: &defaultPathStrip,
defaultPathConfig.Filename.OutputExtension = &defaultFilenameOutputExtension IgnoreForNav: &defaultPathIgnoreForNav,
}
defaultPathConfig.Filename = &filenameStruct{
Strip: &defaultFilenameStrip,
Ignore: &defaultFilenameIgnore,
OutputExtension: &defaultFilenameOutputExtension,
}
readContentDir(*inDir+"/content", *outDir, "", defaultPathConfig, contentConfig) readContentDir(*inDir+"/content", *outDir, "", defaultPathConfig, contentConfig)
//spew.Dump(contentConfig) //spew.Dump(contentConfig)

View File

@ -7,4 +7,5 @@ Meta:
Keywords: mark2web, Website, HTML, markdown, Generator, CMS, Content-Management-System Keywords: mark2web, Website, HTML, markdown, Generator, CMS, Content-Management-System
Markdown: Markdown:
SyntaxHighlight: True ChromaRenderer: True
ChromaStyle: monokai

View File

@ -1,7 +1,41 @@
---
Markdown:
ChromaRenderer: False
---
# mark2web # mark2web
mark2web ist ein Generator, der aus Markdown- und Konfig-Dateien in einer Ordnerstruktur eine statische Website unter Zuhilfenahme von Templates generiert. mark2web ist ein Generator, der aus Markdown- und Konfig-Dateien in einer Ordnerstruktur eine statische Website unter Zuhilfenahme von Templates generiert.
```mermaid
graph TD
C(Konfiguration)
M(Markdown)
A(Assets)
D(Templates)
2(mark2web)
W(Website)
C==>2
M==>2
A==>2
D==>2
2==>W
style 2 fill:#b5c50f,stroke:#000
classDef in fill:#464645,color:#fff,stroke:#000
classDef out stroke-width:5px,stroke:#b5c50f,fill:#ccc
class M,C,D,A in
class W out
```
<script defer>
window.onload = function() {
mermaid.init(undefined,$("code.language-mermaid"));
};
</script>
--- ---
Der Generator selbst wurde in [Go](https://golang.org/) geschrieben. Es wurden dabei eine Vielzahl existierender Packages verwendet. Unter Anderem: Der Generator selbst wurde in [Go](https://golang.org/) geschrieben. Es wurden dabei eine Vielzahl existierender Packages verwendet. Unter Anderem:

View File

@ -11,86 +11,102 @@ Nachfolgend ist ein Beispiel eines Templates:
```django ```django
<html> <html>
<meta> <meta>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>{{ Meta.Title }}</title> <title>{{ Meta.Title }}</title>
<meta name="description" content="{{ Meta.Description }}" /> <meta name="description" content="{{ Meta.Description }}" />
<meta name="keywords" content="{{ Meta.Keywords }}" /> <meta name="keywords" content="{{ Meta.Keywords }}" />
<link rel="stylesheet" type="text/css" href="../assets/css/main.css"> <link rel="stylesheet" type="text/css" href="../assets/css/main.css">
</meta> </meta>
<body> <body>
{% block header %} {% block header %}
<header> <header>
<div class="langSelect"> <div class="langSelect">
{% for nav in NavSlice %} {% for nav in NavSlice %}
<a href="{{ nav.GoTo }}" {% if nav.Active %}class="active"{% endif %}><img src="../assets/img/{{ nav.Navname }}.png" alt="{{ nav.Navname }}" style="height: 20px;"></a> <a href="{{ nav.GoTo }}" {% if nav.Active %}class="active"{% endif %}>
<img src="../assets/img/{{ nav.Navname }}.png" alt="{{ nav.Navname }}" style="height: 20px;">
</a>
{% endfor %}
</div>
<div id="logoDiv"><img src="../assets/img/logo.png"></div>
<div id="mainNavDiv" class="nav">
<table border="0" style="width: 100%">
<tr>
<td>
<div><b>main Level 1 ...</b></div>
<ul>
{% for nav in NavActive.0.SubMap.main.SubSlice %}
<li {% if nav.Active %}class="active"{% endif %}>
<a href="{{ nav.GoTo }}" title="{{ nav.This.Data.hoverText }}">
{{ nav.Navname }}
</a>
{% if nav.SubSlice %}
<ul>
{% for nav2 in nav.SubSlice %}
<li {% if nav2.Active %}class="active"{% endif %}>
<a href="{{ nav2.GoTo }}" title="{{ nav2.This.Data.hoverText }}">
{{ nav2.Navname }}
</a>
</li>
{% endfor %}
</ul
{% endif %}
</li>
{% endfor %} {% endfor %}
</div> </ul>
<div id="logoDiv"><img src="../assets/img/logo.png"></div> </td>
<div id="mainNavDiv" class="nav"> <td>
<table border="0" style="width: 100%"> <div><b>main/service Level 2</b></div>
<tr> <ul>
<td> {% for nav in NavActive.2.SubSlice %}
<div><b>main Level 1 ...</b></div> <li {% if nav.Active %}class="active"{% endif %}>
<ul> <a href="{{ nav.GoTo }}" title="{{ nav.This.Data.hoverText }}">
{% for nav in NavActive.0.SubMap.main.SubSlice %} {{ nav.Navname }}
<li {% if nav.Active %}class="active"{% endif %}><a href="{{ nav.GoTo }}" title="{{ nav.This.Data.hoverText }}">{{ nav.Navname }}</a> </a>
{% if nav.SubSlice %} </li>
<ul>
{% for nav2 in nav.SubSlice %}
<li {% if nav2.Active %}class="active"{% endif %}><a href="{{ nav2.GoTo }}" title="{{ nav2.This.Data.hoverText }}">{{ nav2.Navname }}</a>
</li>
{% endfor %}
</ul
{% endif %}
</li>
{% endfor %}
</ul>
</td>
<td>
<div><b>main/service Level 2</b></div>
<ul>
{% for nav in NavActive.2.SubSlice %}
<li {% if nav.Active %}class="active"{% endif %}><a href="{{ nav.GoTo }}" title="{{ nav.This.Data.hoverText }}">{{ nav.Navname }}</a>
</li>
{% endfor %}
</ul>
</td>
</tr>
</table>
</div>
</header>
{% endblock %}
{% block breadcrumb %}
<div id="breadcrumb">
{% for nav in NavActive %}
<a href="{{ nav.GoTo }}" title="{{ nav.This.Data.hoverText }}">{{ nav.Navname }}</a>
{% endfor %}
</div>
{% endblock %}
{% block content %}
<div id="content">
{{ Body }}
</div>
{% endblock %}
{% block footer %}
<footer class="nav">
<div><b>service Level 1</b></div>
<ul>
{% for nav in NavActive.0.SubMap.service.SubSlice %}
<li {% if nav.Active %}class="active"{% endif %}><a href="{{ nav.GoTo }}" title="{{ nav.This.Data.hoverText }}">{{ nav.Navname }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
</footer> </td>
{% endblock %} </tr>
</table>
</div>
</header>
{% endblock %}
</body>
{% block breadcrumb %}
<div id="breadcrumb">
{% for nav in NavActive %}
<a href="{{ nav.GoTo }}" title="{{ nav.This.Data.hoverText }}">
{{ nav.Navname }}
</a>
{% endfor %}
</div>
{% endblock %}
{% block content %}
<div id="content">
{{ Body }}
</div>
{% endblock %}
{% block footer %}
<footer class="nav">
<div><b>service Level 1</b></div>
<ul>
{% for nav in NavActive.0.SubMap.service.SubSlice %}
<li {% if nav.Active %}class="active"{% endif %}>
<a href="{{ nav.GoTo }}" title="{{ nav.This.Data.hoverText }}">
{{ nav.Navname }}</a>
</li>
{% endfor %}
</ul>
</footer>
{% endblock %}
</body>
</html> </html>
``` ```
@ -111,7 +127,7 @@ Blockanweisungen dagegen verwenden zum Beispiel folgende Platzhalter:
```django ```django
{% if Variable %} {% if Variable %}
... ...
{% endif %} {% endif %}
``` ```
@ -164,13 +180,13 @@ wird für `{{ Body }}` folgendes HTML:
```django ```django
<table> <table>
<tr> <tr>
{% for part in BodyParts %} {% for part in BodyParts %}
<td> <td>
{{ part }} {{ part }}
</td> </td>
{% endfor %} {% endfor %}
</tr> </tr>
</table> </table>
``` ```
@ -178,16 +194,16 @@ Aus dem Template wird nach dem Rendern mit obiger Markdown-Datei also folgendes
```html ```html
<table> <table>
<tr> <tr>
<td> <td>
<h1>Titel 1</h1> <h1>Titel 1</h1>
<p>Text 1</p> <p>Text 1</p>
</td> </td>
<td> <td>
<h2>Titel 2</h2> <h2>Titel 2</h2>
<p>Text 2</p> <p>Text 2</p>
</td> </td>
</tr> </tr>
</table> </table>
``` ```
@ -199,16 +215,16 @@ Jedes Navigationselement steht intern in folgender go-Struktur zur Verfügung:
```go ```go
type navElement struct { type navElement struct {
Navname string Navname string
GoTo string GoTo string
Active bool Active bool
Data interface{} Data interface{}
This ThisPathConfig This ThisPathConfig
SubMap *map[string]*navElement SubMap *map[string]*navElement
SubSlice *[]*navElement SubSlice *[]*navElement
} }
``` ```
@ -220,24 +236,24 @@ Wird z.B. folgende Navigation als Zielverzeichnis-Struktur angenommen:
```plain ```plain
de de
main main
home home
leistungen leistungen
referenzen referenzen
service service
impressum impressum
en en
main main
home home
... ...
``` ```
Der Teasertext aus folgender `config.yml` im `content`-Verzeichnis `de/main/02_Leistungen` Der Teasertext aus folgender `config.yml` im `content`-Verzeichnis `de/main/02_Leistungen`
```yaml ```yaml
This: This:
Data: Data:
teaser: Teasertext teaser: Teasertext
``` ```
welcher zum Navigationspunkt im Zielpfad *de/main/leistungen* gehört, ist über folgende Template-Variablen erreichbar: welcher zum Navigationspunkt im Zielpfad *de/main/leistungen* gehört, ist über folgende Template-Variablen erreichbar:
@ -258,11 +274,11 @@ Natürlich wird diese Variable in der Form so nie verwendet, sondern soll nur de
```django ```django
<ul> <ul>
{% for lang in NavMap %} {% for lang in NavMap %}
<li {% if lang.Active %}class="active"{% endif %}> <li {% if lang.Active %}class="active"{% endif %}>
<a href="{{ lang.GoTo }}">{{ lang.Navname }}</a> <a href="{{ lang.GoTo }}">{{ lang.Navname }}</a>
</li> </li>
{% endfor %} {% endfor %}
</ul> </ul>
``` ```
@ -291,9 +307,9 @@ Somit lassen sich leicht Pfade anzeigen, bzw. Breadcrumbs in die Website einbind
```django ```django
aktiver Pfad: aktiver Pfad:
{% for nav in NavActive %} {% for nav in NavActive %}
<a href="{{ nav.GoTo }}" title="{{ nav.This.Data.hoverText }}">{{ nav.Navname }}</a> <a href="{{ nav.GoTo }}" title="{{ nav.This.Data.hoverText }}">{{ nav.Navname }}</a>
{% endfor %} {% endfor %}
``` ```
Ebenso lässt sich bei mehrsprachigen Seite immer die richte Hauptnavigation zur aktuelle Sprache laden: Ebenso lässt sich bei mehrsprachigen Seite immer die richte Hauptnavigation zur aktuelle Sprache laden:
@ -301,24 +317,24 @@ Ebenso lässt sich bei mehrsprachigen Seite immer die richte Hauptnavigation zur
```django ```django
<h3>Hauptnavigation</h3> <h3>Hauptnavigation</h3>
<ul> <ul>
{% for nav in NavActive.0.SubMap.main.SubSlice %} {% for nav in NavActive.0.SubMap.main.SubSlice %}
<li {% if nav.Active %}class="active"{% endif %}> <li {% if nav.Active %}class="active"{% endif %}>
<a href="{{ nav.GoTo }}" title="{{ nav.This.Data.hoverText }}"> <a href="{{ nav.GoTo }}" title="{{ nav.This.Data.hoverText }}">
{{ nav.Navname }} {{ nav.Navname }}
</a>
{% if nav.SubSlice %}
<ul>
{% for nav2 in nav.SubSlice %}
<li {% if nav2.Active %}class="active"{% endif %}>
<a href="{{ nav2.GoTo }}" title="{{ nav2.This.Data.hoverText }}">
{{ nav2.Navname }}
</a> </a>
{% if nav.SubSlice %} </li>
<ul> {% endfor %}
{% for nav2 in nav.SubSlice %} </ul
<li {% if nav2.Active %}class="active"{% endif %}> {% endif %}
<a href="{{ nav2.GoTo }}" title="{{ nav2.This.Data.hoverText }}"> </li>
{{ nav2.Navname }} {% endfor %}
</a>
</li>
{% endfor %}
</ul
{% endif %}
</li>
{% endfor %}
</ul> </ul>
``` ```

View File

@ -166,6 +166,8 @@
<script src="project-files/js/preloader.js"></script> <script src="project-files/js/preloader.js"></script>
<script src="project-files/js/functions.js"></script> <script src="project-files/js/functions.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mermaid/8.0.0/mermaid.min.js"></script>
</body> </body>
</html> </html>