Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New kit theme #40

Merged
merged 11 commits into from
Mar 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
v 1.3
- New kit theme. #28
- refac: generate Go code to render themes. #38
- doc: fix semver in README. #36

Expand Down
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
# Gocov HTML export

This is a simple helper tool for generating HTML output from [axw/gocov](https://github.com/axw/gocov/)
This is a simple helper tool for generating HTML output from [axw/gocov](https://github.com/axw/gocov/).

Here is a screenshot:

![HTML coverage report screenshot](https://github.com/matm/gocov-html/blob/master/gocovh-html.png)
`gocov-html` has support for themes, you might want to have a [look at the screenshots](themes/README.md).

## Installation

Binaries for most amd64 systems are built for every release. Please just [grab a binary version of the latest release](https://github.com/matm/gocov-html/releases).

However you can build it from source. Please note that building from source requires Go 1.11+.
You can also build it from source. In this case, a working Go 1.11+ compiler is required.

Just type the following to install the program and its dependencies:
The easiest way to compile this tool is to fetch the repository's code and run `make` (which defaults to using the `build` target):
```bash
$ go install github.com/axw/gocov/gocov@latest
$ go install github.com/matm/gocov-html/cmd/gocov-html@latest
$ git clone https://github.com/matm/gocov-html.git
$ cd gocov-html
$ make
```

## Features Matrix
Expand All @@ -28,6 +27,7 @@ Write CSS of default theme to stdout|`-d`|`1.2.0`
Embbed custom CSS into final HTML document|-|`1.2.0`
List available themes|`-lt`|`1.2.0`
Render with a specific theme|`-t <theme>`|`1.2.0`
New `kit` theme |`-t kit`|`1.3.0`

## Usage

Expand Down
7 changes: 4 additions & 3 deletions build.mk
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,10 @@ cleardist:
@rm -rf ${DISTDIR} && mkdir -p ${BINDIR} && mkdir -p ${BUILDDIR}

build:
@go build ${GENERATOR_CMD}
@go generate ./...
@go build -ldflags "all=$(GO_LDFLAGS)" ${MAIN_CMD}
go build ${GENERATOR_CMD} && \
go generate ./...
@echo "building ..." && \
go build -ldflags "all=$(GO_LDFLAGS)" ${MAIN_CMD}

test:
@go test ./...
Expand Down
89 changes: 54 additions & 35 deletions cmd/generator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,40 +27,41 @@ import (
"github.com/matm/gocov-html/pkg/types"
)

func (t defaultTheme) Data() *types.TemplateData {
func (t {{.Type}}) Data() *types.TemplateData {
td:= &types.TemplateData{
When: time.Now().Format(time.RFC822Z),
When: time.Now().Format(time.RFC1123),
ProjectURL: types.ProjectURL,
}
{{if .Style}}
td.Style = {{.Style}}
td.Style = string({{.Style}})
{{end}}
{{if .Script}}
td.Script = {{.Script}}
td.Script = string({{.Script}})
{{end}}
return td
}

func (t defaultTheme) Template() *template.Template {
func (t {{.Type}}) Template() *template.Template {
tmpl := {{.Template}}
p := template.Must(template.New("theme").Parse(tmpl))
return p
}
`

func inspect(name string, theme *string, assets *types.StaticAssets) error {
func inspect(p *params) error {
fset := token.NewFileSet()
token, err := parser.ParseFile(fset, name, nil, parser.ParseComments)
token, err := parser.ParseFile(fset, p.filename, nil, parser.ParseComments)
if err != nil {
return err
}
ast.Inspect(token, func(n ast.Node) bool {
fn, ok := n.(*ast.FuncDecl)
if ok {
p.rtype = fn.Recv.List[0].Type.(*ast.Ident).Name
switch fn.Name.Name {
case "Name":
*theme = fn.Body.List[0].(*ast.ReturnStmt).Results[0].(*ast.BasicLit).Value
*theme = strings.Replace(*theme, `"`, "", -1)
p.theme = fn.Body.List[0].(*ast.ReturnStmt).Results[0].(*ast.BasicLit).Value
p.theme = strings.Replace(p.theme, `"`, "", -1)
case "Assets":
es := fn.Body.List[0].(*ast.ReturnStmt).Results[0].(*ast.CompositeLit).Elts
for _, e := range es {
Expand All @@ -71,16 +72,16 @@ func inspect(name string, theme *string, assets *types.StaticAssets) error {
elems := kv.Value.(*ast.CompositeLit).Elts
for _, elem := range elems {
sheet := elem.(*ast.BasicLit).Value
assets.Stylesheets = append(assets.Stylesheets, strings.Replace(sheet, `"`, "", -1))
p.assets.Stylesheets = append(p.assets.Stylesheets, strings.Replace(sheet, `"`, "", -1))
}
case "Index":
tmplName := kv.Value.(*ast.BasicLit).Value
assets.Index = strings.Replace(tmplName, `"`, "", -1)
p.assets.Index = strings.Replace(tmplName, `"`, "", -1)
case "Scripts":
elems := kv.Value.(*ast.CompositeLit).Elts
for _, elem := range elems {
script := elem.(*ast.BasicLit).Value
assets.Scripts = append(assets.Scripts, strings.Replace(script, `"`, "", -1))
p.assets.Scripts = append(p.assets.Scripts, strings.Replace(script, `"`, "", -1))
}
}
}
Expand All @@ -92,36 +93,46 @@ func inspect(name string, theme *string, assets *types.StaticAssets) error {
return nil
}

func render(name, theme string, assets types.StaticAssets) error {
baseThemeDir := path.Join("..", "..", "themes", theme)
out := strings.Replace(name, ".go", "_gen.go", 1)
func render(p *params) error {
baseThemeDir := path.Join("..", "..", "themes", p.theme)
out := strings.Replace(p.filename, ".go", "_gen.go", 1)
outFile, err := os.Create(out)
if err != nil {
return err
}
defer outFile.Close()
index, err := ioutil.ReadFile(path.Join(baseThemeDir, assets.Index))
index, err := ioutil.ReadFile(path.Join(baseThemeDir, p.assets.Index))
if err != nil {
return err
}
// Contains all stylesheets' data.
var allStyles bytes.Buffer
for _, css := range assets.Stylesheets {
style, err := ioutil.ReadFile(path.Join(baseThemeDir, css))
if err != nil {
return err
}
fmt.Fprintf(&allStyles, "`%s`", style)
}

// Contains all scripts' data.
var allScripts bytes.Buffer
for _, script := range assets.Scripts {
js, err := ioutil.ReadFile(path.Join(baseThemeDir, script))
if err != nil {
return err

type static struct {
buf *bytes.Buffer
assets []string
}

for _, st := range []static{
{&allStyles, p.assets.Stylesheets},
{&allScripts, p.assets.Scripts},
} {
var buf bytes.Buffer
for _, asset := range st.assets {
raw, err := ioutil.ReadFile(path.Join(baseThemeDir, asset))
if err != nil {
return err
}
_, err = buf.Write(raw)
if err != nil {
return err
}
}
fmt.Fprintf(&allScripts, "`%s`", js)
// Write a slice of bytes to deal with any invalid character.
// Later converted to a string before template rendering.
fmt.Fprintf(st.buf, "%#v", buf.Bytes())
}
t, err := template.New("").Parse(tmpl)
if err != nil {
Expand All @@ -131,28 +142,36 @@ func render(name, theme string, assets types.StaticAssets) error {
Script string
Style string
Template string
Type string
}
err = t.Execute(outFile, &data{
Script: allScripts.String(),
Style: allStyles.String(),
Template: "`" + string(index) + "`"},
)
Template: "`" + string(index) + "`",
Type: p.rtype,
})
return err
}

type params struct {
filename string
rtype string // Receiver type.
theme string
assets types.StaticAssets
}

func main() {
name := os.Getenv("GOFILE")
if name == "" {
fmt.Println("Must be run by the \"go generate\" tool, like \"go generate ./...\"")
os.Exit(1)
}
assets := new(types.StaticAssets)
theme := new(string)
err := inspect(name, theme, assets)
p := &params{filename: name}
err := inspect(p)
if err != nil {
log.Fatal(err)
}
if err := render(name, *theme, *assets); err != nil {
if err := render(p); err != nil {
log.Fatal(err)
}
}
7 changes: 7 additions & 0 deletions pkg/cov/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import (
"io/ioutil"
"os"
"sort"
"strings"
"time"

"github.com/axw/gocov"
"github.com/matm/gocov-html/pkg/themes"
Expand Down Expand Up @@ -120,12 +122,15 @@ func printReport(w io.Writer, r *report) error {
css = string(style)
}
reportPackages := make(types.ReportPackageList, len(r.packages))
pkgNames := make([]string, len(r.packages))
for i, pkg := range r.packages {
reportPackages[i] = buildReportPackage(pkg)
pkgNames[i] = pkg.Name
}

data.Style = css
data.Packages = reportPackages
data.Command = fmt.Sprintf("gocov test %s | gocov-html -t %s", strings.Join(pkgNames, " "), theme.Name())

if len(reportPackages) > 1 {
rv := types.ReportPackage{
Expand Down Expand Up @@ -153,6 +158,7 @@ func exists(path string) (bool, error) {
// is an absolute path to a custom stylesheet. Use an empty
// string to use the default stylesheet available.
func HTMLReportCoverage(r io.Reader, css string) error {
t0 := time.Now()
report := newReport()

// Custom stylesheet?
Expand Down Expand Up @@ -180,5 +186,6 @@ func HTMLReportCoverage(r io.Reader, css string) error {
}
fmt.Println()
err = printReport(os.Stdout, report)
fmt.Fprintf(os.Stderr, "Took %v\n", time.Since(t0))
return eris.Wrap(err, "HTML report")
}
31 changes: 31 additions & 0 deletions pkg/themes/kit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package themes

//go:generate ../../generator

import (
"github.com/matm/gocov-html/pkg/types"
)

type kitTheme struct{}

func (t kitTheme) Assets() types.StaticAssets {
return types.StaticAssets{
Stylesheets: []string{
// From the official theme.
"app.css",
//"a.css", "b.css",
// Custom rules.
"kit.css",
},
Scripts: []string{"app.js"},
Index: "index.html",
}
}

func (t kitTheme) Name() string {
return "kit"
}

func (t kitTheme) Description() string {
return "AdminKit theme"
}
1 change: 1 addition & 0 deletions pkg/themes/theme.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

var themes = []types.Beautifier{
defaultTheme{},
kitTheme{},
}

// Theme to use for rendering.
Expand Down
2 changes: 2 additions & 0 deletions pkg/types/theme.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ type Beautifier interface {

// TemplateData has all the fields needed by the the HTML template for rendering.
type TemplateData struct {
// Command is the shell command used to generate the HTML report.
Command string
// Style is the stylesheet content that will be embedded in the HTML page.
Style string
// Script is the javascript content that will be embedded in the HTML page.
Expand Down
21 changes: 21 additions & 0 deletions themes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Available Themes

## golang

This is the default theme:

```shell
$ gocov test strings | gocov-html -t golang > strings.html
```

![golang theme screenshot](golang/screenshot.png)

## kit

Uses the [AdminKit](https://adminkit.io) theme:

```shell
$ gocov test encoding/csv strings | gocov-html -t kit > strings.html
```

![kit theme screenshot](kit/screenshot.png)
Loading