Skip to content
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
46 changes: 39 additions & 7 deletions table/render_markdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,22 +51,49 @@
if colIdx < len(row) {
colStr = row[colIdx]
}
out.WriteRune(' ')
colStr = strings.ReplaceAll(colStr, "|", "\\|")
colStr = strings.ReplaceAll(colStr, "\n", "<br/>")
out.WriteString(colStr)
out.WriteRune(' ')
if t.style.Markdown.PadContent {
out.WriteRune(' ')
align := t.getAlign(colIdx, hint)
out.WriteString(align.Apply(colStr, t.maxColumnLengths[colIdx]))
out.WriteRune(' ')
} else {
out.WriteRune(' ')
out.WriteString(colStr)
out.WriteRune(' ')
}
out.WriteRune('|')
}
}

func (t *Table) markdownRenderRowAutoIndex(out *strings.Builder, colIdx int, hint renderHint) {

Check failure on line 70 in table/render_markdown.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this method to reduce its Cognitive Complexity from 18 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=jedib0t_go-pretty&issues=AZygEA01BdVmCw2Yefkp&open=AZygEA01BdVmCw2Yefkp&pullRequest=403
if colIdx == 0 && t.autoIndex {
out.WriteRune(' ')
if hint.isSeparatorRow {
out.WriteString("---:")
if t.style.Markdown.PadContent {
out.WriteString(" " + strings.Repeat("-", t.autoIndexVIndexMaxLength) + ":")
} else {
out.WriteRune(' ')
out.WriteString("---:")
}
} else if hint.isRegularRow() {
fmt.Fprintf(out, "%d ", hint.rowNumber)
if t.style.Markdown.PadContent {
rowNumStr := fmt.Sprint(hint.rowNumber)
out.WriteRune(' ')
fmt.Fprintf(out, "%*s", t.autoIndexVIndexMaxLength, rowNumStr)
out.WriteRune(' ')
} else {
out.WriteRune(' ')
fmt.Fprintf(out, "%d ", hint.rowNumber)
}
} else {
if t.style.Markdown.PadContent {
out.WriteRune(' ')
out.WriteString(strings.Repeat(" ", t.autoIndexVIndexMaxLength))
out.WriteRune(' ')
} else {
out.WriteRune(' ')
}
}
out.WriteRune('|')
}
Expand Down Expand Up @@ -107,7 +134,12 @@
for colIdx := 0; colIdx < t.numColumns; colIdx++ {
t.markdownRenderRowAutoIndex(out, colIdx, hint)

out.WriteString(t.getAlign(colIdx, hint).MarkdownProperty())
align := t.getAlign(colIdx, hint)
if t.style.Markdown.PadContent {
out.WriteString(align.MarkdownProperty(t.maxColumnLengths[colIdx]))
} else {
out.WriteString(align.MarkdownProperty())
}
out.WriteRune('|')
}
}
Expand Down
60 changes: 60 additions & 0 deletions table/render_markdown_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,66 @@ func TestTable_RenderMarkdown_AutoIndex(t *testing.T) {
| | AF | BF | CF | DF | EF | FF | GF | HF | IF | JF |`)
}

func TestTable_RenderMarkdown_Padded(t *testing.T) {
tw := NewWriter()
tw.AppendHeader(testHeader)
tw.AppendRows(testRows)
tw.AppendRow(testRowNewLines)
tw.AppendRow(testRowPipes)
tw.AppendFooter(testFooter)
tw.SetCaption(testCaption)
tw.SetTitle(testTitle1)
tw.Style().Markdown.PadContent = true

compareOutput(t, tw.RenderMarkdown(), `
# Game of Thrones
| # | First Name | Last Name | Salary | |
| ---:| ---------- | --------- | ------:| --------------------------- |
| 1 | Arya | Stark | 3000 | |
| 20 | Jon | Snow | 2000 | You know nothing, Jon Snow! |
| 300 | Tyrion | Lannister | 5000 | |
| 0 | Valar | Morghulis | 0 | Faceless<br/>Men |
| 0 | Valar | Morghulis | 0 | Faceless\|Men |
| | | Total | 10000 | |
_A Song of Ice and Fire_`)
}

func TestTable_RenderMarkdown_Padded_AutoIndex(t *testing.T) {
tw := NewWriter()
for rowIdx := 0; rowIdx < 10; rowIdx++ {
row := make(Row, 10)
for colIdx := 0; colIdx < 10; colIdx++ {
row[colIdx] = fmt.Sprintf("%s%d", AutoIndexColumnID(colIdx), rowIdx+1)
}
tw.AppendRow(row)
}
for rowIdx := 0; rowIdx < 1; rowIdx++ {
row := make(Row, 10)
for colIdx := 0; colIdx < 10; colIdx++ {
row[colIdx] = AutoIndexColumnID(colIdx) + "F"
}
tw.AppendFooter(row)
}
tw.SetAutoIndex(true)
tw.SetStyle(StyleLight)
tw.Style().Markdown.PadContent = true

compareOutput(t, tw.RenderMarkdown(), `
| | A | B | C | D | E | F | G | H | I | J |
| --:| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 1 | A1 | B1 | C1 | D1 | E1 | F1 | G1 | H1 | I1 | J1 |
| 2 | A2 | B2 | C2 | D2 | E2 | F2 | G2 | H2 | I2 | J2 |
| 3 | A3 | B3 | C3 | D3 | E3 | F3 | G3 | H3 | I3 | J3 |
| 4 | A4 | B4 | C4 | D4 | E4 | F4 | G4 | H4 | I4 | J4 |
| 5 | A5 | B5 | C5 | D5 | E5 | F5 | G5 | H5 | I5 | J5 |
| 6 | A6 | B6 | C6 | D6 | E6 | F6 | G6 | H6 | I6 | J6 |
| 7 | A7 | B7 | C7 | D7 | E7 | F7 | G7 | H7 | I7 | J7 |
| 8 | A8 | B8 | C8 | D8 | E8 | F8 | G8 | H8 | I8 | J8 |
| 9 | A9 | B9 | C9 | D9 | E9 | F9 | G9 | H9 | I9 | J9 |
| 10 | A10 | B10 | C10 | D10 | E10 | F10 | G10 | H10 | I10 | J10 |
| | AF | BF | CF | DF | EF | FF | GF | HF | IF | JF |`)
}

func TestTable_RenderMarkdown_Empty(t *testing.T) {
tw := NewWriter()
assert.Empty(t, tw.RenderMarkdown())
Expand Down
17 changes: 9 additions & 8 deletions table/style.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ package table
// Style declares how to render the Table and provides very fine-grained control
// on how the Table gets rendered on the Console.
type Style struct {
Name string // name of the Style
Box BoxStyle // characters to use for the boxes
Color ColorOptions // colors to use for the rows and columns
Format FormatOptions // formatting options for the rows and columns
HTML HTMLOptions // rendering options for HTML mode
Options Options // misc. options for the table
Size SizeOptions // size (width) options for the table
Title TitleOptions // formation options for the title text
Name string // name of the Style
Box BoxStyle // characters to use for the boxes
Color ColorOptions // colors to use for the rows and columns
Format FormatOptions // formatting options for the rows and columns
HTML HTMLOptions // rendering options for HTML mode
Markdown MarkdownOptions // rendering options for Markdown mode
Options Options // misc. options for the table
Size SizeOptions // size (width) options for the table
Title TitleOptions // formation options for the title text
}

var (
Expand Down
25 changes: 25 additions & 0 deletions table/style_markdown.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package table

// MarkdownOptions defines options to control Markdown rendering.
type MarkdownOptions struct {
// PadContent pads each column content to match the longest content in
// the column, and extends the separator dashes to match. This makes the
// raw Markdown source more readable without affecting the rendered
// output.
//
// When disabled (default):
// | # | First Name | Last Name | Salary | |
// | ---:| --- | --- | ---:| --- |
// | 1 | Arya | Stark | 3000 | |
//
// When enabled:
// | # | First Name | Last Name | Salary | |
// | ---:| ---------- | --------- | ------:| --------------------------- |
// | 1 | Arya | Stark | 3000 | |
PadContent bool
}

var (
// DefaultMarkdownOptions defines sensible Markdown rendering defaults.
DefaultMarkdownOptions = MarkdownOptions{}
)
18 changes: 13 additions & 5 deletions text/align.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,24 @@ func (a Align) HTMLProperty() string {
}

// MarkdownProperty returns the equivalent Markdown horizontal-align separator.
func (a Align) MarkdownProperty() string {
// An optional minLength can be provided to extend the dashes to match the
// column content width; the result will be max(minLength, 3)+2 wide (including
// leading/trailing space or colon). Without minLength (or 0), it defaults to 3.
func (a Align) MarkdownProperty(minLength ...int) string {
length := 3
if len(minLength) > 0 && minLength[0] > length {
length = minLength[0]
}
dashes := strings.Repeat("-", length)
switch a {
case AlignLeft:
return ":--- "
return ":" + dashes + " "
case AlignCenter:
return ":---:"
return ":" + dashes + ":"
case AlignRight:
return " ---:"
return " " + dashes + ":"
default:
return " --- "
return " " + dashes + " "
}
}

Expand Down
13 changes: 13 additions & 0 deletions text/align_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,16 @@ func TestAlign_MarkdownProperty(t *testing.T) {
assert.Contains(t, align.MarkdownProperty(), markdownSeparator)
}
}

func TestAlign_MarkdownProperty_WithMinLength(t *testing.T) {
assert.Equal(t, " ---------- ", AlignDefault.MarkdownProperty(10))
assert.Equal(t, ":---------- ", AlignLeft.MarkdownProperty(10))
assert.Equal(t, ":----------:", AlignCenter.MarkdownProperty(10))
assert.Equal(t, " ---------- ", AlignJustify.MarkdownProperty(10))
assert.Equal(t, " ----------:", AlignRight.MarkdownProperty(10))

// minimum width of 3
assert.Equal(t, " --- ", AlignDefault.MarkdownProperty(1))
assert.Equal(t, " --- ", AlignDefault.MarkdownProperty(3))
assert.Equal(t, " ---- ", AlignDefault.MarkdownProperty(4))
}
Loading