github.com/kyleu/dbaudit@v0.0.2-0.20240321155047-ff2f2c940496/app/util/markdown.go (about)

     1  // Package util - Content managed by Project Forge, see [projectforge.md] for details.
     2  package util
     3  
     4  import (
     5  	"github.com/pkg/errors"
     6  	"github.com/samber/lo"
     7  )
     8  
     9  func MarkdownTable(header []string, rows [][]string, linebreak string) (string, error) {
    10  	maxes := lo.Map(header, func(h string, _ int) int {
    11  		return len(h)
    12  	})
    13  	for vi, v := range rows {
    14  		if len(v) != len(header) {
    15  			return "", errors.Errorf("row [%d] contains [%d] fields, but [%d] header fields were provided", vi, len(v), len(header))
    16  		}
    17  		lo.ForEach(v, func(cellVal string, cellIdx int) {
    18  			if cellIdx <= len(maxes)-1 && len(cellVal) > maxes[cellIdx] {
    19  				maxes[cellIdx] = len(cellVal)
    20  			}
    21  		})
    22  	}
    23  
    24  	ret := NewStringSlice(make([]string, 0, len(rows)))
    25  	add := func(x []string) {
    26  		line := "| "
    27  		lo.ForEach(x, func(v string, vi int) {
    28  			mx := 0
    29  			if vi < len(maxes) {
    30  				mx = maxes[vi]
    31  			}
    32  			line += StringPad(v, mx)
    33  			if vi < len(x)-1 {
    34  				line += " | "
    35  			}
    36  		})
    37  		line += " |"
    38  		ret.Push(line)
    39  	}
    40  
    41  	add(header)
    42  
    43  	divider := "|-"
    44  	lo.ForEach(maxes, func(m int, mi int) {
    45  		lo.Times(m, func(_ int) struct{} {
    46  			divider += "-"
    47  			return struct{}{}
    48  		})
    49  		if mi < len(maxes)-1 {
    50  			divider += "-|-"
    51  		}
    52  	})
    53  	divider += "-|"
    54  	ret.Push(divider)
    55  
    56  	lo.ForEach(rows, func(row []string, _ int) {
    57  		add(row)
    58  	})
    59  	return ret.Join(linebreak), nil
    60  }
    61  
    62  func MarkdownTableParse(md string) ([]string, [][]string) {
    63  	var header []string
    64  	var rows [][]string
    65  	for idx, line := range StringSplitLines(md) {
    66  		split := StringSplitAndTrim(line, "|")
    67  		if idx == 0 {
    68  			header = split
    69  		} else if idx == 1 {
    70  			// spacer, noop
    71  		} else {
    72  			rows = append(rows, split)
    73  		}
    74  	}
    75  	return header, rows
    76  }