Skip to content
Open
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
54 changes: 54 additions & 0 deletions html2text.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package html2text

import (
"bytes"
"fmt"
"io"
"math"
"regexp"
"strings"
"unicode"
Expand All @@ -26,13 +28,15 @@ type PrettyTablesOptions struct {
AutoWrapText bool
ReflowDuringAutoWrap bool
ColWidth int
MinColWidth int
ColumnSeparator string
RowSeparator string
CenterSeparator string
HeaderAlignment int
FooterAlignment int
Alignment int
ColumnAlignment []int
NoWhiteSapce bool
NewLine string
HeaderLine bool
RowLine bool
Expand All @@ -54,6 +58,7 @@ func NewPrettyTablesOptions() *PrettyTablesOptions {
FooterAlignment: tablewriter.ALIGN_DEFAULT,
Alignment: tablewriter.ALIGN_DEFAULT,
ColumnAlignment: []int{},
NoWhiteSapce: false,
NewLine: tablewriter.NEWLINE,
HeaderLine: true,
RowLine: false,
Expand Down Expand Up @@ -338,6 +343,7 @@ func (ctx *textifyTraverseContext) handleTableElement(node *html.Node) error {
table.SetRowLine(options.RowLine)
table.SetAutoMergeCells(options.AutoMergeCells)
table.SetBorders(options.Borders)
table.SetNoWhiteSpace(options.NoWhiteSapce)
}
table.SetHeader(ctx.tableCtx.header)
table.SetFooter(ctx.tableCtx.footer)
Expand Down Expand Up @@ -507,11 +513,43 @@ func (ctx *textifyTraverseContext) normalizeHrefLink(link string) string {
// textuual representaitons separated by a single newline.
func (ctx *textifyTraverseContext) renderEachChild(node *html.Node) (string, error) {
buf := &bytes.Buffer{}

l := ctx.options.PrettyTablesOptions.MinColWidth

for c := node.FirstChild; c != nil; c = c.NextSibling {
s, err := FromHTMLNode(c, ctx.options)
if err != nil {
return "", err
}

// See if a minimum width has been specified and pad as necessary.
if l > 0 && len(s) < l {
c := 0
// Check alignment and pad appropriately.
switch ctx.options.PrettyTablesOptions.Alignment {
case tablewriter.ALIGN_LEFT:
c = l - len(s)
spc := strings.Repeat(" ", c)
s = fmt.Sprintf("%s%s", s, spc)
case tablewriter.ALIGN_RIGHT:
c = l - len(s)
spc := strings.Repeat(" ", c)
s = fmt.Sprintf("%s%s", spc, s)
case tablewriter.ALIGN_CENTER:
ls := len(s)
c := 0.0 // We need to use a float to have the division work properly here, so declare a local scope variable named c rather than use the int version of c from the parent.
c = math.Floor(float64(l-ls) / 2.0)
spc := strings.Repeat(" ", int(c))
s = fmt.Sprintf("%s%s", spc, s)
c = math.Ceil(float64(l-ls) / 2.0)
spc = strings.Repeat(" ", int(c))
s = fmt.Sprintf("%s%s", s, spc)
case tablewriter.ALIGN_DEFAULT: // Default to left alignment.
c = l - len(s)
spc := strings.Repeat(" ", c)
s = fmt.Sprintf("%s%s", s, spc)
}
}
if _, err = buf.WriteString(s); err != nil {
return "", err
}
Expand All @@ -524,6 +562,22 @@ func (ctx *textifyTraverseContext) renderEachChild(node *html.Node) (string, err
return buf.String(), nil
}

// largestChildWidth - Returns the width (in characters) of the largest child of a node.
func (ctx *textifyTraverseContext) largestChildWidth(node *html.Node) (int, error) {
l := 0
for c := node.FirstChild; c != nil; c = c.NextSibling {
s, err := FromHTMLNode(c, ctx.options)
if err != nil {
return l, err
}

if len(s) > l {
l = len(s)
}
}
return l, nil
}

func getAttrVal(node *html.Node, attrName string) string {
for _, attr := range node.Attr {
if attr.Key == attrName {
Expand Down
76 changes: 76 additions & 0 deletions html2text_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"regexp"
"strings"
"testing"

"github.com/olekukonko/tablewriter"
)

const destPath = "testdata"
Expand Down Expand Up @@ -337,6 +339,79 @@ Table 2 Header 1 Table 2 Header 2 Table 2 Footer 1 Table 2 Footer 2 Table 2 Row
PrettyTables: true,
PrettyTablesOptions: NewPrettyTablesOptions(),
}

// Check pretty tabular ASCII version.
if msg, err := wantString(testCase.input, testCase.tabularOutput, options); err != nil {
t.Error(err)
} else if len(msg) > 0 {
t.Log(msg)
}

// Check plain version.
if msg, err := wantString(testCase.input, testCase.plaintextOutput); err != nil {
t.Error(err)
} else if len(msg) > 0 {
t.Log(msg)
}
}
}

func TestMinColWidthTable(t *testing.T) {
testCases := []struct {
input string
tabularOutput string
plaintextOutput string
alignment string
}{
{
"<table><tr><td>Hello</td><td>World!</td></tr></table>",
// Empty table
// +--+--+
// | | |
// +--+--+
"+------------+------------+\n| Hello | World! |\n+------------+------------+",
"Hello World!",
"Left",
},
{
"<table><tr><td>Hello</td><td>World!</td></tr></table>",
// Empty table
// +--+--+
// | | |
// +--+--+
"+------------+------------+\n| Hello | World! |\n+------------+------------+",
"Hello World!",
"Right",
},
{
"<table><tr><td>Hello</td><td>World!</td></tr></table>",
// Empty table
// +--+--+
// | | |
// +--+--+
"+------------+------------+\n| Hello | World! |\n+------------+------------+",
"Hello World!",
"Center",
},
}

for _, testCase := range testCases {
options := Options{
PrettyTables: true,
PrettyTablesOptions: NewPrettyTablesOptions(),
}
options.PrettyTablesOptions.MinColWidth = 10

switch testCase.alignment {
case "Left":
options.PrettyTablesOptions.Alignment = tablewriter.ALIGN_LEFT
case "Right":
options.PrettyTablesOptions.Alignment = tablewriter.ALIGN_RIGHT
case "Center":
options.PrettyTablesOptions.Alignment = tablewriter.ALIGN_CENTER
default:
options.PrettyTablesOptions.Alignment = tablewriter.ALIGN_DEFAULT
}
// Check pretty tabular ASCII version.
if msg, err := wantString(testCase.input, testCase.tabularOutput, options); err != nil {
t.Error(err)
Expand All @@ -351,6 +426,7 @@ Table 2 Header 1 Table 2 Header 2 Table 2 Footer 1 Table 2 Footer 2 Table 2 Row
t.Log(msg)
}
}

}

func TestStrippingLists(t *testing.T) {
Expand Down