github.com/kyleu/dbaudit@v0.0.2-0.20240321155047-ff2f2c940496/app/controller/cmenu/docs.go (about)

     1  // Package cmenu - Content managed by Project Forge, see [projectforge.md] for details.
     2  package cmenu
     3  
     4  import (
     5  	"cmp"
     6  	"io/fs"
     7  	"path"
     8  	"slices"
     9  	"strings"
    10  
    11  	"github.com/samber/lo"
    12  
    13  	"github.com/kyleu/dbaudit/app/lib/menu"
    14  	"github.com/kyleu/dbaudit/app/util"
    15  	"github.com/kyleu/dbaudit/doc"
    16  )
    17  
    18  var docMenuCached *menu.Item
    19  
    20  func docMenu(logger util.Logger) *menu.Item {
    21  	if docMenuCached == nil {
    22  		docMenuCached = docMenuCreate(logger)
    23  	}
    24  	return docMenuCached
    25  }
    26  
    27  func docMenuCreate(logger util.Logger) *menu.Item {
    28  	var paths []string
    29  	err := fs.WalkDir(doc.FS, ".", func(path string, _ fs.DirEntry, err error) error {
    30  		paths = append(paths, path)
    31  		return err
    32  	})
    33  	if err != nil {
    34  		logger.Errorf("unable to build documentation menu: %+v", err)
    35  	}
    36  	slices.Sort(paths)
    37  
    38  	ret := &menu.Item{Key: "docs", Title: "Documentation", Icon: "folder"}
    39  	for _, p := range paths {
    40  		if p == "." || strings.HasPrefix(p, "module/") || !strings.HasSuffix(p, util.ExtMarkdown) {
    41  			continue
    42  		}
    43  		split := util.StringSplitAndTrim(p, "/")
    44  		p = strings.TrimSuffix(p, util.ExtMarkdown)
    45  		mi := ret
    46  		lo.ForEach(split, func(comp string, idx int) {
    47  			name := strings.TrimSuffix(comp, util.ExtMarkdown)
    48  			addFolder := func() {
    49  				i := &menu.Item{Key: name, Title: util.StringToCamel(name), Icon: "folder"}
    50  				mi.Children = append(mi.Children, i)
    51  				slices.SortFunc(mi.Children, func(l *menu.Item, r *menu.Item) int {
    52  					return cmp.Compare(l.Title, r.Title)
    53  				})
    54  				mi = i
    55  			}
    56  			if idx == len(split)-1 {
    57  				if strings.HasSuffix(comp, util.ExtMarkdown) {
    58  					mi.Children = append(mi.Children, addChild(p, name))
    59  				} else {
    60  					addFolder()
    61  				}
    62  			} else {
    63  				if kid := mi.Children.Get(comp); kid == nil {
    64  					addFolder()
    65  				} else {
    66  					mi = kid
    67  				}
    68  			}
    69  		})
    70  	}
    71  	slices.SortFunc(ret.Children, func(l *menu.Item, r *menu.Item) int {
    72  		return cmp.Compare(l.Title, r.Title)
    73  	})
    74  
    75  	return ret
    76  }
    77  
    78  func addChild(p string, name string) *menu.Item {
    79  	r := "/" + path.Join("docs", p)
    80  	title := util.StringToCamel(name)
    81  	b, err := doc.FS.ReadFile(p + util.ExtMarkdown)
    82  	if err != nil {
    83  		panic(err)
    84  	}
    85  
    86  	lines := util.StringSplitLines(string(b))
    87  	for _, line := range lines {
    88  		if strings.HasPrefix(line, "#") {
    89  			for strings.HasPrefix(line, "#") {
    90  				line = line[1:]
    91  			}
    92  			title = strings.TrimSpace(line)
    93  			break
    94  		}
    95  	}
    96  
    97  	return &menu.Item{Key: name, Title: title, Icon: "file", Route: r}
    98  }