github.com/GoogleContainerTools/kpt@v1.0.0-beta.50.0.20240520170205-c25345ffcbee/scripts/generate_site_sidebar/generate_site_sidebar.go (about) 1 // Copyright 2019 The kpt Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package main 16 17 import ( 18 "fmt" 19 "html/template" 20 "os" 21 "path" 22 "path/filepath" 23 "regexp" 24 "sort" 25 "strings" 26 27 "github.com/igorsobreira/titlecase" 28 ) 29 30 const markdownExtension = ".md" 31 const introPage = "00.md" 32 const templatePath = "scripts/generate_site_sidebar/sidebar_template.md.tmpl" 33 34 var pagePrefix = regexp.MustCompile(`^\d\d-?`) 35 36 func main() { 37 fmt.Println("<!--This sidebar was automatically generated by 'generate_site_sidebar'-->") 38 t := template.Must( 39 template.New(path.Base(templatePath)). 40 Funcs(template.FuncMap{"bookLayout": getBookOutline}). 41 ParseFiles(templatePath)) 42 43 err := t.Execute(os.Stdout, nil) 44 if err != nil { 45 fmt.Fprintf(os.Stderr, "%v\n", err) 46 os.Exit(1) 47 } 48 } 49 50 func getBookOutline() string { 51 sourcePath := "site/book" 52 chapters := collectChapters(sourcePath) 53 54 return getChapterBlock(chapters) 55 } 56 57 func collectChapters(source string) []chapter { 58 chapters := make([]chapter, 0) 59 chapterDirs, err := os.ReadDir(source) 60 if err != nil { 61 fmt.Fprintf(os.Stderr, "%v\n", err) 62 os.Exit(1) 63 } 64 65 for _, dir := range chapterDirs { 66 if dir.IsDir() { 67 chapters = append(chapters, getChapter(dir.Name(), filepath.Join(source, dir.Name()))) 68 } 69 } 70 71 return chapters 72 } 73 74 func getChapter(chapterDirName string, chapterDirPath string) chapter { 75 chapterBuilder := chapter{} 76 77 // Split into chapter number and hyphenated name 78 splitDirName := strings.SplitN(chapterDirName, "-", 2) 79 chapterBuilder.Number = splitDirName[0] 80 chapterBuilder.Name = titlecase.Title(strings.ReplaceAll(splitDirName[1], "-", " ")) 81 82 pageFiles, err := os.ReadDir(chapterDirPath) 83 if err != nil { 84 fmt.Fprintf(os.Stderr, "%v\n", err) 85 os.Exit(1) 86 } 87 88 for _, pageFile := range pageFiles { 89 if filepath.Ext(pageFile.Name()) == markdownExtension && pagePrefix.MatchString(pageFile.Name()) { 90 chapterBuilder.Pages = append(chapterBuilder.Pages, 91 getPage(pageFile.Name(), chapterBuilder.Name, chapterDirPath)) 92 } 93 } 94 95 return chapterBuilder 96 } 97 98 func getPage(pageFileName string, defaultName string, parentPath string) page { 99 // Split into page number and hyphenated name. 100 splitPageName := strings.SplitN(pageFileName, "-", 2) 101 102 pageName := defaultName 103 if pageFileName != introPage { 104 // Strip page number and extension from file name. 105 pageTitle := pagePrefix.ReplaceAll([]byte(pageFileName), []byte("")) 106 pageName = titlecase.Title(strings.ReplaceAll(strings.ReplaceAll(string(pageTitle), ".md", ""), "-", " ")) 107 } 108 109 return page{ 110 Number: splitPageName[0], 111 Name: pageName, 112 Path: filepath.Join(parentPath, pageFileName), 113 } 114 } 115 116 func getChapterBlock(chapters []chapter) string { 117 // Sort chapters in ascending order by chapter number. 118 sort.Slice(chapters, func(i, j int) bool { return chapters[i].Number < chapters[j].Number }) 119 var sb strings.Builder 120 for chapterIndex, chapterEntry := range chapters { 121 chapterNumber := chapterIndex + 1 122 for pageIndex, pageEntry := range chapterEntry.Pages { 123 // Make path relative to site directory. 124 path := strings.Replace(pageEntry.Path, "site/", "", 1) 125 126 // Print non-chapter intro pages as children of chapter intro page. 127 if pageIndex == 0 { 128 sb.WriteString(fmt.Sprintf("\t- [%d %s](%s)\n", chapterNumber, pageEntry.Name, path)) 129 } else { 130 sb.WriteString(fmt.Sprintf("\t\t- [%d.%d %s](%s)\n", chapterNumber, pageIndex, pageEntry.Name, path)) 131 } 132 } 133 } 134 return strings.TrimRight(sb.String(), "\n") 135 } 136 137 type chapter struct { 138 Name string 139 Pages []page 140 Number string 141 } 142 143 type page struct { 144 Name string 145 Path string 146 Number string 147 }