diff --git a/pkg/parser/attributes_test.go b/pkg/parser/attributes_test.go index a484d0d5..03903938 100644 --- a/pkg/parser/attributes_test.go +++ b/pkg/parser/attributes_test.go @@ -522,12 +522,39 @@ var _ = DescribeTable("valid block attributes", }, ), + // options (explicit) + Entry(`[options=header]`, `[options=header]`, + types.Attributes{ + types.AttrOptions: []interface{}{"header"}, + }, + ), + Entry(`[options="header,footer"]`, `[options="header,footer"]`, + types.Attributes{ + types.AttrOptions: []interface{}{"header", "footer"}, + }, + ), + // option shorthand Entry(`[%hardbreaks]`, `[%hardbreaks]`, types.Attributes{ types.AttrOptions: []interface{}{"hardbreaks"}, }, ), + Entry(`[%header]`, `[%header]`, + types.Attributes{ + types.AttrOptions: []interface{}{"header"}, + }, + ), + Entry(`[%footer]`, `[%footer]`, + types.Attributes{ + types.AttrOptions: []interface{}{"footer"}, + }, + ), + Entry(`[%header%footer]`, `[%header%footer]`, + types.Attributes{ + types.AttrOptions: []interface{}{"header", "footer"}, + }, + ), // id (alone) Entry(`[#an_id]`, `[#an_id]`, diff --git a/pkg/parser/document_processing_apply_substitutions.go b/pkg/parser/document_processing_apply_substitutions.go index fc828918..8cce110a 100644 --- a/pkg/parser/document_processing_apply_substitutions.go +++ b/pkg/parser/document_processing_apply_substitutions.go @@ -170,6 +170,11 @@ func applySubstitutionsOnBlockWithElements(ctx *ParseContext, block types.BlockW return err } } + if b.Footer != nil { + if err = s.processBlockWithElements(ctx, b.Footer, opts...); err != nil { + return err + } + } } if err := s.processBlockWithElements(ctx, block, opts...); err != nil { return err diff --git a/pkg/parser/table_test.go b/pkg/parser/table_test.go index a122d700..4f621fc4 100644 --- a/pkg/parser/table_test.go +++ b/pkg/parser/table_test.go @@ -25,10 +25,6 @@ var _ = Describe("tables", func() { expected := &types.Document{ Elements: []interface{}{ &types.Table{ - // Columns: []*types.TableColumn{ - // {Width: "50", VAlign: "top", HAlign: "left"}, - // {Width: "50", VAlign: "top", HAlign: "left"}, - // }, Rows: []*types.TableRow{ { Cells: []*types.TableCell{ @@ -78,11 +74,6 @@ var _ = Describe("tables", func() { expected := &types.Document{ Elements: []interface{}{ &types.Table{ - // Columns: []*types.TableColumn{ - // {Width: "33.3333", VAlign: "top", HAlign: "left"}, - // {Width: "33.3333", VAlign: "top", HAlign: "left"}, - // {Width: "33.3334", VAlign: "top", HAlign: "left"}, - // }, Rows: []*types.TableRow{ { Cells: []*types.TableCell{ @@ -140,11 +131,6 @@ var _ = Describe("tables", func() { expected := &types.Document{ Elements: []interface{}{ &types.Table{ - // Columns: []*types.TableColumn{ - // {Width: "33.3333", VAlign: "top", HAlign: "left"}, - // {Width: "33.3333", VAlign: "top", HAlign: "left"}, - // {Width: "33.3334", VAlign: "top", HAlign: "left"}, - // }, Rows: []*types.TableRow{ { Cells: []*types.TableCell{ @@ -220,11 +206,6 @@ var _ = Describe("tables", func() { Attributes: types.Attributes{ types.AttrTitle: "table title", }, - // Columns: []*types.TableColumn{ - // {Width: "50", HAlign: "left", VAlign: "top"}, - // {Width: "50", HAlign: "left", VAlign: "top"}, - // }, - Header: &types.TableRow{ Cells: []*types.TableCell{ { @@ -327,11 +308,6 @@ var _ = Describe("tables", func() { }, }, }, - // Columns: []*types.TableColumn{ - // // autowidth clears width - // {HAlign: "left", VAlign: "top"}, - // {HAlign: "left", VAlign: "top"}, - // }, Rows: []*types.TableRow{ { Cells: []*types.TableCell{ @@ -381,10 +357,7 @@ var _ = Describe("tables", func() { |===` expected := &types.Document{ Elements: []interface{}{ - &types.Table{ - // Columns: []*types.TableColumn{}, - // Lines: []*types.TableLine{}, - }, + &types.Table{}, }, } Expect(ParseDocument(source)).To(MatchDocument(expected)) @@ -432,9 +405,6 @@ var _ = Describe("tables", func() { |=== |===` expected := &types.Document{ - // Attributes: types.Attributes{ - // "cols": "2*^.^d,s", - // }, Elements: []interface{}{ &types.AttributeDeclaration{ Name: "cols", @@ -471,6 +441,260 @@ var _ = Describe("tables", func() { } Expect(ParseDocument(source)).To(MatchDocument(expected)) }) + + It("with header option", func() { + source := `[cols="3*^",options="header"] +|=== +|Dir (X,Y,Z) |Num Cells |Size +|X |10 |0.1 +|Y |5 |0.2 +|Z |10 |0.1 +|===` + expected := &types.Document{ + Elements: []interface{}{ + &types.Table{ + Attributes: types.Attributes{ + types.AttrCols: []interface{}{ + &types.TableColumn{ + Multiplier: 3, + HAlign: types.HAlignCenter, + VAlign: types.VAlignTop, + Weight: 1, + }, + }, + types.AttrOptions: []interface{}{"header"}, + }, + Header: &types.TableRow{ + Cells: []*types.TableCell{ + { + Elements: []interface{}{ + &types.StringElement{ + Content: "Dir (X,Y,Z) ", + }, + }, + }, + { + Elements: []interface{}{ + &types.StringElement{ + Content: "Num Cells ", + }, + }, + }, + { + Elements: []interface{}{ + &types.StringElement{ + Content: "Size", + }, + }, + }, + }, + }, + Rows: []*types.TableRow{ + { + Cells: []*types.TableCell{ + { + Elements: []interface{}{ + &types.StringElement{ + Content: "X ", + }, + }, + }, + { + Elements: []interface{}{ + &types.StringElement{ + Content: "10 ", + }, + }, + }, + { + Elements: []interface{}{ + &types.StringElement{ + Content: "0.1", + }, + }, + }, + }, + }, + { + Cells: []*types.TableCell{ + { + Elements: []interface{}{ + &types.StringElement{ + Content: "Y ", + }, + }, + }, + { + Elements: []interface{}{ + &types.StringElement{ + Content: "5 ", + }, + }, + }, + { + Elements: []interface{}{ + &types.StringElement{ + Content: "0.2", + }, + }, + }, + }, + }, + { + Cells: []*types.TableCell{ + { + Elements: []interface{}{ + &types.StringElement{ + Content: "Z ", + }, + }, + }, + { + Elements: []interface{}{ + &types.StringElement{ + Content: "10 ", + }, + }, + }, + { + Elements: []interface{}{ + &types.StringElement{ + Content: "0.1", + }, + }, + }, + }, + }, + }, + }, + }, + } + Expect(ParseDocument(source)).To(MatchDocument(expected)) + }) + + It("with header and footer options", func() { + source := `[%header%footer,cols="2,2,1"] +|=== +|Column 1, header row +|Column 2, header row +|Column 3, header row + +|Cell in column 1, row 2 +|Cell in column 2, row 2 +|Cell in column 3, row 2 + +|Column 1, footer row +|Column 2, footer row +|Column 3, footer row +|===` + expected := &types.Document{ + Elements: []interface{}{ + &types.Table{ + Attributes: types.Attributes{ + types.AttrCols: []interface{}{ + &types.TableColumn{ + Multiplier: 1, + HAlign: types.HAlignLeft, + VAlign: types.VAlignTop, + Weight: 2, + }, + &types.TableColumn{ + Multiplier: 1, + HAlign: types.HAlignLeft, + VAlign: types.VAlignTop, + Weight: 2, + }, + &types.TableColumn{ + Multiplier: 1, + HAlign: types.HAlignLeft, + VAlign: types.VAlignTop, + Weight: 1, + }, + }, + types.AttrOptions: []interface{}{"header", "footer"}, + }, + Header: &types.TableRow{ + Cells: []*types.TableCell{ + { + Elements: []interface{}{ + &types.StringElement{ + Content: "Column 1, header row", + }, + }, + }, + { + Elements: []interface{}{ + &types.StringElement{ + Content: "Column 2, header row", + }, + }, + }, + { + Elements: []interface{}{ + &types.StringElement{ + Content: "Column 3, header row", + }, + }, + }, + }, + }, + Rows: []*types.TableRow{ + { + Cells: []*types.TableCell{ + { + Elements: []interface{}{ + &types.StringElement{ + Content: "Cell in column 1, row 2", + }, + }, + }, + { + Elements: []interface{}{ + &types.StringElement{ + Content: "Cell in column 2, row 2", + }, + }, + }, + { + Elements: []interface{}{ + &types.StringElement{ + Content: "Cell in column 3, row 2", + }, + }, + }, + }, + }, + }, + Footer: &types.TableRow{ + Cells: []*types.TableCell{ + { + Elements: []interface{}{ + &types.StringElement{ + Content: "Column 1, footer row", + }, + }, + }, + { + Elements: []interface{}{ + &types.StringElement{ + Content: "Column 2, footer row", + }, + }, + }, + { + Elements: []interface{}{ + &types.StringElement{ + Content: "Column 3, footer row", + }, + }, + }, + }, + }, + }, + }, + } + Expect(ParseDocument(source)).To(MatchDocument(expected)) + }) }) }) @@ -511,6 +735,30 @@ var _ = Describe("table cols", func() { Width: "100", }, }), + Entry(`3*^`, `3*^`, + []*types.TableColumn{ + { + Multiplier: 3, + HAlign: types.HAlignCenter, + VAlign: types.VAlignTop, + Weight: 1, + Width: "33.3333", + }, + { + Multiplier: 3, + HAlign: types.HAlignCenter, + VAlign: types.VAlignTop, + Weight: 1, + Width: "33.3333", + }, + { + Multiplier: 3, + HAlign: types.HAlignCenter, + VAlign: types.VAlignTop, + Weight: 1, + Width: "33.3334", + }, + }), Entry(`20,~,~`, `20,~,~`, []*types.TableColumn{ { diff --git a/pkg/renderer/sgml/html5/table.go b/pkg/renderer/sgml/html5/table.go index 66edee63..e48a1432 100644 --- a/pkg/renderer/sgml/html5/table.go +++ b/pkg/renderer/sgml/html5/table.go @@ -18,6 +18,7 @@ const ( "\n" + "{{ .Header }}" + "{{ .Body }}" + + "{{ .Footer }}" + "{{ end }}" + "\n" @@ -25,9 +26,13 @@ const ( tableHeaderTmpl = "{{ if .Content }}\n\n{{ .Content }}\n\n{{ end }}" - tableRowTmpl = "\n{{ .Content }}\n" - tableHeaderCellTmpl = "{{ .Content }}\n" + tableFooterTmpl = "{{ if .Content }}\n\n{{ .Content }}\n\n{{ end }}" + + tableFooterCellTmpl = "

