Compare commits

..

No commits in common. "master" and "v0.4.2" have entirely different histories.

5 changed files with 16 additions and 128 deletions

View file

@ -64,23 +64,8 @@ Hear goes content. It can be written in html, markdown or whatever what can be p
There are two main commands: `PopulateTree` to prepare source (format, add metadata and add Id) and separate images and other data files and `BuildTree` to get object of tree. There are two main commands: `PopulateTree` to prepare source (format, add metadata and add Id) and separate images and other data files and `BuildTree` to get object of tree.
Also both commands use `Config` object that can be prepared by `NewConfig` command. With it can be configurable readable formats, attachment directory, custom meta, excludes (not movable files by regexp) and list of functions to apply before file formatting (read bellow). Also both commands use `Config` object that can be prepared by `NewConfig` command. With it can be configurable readable formats, attachment directory, custom meta and excludes (not movable files by regexp).
`Tree` object has methods: `FileById` to get `File` by Id, `Slice` to get sub-tree of given path and `Filter` to filter tree by filter. `Tree` object has methods: `FileById` to get `File` by Id, `Slice` to get sub-tree of given path and `Filter` to filter tree by filter.
Filter contains array of meta key and searching value. `tag` key is searched as equal and other meta values of keys can contain part. If `-` is before key - filter is filter out. Filter contains array of meta key and searching value. `tag` key is searched as equal and other meta values of keys can contain part. If `-` is before key - filter is filter out.
By full file path and config meta there is possibility to get file params: `Id`, `Meta` and `Tags`:
```
GetFileParams(fullPath string, meta []string) (string, []string, map[string]string, error)
```
### Functions to apply before file formatting
There is possibility to add custom functions to apply before file formatting. That is passed with custom function what returns string.
```
func(dir string, content string, info os.FileInfo) (string, error)
```
`dir` is path to directory of file, `content` is file content and `info` is file info.

2
go.mod
View file

@ -3,7 +3,7 @@ module g.arns.lt/zordsdavini/zord-tree
go 1.21 go 1.21
require ( require (
g.arns.lt/zordsdavini/abcex/v4 v4.0.4 g.arns.lt/zordsdavini/abcex v1.0.0
github.com/otiai10/copy v1.6.0 github.com/otiai10/copy v1.6.0
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1
) )

4
go.sum
View file

@ -1,5 +1,5 @@
g.arns.lt/zordsdavini/abcex/v4 v4.0.4 h1:idjvgkCjrjZfDxLyOcX7lCIdIndISDAkj77VCvhu8/c= g.arns.lt/zordsdavini/abcex v1.0.0 h1:qQqlZ4DMfethCGK4I6yGaLqMrTzKNIshqpINd1l3t0E=
g.arns.lt/zordsdavini/abcex/v4 v4.0.4/go.mod h1:/+//gYSUtJrdsmTtWNoffRO4xD1BuPRUMGW4ynet7iE= g.arns.lt/zordsdavini/abcex v1.0.0/go.mod h1:YRcJgts3XZwI+LEkngpfUab3DkUAW387Irpr43hIym8=
github.com/otiai10/copy v1.6.0 h1:IinKAryFFuPONZ7cm6T6E2QX/vcJwSnlaA5lfoaXIiQ= github.com/otiai10/copy v1.6.0 h1:IinKAryFFuPONZ7cm6T6E2QX/vcJwSnlaA5lfoaXIiQ=
github.com/otiai10/copy v1.6.0/go.mod h1:XWfuS3CrI0R6IE0FbgHsEazaXO8G0LpMp9o8tos0x4E= github.com/otiai10/copy v1.6.0/go.mod h1:XWfuS3CrI0R6IE0FbgHsEazaXO8G0LpMp9o8tos0x4E=
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=

119
tree.go
View file

