collections via markdown files
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Sebastian Frank
2019-03-22 17:22:03 +01:00
parent 4a9a3eec06
commit ff1da084af
46 changed files with 547 additions and 362 deletions

View File

@@ -130,7 +130,7 @@ func ImageProcessFilter(in *pongo2.Value, param *pongo2.Value) (*pongo2.Value, *
}
} else {
// local file
imgSource = mark2web.ResolveInputPath(imgSource)
imgSource = mark2web.CurrentTreeNode.ResolveInputPath(imgSource)
if p.Filename == "" {
p.Filename = fmt.Sprintf(
"%s_%s",
@@ -142,7 +142,7 @@ func ImageProcessFilter(in *pongo2.Value, param *pongo2.Value) (*pongo2.Value, *
var imgTarget string
if p.TargetDir != "" {
imgTarget = mark2web.ResolveOutputPath(
imgTarget = mark2web.CurrentTreeNode.ResolveOutputPath(
path.Clean(p.TargetDir) + "/" +
p.Filename,
)
@@ -158,10 +158,10 @@ func ImageProcessFilter(in *pongo2.Value, param *pongo2.Value) (*pongo2.Value, *
}
}
p.Filename = mark2web.ResolveNavPath(p.TargetDir + "/" + p.Filename)
p.Filename = mark2web.CurrentTreeNode.ResolveNavPath(p.TargetDir + "/" + p.Filename)
} else {
imgTarget = mark2web.ResolveOutputPath(p.Filename)
imgTarget = mark2web.CurrentTreeNode.ResolveOutputPath(p.Filename)
}
if f, err := os.Stat(imgTarget); err == nil && !f.IsDir() {
@@ -226,5 +226,5 @@ func ImageProcessFilter(in *pongo2.Value, param *pongo2.Value) (*pongo2.Value, *
helper.Log.Noticef("finished image: %s", imgTarget)
})
}
return pongo2.AsValue(mark2web.ResolveNavPath(p.Filename)), nil
return pongo2.AsValue(mark2web.CurrentTreeNode.ResolveNavPath(p.Filename)), nil
}

View File

@@ -36,9 +36,6 @@ func TestImageProcessFilter(t *testing.T) {
},
},
}
mark2web.CurrentContext = &pongo2.Context{
"CurrentPath": "",
}
os.Remove("../../test/out/fit_300x300_q060_test.jpg")

View File