{{ .Content }}

\n" + + tableRowTmpl = "\n{{ .Content }}\n" + tableCellTmpl = "

{{ .Content }}

\n" ) diff --git a/pkg/renderer/sgml/html5/table_test.go b/pkg/renderer/sgml/html5/table_test.go index d22ced52..7231504e 100644 --- a/pkg/renderer/sgml/html5/table_test.go +++ b/pkg/renderer/sgml/html5/table_test.go @@ -532,5 +532,94 @@ var _ = Describe("tables", func() { Expect(RenderHTML(source)).To(MatchHTML(expected)) }) + It("with header option", func() { + source := `[cols="3*^",options="header"] +|=== +|Dir (X,Y,Z) |Num Cells |Size +|X |10 |0.1 +|Y |5 |0.2 +|Z |10 |0.1 +|===` + expected := ` +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
Dir (X,Y,Z)Num CellsSize

X

10

0.1

Y

5

0.2

Z

10

0.1

+` + Expect(RenderHTML(source)).To(MatchHTML(expected)) + }) + + It("with header and footer options", func() { + source := `[%header%footer,cols="2,2,1"] +|=== +|Column 1, header row +|Column 2, header row +|Column 3, header row + +|Cell in column 1, row 2 +|Cell in column 2, row 2 +|Cell in column 3, row 2 + +|Column 1, footer row +|Column 2, footer row +|Column 3, footer row +|===` + expected := ` +++++ + + + + + + + + + + + + + + + + + + + + + +
Column 1, header rowColumn 2, header rowColumn 3, header row

