github.com/oam-dev/kubevela@v1.9.11/hack/docgen/cli/gen.go (about)

     1  /*
     2   Copyright 2022 The KubeVela Authors.
     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  	"io/fs"
    23  	"log"
    24  	"os"
    25  	"path/filepath"
    26  	"strings"
    27  
    28  	"github.com/kubevela/pkg/util/slices"
    29  	"github.com/spf13/cobra"
    30  	"github.com/spf13/cobra/doc"
    31  
    32  	"github.com/oam-dev/kubevela/apis/types"
    33  	"github.com/oam-dev/kubevela/references/cli"
    34  )
    35  
    36  // PrintCLIByTag print custom defined index
    37  func PrintCLIByTag(cmd *cobra.Command, all []*cobra.Command, tag string) string {
    38  	var result string
    39  	var pl []cli.Printable
    40  	for _, c := range all {
    41  		if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() {
    42  			continue
    43  		}
    44  		if val, ok := c.Annotations[types.TagCommandType]; !ok || val != tag {
    45  			continue
    46  		}
    47  		cname := cmd.Name() + " " + c.Name()
    48  		link := cname
    49  		link = strings.Replace(link, " ", "_", -1)
    50  		pl = append(pl, cli.NewPrintable(c, fmt.Sprintf("* [%s](%s)\t - %s\n", cname, link, c.Long)))
    51  	}
    52  
    53  	slices.Sort(pl, func(i, j cli.Printable) bool { return i.Order < j.Order })
    54  
    55  	for _, v := range pl {
    56  		result += v.Desc
    57  	}
    58  	result += "\n"
    59  	return result
    60  }
    61  
    62  // GenMarkdownTreeForIndex will generate the Markdown doc for vela index
    63  func GenMarkdownTreeForIndex(cmd *cobra.Command, dir string) error {
    64  	basename := strings.Replace(cmd.CommandPath(), " ", "_", -1) + ".md"
    65  	filename := filepath.Join(dir, basename)
    66  	f, err := os.Create(filename)
    67  	if err != nil {
    68  		return err
    69  	}
    70  	defer f.Close()
    71  
    72  	if _, err = io.WriteString(f, "---\ntitle: CLI Commands\n---\n\n\n"); err != nil {
    73  		return err
    74  	}
    75  	for _, tp := range []string{types.TypeStart, types.TypeApp, types.TypeCD, types.TypeExtension, types.TypeSystem} {
    76  		// write header of type
    77  		_, err = io.WriteString(f, "## "+tp+"\n\n")
    78  		if err != nil {
    79  			return err
    80  		}
    81  		str := PrintCLIByTag(cmd, cmd.Commands(), tp)
    82  		// write header of type
    83  		_, err = io.WriteString(f, str)
    84  		if err != nil {
    85  			return err
    86  		}
    87  	}
    88  	_, err = io.WriteString(f, "###### Auto generated by [script in KubeVela](https://github.com/kubevela/kubevela/tree/master/hack/docgen).")
    89  	if err != nil {
    90  		return err
    91  	}
    92  	return nil
    93  }
    94  
    95  func main() {
    96  
    97  	rootPath := "../kubevela.io/docs/cli/"
    98  	if len(os.Args) > 1 {
    99  		rootPath = os.Args[1]
   100  	}
   101  	fmt.Println("scanning rootPath of CLI docs for replace: ", rootPath)
   102  	vela := cli.NewCommand()
   103  	err := doc.GenMarkdownTree(vela, rootPath)
   104  	if err != nil {
   105  		log.Fatal(err)
   106  	}
   107  	err = GenMarkdownTreeForIndex(vela, rootPath)
   108  	if err != nil {
   109  		log.Fatal("generate docs for vela index fail", err)
   110  	}
   111  	err = filepath.Walk(rootPath, func(path string, info fs.FileInfo, err error) error {
   112  		if err != nil {
   113  			return err
   114  		}
   115  		if info.IsDir() {
   116  			return nil
   117  		}
   118  		data, err := os.ReadFile(path)
   119  		if err != nil {
   120  			return err
   121  		}
   122  		lines := strings.Split(string(data), "\n")
   123  		if len(lines) < 1 {
   124  			return nil
   125  		}
   126  
   127  		// check first line to make sure it's autogenerated docs
   128  		firstL := lines[0]
   129  		if !strings.HasPrefix(firstL, "## vela") {
   130  			return nil
   131  		}
   132  
   133  		// find the last line and add some link.
   134  		var lastIdx int
   135  		for idx := len(lines) - 1; idx >= 0; idx-- {
   136  			if strings.Contains(lines[idx], "Auto generated") {
   137  				lastIdx = idx
   138  				break
   139  			}
   140  		}
   141  		if lastIdx == 0 {
   142  			return nil
   143  		}
   144  		lines[lastIdx] = "#### Go Back to [CLI Commands](vela) Homepage.\n\n\n###### Auto generated by [spf13/cobra script in KubeVela](https://github.com/kubevela/kubevela/tree/master/hack/docgen)."
   145  
   146  		// update the title format
   147  		title := strings.TrimPrefix(firstL, "## ")
   148  
   149  		lines[0] = "---"
   150  		newlines := []string{"---", "title: " + title}
   151  
   152  		for idx, line := range lines {
   153  			if strings.Contains(line, "[vela](vela.md)") {
   154  				lines[idx] = ""
   155  				continue
   156  			}
   157  			if strings.Contains(line, ".md") && strings.Contains(line, "](") {
   158  				lines[idx] = strings.Replace(line, ".md", "", -1)
   159  			}
   160  		}
   161  
   162  		newlines = append(newlines, lines...)
   163  		newcontent := strings.Join(newlines, "\n")
   164  		return os.WriteFile(path, []byte(newcontent), info.Mode())
   165  	})
   166  	if err != nil {
   167  		log.Fatal(err)
   168  	}
   169  }