@ -3,7 +3,6 @@ package zord_tree
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"cmp"
"crypto/md5" "crypto/md5"
"errors" "errors"
"fmt" "fmt"
@ -14,10 +13,10 @@ import (
"path" "path"
"path/filepath" "path/filepath"
"regexp" "regexp"
"slices"
"strings" "strings"
abcex "g.arns.lt/zordsdavini/abcex/v4" "g.arns.lt/zordsdavini/abcex"
"golang.org/x/exp/slices"
) )
type Config struct { type Config struct {
@ -25,11 +24,8 @@ type Config struct {
AttachmentDirName string AttachmentDirName string
CustomMeta map[string]func() string CustomMeta map[string]func() string
Excludes []string Excludes []string
Apps map[string]AppCallback
} }
type AppCallback func(dir string, content string, info os.FileInfo) (string, error)
type File struct { type File struct {
Id string Id string
Name string Name string
@ -108,14 +104,6 @@ func (t Tree) Filter(filter map[string][]string) (Tree, bool) {
} }
continue continue
} }
if negative && option == "category" {
for _, category := range f.Category {
if category == value {
exclude = true
}
}
continue
}
if !negative && strings.Contains(f.Meta[option], value) { if !negative && strings.Contains(f.Meta[option], value) {
addFile = true addFile = true
continue continue
@ -151,14 +139,12 @@ func NewConfig(
attachmentDirName string, attachmentDirName string,
customMeta map[string]func() string, customMeta map[string]func() string,
excludes []string, excludes []string,
apps map[string]AppCallback,
) Config { ) Config {
return Config{ return Config{
ReadableFormats: readableFormats, ReadableFormats: readableFormats,
AttachmentDirName: attachmentDirName, AttachmentDirName: attachmentDirName,
CustomMeta: customMeta, CustomMeta: customMeta,
Excludes: excludes, Excludes: excludes,
Apps: apps,
} }
} }
@ -170,13 +156,6 @@ func PopulateTree(sourcePath string, meta []string, config Config) error {
var err error var err error
var attachmentRegistry map[string]string var attachmentRegistry map[string]string
for _, app := range config.Apps {
err = applyApp(app, sourcePath, config)
if err != nil {
return err
}
}
attachmentRegistry, err = moveAttachments(sourcePath, config) attachmentRegistry, err = moveAttachments(sourcePath, config)
if err != nil { if err != nil {
return err return err
@ -263,57 +242,6 @@ func moveAttachments(dir string, config Config) (map[string]string, error) {
return attachmentRegistry, err return attachmentRegistry, err
} }
func applyApp(app AppCallback, dir string, config Config) error {
err := filepath.Walk(dir, func(fullPath string, info os.FileInfo, e error) error {
if e != nil {
return e
}
if info.Mode().IsRegular() && slices.Contains(config.ReadableFormats, path.Ext(fullPath)) {
osf, err := os.Open(fullPath)
if err != nil {
return err
}
// remove all empty lines and separate split line
content := ""
format := true
scanner := bufio.NewScanner(osf)
scanner.Split(bufio.ScanLines)
for scanner.Scan() {
line := scanner.Text()
if line == "---" {
format = false
}
if format {
line = strings.Trim(line, " ")
if line != "" {
content = content + "\n" + line
}
} else {
content = content + "\n" + line
}
}
content, err = app(path.Dir(fullPath), content, info)
if err != nil {
return err
}
data := []byte(content)
err = os.WriteFile(fullPath, data, 0644)
if err != nil {
return err
}
}
return nil
})
return err
}
func fixFormat(dir string, attachmentRegistry map[string]string, config Config) error { func fixFormat(dir string, attachmentRegistry map[string]string, config Config) error {
err := filepath.Walk(dir, func(fullPath string, info os.FileInfo, e error) error { err := filepath.Walk(dir, func(fullPath string, info os.FileInfo, e error) error {
if e != nil { if e != nil {
@ -450,7 +378,7 @@ func addMissingId(dir string, id int64) error {
break break
} }
if line == "---" { if line == "---" {
err = addMeta(path, "id", abcex.Encode(id, abcex.BASE36)) err = addMeta(path, "id", abcex.Encode(id))
if err != nil { if err != nil {
return err return err
} }
@ -504,7 +432,7 @@ func getMaxId(dir string) (int64, error) {
if strings.HasPrefix(line, "* id:") { if strings.HasPrefix(line, "* id:") {
line = strings.TrimPrefix(line, "* id:") line = strings.TrimPrefix(line, "* id:")
i := abcex.Decode(strings.Trim(line, " "), abcex.BASE36) i := abcex.Decode(strings.Trim(line, " "))
if i > max { if i > max {
max = i max = i
} }
@ -569,16 +497,7 @@ FILE_LOOP:
if err != nil { if err != nil {
return tree, err return tree, err
} }
if nextFile.Id == "" {
continue
}
tree.Files = append(tree.Files, nextFile) tree.Files = append(tree.Files, nextFile)
slices.SortFunc(tree.Files, func(a, b File) int {
if len(a.Id) == len(b.Id) {
return strings.Compare(a.Id, b.Id)
}
return cmp.Compare(len(a.Id), len(b.Id))
})
} }
return tree, nil return tree, nil
@ -589,30 +508,13 @@ func readFile(file fs.DirEntry, fullPath string, category []string, meta []strin
Name: file.Name(), Name: file.Name(),
FullPath: fullPath, FullPath: fullPath,
Category: category, Category: category,
Meta: map[string]string{},
} }
id, tags, fileMeta, err := GetFileParams(fullPath, meta)
if err != nil {
return f, err
}
f.Id = id
f.Tags = tags
f.Meta = fileMeta
return f, nil
}
func GetFileParams(fullPath string, meta []string) (string, []string, map[string]string, error) {
fileMeta := map[string]string{}
tags := []string{}
id := ""
osf, err := os.Open(fullPath) osf, err := os.Open(fullPath)
if err != nil { if err != nil {
return id, tags, fileMeta, err return File{}, err
} }
scanner := bufio.NewScanner(osf) scanner := bufio.NewScanner(osf)
scanner.Split(bufio.ScanLines) scanner.Split(bufio.ScanLines)
for scanner.Scan() { for scanner.Scan() {
@ -624,24 +526,27 @@ func GetFileParams(fullPath string, meta []string) (string, []string, map[string
if strings.HasPrefix(line, "* tags:") { if strings.HasPrefix(line, "* tags:") {
line = strings.TrimPrefix(line, "* tags:") line = strings.TrimPrefix(line, "* tags:")
t := strings.Split(line, ",") t := strings.Split(line, ",")
tags := []string{}
for _, tag := range t { for _, tag := range t {
tags = append(tags, strings.Trim(tag, " ")) tags = append(tags, strings.Trim(tag, " "))
} }
f.Tags = tags
} }
if strings.HasPrefix(line, "* id:") { if strings.HasPrefix(line, "* id:") {
line = strings.TrimPrefix(line, "* id:") line = strings.TrimPrefix(line, "* id:")
id = strings.Trim(line, " ") f.Id = strings.Trim(line, " ")
} }
for _, option := range meta { for _, option := range meta {
if strings.HasPrefix(line, "* "+option) { if strings.HasPrefix(line, "* "+option) {
line = strings.TrimPrefix(line, "* "+option+":") line = strings.TrimPrefix(line, "* "+option+":")
fileMeta[option] = strings.Trim(line, " ") f.Meta[option] = strings.Trim(line, " ")
} }
} }
} }
_ = osf.Close() _ = osf.Close()
return id, tags, fileMeta, nil return f, nil
} }
func ReadFileContent(file File) (string, error) { func ReadFileContent(file File) (string, error) {

View file

@ -22,7 +22,6 @@ func prepare(t *testing.T) Config {
"__a", "__a",
make(map[string]func() string), make(map[string]func() string),
[]string{"exclude_[0-9]+.bin"}, []string{"exclude_[0-9]+.bin"},
map[string]AppCallback{},
) )
err = PopulateTree("./testdata/sunny1", []string{}, config) err = PopulateTree("./testdata/sunny1", []string{}, config)
@ -39,7 +38,6 @@ func TestFromNotExistingDirectory(t *testing.T) {
"__a", "__a",
make(map[string]func() string), make(map[string]func() string),
[]string{}, []string{},
map[string]AppCallback{},
) )
_, err := BuildTree("./testing/i_dont_exist", []string{}, config) _, err := BuildTree("./testing/i_dont_exist", []string{}, config)