Cell in column 1, row 2

Cell in column 2, row 2

Cell in column 3, row 2

Column 1, footer row

Column 2, footer row

Column 3, footer row

+` + Expect(RenderHTML(source)).To(MatchHTML(expected)) + }) // TODO: Verify styles -- it's verified in the parser for now, but we still need to implement styles. }) diff --git a/pkg/renderer/sgml/html5/templates.go b/pkg/renderer/sgml/html5/templates.go index 2105379c..7300f115 100644 --- a/pkg/renderer/sgml/html5/templates.go +++ b/pkg/renderer/sgml/html5/templates.go @@ -74,6 +74,8 @@ var templates = sgml.Templates{ TableCell: tableCellTmpl, TableHeader: tableHeaderTmpl, TableHeaderCell: tableHeaderCellTmpl, + TableFooter: tableFooterTmpl, + TableFooterCell: tableFooterCellTmpl, TableRow: tableRowTmpl, ThematicBreak: thematicBreakTmpl, TocRoot: tocRootTmpl, diff --git a/pkg/renderer/sgml/sgml_renderer.go b/pkg/renderer/sgml/sgml_renderer.go index 85871592..493f2d9a 100644 --- a/pkg/renderer/sgml/sgml_renderer.go +++ b/pkg/renderer/sgml/sgml_renderer.go @@ -74,6 +74,8 @@ type sgmlRenderer struct { tableCell *textTemplate tableHeader *textTemplate tableHeaderCell *textTemplate + tableFooter *textTemplate + tableFooterCell *textTemplate tableRow *textTemplate thematicBreak *textTemplate tocEntry *textTemplate @@ -154,6 +156,8 @@ func (r *sgmlRenderer) prepareTemplates() error { r.tableCell, err = r.newTemplate("table-cell", tmpls.TableCell, err) r.tableHeader, err = r.newTemplate("table-header", tmpls.TableHeader, err) r.tableHeaderCell, err = r.newTemplate("table-header-cell", tmpls.TableHeaderCell, err) + r.tableFooter, err = r.newTemplate("table-header", tmpls.TableFooter, err) + r.tableFooterCell, err = r.newTemplate("table-header-cell", tmpls.TableFooterCell, err) r.tableRow, err = r.newTemplate("table-row", tmpls.TableRow, err) r.thematicBreak, err = r.newTemplate("thematic-break", tmpls.ThematicBreak, err) r.tocEntry, err = r.newTemplate("toc-entry", tmpls.TocEntry, err) diff --git a/pkg/renderer/sgml/table.go b/pkg/renderer/sgml/table.go index 41d84c73..51e928b5 100644 --- a/pkg/renderer/sgml/table.go +++ b/pkg/renderer/sgml/table.go @@ -3,6 +3,7 @@ package sgml import ( "strconv" "strings" + "text/template" "github.com/bytesparadise/libasciidoc/pkg/renderer" "github.com/bytesparadise/libasciidoc/pkg/types" @@ -75,6 +76,10 @@ func (r *sgmlRenderer) renderTable(ctx *renderer.Context, t *types.Table) (strin if err != nil { return "", errors.Wrap(err, "failed to render table") } + footer, err := r.renderTableFooter(ctx, t.Footer, columns) + if err != nil { + return "", errors.Wrap(err, "failed to render table") + } body, err := r.renderTableBody(ctx, t.Rows, columns) if err != nil { return "", errors.Wrap(err, "failed to render table") @@ -102,6 +107,7 @@ func (r *sgmlRenderer) renderTable(ctx *renderer.Context, t *types.Table) (strin Roles string Header string Body string + Footer string }{ Context: ctx, Title: title, @@ -117,6 +123,7 @@ func (r *sgmlRenderer) renderTable(ctx *renderer.Context, t *types.Table) (strin Width: width, Header: header, Body: body, + Footer: footer, }) if err != nil { return "", errors.Wrap(err, "failed to render table") @@ -132,7 +139,7 @@ func (r *sgmlRenderer) renderTableHeader(ctx *renderer.Context, h *types.TableRo content := &strings.Builder{} col := 0 for _, cell := range h.Cells { - c, err := r.renderTableHeaderCell(ctx, cell, cols[col%len(cols)]) + c, err := r.renderTableCell(ctx, r.tableHeaderCell, cell, cols[col%len(cols)]) col++ if err != nil { return "", errors.Wrap(err, "unable to render header") @@ -151,24 +158,29 @@ func (r *sgmlRenderer) renderTableHeader(ctx *renderer.Context, h *types.TableRo return result.String(), err } -func (r *sgmlRenderer) renderTableHeaderCell(ctx *renderer.Context, cell *types.TableCell, col *types.TableColumn) (string, error) { +func (r *sgmlRenderer) renderTableFooter(ctx *renderer.Context, f *types.TableRow, cols []*types.TableColumn) (string, error) { + if f == nil { + return "", nil + } result := &strings.Builder{} - content, err := r.renderInlineElements(ctx, cell.Elements) - if err != nil { - return "", errors.Wrap(err, "unable to render header cell") + content := &strings.Builder{} + col := 0 + for _, cell := range f.Cells { + c, err := r.renderTableCell(ctx, r.tableFooterCell, cell, cols[col%len(cols)]) + col++ + if err != nil { + return "", errors.Wrap(err, "unable to render header") + } + content.WriteString(c) } - err = r.tableHeaderCell.Execute(result, struct { + err := r.tableFooter.Execute(result, struct { Context *renderer.Context Content string - Cell []interface{} - HAlign types.HAlign - VAlign types.VAlign + Cells []*types.TableCell }{ Context: ctx, - Content: content, - Cell: cell.Elements, - HAlign: col.HAlign, - VAlign: col.VAlign, + Content: content.String(), + Cells: f.Cells, }) return result.String(), err } @@ -206,7 +218,7 @@ func (r *sgmlRenderer) renderTableRow(ctx *renderer.Context, l *types.TableRow, result := &strings.Builder{} content := &strings.Builder{} for i, cell := range l.Cells { - c, err := r.renderTableCell(ctx, cell, cols[i]) + c, err := r.renderTableCell(ctx, r.tableCell, cell, cols[i]) if err != nil { return "", errors.Wrap(err, "unable to render row") } @@ -224,7 +236,7 @@ func (r *sgmlRenderer) renderTableRow(ctx *renderer.Context, l *types.TableRow, return result.String(), err } -func (r *sgmlRenderer) renderTableCell(ctx *renderer.Context, cell *types.TableCell, col *types.TableColumn) (string, error) { +func (r *sgmlRenderer) renderTableCell(ctx *renderer.Context, tmpl *template.Template, cell *types.TableCell, col *types.TableColumn) (string, error) { result := &strings.Builder{} content, err := r.renderInlineElements(ctx, cell.Elements) if err != nil { @@ -233,7 +245,7 @@ func (r *sgmlRenderer) renderTableCell(ctx *renderer.Context, cell *types.TableC if log.IsLevelEnabled(log.DebugLevel) { log.Debugf("rendering cell with content '%s' and def %s", content, spew.Sdump(col)) } - err = r.tableCell.Execute(result, struct { + err = tmpl.Execute(result, struct { Context *renderer.Context Content string Cell *types.TableCell diff --git a/pkg/renderer/sgml/templates.go b/pkg/renderer/sgml/templates.go index 3cd2ec96..ce724b65 100644 --- a/pkg/renderer/sgml/templates.go +++ b/pkg/renderer/sgml/templates.go @@ -67,6 +67,8 @@ type Templates struct { TableCell string TableHeader string TableHeaderCell string + TableFooter string + TableFooterCell string TableRow string ThematicBreak string TocEntry string diff --git a/pkg/renderer/sgml/xhtml5/table_test.go b/pkg/renderer/sgml/xhtml5/table_test.go index 5024ab01..a3f18f21 100644 --- a/pkg/renderer/sgml/xhtml5/table_test.go +++ b/pkg/renderer/sgml/xhtml5/table_test.go @@ -532,5 +532,94 @@ var _ = Describe("tables", func() { Expect(RenderXHTML(source)).To(MatchHTML(expected)) }) + It("with header option", func() { + source := `[cols="3*^",options="header"] +|=== +|Dir (X,Y,Z) |Num Cells |Size +|X |10 |0.1 +|Y |5 |0.2 +|Z |10 |0.1 +|===` + expected := ` +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
Dir (X,Y,Z)Num CellsSize

