Inital release of kanbn2md

Renders json output of `kanbn board -j` as a markdown table.
This commit is contained in:
Todd Davis 2021-06-12 08:54:28 -05:00
commit b9acf6cc67
5 changed files with 184 additions and 0 deletions

20
.github/workflows/release-please.yml vendored Normal file
View File

@ -0,0 +1,20 @@
on:
push:
branches:
- master
name: release-please
jobs:
release-please:
runs-on: ubuntu-latest
outputs:
release_created: ${{ steps.release.outputs.release_created }}
steps:
- uses: GoogleCloudPlatform/release-please-action@v2
id: release
with:
token: ${{ secrets.GITHUB_TOKEN }}
release-type: simple
bump-minor-pre-major: Yes
package-name: kanbn2md

20
.gitignore vendored Normal file
View File

@ -0,0 +1,20 @@
#### joe made this: http://goel.io/joe
#### go ####
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
.kanbn

27
README.md Normal file
View File

@ -0,0 +1,27 @@
# kanbn2md
[Kanbn](https://github.com/basementuniverse/kanbn) is a CLI Kanban board. It stores
the task information in markdown format and has a [vscode extension](https://github.com/basementuniverse/vscode-kanbn)
for viewing and editing the board from vscode. What is missing is a way to render the board as a markdown table.
This simple program takes JSON output of `kanbn board -j` on stdin and renders a markdown table on stdout.
## Installation
Download a binary from the releases page or install via go with
```bash
go install github.com/tjdavis3/kanbn2md
```
## Usage
```bash
kanbn board -j | kanbn2md > board.md
```
## Example
| Backlog | Todo | In Progress | Done |
| --- | --- | --- | --- |
| Comment the code | Create github repo | Create a README.md | Build app |
| Add tests | Add error handling | | |

3
go.mod Normal file
View File

@ -0,0 +1,3 @@
module github.com/tjdavis3/kanbn2md
go 1.16

114
main.go Normal file
View File

@ -0,0 +1,114 @@
package main
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"os"
)
// KanbnColumns are the board columns as represented in the kanbn json
type KanbnColumns [][]struct {
Column string `json:"column"`
Comments []interface{} `json:"comments"`
Description string `json:"description"`
ID string `json:"id"`
Metadata struct {
Assigned string `json:"assigned"`
Created string `json:"created"`
Progress int `json:"progress"`
Started *string `json:"started,omitempty"`
Tags []interface{} `json:"tags"`
Updated string `json:"updated"`
} `json:"metadata"`
Name string `json:"name"`
Progress int `json:"progress"`
Relations []interface{} `json:"relations"`
RemainingWorkload int `json:"remainingWorkload"`
SubTasks []struct {
Completed bool `json:"completed"`
Text string `json:"text"`
} `json:"subTasks"`
Workload int `json:"workload"`
}
// KanbnBoard represents the JSON output of `kanbn board -j`
type KanbnBoard struct {
Headings []struct {
Heading string `json:"heading"`
Name string `json:"name"`
} `json:"headings"`
Lanes []struct {
Columns KanbnColumns `json:"columns"`
Name string `json:"name"`
} `json:"lanes"`
}
func main() {
err := renderBoard(os.Stdin, os.Stdout)
if err != nil {
log.Fatal(err)
}
}
// renderBoard takes care of reading the kanbn json
// and rendering it as a markdown table
func renderBoard(r io.Reader, w io.Writer) error {
var kanbn KanbnBoard
var rows [][]string
board, err := ioutil.ReadAll(r)
if err != nil {
return err
}
if err = json.Unmarshal(board, &kanbn); err != nil {
return err
}
// Determine how many columns exists and print the header row
columnCount := len(kanbn.Headings)
for _, col := range kanbn.Headings {
fmt.Fprintf(w, "| %s ", col.Name)
}
fmt.Fprintln(w, "|")
for i := 0; i < columnCount; i++ {
fmt.Fprint(w, "| --- ")
}
fmt.Fprintln(w, "|")
// read the swimlanes
// The lanes themselves are not printed on the table
for _, lane := range kanbn.Lanes {
maxRows := determineMaxRows(lane.Columns)
// initialize an array of rows
rows = make([][]string, maxRows)
for i := range rows {
rows[i] = make([]string, columnCount)
}
// convert columns of rows into rows of columns
for curCol, column := range lane.Columns {
for colRow, task := range column {
rows[colRow][curCol] = task.Name
}
}
// print the rows
for _, row := range rows {
for _, col := range row {
fmt.Fprintf(w, "| %s ", col)
}
fmt.Fprintln(w, "|")
}
}
return nil
}
func determineMaxRows(cols KanbnColumns) int {
var maxRows int
for _, column := range cols {
if len(column) > maxRows {
maxRows = len(column)
}
}
return maxRows
}