diff --git a/doc/doc.go b/doc/doc.go new file mode 100644 index 00000000..d7a2fa48 --- /dev/null +++ b/doc/doc.go @@ -0,0 +1,182 @@ +package doc + +import ( + "bytes" + "fmt" + "io" + "math/rand" + "os" + "path/filepath" + "strings" + + cmd "github.com/goharbor/harbor-cli/cmd/harbor/root" + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +const markdownExtension = ".md" +const frontmdtemplate = `--- +title: %s +weight: %d +--- +` + +func Doc() error { + currentDir, err := os.Getwd() + if err != nil { + return err + } + folderName := "cli-docs" + _, err = os.Stat(folderName) + if os.IsNotExist(err) { + err = os.Mkdir(folderName, 0755) + if err != nil { + log.Fatal("Error creating folder:", err) + } + } + docDir := fmt.Sprintf("%s/%s", currentDir, folderName) + err = MarkdownTreeCustom(cmd.RootCmd(), docDir, preblock, linkHandler) + if err != nil { + return err + } + + fmt.Println("Documentation generated at " + docDir) + return nil +} + +func preblock(filename string) string { + file := strings.Split(filename, markdownExtension) + name := filepath.Base(file[0]) + title := strings.ReplaceAll(name, "-", " ") + randomNumber := rand.Intn(20) + weight := randomNumber * 5 + + return fmt.Sprintf(frontmdtemplate, title, weight) +} + +func linkHandler(s string) string { + return s +} + +func printOptions(buf *bytes.Buffer, cmd *cobra.Command) error { + flags := cmd.NonInheritedFlags() + flags.SetOutput(buf) + if flags.HasAvailableFlags() { + buf.WriteString("### Options\n\n```sh\n") + flags.PrintDefaults() + buf.WriteString("```\n\n") + } + + parentFlags := cmd.InheritedFlags() + parentFlags.SetOutput(buf) + if parentFlags.HasAvailableFlags() { + buf.WriteString("### Options inherited from parent commands\n\n```sh\n") + parentFlags.PrintDefaults() + buf.WriteString("```\n\n") + } + return nil +} + +func MarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) string) error { + cmd.InitDefaultHelpCmd() + cmd.InitDefaultHelpFlag() + + buf := new(bytes.Buffer) + name := cmd.CommandPath() + + buf.WriteString("## " + name + "\n\n") + buf.WriteString("### Description\n\n") + buf.WriteString("##### " + cmd.Short + "\n\n") + if len(cmd.Long) > 0 { + buf.WriteString("### Synopsis\n\n") + buf.WriteString(cmd.Long + "\n\n") + } + + if cmd.Runnable() { + buf.WriteString(fmt.Sprintf("```sh\n%s\n```\n\n", cmd.UseLine())) + } + + if len(cmd.Example) > 0 { + buf.WriteString("### Examples\n\n") + buf.WriteString(fmt.Sprintf("```sh\n%s\n```\n\n", cmd.Example)) + } + + if err := printOptions(buf, cmd); err != nil { + return err + } + if hasSeeAlso(cmd) { + buf.WriteString("### SEE ALSO\n\n") + if cmd.HasParent() { + parent := cmd.Parent() + pname := parent.CommandPath() + link := pname + markdownExtension + link = strings.ReplaceAll(link, " ", "-") + buf.WriteString(fmt.Sprintf("* [%s](%s)\t - %s\n", pname, linkHandler(link), parent.Short)) + cmd.VisitParents(func(c *cobra.Command) { + if c.DisableAutoGenTag { + cmd.DisableAutoGenTag = c.DisableAutoGenTag + } + }) + } + + children := cmd.Commands() + + for _, child := range children { + if !child.IsAvailableCommand() || child.IsAdditionalHelpTopicCommand() { + continue + } + cname := name + " " + child.Name() + link := cname + markdownExtension + link = strings.ReplaceAll(link, " ", "-") + buf.WriteString(fmt.Sprintf("* [%s](%s)\t - %s\n", cname, linkHandler(link), child.Short)) + } + buf.WriteString("\n") + } + + _, err := buf.WriteTo(w) + return err +} + +func MarkdownTreeCustom(cmd *cobra.Command, dir string, filePrepender, linkHandler func(string) string) error { + for _, c := range cmd.Commands() { + if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { + continue + } + if err := MarkdownTreeCustom(c, dir, filePrepender, linkHandler); err != nil { + return err + } + } + + basename := strings.ReplaceAll(cmd.CommandPath(), " ", "-") + markdownExtension + filename := filepath.Join(dir, basename) + if _, err := os.Stat(filename); err == nil { + return nil + } + + f, err := os.Create(filename) + if err != nil { + return err + } + defer f.Close() + + if _, err := io.WriteString(f, filePrepender(filename)); err != nil { + return err + } + if err := MarkdownCustom(cmd, f, linkHandler); err != nil { + return err + } + return nil +} + +func hasSeeAlso(cmd *cobra.Command) bool { + if cmd.HasParent() { + return true + } + for _, c := range cmd.Commands() { + if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { + continue + } + return true + } + return false +}