X

10

0.1

Y

5

0.2

Z

10

0.1

+` + Expect(RenderHTML(source)).To(MatchHTML(expected)) + }) + + It("with header and footer options", func() { + source := `[%header%footer,cols="2,2,1"] +|=== +|Column 1, header row +|Column 2, header row +|Column 3, header row + +|Cell in column 1, row 2 +|Cell in column 2, row 2 +|Cell in column 3, row 2 + +|Column 1, footer row +|Column 2, footer row +|Column 3, footer row +|===` + expected := ` +++++ + + + + + + + + + + + + + + + + + + + + + +
Column 1, header rowColumn 2, header rowColumn 3, header row

Cell in column 1, row 2

Cell in column 2, row 2

Cell in column 3, row 2

Column 1, footer row

Column 2, footer row

Column 3, footer row

+` + Expect(RenderHTML(source)).To(MatchHTML(expected)) + }) // TODO: Verify styles -- it's verified in the parser for now, but we still need to implement styles. }) diff --git a/pkg/types/attributes.go b/pkg/types/attributes.go index 76a92b9c..01b4ee7e 100644 --- a/pkg/types/attributes.go +++ b/pkg/types/attributes.go @@ -117,8 +117,8 @@ const ( AttrFloat = "float" // AttrCols the table columns attribute AttrCols = "cols" - // AttrAutowidth the `autowidth` attribute on a table - AttrAutowidth = "autowidth" + // AttrAutoWidth the `autowidth` attribute on a table + AttrAutoWidth = "autowidth" // AttrPositionalPrefix positional parameter prefix (DEPRECATED - use `AttrPositionalIndex`) AttrPositionalPrefix = "@" // AttrPositionalIndex positional parameter index @@ -403,12 +403,26 @@ func (a Attributes) Set(key string, value interface{}) Attributes { a[AttrRoles] = r } } - case AttrOption: + case AttrOption: // move into `options` if options, ok := a[AttrOptions].([]interface{}); ok { a[AttrOptions] = append(options, value) } else { a[AttrOptions] = []interface{}{value} } + case AttrOptions: // make sure the value is wrapped into a []interface{} + switch v := value.(type) { + case []interface{}: + a[AttrOptions] = v + case string: + values := strings.Split(v, ",") + options := make([]interface{}, len(values)) + for i, v := range values { + options[i] = v + } + a[AttrOptions] = options + default: + a[AttrOptions] = []interface{}{value} + } default: a[key] = value } diff --git a/pkg/types/types.go b/pkg/types/types.go index 6a1fe472..9bd8685b 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -2947,8 +2947,8 @@ func (p *ElementPlaceHolder) String() string { type Table struct { Attributes Attributes Header *TableRow - // Columns []*TableColumn - Rows []*TableRow + Footer *TableRow + Rows []*TableRow } func NewTable(header interface{}, elements []interface{}) (*Table, error) { @@ -3009,6 +3009,16 @@ func (t *Table) AddAttributes(attributes Attributes) { func (t *Table) SetAttributes(attributes Attributes) { t.Attributes = attributes + // if `header` option, then make sure that the first row is the header + if t.Header == nil && len(t.Rows) > 0 && t.Attributes.HasOption("header") { + t.Header = t.Rows[0] + t.Rows = t.Rows[1:] + } + // if `footer` option, then make sure that the last row is the header + if t.Footer == nil && len(t.Rows) > 0 && t.Attributes.HasOption("footer") { + t.Footer = t.Rows[len(t.Rows)-1] + t.Rows = t.Rows[:len(t.Rows)-1] + } } type HAlign string @@ -3093,7 +3103,9 @@ func (t *Table) Columns() ([]*TableColumn, error) { switch col := col.(type) { case *TableColumn: for i := 0; i < col.Multiplier; i++ { - result = append(result, col) + // affect in new variable so we have a *copy*! + c := *col + result = append(result, &c) } default: return nil, fmt.Errorf("invalid type of column definition: '%T'", col) @@ -3111,7 +3123,7 @@ func (t *Table) Columns() ([]*TableColumn, error) { } } // unless table is set with "full autowidth" - if !t.Attributes.HasOption(AttrAutowidth) { + if !t.Attributes.HasOption(AttrAutoWidth) { sumWeight := 0 colsWithAutowidth := false for _, col := range result { @@ -3134,14 +3146,19 @@ func (t *Table) Columns() ([]*TableColumn, error) { width := float64(col.Weight*100) / float64(sumWeight) col.Width = strconv.FormatFloat(width, 'g', 6, 64) sumWidth += int(width * 1e4) + log.Debugf("col %d width: %s", i, col.Width) } else { // rounding on the last column, to make sure that the sum reaches 100 width := (float64(1e6-sumWidth) / 1e4) col.Width = strconv.FormatFloat(width, 'g', 6, 64) + log.Debugf("col %d width (last): %s", i, col.Width) } } } } + if log.IsLevelEnabled(log.DebugLevel) { + log.Debugf("cols: %s", spew.Sdump(result)) + } return result, nil }