diff --git a/.gitignore b/.gitignore index f4d432a..1cb0671 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,6 @@ # Dependency directories (remove the comment below to include it) # vendor/ +/tags +/testdata/sunny1/ +/.idea/ diff --git a/README.md b/README.md index 136dfed..2d6f9a9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ # zord-tree -Library for golang to build articles tree from file system. \ No newline at end of file +Library for golang to build articles tree from file system. + + +## Notes diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..ec8b3ad --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module g.arns.lt/zordsdavini/zord-tree + +go 1.16 + +require github.com/otiai10/copy v1.5.1 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..651daea --- /dev/null +++ b/go.sum @@ -0,0 +1,7 @@ +github.com/otiai10/copy v1.5.1 h1:a/cs2E1/1V0az8K5nblbl+ymEa4E11AfaOLMar8V34w= +github.com/otiai10/copy v1.5.1/go.mod h1:XWfuS3CrI0R6IE0FbgHsEazaXO8G0LpMp9o8tos0x4E= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= +github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/otiai10/mint v1.3.2 h1:VYWnrP5fXmz1MXvjuUvcBrXSjGE6xjON+axB/UrpO3E= +github.com/otiai10/mint v1.3.2/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= diff --git a/testdata/sunny/file1.md b/testdata/sunny/file1.md new file mode 100644 index 0000000..ec37c83 --- /dev/null +++ b/testdata/sunny/file1.md @@ -0,0 +1,10 @@ +tags: t1,t2 +description: Če test file __va__ + +--- + +# Če kažkas torietom būtė + +* lists + +__va__ diff --git a/testdata/sunny/file2.md b/testdata/sunny/file2.md new file mode 100644 index 0000000..d964887 --- /dev/null +++ b/testdata/sunny/file2.md @@ -0,0 +1,8 @@ +tags: t1 +description: Če test 2 + +--- + +# Če kažkas torietom būtė 2 + +ale nie \ No newline at end of file diff --git a/testdata/sunny/subcategory/file3.md b/testdata/sunny/subcategory/file3.md new file mode 100644 index 0000000..d7253ff --- /dev/null +++ b/testdata/sunny/subcategory/file3.md @@ -0,0 +1,10 @@ +tags: t1 +description: Če test 3 + +--- + +# Če kažkas torietom būtė 3 + +* vëns +* do +* trīs diff --git a/tree.go b/tree.go new file mode 100644 index 0000000..768157f --- /dev/null +++ b/tree.go @@ -0,0 +1,109 @@ +package zord_tree + +import ( + "bufio" + "io/fs" + "io/ioutil" + "os" + "path" + "strings" +) + +type File struct { + id string + name string + fullPath string + category []string + tags []string + meta map[string]string + description string + lang string +} + +type Tree struct { + path string + dirs []Tree + files []File +} + +func BuildTree(dirPath string) (Tree, error) { + return readPath(dirPath, []string{}) +} + +func readPath( dirPath string, category []string ) (Tree, error) { + tree := Tree{} + + tree.path = dirPath + + files, err := ioutil.ReadDir(dirPath) + if err != nil { + return tree, err + } + + for _, file := range files { + fullPath := path.Join(dirPath, file.Name()) + if file.IsDir() { + nextDir, err := readPath(fullPath, append(category, file.Name())) + if err != nil { + return tree, err + } + tree.dirs = append(tree.dirs, nextDir) + continue + } + + _, err := ioutil.ReadFile(fullPath) + if err != nil { + return tree, err + } + nextFile, err := readFile(file, fullPath, category) + if err != nil { + return tree, err + } + tree.files = append(tree.files, nextFile) + } + + return tree, nil +} + +func readFile(file fs.FileInfo, fullPath string, category []string) (File, error) { + f := File{ + name: file.Name(), + fullPath: fullPath, + category: category, + } + + osf, err := os.Open(fullPath) + if err != nil { + return File{}, err + } + scanner := bufio.NewScanner(osf) + scanner.Split(bufio.ScanLines) + for scanner.Scan() { + line := scanner.Text() + if line == "---" { + break + } + + if strings.HasPrefix(line, "tags:") { + line = strings.TrimPrefix(line, "tags:") + t := strings.Split(line, ",") + tags := []string{} + for _, tag := range t { + tags = append(tags, strings.Trim(tag, " ")) + } + + f.tags = tags + } + if strings.HasPrefix(line, "description:") { + line = strings.TrimPrefix(line, "description:") + f.description = strings.Trim(line, " ") + } + if strings.HasPrefix(line, "lang:") { + line = strings.TrimPrefix(line, "lang:") + f.lang = strings.Trim(line, " ") + } + } + osf.Close() + + return f, nil +} diff --git a/tree_test.go b/tree_test.go new file mode 100644 index 0000000..db739dd --- /dev/null +++ b/tree_test.go @@ -0,0 +1,46 @@ +package zord_tree + +import ( + cp "github.com/otiai10/copy" + "os" + "testing" +) + +func TestFromNotExistingDirectory(t *testing.T) { + _, err := BuildTree("./testing/i_dont_exist") + if err == nil { + t.Error("Not existing directory should return error, got NIL.") + } +} + +func TestSunny(t *testing.T) { + err := os.Remove("./testdata/sunny1") + if err != nil { + } + err = cp.Copy("./testdata/sunny", "./testdata/sunny1") + if err != nil { + t.Fatal("Couldn't prepare data for testing") + } + tree, err := BuildTree("./testdata/sunny1") + if err != nil { + t.Errorf("Got error: %v", err) + } + + if len(tree.dirs) != 1 { + t.Errorf("Should be 1 subdirectory, got %v", len(tree.dirs)) + } + + if tree.dirs[0].files[0].name != "file3.md" { + t.Errorf("File should be 'file3.md', got %v", tree.dirs[0].files[0].name) + } + if tree.files[0].name != "file1.md" { + t.Errorf("File should be 'file1.md', got %v", tree.files[0].name) + } + if len(tree.files[0].tags) != 2 { + t.Errorf("File 'file1.md' should have 2 tags, got %v", len(tree.files[0].tags)) + } + if tree.files[0].tags[1] != "t2" { + t.Errorf("File 'file1.md' 2nd tag 't2', got %v", tree.files[0].tags[1]) + } + t.Log(tree) +} \ No newline at end of file