Skip to content

Commit

Permalink
(feat) init - go progress SVGs
Browse files Browse the repository at this point in the history
  • Loading branch information
kevincobain2000 committed May 26, 2024
0 parents commit 263c6a3
Show file tree
Hide file tree
Showing 12 changed files with 613 additions and 0 deletions.
74 changes: 74 additions & 0 deletions .github/workflows/coveritup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
on:
pull_request:
push:
tags-ignore:
- '**'
branches:
- '**'

name: "Cover It Up"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
jobs:
coveritup:
strategy:
matrix:
go-version: [mod]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: kevincobain2000/action-gobrew@v2
with:
version: ${{ matrix.go-version }}

- name: Install Tools
run: |
go install github.com/securego/gosec/v2/cmd/gosec@latest
go install github.com/axw/gocov/gocov@latest
go install github.com/AlekSi/gocov-xml@latest
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
curl -sLk https://raw.githubusercontent.com/kevincobain2000/cover-totalizer/master/install.sh | sh
- run: go mod tidy
- name: Lint Errors
uses: kevincobain2000/action-coveritup@v2
with:
type: go-lint-errors
command: golangci-lint run ./... | grep -c "\^"

- name: Test
uses: kevincobain2000/action-coveritup@v2
with:
type: go-test-run-time
command: go test -race -v ./... -count=1 -coverprofile=coverage.out
record: runtime

- name: Test
uses: kevincobain2000/action-coveritup@v2
with:
type: go-build-time
command: go build
record: runtime

- name: Coverage
run: gocov convert coverage.out | gocov-xml > coverage.xml
- name: Coveritup
uses: kevincobain2000/action-coveritup@v2
with:
type: coverage
command: ./cover-totalizer coverage.xml

- name: Number of dependencies
uses: kevincobain2000/action-coveritup@v2
with:
type: go-mod-dependencies
command: go list -m all|wc -l|awk '{$1=$1};1'

- uses: kevincobain2000/action-coveritup@v2
with:
pr_comment: true
- uses: kevincobain2000/action-coveritup@v2
with:
pr_comment: true
23 changes: 23 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Binaries for programs and plugins
*.dll
*.so
*.dylib

