github.com/nozzle/golangci-lint@v1.49.0-nz3/pkg/printers/html.go (about) 1 package printers 2 3 import ( 4 "context" 5 "fmt" 6 "html/template" 7 "io" 8 "strings" 9 10 "github.com/golangci/golangci-lint/pkg/result" 11 ) 12 13 const templateContent = `<!doctype html> 14 <html lang="en"> 15 <head> 16 <meta charset="utf-8"> 17 <title>golangci-lint</title> 18 <link rel="shortcut icon" type="image/png" href="https://golangci-lint.run/favicon-32x32.png"> 19 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.9.2/css/bulma.min.css" 20 integrity="sha512-byErQdWdTqREz6DLAA9pCnLbdoGGhXfU6gm1c8bkf7F51JVmUBlayGe2A31VpXWQP+eiJ3ilTAZHCR3vmMyybA==" 21 crossorigin="anonymous" referrerpolicy="no-referrer"/> 22 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/styles/default.min.css" 23 integrity="sha512-kZqGbhf9JTB4bVJ0G8HCkqmaPcRgo88F0dneK30yku5Y/dep7CZfCnNml2Je/sY4lBoqoksXz4PtVXS4GHSUzQ==" 24 crossorigin="anonymous" referrerpolicy="no-referrer"/> 25 <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/highlight.min.js" 26 integrity="sha512-s+tOYYcC3Jybgr9mVsdAxsRYlGNq4mlAurOrfNuGMQ/SCofNPu92tjE7YRZCsdEtWL1yGkqk15fU/ark206YTg==" 27 crossorigin="anonymous" referrerpolicy="no-referrer"></script> 28 <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/languages/go.min.js" 29 integrity="sha512-+UYV2NyyynWEQcZ4sMTKmeppyV331gqvMOGZ61/dqc89Tn1H40lF05ACd03RSD9EWwGutNwKj256mIR8waEJBQ==" 30 crossorigin="anonymous" referrerpolicy="no-referrer"></script> 31 <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js" 32 integrity="sha512-qlzIeUtTg7eBpmEaS12NZgxz52YYZVF5myj89mjJEesBd/oE9UPsYOX2QAXzvOAZYEvQohKdcY8zKE02ifXDmA==" 33 crossorigin="anonymous" referrerpolicy="no-referrer"></script> 34 <script type="text/javascript" 35 src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js" 36 integrity="sha512-9jGNr5Piwe8nzLLYTk8QrEMPfjGU0px80GYzKZUxi7lmCfrBjtyCc1V5kkS5vxVwwIB7Qpzc7UxLiQxfAN30dw==" 37 crossorigin="anonymous" referrerpolicy="no-referrer"></script> 38 <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js" 39 integrity="sha512-kp7YHLxuJDJcOzStgd6vtpxr4ZU9kjn77e6dBsivSz+pUuAuMlE2UTdKB7jjsWT84qbS8kdCWHPETnP/ctrFsA==" 40 crossorigin="anonymous" referrerpolicy="no-referrer"></script> 41 </head> 42 <body> 43 <section class="section"> 44 <div class="container"> 45 <div id="content"></div> 46 </div> 47 </section> 48 <script> 49 const data = {{ . }}; 50 </script> 51 <script type="text/babel"> 52 class Highlight extends React.Component { 53 componentDidMount() { 54 hljs.highlightElement(ReactDOM.findDOMNode(this)); 55 } 56 57 render() { 58 return <pre className="go"><code>{this.props.code}</code></pre>; 59 } 60 } 61 62 class Issue extends React.Component { 63 render() { 64 return ( 65 <div className="issue box"> 66 <div> 67 <div className="columns"> 68 <div className="column is-four-fifths"> 69 <h5 className="title is-5 has-text-danger-dark">{this.props.data.Title}</h5> 70 </div> 71 <div className="column is-one-fifth"> 72 <h6 className="title is-6">{this.props.data.Linter}</h6> 73 </div> 74 </div> 75 <strong>{this.props.data.Pos}</strong> 76 </div> 77 <div className="highlight"> 78 <Highlight code={this.props.data.Code}/> 79 </div> 80 </div> 81 ); 82 } 83 } 84 85 class Issues extends React.Component { 86 render() { 87 if (!this.props.data.Issues || this.props.data.Issues.length === 0) { 88 return ( 89 <div> 90 <div className="notification"> 91 No issues found! 92 </div> 93 </div> 94 ); 95 } 96 97 return ( 98 <div className="issues"> 99 {this.props.data.Issues.map(issue => (<Issue data={issue}/>))} 100 </div> 101 ); 102 } 103 } 104 105 ReactDOM.render( 106 <div className="content"> 107 <div className="columns is-centered"> 108 <div className="column is-three-quarters"> 109 <Issues data={data}/> 110 </div> 111 </div> 112 </div>, 113 document.getElementById("content") 114 ); 115 </script> 116 </body> 117 </html>` 118 119 type htmlIssue struct { 120 Title string 121 Pos string 122 Linter string 123 Code string 124 } 125 126 type HTML struct { 127 w io.Writer 128 } 129 130 func NewHTML(w io.Writer) *HTML { 131 return &HTML{w: w} 132 } 133 134 func (p HTML) Print(_ context.Context, issues []result.Issue) error { 135 var htmlIssues []htmlIssue 136 137 for i := range issues { 138 pos := fmt.Sprintf("%s:%d", issues[i].FilePath(), issues[i].Line()) 139 if issues[i].Pos.Column != 0 { 140 pos += fmt.Sprintf(":%d", issues[i].Pos.Column) 141 } 142 143 htmlIssues = append(htmlIssues, htmlIssue{ 144 Title: strings.TrimSpace(issues[i].Text), 145 Pos: pos, 146 Linter: issues[i].FromLinter, 147 Code: strings.Join(issues[i].SourceLines, "\n"), 148 }) 149 } 150 151 t, err := template.New("golangci-lint").Parse(templateContent) 152 if err != nil { 153 return err 154 } 155 156 return t.Execute(p.w, struct{ Issues []htmlIssue }{Issues: htmlIssues}) 157 }