github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/blueprint/bootstrap/writedocs.go (about) 1 package bootstrap 2 3 import ( 4 "bytes" 5 "fmt" 6 "html/template" 7 "io/ioutil" 8 "path/filepath" 9 10 "github.com/google/blueprint" 11 "github.com/google/blueprint/bootstrap/bpdoc" 12 "github.com/google/blueprint/pathtools" 13 ) 14 15 // ModuleTypeDocs returns a list of bpdoc.ModuleType objects that contain information relevant 16 // to generating documentation for module types supported by the primary builder. 17 func ModuleTypeDocs(ctx *blueprint.Context) ([]*bpdoc.ModuleType, error) { 18 // Find the module that's marked as the "primary builder", which means it's 19 // creating the binary that we'll use to generate the non-bootstrap 20 // build.ninja file. 21 var primaryBuilders []*goBinary 22 var minibp *goBinary 23 ctx.VisitAllModulesIf(isBootstrapBinaryModule, 24 func(module blueprint.Module) { 25 binaryModule := module.(*goBinary) 26 if binaryModule.properties.PrimaryBuilder { 27 primaryBuilders = append(primaryBuilders, binaryModule) 28 } 29 if ctx.ModuleName(binaryModule) == "minibp" { 30 minibp = binaryModule 31 } 32 }) 33 34 if minibp == nil { 35 panic("missing minibp") 36 } 37 38 var primaryBuilder *goBinary 39 switch len(primaryBuilders) { 40 case 0: 41 // If there's no primary builder module then that means we'll use minibp 42 // as the primary builder. 43 primaryBuilder = minibp 44 45 case 1: 46 primaryBuilder = primaryBuilders[0] 47 48 default: 49 return nil, fmt.Errorf("multiple primary builder modules present") 50 } 51 52 pkgFiles := make(map[string][]string) 53 ctx.VisitDepsDepthFirst(primaryBuilder, func(module blueprint.Module) { 54 switch m := module.(type) { 55 case (*goPackage): 56 pkgFiles[m.properties.PkgPath] = pathtools.PrefixPaths(m.properties.Srcs, 57 filepath.Join(SrcDir, ctx.ModuleDir(m))) 58 default: 59 panic(fmt.Errorf("unknown dependency type %T", module)) 60 } 61 }) 62 63 return bpdoc.ModuleTypes(pkgFiles, ctx.ModuleTypePropertyStructs()) 64 } 65 66 func writeDocs(ctx *blueprint.Context, filename string) error { 67 moduleTypeList, err := ModuleTypeDocs(ctx) 68 if err != nil { 69 return err 70 } 71 72 buf := &bytes.Buffer{} 73 74 unique := 0 75 76 tmpl, err := template.New("file").Funcs(map[string]interface{}{ 77 "unique": func() int { 78 unique++ 79 return unique 80 }}).Parse(fileTemplate) 81 if err != nil { 82 return err 83 } 84 85 err = tmpl.Execute(buf, moduleTypeList) 86 if err != nil { 87 return err 88 } 89 90 err = ioutil.WriteFile(filename, buf.Bytes(), 0666) 91 if err != nil { 92 return err 93 } 94 95 return nil 96 } 97 98 const ( 99 fileTemplate = ` 100 <html> 101 <head> 102 <title>Build Docs</title> 103 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> 104 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> 105 <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script> 106 </head> 107 <body> 108 <h1>Build Docs</h1> 109 <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true"> 110 {{range .}} 111 {{ $collapseIndex := unique }} 112 <div class="panel panel-default"> 113 <div class="panel-heading" role="tab" id="heading{{$collapseIndex}}"> 114 <h2 class="panel-title"> 115 <a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion" href="#collapse{{$collapseIndex}}" aria-expanded="false" aria-controls="collapse{{$collapseIndex}}"> 116 {{.Name}} 117 </a> 118 </h2> 119 </div> 120 </div> 121 <div id="collapse{{$collapseIndex}}" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading{{$collapseIndex}}"> 122 <div class="panel-body"> 123 <p>{{.Text}}</p> 124 {{range .PropertyStructs}} 125 <p>{{.Text}}</p> 126 {{template "properties" .Properties}} 127 {{end}} 128 </div> 129 </div> 130 {{end}} 131 </div> 132 </body> 133 </html> 134 135 {{define "properties"}} 136 <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true"> 137 {{range .}} 138 {{$collapseIndex := unique}} 139 {{if .Properties}} 140 <div class="panel panel-default"> 141 <div class="panel-heading" role="tab" id="heading{{$collapseIndex}}"> 142 <h4 class="panel-title"> 143 <a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion" href="#collapse{{$collapseIndex}}" aria-expanded="false" aria-controls="collapse{{$collapseIndex}}"> 144 {{.Name}}{{range .OtherNames}}, {{.}}{{end}} 145 </a> 146 </h4> 147 </div> 148 </div> 149 <div id="collapse{{$collapseIndex}}" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading{{$collapseIndex}}"> 150 <div class="panel-body"> 151 <p>{{.Text}}</p> 152 {{range .OtherTexts}}<p>{{.}}</p>{{end}} 153 {{template "properties" .Properties}} 154 </div> 155 </div> 156 {{else}} 157 <div> 158 <h4>{{.Name}}{{range .OtherNames}}, {{.}}{{end}}</h4> 159 <p>{{.Text}}</p> 160 {{range .OtherTexts}}<p>{{.}}</p>{{end}} 161 <p><i>Type: {{.Type}}</i></p> 162 {{if .Default}}<p><i>Default: {{.Default}}</i></p>{{end}} 163 </div> 164 {{end}} 165 {{end}} 166 </div> 167 {{end}} 168 ` 169 )