kanbn2md/main.go
Todd Davis b9acf6cc67 Inital release of kanbn2md
Renders json output of `kanbn board -j` as a markdown table.
2021-06-12 08:54:28 -05:00

115 lines
2.8 KiB
Go

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
}