github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/hack/docgen/lorryctl/main.go (about)

     1  /*
     2  Copyright (C) 2022-2023 ApeCloud Co., Ltd
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package main
    18  
    19  import (
    20  	"fmt"
    21  	"io"
    22  	"log"
    23  	"os"
    24  	"path/filepath"
    25  	"strings"
    26  
    27  	"github.com/spf13/cobra"
    28  	"github.com/spf13/cobra/doc"
    29  
    30  	lorryctl "github.com/1aal/kubeblocks/pkg/lorry/ctl"
    31  )
    32  
    33  func genMarkdownTreeForOverview(cmd *cobra.Command, dir string) error {
    34  	filename := filepath.Join(dir, "cli.md")
    35  	f, err := os.Create(filename)
    36  	if err != nil {
    37  		return err
    38  	}
    39  	defer f.Close()
    40  
    41  	if _, err = io.WriteString(f, `---
    42  title: KubeBlocks Lorry CLI Overview
    43  description: KubeBlocks Lorry CLI overview
    44  sidebar_position: 1
    45  ---
    46  
    47  `); err != nil {
    48  		return err
    49  	}
    50  
    51  	for _, c := range cmd.Commands() {
    52  		if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() {
    53  			continue
    54  		}
    55  
    56  		// write parent command name
    57  		link := strings.ReplaceAll(cmd.Name()+" "+c.Name(), " ", "_")
    58  		_, err = io.WriteString(f, fmt.Sprintf("## [%s](%s.md)\n\n", c.Name(), link))
    59  		if err != nil {
    60  			return err
    61  		}
    62  
    63  		// write command description
    64  		switch {
    65  		case c.Long != "":
    66  			_, err = io.WriteString(f, fmt.Sprintf("%s\n\n", c.Long))
    67  		case c.Short != "":
    68  			_, err = io.WriteString(f, fmt.Sprintf("%s\n\n", c.Short))
    69  		}
    70  		if err != nil {
    71  			return err
    72  		}
    73  
    74  		// write subcommands
    75  		for _, sub := range c.Commands() {
    76  			if !sub.IsAvailableCommand() || sub.IsAdditionalHelpTopicCommand() {
    77  				continue
    78  			}
    79  			subName := cmd.Name() + " " + c.Name() + " " + sub.Name()
    80  			link = strings.ReplaceAll(subName, " ", "_")
    81  			_, err = io.WriteString(f, fmt.Sprintf("* [%s](%s.md)\t - %s\n", subName, link, sub.Short))
    82  			if err != nil {
    83  				return err
    84  			}
    85  		}
    86  		_, err = io.WriteString(f, "\n\n")
    87  		if err != nil {
    88  			return err
    89  		}
    90  	}
    91  	return nil
    92  }
    93  
    94  func main() {
    95  	rootPath := "./docs/user_docs/lorryctl"
    96  	if len(os.Args) > 1 {
    97  		rootPath = os.Args[1]
    98  	}
    99  
   100  	fmt.Println("Scanning CLI docs rootPath: ", rootPath)
   101  	ctl := lorryctl.RootCmd
   102  	ctl.Long = fmt.Sprintf("```\n%s\n```", ctl.Long)
   103  
   104  	err := doc.GenMarkdownTree(ctl, rootPath)
   105  	if err != nil {
   106  		log.Fatal(err)
   107  	}
   108  
   109  	ctl.Long = fmt.Sprintf("```\n%s\n```", ctl.Long)
   110  	err = genMarkdownTreeForOverview(ctl, rootPath)
   111  	if err != nil {
   112  		log.Fatal("generate docs for cli overview failed", err)
   113  	}
   114  
   115  	err = filepath.Walk(rootPath, func(path string, info os.FileInfo, err error) error {
   116  		if err != nil {
   117  			return err
   118  		}
   119  		if info.IsDir() {
   120  			return nil
   121  		}
   122  		data, err := os.ReadFile(path)
   123  		if err != nil {
   124  			return err
   125  		}
   126  		lines := strings.Split(string(data), "\n")
   127  		if len(lines) == 0 {
   128  			return nil
   129  		}
   130  
   131  		firstLine := lines[0]
   132  		if !strings.HasPrefix(firstLine, "## lorryctl") {
   133  			return nil
   134  		}
   135  
   136  		var lastIdx int
   137  		for idx := len(lines) - 1; idx >= 0; idx-- {
   138  			if strings.Contains(lines[idx], "Auto generated") {
   139  				lastIdx = idx
   140  				break
   141  			}
   142  		}
   143  		if lastIdx == 0 {
   144  			return nil
   145  		}
   146  		lines[lastIdx] = "#### Go Back to [LorryCtl Overview](cli.md) Homepage.\n"
   147  
   148  		// update the title
   149  		lines[0] = "---"
   150  		title := strings.TrimPrefix(firstLine, "## ")
   151  		newLines := []string{"---", "title: " + title}
   152  		for idx, line := range lines {
   153  			if strings.Contains(line, "[kbcli](kbcli.md)") {
   154  				lines[idx] = ""
   155  				continue
   156  			}
   157  		}
   158  		newLines = append(newLines, lines...)
   159  		content := strings.Join(newLines, "\n")
   160  		return os.WriteFile(path, []byte(content), info.Mode())
   161  	})
   162  	if err != nil {
   163  		log.Fatal(err)
   164  	}
   165  }