From c5dd45cfeacca52fd3110cc92aa92a17a3c8f7f7 Mon Sep 17 00:00:00 2001 From: Mark Hindess Date: Fri, 3 May 2024 09:57:58 +0100 Subject: [PATCH] table: html row automerge support --- table/render_html.go | 29 +++++++++++-- table/render_html_test.go | 85 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 3 deletions(-) diff --git a/table/render_html.go b/table/render_html.go index fcea86b..decf4fa 100644 --- a/table/render_html.go +++ b/table/render_html.go @@ -4,6 +4,8 @@ import ( "fmt" "html" "strings" + + "github.com/jedib0t/go-pretty/v6/text" ) const ( @@ -113,9 +115,9 @@ func (t *Table) htmlRenderColumn(out *strings.Builder, colStr string) { out.WriteString(colStr) } -func (t *Table) htmlRenderColumnAttributes(out *strings.Builder, colIdx int, hint renderHint) { +func (t *Table) htmlRenderColumnAttributes(out *strings.Builder, colIdx int, hint renderHint, alignOverride text.Align) { // determine the HTML "align"/"valign" property values - align := t.getAlign(colIdx, hint).HTMLProperty() + align := alignOverride.HTMLProperty() vAlign := t.getVAlign(colIdx, hint).HTMLProperty() // determine the HTML "class" property values for the colors class := t.getColumnColors(colIdx, hint).HTMLProperty() @@ -158,11 +160,31 @@ func (t *Table) htmlRenderRow(out *strings.Builder, row rowStr, hint renderHint) t.htmlRenderColumnAutoIndex(out, hint) } + align := t.getAlign(colIdx, hint) + rowConfig := t.getRowConfig(hint) + extraColumnsRendered := 0 + if rowConfig.AutoMerge && !hint.isSeparatorRow { + // get the real row to consider all lines in each column instead of just + // looking at the current "line" + rowUnwrapped := t.getRow(hint.rowNumber-1, hint) + for idx := colIdx + 1; idx < len(rowUnwrapped); idx++ { + if rowUnwrapped[colIdx] != rowUnwrapped[idx] { + break + } + align = rowConfig.getAutoMergeAlign() + extraColumnsRendered++ + } + } + colStr, colTagName := t.htmlGetColStrAndTag(row, colIdx, hint) // write the row out.WriteString(" <") out.WriteString(colTagName) - t.htmlRenderColumnAttributes(out, colIdx, hint) + t.htmlRenderColumnAttributes(out, colIdx, hint, align) + if extraColumnsRendered > 0 { + out.WriteString(" colspan=") + out.WriteString(fmt.Sprint(extraColumnsRendered + 1)) + } out.WriteString(">") if len(colStr) == 0 { out.WriteString(t.style.HTML.EmptyColumn) @@ -172,6 +194,7 @@ func (t *Table) htmlRenderRow(out *strings.Builder, row rowStr, hint renderHint) out.WriteString("\n") + colIdx += extraColumnsRendered } out.WriteString(" \n") } diff --git a/table/render_html_test.go b/table/render_html_test.go index ec507ee..ad2eae3 100644 --- a/table/render_html_test.go +++ b/table/render_html_test.go @@ -517,3 +517,88 @@ func TestTable_RenderHTML_Sorted(t *testing.T) { `) } + +func TestTable_RenderHTML_RowAutoMerge(t *testing.T) { + t.Run("simple", func(t *testing.T) { + rcAutoMerge := RowConfig{AutoMerge: true} + tw := NewWriter() + tw.AppendHeader(Row{"A", "B"}) + tw.AppendRow(Row{"Y", "Y"}, rcAutoMerge) + tw.AppendRow(Row{"Y", "N"}, rcAutoMerge) + compareOutput(t, tw.RenderHTML(), ` + + + + + + + + + + + + + + + + +
AB
Y
YN
`) + }) + t.Run("merged and unmerged entries", func(t *testing.T) { + rcAutoMerge := RowConfig{AutoMerge: true} + tw := NewWriter() + tw.AppendHeader(Row{"A", "B", "C", "D"}) + tw.AppendRow(Row{"Y", "Y", "0", "1"}, rcAutoMerge) + tw.AppendRow(Row{"0", "Y", "Y", "1"}, rcAutoMerge) + tw.AppendRow(Row{"0", "1", "Y", "Y"}, rcAutoMerge) + tw.AppendRow(Row{"Y", "Y", "Y", "0"}, rcAutoMerge) + tw.AppendRow(Row{"0", "Y", "Y", "Y"}, rcAutoMerge) + tw.AppendRow(Row{"Y", "Y", "Y", "Y"}, rcAutoMerge) + tw.AppendRow(Row{"0", "1", "2", "3"}, rcAutoMerge) + compareOutput(t, tw.RenderHTML(), ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ABCD
Y01
0Y1
01Y
Y0
0Y
Y
0123
`) + }) +}