@@ -8,7 +8,7 @@ import (
// RelativePathFilter returns the relative path to navpoint based on current nav
func RelativePathFilter(in, param *pongo2.Value) (*pongo2.Value, *pongo2.Error) {
return pongo2.AsValue(
mark2web.ResolveNavPath(
mark2web.CurrentTreeNode.ResolveNavPath(
in.String(),
),
), nil

View File

@@ -17,10 +17,23 @@ func TestRelativePathFilter(t *testing.T) {
"testabs": "/abs",
"testsub": "../sub/rel",
}
mark2web.Config.Directories.Output = "../../test/out"
mark2web.CurrentTreeNode = &mark2web.TreeNode{
InputPath: "../../test/in/content",
OutputPath: "../../test/out/sub",
Config: &mark2web.PathConfig{
Imaging: &mark2web.ImagingConfig{
Quality: 60,
Height: 300,
Width: 300,
Process: "fit",
},
},
}
Convey("parse template", func() {
mark2web.CurrentContext = &pongo2.Context{
"CurrentPath": "sub",
}
output, err := pongo2.RenderTemplateString("{{ testrel|relative_path }}", ctx)
So(err, ShouldBeNil)

View File

@@ -2,7 +2,6 @@ package helper
import (
"os"
"strings"
)
// CreateDirectory creates direcory with all missing parents and panic if error
@@ -25,14 +24,3 @@ func CreateDirectory(dir string) {
Log.Panicf("unknown error for output directory '%s': %s", dir, err)
}
}
// BackToRoot builds ../../ string
func BackToRoot(curNavPath string) string {
tmpPath := ""
if curNavPath != "" {
for i := strings.Count(curNavPath, "/") + 1; i > 0; i-- {
tmpPath += "../"
}
}
return tmpPath
}

18
pkg/helper/regexp.go Normal file
View File

@@ -0,0 +1,18 @@
package helper
import "regexp"
// GetRegexpParams gets a map of named regexp group matches
// use pe. (?P<Year>\d{4})-(?P<Month>\d{2})-(?P<Day>\d{2}) as regexp
func GetRegexpParams(regEx *regexp.Regexp, str string) (paramsMap map[string]string) {
match := regEx.FindStringSubmatch(str)
paramsMap = make(map[string]string)
for i, name := range regEx.SubexpNames() {
if i > 0 && i <= len(match) {
paramsMap[name] = match[i]
}
}
return
}

View File

@@ -35,13 +35,13 @@ func ProcessAssets() {
}
// fixAssetsPath replaces assets path based on current path
func fixAssetsPath(str, curNavPath string) string {
func (node *TreeNode) fixAssetsPath(str string) string {
if find := Config.Assets.FixTemplate.Find; find != "" {
helper.Log.Debugf("fixing assets paths for path '%s'", curNavPath)
helper.Log.Debugf("fixing assets paths for path '%s'", node.CurrentNavPath())
repl := Config.Assets.FixTemplate.Replace
toPath := Config.Assets.ToPath
bToRoot := helper.BackToRoot(curNavPath)
bToRoot := node.BackToRootPath()
regex, err := regexp.Compile(find)
if err != nil {
log.Panicf("could not compile regexp '%s' for assets path: %s", find, err)

View File

@@ -1,7 +1,9 @@
package mark2web
import (
"io/ioutil"
"path"
"regexp"
"strings"
"gitbase.de/apairon/mark2web/pkg/helper"
@@ -20,13 +22,12 @@ var colCache = make(map[string]*colCacheEntry)
func (node *TreeNode) handleCollections() {
collections := append(node.Config.Collections, node.Config.This.Collections...)
for _, colConfig := range collections {
if colConfig != nil {
if colConfig.Name == nil || *colConfig.Name == "" {
helper.Log.Panicf("missing Name in collection config in '%s'", node.InputPath)
}
if colConfig.URL == nil || *colConfig.URL == "" {
helper.Log.Panicf("missing EntriesJSON in collection config in '%s'", node.InputPath)
}
if colConfig.Name == nil || *colConfig.Name == "" {
helper.Log.Panicf("missing Name in collection config in '%s'", node.InputPath)
}
if (colConfig.URL == nil || *colConfig.URL == "") &&
(colConfig.Directory == nil) {
helper.Log.Panicf("missing URL and Directory in collection config in '%s'", node.InputPath)
}
if node.ColMap == nil {
@@ -36,21 +37,73 @@ func (node *TreeNode) handleCollections() {
ctx["This"] = node.Config.This
ctx["Data"] = node.Config.Data
url, err := pongo2.RenderTemplateString(*colConfig.URL, ctx)
if err != nil {
helper.Log.Panicf("invalid template string for Collection Element.URL in '%s': %s", node.InputPath, err)
}
var colData interface{}
if cacheEntry, ok := colCache[url]; ok {
colData = cacheEntry.data
cacheEntry.hit++
} else {
colData = helper.JSONWebRequest(url)
colCache[url] = &colCacheEntry{
data: colData,
navnames: make([]string, 0),
errSrcText := ""
cacheKey := ""
if colConfig.URL != nil {
url, err := pongo2.RenderTemplateString(*colConfig.URL, ctx)
if err != nil {
helper.Log.Panicf("invalid template string for Collection Element.URL in '%s': %s", node.InputPath, err)
}
errSrcText = "URL " + url
cacheKey = url
if cacheEntry, ok := colCache[url]; ok {
colData = cacheEntry.data
cacheEntry.hit++
} else {
helper.Log.Noticef("reading collection from: %s", errSrcText)
colData = helper.JSONWebRequest(url)
colCache[url] = &colCacheEntry{
data: colData,
navnames: make([]string, 0),
}
}
} else {
path := node.ResolveInputPath(colConfig.Directory.Path)
errSrcText = "DIR " + path
helper.Log.Noticef("reading collection from: %s", errSrcText)
d, err := ioutil.ReadDir(path)
if err != nil {
helper.Log.Panicf("could not read directory '%s': %s", path, err)
}
mStr := "."
if colConfig.Directory.MatchFilename != "" {
mStr = colConfig.Directory.MatchFilename
}
matcher, err := regexp.Compile(mStr)
if err != nil {
helper.Log.Panicf("could not compile regex for MatchFilename '%s' in '%s': %s", mStr, path, err)
}
if colConfig.Directory.ReverseOrder {
for i := len(d)/2 - 1; i >= 0; i-- {
opp := len(d) - 1 - i
d[i], d[opp] = d[opp], d[i]
}
}
fcolData := make([]pongo2.Context, 0)
for _, fh := range d {
if !fh.IsDir() && matcher.MatchString(fh.Name()) {
inFile := path + "/" + fh.Name()
md, err := ioutil.ReadFile(inFile)
if err != nil {
helper.Log.Panicf("could not read file '%s': %s", inFile, err)
}
_, ctx := node.processMarkdownWithHeader(md, inFile)
(*ctx)["FilenameMatch"] = helper.GetRegexpParams(matcher, fh.Name())
fcolData = append(fcolData, *ctx)
}
}
colData = fcolData
}
node.ColMap[*colConfig.Name] = colData
@@ -64,7 +117,7 @@ func (node *TreeNode) handleCollections() {
entries, ok = colDataMap[navT.EntriesAttribute].([]interface{})
if !ok {
helper.Log.Debug(spew.Sdump(colDataMap))
helper.Log.Panicf("invalid json data in [%s] from url '%s' for entries", navT.EntriesAttribute, url)
helper.Log.Panicf("invalid json data in [%s] from '%s' for entries", navT.EntriesAttribute, errSrcText)
}
}
} else {
@@ -72,7 +125,7 @@ func (node *TreeNode) handleCollections() {
}
if !ok {
helper.Log.Debug(spew.Sdump(colData))
helper.Log.Panicf("invalid json data from url '%s', need array of objects for entries or object with configured NavTemplate.EntriesAttribute", url)
helper.Log.Panicf("invalid json data from '%s', need array of objects for entries or object with configured NavTemplate.EntriesAttribute", errSrcText)
}
// build navigation with detail sites
@@ -85,7 +138,7 @@ func (node *TreeNode) handleCollections() {
var jsonCtx map[string]interface{}
if jsonCtx, ok = colEl.(map[string]interface{}); !ok {
helper.Log.Debug(spew.Sdump(colEl))
helper.Log.Panicf("no json object for entry index %d from url '%s'", idx, url)
helper.Log.Panicf("no json object for entry index %d from '%s'", idx, errSrcText)
}
err = helper.Merge(&ctxE, pongo2.Context(jsonCtx))
if err != nil {
@@ -143,14 +196,14 @@ func (node *TreeNode) handleCollections() {
}
}
if l := len(colCache[url].navnames); colCache[url].hit > 1 &&
if l := len(colCache[cacheKey].navnames); colCache[cacheKey].hit > 1 &&
l > 0 &&
navname == colCache[url].navnames[l-1] {
navname == colCache[cacheKey].navnames[l-1] {
// navname before used same url, so recursion loop
helper.Log.Panicf("collection request loop detected for in '%s' for url: %s", node.InputPath, url)
helper.Log.Panicf("collection request loop detected for in '%s' for : %s", node.InputPath, errSrcText)
}
colCache[url].navnames = append(colCache[url].navnames, navname)
colCache[cacheKey].navnames = append(colCache[cacheKey].navnames, navname)
node.addSubNode(tpl, goTo, navname, colEl, dataKey, body, navT.Hidden)
}

View File

@@ -2,10 +2,18 @@ package mark2web
import "gitbase.de/apairon/mark2web/pkg/helper"
// CollectionDirectoryConfig specifies how to handle a directory of markdown files as a collection
type CollectionDirectoryConfig struct {
Path string `yaml:"Path"`
MatchFilename string `yaml:"MatchFilename"`
ReverseOrder bool `yaml:"ReverseOrder"`
}
// CollectionConfig describes a collection
type CollectionConfig struct {
Name *string `yaml:"Name"`
URL *string `yaml:"URL"`
Name *string `yaml:"Name"`
URL *string `yaml:"URL"`
Directory *CollectionDirectoryConfig `yaml:"Directory"`
NavTemplate *struct {
EntriesAttribute string `yaml:"EntriesAttribute"`
GoTo string `yaml:"GoTo"`

View File

@@ -65,24 +65,104 @@ func (node *TreeNode) ReadContentDir(inBase string, outBase string, dir string,
}
}
func (node *TreeNode) processMarkdownWithHeader(md []byte, errorRef string) (*PathConfig, *pongo2.Context) {
newConfig := new(PathConfig)
headerRegex := regexp.MustCompile("(?s)^---(.*?)\\r?\\n\\r?---\\r?\\n\\r?")
yamlData := headerRegex.Find(md)
if string(yamlData) != "" {
// replace tabs
yamlData = bytes.Replace(yamlData, []byte("\t"), []byte(" "), -1)
helper.Log.Debugf("found yaml header in '%s', merging config", errorRef)
err := yaml.Unmarshal(yamlData, newConfig)
if err != nil {
helper.Log.Panicf("could not parse YAML header from '%s': %s", errorRef, err)
}
helper.Log.Debug("merging config with upper config")
oldThis := newConfig.This
helper.Merge(newConfig, node.Config)
newConfig.This = oldThis
helper.Log.Debug(spew.Sdump(newConfig))
md = headerRegex.ReplaceAll(md, []byte(""))
} else {
helper.Merge(newConfig, node.Config)
}
// use --- for splitting document in markdown parts
regex := regexp.MustCompile("\\r?\\n\\r?---\\r?\\n\\r?")
inputParts := regex.Split(string(md), -1)
htmlParts := make([]*pongo2.Value, 0)
chromaRenderer := false
chromaStyle := "monokai"
if m := newConfig.Markdown; m != nil {
if m.ChromaRenderer != nil && *m.ChromaRenderer {
chromaRenderer = true
}
if m.ChromaStyle != nil && *m.ChromaStyle != "" {
chromaStyle = *m.ChromaStyle
}
}
for _, iPart := range inputParts {
htmlParts = append(htmlParts,
pongo2.AsSafeValue(
string(helper.RenderMarkdown([]byte(iPart), chromaRenderer, chromaStyle))))
}
// build navigation
navMap := make(map[string]*NavElement)
navSlice := make([]*NavElement, 0)
navActive := make([]*NavElement, 0)
node.buildNavigation(&navMap, &navSlice, &navActive)
// read yaml header as data for template
ctx := NewContext()
ctx["This"] = newConfig.This
ctx["Meta"] = newConfig.Meta
ctx["Markdown"] = newConfig.Markdown
ctx["Data"] = newConfig.Data
ctx["ColMap"] = node.root.ColMap // root as NavMap and NavSlice, for sub go to NavElement.ColMap
ctx["NavMap"] = navMap
ctx["NavSlice"] = navSlice
ctx["NavActive"] = navActive
ctx["Body"] = pongo2.AsSafeValue(string(helper.RenderMarkdown(md, chromaRenderer, chromaStyle)))
ctx["BodyParts"] = htmlParts
ctx["CurrentPath"] = node.CurrentNavPath()
// set active nav element
if len(navActive) > 0 {
ctx["NavElement"] = navActive[len(navActive)-1]
} else {
// if no active path to content, we are in root dir
ctx["NavElement"] = &NavElement{
GoTo: node.BackToRootPath(),
Active: true,
ColMap: node.ColMap,
Data: node.Config.Data,
This: node.Config.This,
SubMap: &navMap,
SubSlice: &navSlice,
}
}
return newConfig, &ctx
}
// ProcessContent walks recursivly through the input paths and processes all files for output
func (node *TreeNode) ProcessContent() {
helper.CreateDirectory(node.OutputPath)
curNavPath := strings.TrimPrefix(node.OutputPath, Config.Directories.Output)
curNavPath = strings.TrimPrefix(curNavPath, "/")
curNavPath = path.Clean(curNavPath)
if curNavPath == "." {
curNavPath = ""
}
if node.root != node {
// write htaccess for rewrites, root will be written in WriteWebserverConfig()
goTo := node.Config.This.GoTo
if goTo != nil && *goTo != "" {
goToFixed := *goTo
if strings.HasPrefix(goToFixed, "/") {
goToFixed = helper.BackToRoot(curNavPath) + goToFixed
goToFixed = node.BackToRootPath() + goToFixed
}
goToFixed = path.Clean(goToFixed)
@@ -91,82 +171,63 @@ func (node *TreeNode) ProcessContent() {
}
for _, file := range node.InputFiles {
var input []byte
inFile := "InputString"
if file != "" {
inFile = node.InputPath + "/" + file
helper.Log.Debugf("reading file: %s", inFile)
var err error
input, err = ioutil.ReadFile(inFile)
if err != nil {
helper.Log.Panicf("could not read '%s':%s", inFile, err)
}
helper.Log.Infof("processing input file '%s'", inFile)
} else {
// use input string if available and input filename == ""
var inputString *string
if i := node.Config.Index; i != nil {
inputString = i.InputString
}
if inputString != nil {
helper.Log.Debugf("using input string instead of file")
input = []byte(*inputString)
}
}
newConfig := new(PathConfig)
regex := regexp.MustCompile("(?s)^---(.*?)\\r?\\n\\r?---\\r?\\n\\r?")
yamlData := regex.Find(input)
if string(yamlData) != "" {
// replace tabs
yamlData = bytes.Replace(yamlData, []byte("\t"), []byte(" "), -1)
helper.Log.Debugf("found yaml header in '%s', merging config", inFile)
err := yaml.Unmarshal(yamlData, newConfig)
if err != nil {
helper.Log.Panicf("could not parse YAML header from '%s': %s", inFile, err)
}
helper.Log.Debug("merging config with upper config")
oldThis := newConfig.This
helper.Merge(newConfig, node.Config)
newConfig.This = oldThis
helper.Log.Debug(spew.Sdump(newConfig))
input = regex.ReplaceAll(input, []byte(""))
} else {
helper.Merge(newConfig, node.Config)
}
// ignore ???
ignoreFile := false
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 != "" {
regex, err := regexp.Compile(*ignoreRegex)
if err != nil {
helper.Log.Panicf("could not compile filename.ignore regexp '%s' for file '%s': %s", *ignoreRegex, inFile, err)
if file != "" {
inFile = node.InputPath + "/" + file
var ignoreRegex *string
if f := node.Config.Filename; f != nil {
ignoreRegex = f.Ignore
}
if ignoreRegex != nil && *ignoreRegex != "" {
regex, err := regexp.Compile(*ignoreRegex)
if err != nil {
helper.Log.Panicf("could not compile filename.ignore regexp '%s' for file '%s': %s", *ignoreRegex, inFile, err)
}
ignoreFile = regex.MatchString(file)
}
ignoreFile = regex.MatchString(file)
}
if ignoreFile {
helper.Log.Infof("ignoring file '%s', because of filename.ignore", inFile)
} else {
var input []byte
if file != "" {
helper.Log.Debugf("reading file: %s", inFile)
var err error
input, err = ioutil.ReadFile(inFile)
if err != nil {
helper.Log.Panicf("could not read '%s':%s", inFile, err)
}
helper.Log.Infof("processing input file '%s'", inFile)
} else {
// use input string if available and input filename == ""
var inputString *string
if i := node.Config.Index; i != nil {
inputString = i.InputString
}
if inputString != nil {
helper.Log.Debugf("using input string instead of file")
input = []byte(*inputString)
}
}
newConfig, ctx := node.processMarkdownWithHeader(input, inFile)
// build output filename
outputFilename := file
var stripRegex *string
var outputExt *string
if f := newConfig.Filename; f != nil {
stripRegex = f.Strip
outputExt = f.OutputExtension
}
var indexInputFile *string
var indexOutputFile *string
if i := newConfig.Index; i != nil {
@@ -194,71 +255,14 @@ func (node *TreeNode) ProcessContent() {
outFile := node.OutputPath + "/" + outputFilename
helper.Log.Debugf("using '%s' as output file", outFile)
// use --- for splitting document in markdown parts
regex := regexp.MustCompile("\\r?\\n\\r?---\\r?\\n\\r?")
inputParts := regex.Split(string(input), -1)
htmlParts := make([]*pongo2.Value, 0)
chromaRenderer := false
chromaStyle := "monokai"
if m := newConfig.Markdown; m != nil {
if m.ChromaRenderer != nil && *m.ChromaRenderer {
chromaRenderer = true
}
if m.ChromaStyle != nil && *m.ChromaStyle != "" {
chromaStyle = *m.ChromaStyle
}
}
for _, iPart := range inputParts {
htmlParts = append(htmlParts,
pongo2.AsSafeValue(
string(helper.RenderMarkdown([]byte(iPart), chromaRenderer, chromaStyle))))
}
// build navigation
navMap := make(map[string]*NavElement)
navSlice := make([]*NavElement, 0)
navActive := make([]*NavElement, 0)
buildNavigation(node.root, &navMap, &navSlice, &navActive, curNavPath)
// read yaml header as data for template
ctx := NewContext()
ctx["This"] = newConfig.This
ctx["Meta"] = newConfig.Meta
ctx["Markdown"] = newConfig.Markdown
ctx["Data"] = newConfig.Data
ctx["ColMap"] = node.root.ColMap // root as NavMap and NavSlice, for sub go to NavElement.ColMap
ctx["NavMap"] = navMap
ctx["NavSlice"] = navSlice
ctx["NavActive"] = navActive
ctx["Body"] = pongo2.AsSafeValue(string(helper.RenderMarkdown(input, chromaRenderer, chromaStyle)))
ctx["BodyParts"] = htmlParts
ctx["CurrentPath"] = curNavPath
// set active nav element
if len(navActive) > 0 {
ctx["NavElement"] = navActive[len(navActive)-1]
} else {
// if no active path to content, we are in root dir
ctx["NavElement"] = &NavElement{
GoTo: helper.BackToRoot(curNavPath),
Active: true,
ColMap: node.ColMap,
Data: node.Config.Data,
This: node.Config.This,
SubMap: &navMap,
SubSlice: &navSlice,
}
}
helper.Log.Debugf("rendering template '%s' for '%s'", *newConfig.Template, outFile)
templateFilename := *newConfig.Template
result, err := renderTemplate(*newConfig.Template, node, newConfig, &ctx)
result, err := renderTemplate(*newConfig.Template, node, newConfig, ctx)
if err != nil {
helper.Log.Panicf("could not execute template '%s' for input file '%s': %s", templateFilename, inFile, err)
}
result = fixAssetsPath(result, curNavPath)
result = node.fixAssetsPath(result)
helper.Log.Noticef("writing to output file: %s", outFile)
err = ioutil.WriteFile(outFile, []byte(result), 0644)

View File

@@ -25,7 +25,11 @@ type NavElement struct {
}
// buildNavigation builds the navigation trees for use in templates
func buildNavigation(tree *TreeNode, curNavMap *map[string]*NavElement, curNavSlice *[]*NavElement, navActive *[]*NavElement, activeNav string) {
func (node *TreeNode) buildNavigation(curNavMap *map[string]*NavElement, curNavSlice *[]*NavElement, navActive *[]*NavElement) {
buildNavigationRecursive(node.root, curNavMap, curNavSlice, navActive, node.CurrentNavPath(), node.BackToRootPath())
}
func buildNavigationRecursive(tree *TreeNode, curNavMap *map[string]*NavElement, curNavSlice *[]*NavElement, navActive *[]*NavElement, activeNav string, backToRoot string) {
for _, el := range tree.Sub {
if el.Hidden {
continue // ignore hidden nav points from collections
@@ -88,8 +92,7 @@ func buildNavigation(tree *TreeNode, curNavMap *map[string]*NavElement, curNavSl
if activeNav != "" && activeNav != "/" {
// calculate relative path
bToRoot := helper.BackToRoot(activeNav)
navEl.GoTo = bToRoot + navEl.GoTo
navEl.GoTo = backToRoot + navEl.GoTo
navEl.GoTo = path.Clean(navEl.GoTo)
}
@@ -98,6 +101,6 @@ func buildNavigation(tree *TreeNode, curNavMap *map[string]*NavElement, curNavSl
*curNavSlice = append(*curNavSlice, &navEl)
}
buildNavigation(el, &subMap, &subSlice, navActive, activeNav)
buildNavigationRecursive(el, &subMap, &subSlice, navActive, activeNav, backToRoot)
}
}

View File

@@ -3,36 +3,58 @@ package mark2web
import (
"path"
"strings"
"gitbase.de/apairon/mark2web/pkg/helper"
)
// ResolveNavPath fixes nav target relative to current navigation path
func ResolveNavPath(target string) string {
curNavPath := (*CurrentContext)["CurrentPath"].(string)
func (node *TreeNode) ResolveNavPath(target string) string {
if strings.HasPrefix(target, "/") {
target = helper.BackToRoot(curNavPath) + target
target = node.BackToRootPath() + target
}
target = path.Clean(target)
return target
}
// ResolveOutputPath fixes output directory relative to current navigation path
func ResolveOutputPath(target string) string {
func (node *TreeNode) ResolveOutputPath(target string) string {
if strings.HasPrefix(target, "/") {
target = Config.Directories.Output + "/" + target
} else {
target = CurrentTreeNode.OutputPath + "/" + target
target = node.OutputPath + "/" + target
}
return path.Clean(target)
}
// ResolveInputPath fixes input directory relative to current navigation path
func ResolveInputPath(target string) string {
func (node *TreeNode) ResolveInputPath(target string) string {
if strings.HasPrefix(target, "/") {
target = Config.Directories.Input + "/" + target
} else {
target = CurrentTreeNode.InputPath + "/" + target
target = node.InputPath + "/" + target
}
return path.Clean(target)
}
// CurrentNavPath is current navigation path for this node
func (node *TreeNode) CurrentNavPath() string {
curNavPath := strings.TrimPrefix(node.OutputPath, Config.Directories.Output)
curNavPath = strings.TrimPrefix(curNavPath, "/")
curNavPath = path.Clean(curNavPath)
if curNavPath == "." {
curNavPath = ""
}
return curNavPath
}
// BackToRootPath builds ../../ string
func (node *TreeNode) BackToRootPath() string {
curNavPath := node.CurrentNavPath()
tmpPath := ""
if curNavPath != "" {
for i := strings.Count(curNavPath, "/") + 1; i > 0; i-- {
tmpPath += "../"
}
}
return tmpPath
}