diff --git a/README.md b/README.md index 2d6f9a9..9807288 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,55 @@ # zord-tree -Library for golang to build articles tree from file system. +Library for golang to build articles tree from file system. The file should be in specific format to hold meta data, id and +content. + +Process should go in two steps: + +* populate existing `source` directory with formatting files, add missing `id` and meta data +* build `Tree` to operate on object for your app +* read file content without meta data by path + + +## File and tree format + +### Category + +During building `Tree` directory path is converted into array of categories. So, file in path `linux/command/video` will get +categories: `linux`, `command`, `video`. + +### Split line + +File meta should be split by `---` line. If there is markdown formating to mark header, first such case (`---`) will be formatted +to contain empty line. Example: + +``` +Text +--- +``` + +will become + +``` +Text + +--- +``` + +### Meta data + +Meta data separated by lines and in format `name: value`. By default library supports `tags` as comma separated array. +During populating tree it adds missing `id` in `abcex` format and empty meta data lines and saves in `source` directory then copy +to `destination` directory. ## Notes + +### Future plans + +* add meta as function, ex. today date +* add meta with default value that should be used if other value is not set, ex. license +* add search on Tree + +### TODO + +* test to read file content diff --git a/testdata/sunny/file1.md b/testdata/sunny/file1.md index 039c9b4..6563f8d 100644 --- a/testdata/sunny/file1.md +++ b/testdata/sunny/file1.md @@ -1,7 +1,7 @@ tags: t1,t2 + description: Če test file __va__ option1: test option - --- # Če kažkas torietom būtė diff --git a/tree.go b/tree.go index 1744a1e..3d181af 100644 --- a/tree.go +++ b/tree.go @@ -33,6 +33,11 @@ func BuildTree(dirPath string, meta []string) (Tree, error) { } func PopulateTree(sourcePath string, destPath string, meta []string) error { + err = fixFormat(sourcePath) + if err != nil { + return err + } + id, err := getMaxId(sourcePath) if err != nil { return err @@ -54,6 +59,56 @@ func PopulateTree(sourcePath string, destPath string, meta []string) error { return err } +func fixFormat(dir string) error { + err := filepath.Walk(dir, func(path string, info os.FileInfo, e error) error { + if e != nil { + return e + } + + if info.Mode().IsRegular() { + b, err := ioutil.ReadFile(path) // just pass the file name + if err != nil { + return err + } + + osf, err := os.Open(path) + 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 + } + } + err = ioutil.WriteFile(path, []byte(content), 0644) + + // format split line + str := string(b) + str = strings.Replace(str, "\n---\n", "\n\n---\n", 1) + err = ioutil.WriteFile(path, []byte(str), 0644) + } + return nil + }) + + return err +} + func addMissingMeta(dir string, meta []string) error { err := filepath.Walk(dir, func(path string, info os.FileInfo, e error) error { if e != nil { @@ -95,11 +150,8 @@ func addMissingMeta(dir string, meta []string) error { } return nil }) - if err != nil { - return err - } - return nil + return err } func addMissingId(dir string, id int64) error { @@ -271,3 +323,40 @@ func readFile(file fs.FileInfo, fullPath string, category []string, meta []strin return f, nil } + +func ReadFileContent(file File) (string, error) { + osf, err := os.Open(path) + if err != nil { + return nil, err + } + + content := "" + removeEmptyLine := true + isMetaPart := true + scanner := bufio.NewScanner(osf) + scanner.Split(bufio.ScanLines) + for scanner.Scan() { + line := scanner.Text() + if line == "---" { + isMetaPart = false + continue + } + + if (isMetaPart) { + continue + } + + if (removeEmptyLine) { + line = strings.Trim(line, " ") + if (line == "") { + continue + } else { + removeEmptyLine = false + } + } + + content = content + "\n" + line + } + + return content, nil +} diff --git a/tree_test.go b/tree_test.go index 42b048b..8efa48e 100644 --- a/tree_test.go +++ b/tree_test.go @@ -47,6 +47,38 @@ func TestSunny(t *testing.T) { t.Log(tree) } +func TestFixFormat(t *testing.T) { + err := os.Remove("./testdata/sunny1") + if err != nil { + } + err = os.Remove("./testdata/sunny2") + if err != nil { + } + err = cp.Copy("./testdata/sunny", "./testdata/sunny1") + if err != nil { + t.Fatal("Couldn't prepare data for testing") + } + + err = PopulateTree("./testdata/sunny1", "./testdata/sunny2", []string{}) + if err != nil { + t.Fatal("Population ended in err:", err) + } + + b, err := ioutil.ReadFile("./testdata/sunny2/file1.md") + if err != nil { + t.Fatal("No destination file 'file1.md'.") + } + str := string(b) + if !strings.Contains(str, "tags: t1,t2\ndescription: Če test file __va__\n") { + t.Fatal("Empty lines has not been removed in file 'file1.md'.") + } + if !strings.Contains(str, "\n\n---\n") { + t.Fatal("Split line has not been formatted in file 'file1.md'.") + } + + t.Log(tree) +} + func TestMeta(t *testing.T) { err := os.Remove("./testdata/sunny1") if err != nil {