# Test binary, build with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# diskcache directory
cache/*
vendor/*

tmp/

.env
*.pid
dist/
bin/
main
.DS_Store
output.svg
22 changes: 22 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
linters:
disable-all: true
# Enable specific linter
# https://golangci-lint.run/usage/linters/#enabled-by-default
enable:
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- dupl
- errorlint
- exportloopref
- goconst
- gocritic
- gocyclo
- goprintffuncname
- gosec
- prealloc
- revive
- stylecheck
- whitespace
89 changes: 89 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<p align="center">
<img alt="svg circle progress sample" src="https://imgur.com/UOfAB33.png">
</p>
<h2 align="center">
SVG - Circle & Bar Progress generator
<br>
in Golang.
<br>
<br>
</h2>


**Circle Progress:** Generate pure SVG circle progress bar.

**Bar Progress:** Generate pure SVG bar progress bar.

**Supports Captions:** Add captions horizontally or vertically.

**Customizable:** Customize with various color, width, height, background and caption options.

**Lightweight:** No dependencies, just a single file.

**Beautiful:** Customizable to rounded corners, different colors, and caption options.


## Usage

### Circle Progress

```go
import (
"fmt"
"os"

gps "github.com/kevincobain2000/go-progress-svg"
)

func main() {
circular, _ := gps.NewCircular(func(o *gps.CircularOptions) error {
o.Size = 200
o.CircleWidth = 16
o.ProgressWidth = 16
o.CircleColor = "#e0e0e0"
o.ProgressColor = "#76e5b1"
o.TextColor = "#6bdba7"
o.TextSize = 52
o.ShowPercentage = true
o.BackgroundColor = ""
o.Caption = ""
o.CaptionPos = "bottom"
o.CaptionSize = 20
o.CaptionColor = "#000000"
return nil
})

circular.SVG()
}
```

### Bar Progress

```go
import (
"fmt"
"os"

gps "github.com/kevincobain2000/go-progress-svg"
)

func main() {
bar, _ := gps.NewBar(func(o *gps.BarOptions) error {
o.Progress = 97
o.Width = 200
o.Height = 50
o.ProgressColor = "#76e5b1"
o.TextColor = "#6bdba7"
o.TextSize = 20
o.ShowPercentage = true
o.Caption = ""
o.CaptionSize = 16
o.CaptionColor = "#000000"
o.BackgroundColor = "#e0e0e0"
o.CornerRadius = 10
return nil
})

bar.SVG()
}
```
100 changes: 100 additions & 0 deletions bar.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package gps

import (
"fmt"
"strings"
"text/template"

"github.com/kevincobain2000/go-progress-svg/utils"
)

var barTPL = `
<svg width="{{.Width}}" height="{{.TotalHeight}}" version="1.1" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="100%" height="{{.Height}}" fill="{{.BackgroundColor}}" />
<rect x="0" y="0" width="{{.ProgressWidth}}" height="{{.Height}}" fill="{{.ProgressColor}}" rx="{{.CornerRadius}}" ry="{{.CornerRadius}}" />
{{if .ShowPercentage}}
<text x="50%" y="{{.HeightHalf}}" font-family="sans-serif" fill="{{.TextColor}}" font-size="{{.TextSize}}px" font-weight="bold" text-anchor="middle" alignment-baseline="middle">{{.Progress}}%</text>
{{end}}
{{if .Caption}}
<text x="50%" y="{{.CaptionY}}" font-family="sans-serif" fill="{{.CaptionColor}}" font-size="{{.CaptionSize}}px" font-weight="bold" text-anchor="middle">{{.Caption}}</text>
{{end}}
</svg>
`

type Bar struct {
options *BarOptions
strings *utils.Strings
}

type BarOptions struct {
Progress int
Width int
Height int
ProgressWidth string
ProgressColor string
TextColor string
TextSize int
ShowPercentage bool
Caption string
CaptionSize int
CaptionColor string
BackgroundColor string
TotalHeight int
HeightHalf int
CaptionY int
CornerRadius int
}

type BarOption func(*BarOptions) error

func NewBar(opts ...BarOption) (*Bar, error) {
options := &BarOptions{
Progress: 0,
Width: 200,
Height: 50,
ProgressColor: "#76e5b1",
TextColor: "#6bdba7",
TextSize: 20,
ShowPercentage: true,
Caption: "",
CaptionSize: 16,
CaptionColor: "#000000",
BackgroundColor: "#e0e0e0",
CornerRadius: 10,
}

for _, opt := range opts {
err := opt(options)
if err != nil {
return nil, err
}
}

options.ProgressWidth = fmt.Sprintf("%d%%", options.Progress)
options.TotalHeight = options.Height + options.CaptionSize + 10 // Additional space for caption
options.HeightHalf = options.Height / 2
options.CaptionY = options.Height + options.CaptionSize // Position caption below the bar

return &Bar{
options: options,
strings: utils.NewStrings(),
}, nil
}

func (b *Bar) SVG() string {
tpl := b.strings.StripXMLWhitespace(barTPL)
tmpl, err := template.New("svg").Parse(tpl)
if err != nil {
fmt.Println("Error parsing template:", err)
return ""
}

var rendered strings.Builder
err = tmpl.Execute(&rendered, b.options)
if err != nil {
fmt.Println("Error rendering template:", err)
return ""
}

return rendered.String()
}
39 changes: 39 additions & 0 deletions bar_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package gps

import (
"strings"
"testing"
)

func TestBarSVG(t *testing.T) {
// Test rendering the SVG with default options
bar, err := NewBar()
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}

svg := bar.SVG()
expectedStart := `<svg width="200" height="76"`
if !strings.HasPrefix(svg, expectedStart) {
t.Errorf("Expected SVG to start with %s, got %s", expectedStart, svg)
}

// Test rendering the SVG with custom options
bar, err = NewBar(
func(o *BarOptions) error {
o.Progress = 75
o.ProgressColor = "#ff0000"
o.BackgroundColor = "#0000ff"
return nil
},
)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}

svg = bar.SVG()
expectedStart = `<svg width="200" height="76"`
if !strings.HasPrefix(svg, expectedStart) {
t.Errorf("Expected SVG to start with %s, got %s", expectedStart, svg)
}
}
Loading

0 comments on commit 263c6a3

Please sign in to comment.