github.com/getgauge/gauge@v1.6.9/build/man/man.go (about) 1 /*---------------------------------------------------------------- 2 * Copyright (c) ThoughtWorks, Inc. 3 * Licensed under the Apache License, Version 2.0 4 * See LICENSE in the project root for license information. 5 *----------------------------------------------------------------*/ 6 7 package main 8 9 import ( 10 "log" 11 12 "strings" 13 14 "os" 15 "path/filepath" 16 17 "math" 18 19 "github.com/getgauge/common" 20 "github.com/getgauge/gauge/cmd" 21 "github.com/russross/blackfriday/v2" 22 "github.com/spf13/cobra" 23 "github.com/spf13/cobra/doc" 24 ) 25 26 const ( 27 maxDescLength = 46 28 maxLineLength = 77 29 ) 30 31 type text struct { 32 name string 33 content string 34 } 35 36 func main() { 37 mdPath := filepath.Join("_man", "md") 38 htmlPath := filepath.Join("_man", "html") 39 createDir(mdPath) 40 createDir(htmlPath) 41 if err := genMarkdownManPages(mdPath); err != nil { 42 log.Fatal(err.Error()) 43 } 44 texts := indentText(mdPath) 45 for _, t := range texts { 46 name := strings.TrimSuffix(t.name, filepath.Ext(t.name)) + ".html" 47 output := strings.Replace(html, "<!--CONTENT-->", string(blackfriday.Run([]byte(t.content))), -1) 48 p := filepath.Join(htmlPath, name) 49 err := os.WriteFile(p, []byte(output), 0644) 50 if err != nil { 51 log.Fatalf("Unable to write file %s: %s", p, err.Error()) 52 } 53 } 54 log.Printf("HTML man pages are available in %s dir\n", htmlPath) 55 } 56 func createDir(p string) { 57 if err := os.MkdirAll(p, common.NewDirectoryPermissions); err != nil { 58 log.Fatal(err.Error()) 59 } 60 } 61 62 func genMarkdownManPages(out string) error { 63 if err := doc.GenMarkdownTree(setupCmd(), out); err != nil { 64 return err 65 } 66 log.Printf("Added markdown man pages to `%s`\n", out) 67 return nil 68 } 69 70 func setupCmd() *cobra.Command { 71 cmd.GaugeCmd.Short = "A light-weight cross-platform test automation tool" 72 cmd.GaugeCmd.Long = "Gauge is a light-weight cross-platform test automation tool with the ability to author test cases in the business language." 73 return cmd.GaugeCmd 74 } 75 76 func indentText(p string) (texts []text) { 77 err := filepath.Walk(p, func(path string, info os.FileInfo, err error) error { 78 if strings.HasSuffix(info.Name(), ".md") { 79 bytes, err := os.ReadFile(path) 80 if err != nil { 81 return err 82 } 83 var lines []string 84 for _, l := range strings.Split(string(bytes), string("\n")) { 85 tLine := strings.TrimSpace(l) 86 if strings.HasPrefix(tLine, "-") && len(tLine) > maxLineLength { 87 lines = append(lines, indentFlag(l, tLine)...) 88 } else { 89 lines = append(lines, strings.Replace(l, ".md", ".html", -1)) 90 } 91 } 92 texts = append(texts, text{name: info.Name(), content: strings.Join(lines, "\n")}) 93 } 94 return nil 95 }) 96 if err != nil { 97 log.Fatal(err.Error()) 98 } 99 100 return 101 } 102 103 func indentFlag(line, tLine string) (lines []string) { 104 words := strings.Split(tLine, " ") 105 desc := strings.TrimSpace(words[len(words)-1]) 106 dWords := strings.Split(desc, " ") 107 times := math.Ceil(float64(len(desc)) / maxDescLength) 108 for i := 0; float64(i) < times; i++ { 109 till := 0 110 length := 0 111 for i, v := range dWords { 112 length += len(v) 113 if length > maxDescLength { 114 till = i - 1 115 break 116 } 117 if i == len(dWords)-1 { 118 till = len(dWords) 119 } 120 } 121 if len(dWords) == 0 { 122 continue 123 } 124 prefix := strings.Replace(line, desc, strings.Join(dWords[:till], " "), -1) 125 if i != 0 { 126 prefix = strings.Repeat(" ", strings.Index(line, desc)) + strings.Join(dWords[:till], " ") 127 } 128 lines = append(lines, prefix) 129 dWords = dWords[till:] 130 } 131 return 132 } 133 134 const html = ` 135 <!DOCTYPE html> 136 <html> 137 138 <head> 139 <title>Gauge - Manual</title> 140 <link href="https://gauge.org/assets/images/favicons/favicon.ico" rel="shortcut icon" type="image/ico" /> 141 <style type='text/css' media='all'> 142 body#manpage { 143 margin: 0; 144 border-top: 3px solid #f5c10e; 145 } 146 147 .mp { 148 max-width: 100ex; 149 padding: 0 9ex 1ex 4ex; 150 margin-top: 1.5%; 151 } 152 153 .mp p, 154 .mp pre, 155 .mp ul, 156 .mp ol, 157 .mp dl { 158 margin: 0 0 20px 0; 159 } 160 161 .mp h2 { 162 margin: 10px 0 0 0 163 } 164 165 .mp h3 { 166 margin: 0 0 0 0; 167 } 168 169 .mp dt { 170 margin: 0; 171 clear: left 172 } 173 174 .mp dt.flush { 175 float: left; 176 width: 8ex 177 } 178 179 .mp dd { 180 margin: 0 0 0 9ex 181 } 182 183 .mp h1, 184 .mp h2, 185 .mp h3, 186 .mp h4 { 187 clear: left 188 } 189 190 .mp pre { 191 margin-bottom: 20px; 192 } 193 194 .mp pre+h2, 195 .mp pre+h3 { 196 margin-top: 22px 197 } 198 199 .mp h2+pre, 200 .mp h3+pre { 201 margin-top: 5px 202 } 203 204 .mp img { 205 display: block; 206 margin: auto 207 } 208 209 .mp h1.man-title { 210 display: none 211 } 212 213 .mp, 214 .mp code, 215 .mp pre, 216 .mp tt, 217 .mp kbd, 218 .mp samp, 219 .mp h3, 220 .mp h4 { 221 font-family: monospace; 222 font-size: 14px; 223 line-height: 1.42857142857143 224 } 225 226 .mp h2 { 227 font-size: 16px; 228 line-height: 1.25 229 } 230 231 .mp h1 { 232 font-size: 20px; 233 line-height: 2 234 } 235 236 .mp { 237 text-align: justify; 238 background: #fff 239 } 240 241 .mp, 242 .mp code, 243 .mp pre, 244 .mp pre code, 245 .mp tt, 246 .mp kbd, 247 .mp samp { 248 color: #131211 249 } 250 251 .mp h1, 252 .mp h2, 253 .mp h3, 254 .mp h4 { 255 color: #030201 256 } 257 258 .mp u { 259 text-decoration: underline 260 } 261 262 .mp code, 263 .mp strong, 264 .mp b { 265 font-weight: bold; 266 color: #131211 267 } 268 269 .mp em, 270 .mp var { 271 font-style: italic; 272 color: #232221; 273 text-decoration: none 274 } 275 276 .mp a, 277 .mp a:link, 278 .mp a:hover, 279 .mp a code, 280 .mp a pre, 281 .mp a tt, 282 .mp a kbd, 283 .mp a samp { 284 color: #0000ff 285 } 286 287 .mp b.man-ref { 288 font-weight: normal; 289 color: #434241 290 } 291 292 .mp pre code { 293 font-weight: normal; 294 color: #434241 295 } 296 297 .mp h2+pre, 298 h3+pre { 299 padding-left: 0 300 } 301 302 ol.man-decor, 303 ol.man-decor li { 304 margin: 3px 0 10px 0; 305 padding: 0; 306 float: left; 307 width: 33%; 308 list-style-type: none; 309 text-transform: uppercase; 310 color: #999; 311 letter-spacing: 1px; 312 } 313 314 ol.man-decor { 315 width: 100%; 316 } 317 318 ol.man-decor li.tl { 319 text-align: left; 320 } 321 322 ol.man-decor li.tc { 323 text-align: center; 324 letter-spacing: 4px; 325 } 326 327 ol.man-decor li.tr { 328 text-align: right; 329 float: right; 330 } 331 </style> 332 </head> 333 334 <body id='manpage'> 335 <div class='mp' id='man'> 336 <!--CONTENT--> 337 <div><b>Complete documentation is available <a href="https://docs.gauge.org/">here</a>.</b></div> 338 </div> 339 340 </body> 341 342 </html> 343 `