diff --git a/vendor/github.com/chilts/sid/ReadMe.md b/vendor/github.com/chilts/sid/ReadMe.md index b4653cb..7761928 100644 --- a/vendor/github.com/chilts/sid/ReadMe.md +++ b/vendor/github.com/chilts/sid/ReadMe.md @@ -20,13 +20,19 @@ go get github.com/chilts/sid ``` id1 := sid.Id() -id2 := sid.Id() +id2 := sid.IdHex() +id3 := sid.IdBase32() +id4 := sid.IdBase64() fmt.Printf("id1 = %s\n", id1) fmt.Printf("id2 = %s\n", id2) +fmt.Printf("id3 = %s\n", id3) +fmt.Printf("id4 = %s\n", id4) -// -> "id1 = 1IeSBAWW83j-2wgJ4PUtlAr" -// -> "id2 = 1IeSBAWW9kK-0cDG64GQgGJ" +// -> "id1 = 1559872035903071353-1186579057231285506" +// -> "id2 = 15a5cf57e7d2a837-6eaafe687e7b3ec3" +// -> "id3 = 1b9efqnl51jj7-4u66ikpfq9ugm" +// -> "id4 = 1IeSBAWW9kK-0cDG64GQgGJ" ``` ## Author @@ -37,6 +43,6 @@ For [AppsAttic](https://appsattic.com/), [@AppsAttic](https://twitter.com/AppsAt ## License -[MIT](https://publish.li/mit-qLQqmVTO). +[MIT](https://chilts.mit-license.org/2017/) (Ends) diff --git a/vendor/github.com/chilts/sid/go.mod b/vendor/github.com/chilts/sid/go.mod new file mode 100644 index 0000000..fbe38d8 --- /dev/null +++ b/vendor/github.com/chilts/sid/go.mod @@ -0,0 +1,3 @@ +module github.com/chilts/sid + +go 1.12 diff --git a/vendor/github.com/chilts/sid/sid.go b/vendor/github.com/chilts/sid/sid.go index 7c1f2c8..d3b55e3 100644 --- a/vendor/github.com/chilts/sid/sid.go +++ b/vendor/github.com/chilts/sid/sid.go @@ -12,6 +12,7 @@ package sid import ( + "fmt" "math/rand" "strconv" "strings" @@ -32,17 +33,39 @@ var chars = make([]string, 11, 11) // 64 chars but ordered by ASCII const base64 string = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~" -func toStr(now int64) string { +func toStr(n int64) string { // now do the generation (backwards, so we just %64 then /64 along the way) for i := 10; i >= 0; i-- { - index := now % 64 + index := n % 64 chars[i] = string(base64[index]) - now = now / 64 + n = n / 64 } return strings.Join(chars, "") } +func toBase32(n int64) string { + b32 := strconv.FormatInt(n, 32) + + for len(b32) < 13 { + b32 = "0" + b32 + } + + // log.Printf("b32=%s\n", b32) + + return b32 +} + +func toHex(n int64) string { + hex := fmt.Sprintf("%x", n) + + for len(hex) < 16 { + hex = "0" + hex + } + + return hex +} + // IdBase64 returns a 23 char string based on timestamp and a random number. The format is "XXXXXXXXXXX-YYYYYYYYYYY" // where X is the timestamp and Y is the random number. If (by any chance) this is called in the same nanosecond, the // random number is incremented instead of a new one being generated. This makes sure that two consecutive Ids @@ -71,10 +94,66 @@ func IdBase64() string { return toStr(now) + "-" + toStr(r) } -// Id returns a 23 char string based on timestamp and a random number. The format is "XXXXXXXXXXX-YYYYYYYYYYY" where X -// is the timestamp and Y is the random number. If (by any chance) this is called in the same nanosecond, the random -// number is incremented instead of a new one being generated. This makes sure that two consecutive Ids generated in -// the same goroutine also ensure those Ids are also sortable. +// IdBase32 returns a 27 char string based on timestamp and a random number. The format is +// "XXXXXXXXXXXXX-YYYYYYYYYYYYY" where X is the timestamp and Y is the random number. If (by any chance) this is called +// in the same nanosecond, the random number is incremented instead of a new one being generated. This makes sure that +// two consecutive Ids generated in the same goroutine also ensure those Ids are also sortable. +// +// It is safe to call from different goroutines since it has it's own locking. +func IdBase32() string { + // lock for lastTime, lastRand, and chars + mu.Lock() + defer mu.Unlock() + + now := time.Now().UTC().UnixNano() + var r int64 + + // if we have the same time, just inc lastRand, else create a new one + if now == lastTime { + lastRand++ + } else { + lastRand = rand.Int63() + } + r = lastRand + + // remember this for next time + lastTime = now + + return toBase32(now) + "-" + toBase32(r) +} + +// IdHex returns a char string based on timestamp and a random number. The format is +// "XXXXXXXXXXXXXXXX-YYYYYYYYYYYYYYYY" where X is the timestamp and Y is the random number. If (by any chance) this is +// called in the same nanosecond, the random number is incremented instead of a new one being generated. This makes +// sure that two consecutive Ids generated in the same goroutine also ensure those Ids are also sortable. +// +// It is safe to call from different goroutines since it has it's own locking. +func IdHex() string { + // lock for lastTime, lastRand, and chars + mu.Lock() + defer mu.Unlock() + + now := time.Now().UTC().UnixNano() + var r int64 + + // if we have the same time, just inc lastRand, else create a new one + if now == lastTime { + lastRand++ + } else { + lastRand = rand.Int63() + } + r = lastRand + + // remember this for next time + lastTime = now + + return toHex(now) + "-" + toHex(r) +} + +// Id returns a 39 char string based on timestamp and a random number. The format is +// "XXXXXXXXXXXXXXXXXXX-YYYYYYYYYYYYYYYYYYY" where X is the timestamp and Y is the random number. If (by any chance) +// this is called in the same nanosecond, the random number is incremented instead of a new one being generated. This +// makes sure that two consecutive Ids generated in the same goroutine also ensure those Ids are also sortable. // // It is safe to call from different goroutines since it has it's own locking. func Id() string { diff --git a/vendor/github.com/olekukonko/tablewriter/README.md b/vendor/github.com/olekukonko/tablewriter/README.md index 92d71ed..cb5e137 100644 --- a/vendor/github.com/olekukonko/tablewriter/README.md +++ b/vendor/github.com/olekukonko/tablewriter/README.md @@ -283,7 +283,7 @@ import ( func main() { tableString := &strings.Builder{} - table := tablewriter.NewWriter(tableString) + table := tablewriter.NewWriter(tableString) /* * Code to fill the table diff --git a/vendor/github.com/olekukonko/tablewriter/go.mod b/vendor/github.com/olekukonko/tablewriter/go.mod new file mode 100644 index 0000000..84b405d --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/go.mod @@ -0,0 +1,8 @@ +module github.com/olekukonko/tablewriter + +go 1.12 + +require ( + github.com/mattn/go-runewidth v0.0.4 + github.com/olekukonko/tablewriter v0.0.1 +) diff --git a/vendor/github.com/olekukonko/tablewriter/go.sum b/vendor/github.com/olekukonko/tablewriter/go.sum new file mode 100644 index 0000000..9d5e335 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/go.sum @@ -0,0 +1,4 @@ +github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/olekukonko/tablewriter v0.0.1 h1:b3iUnf1v+ppJiOfNX4yxxqfWKMQPZR5yoh8urCTFX88= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= diff --git a/vendor/github.com/olekukonko/tablewriter/table.go b/vendor/github.com/olekukonko/tablewriter/table.go index 3cf0996..06341bc 100644 --- a/vendor/github.com/olekukonko/tablewriter/table.go +++ b/vendor/github.com/olekukonko/tablewriter/table.go @@ -766,7 +766,7 @@ func (t *Table) printRowMergeCells(writer io.Writer, columns [][]string, rowIdx if t.autoMergeCells { //Store the full line to merge mutli-lines cells - fullLine := strings.Join(columns[y], " ") + fullLine := strings.TrimRight(strings.Join(columns[y], " "), " ") if len(previousLine) > y && fullLine == previousLine[y] && fullLine != "" { // If this cell is identical to the one above but not empty, we don't display the border and keep the cell empty. displayCellBorder = append(displayCellBorder, false) @@ -804,7 +804,7 @@ func (t *Table) printRowMergeCells(writer io.Writer, columns [][]string, rowIdx //The new previous line is the current one previousLine = make([]string, total) for y := 0; y < total; y++ { - previousLine[y] = strings.Join(columns[y], " ") //Store the full line for multi-lines cells + previousLine[y] = strings.TrimRight(strings.Join(columns[y], " ")," ") //Store the full line for multi-lines cells } //Returns the newly added line and wether or not a border should be displayed above. return previousLine, displayCellBorder diff --git a/vendor/jaytaylor.com/html2text/LICENSE b/vendor/jaytaylor.com/html2text/LICENSE deleted file mode 100644 index 24dc4ab..0000000 --- a/vendor/jaytaylor.com/html2text/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Jay Taylor - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/vendor/jaytaylor.com/html2text/README.md b/vendor/jaytaylor.com/html2text/README.md deleted file mode 100644 index 6b2494e..0000000 --- a/vendor/jaytaylor.com/html2text/README.md +++ /dev/null @@ -1,137 +0,0 @@ -# html2text - -[![Documentation](https://godoc.org/github.com/jaytaylor/html2text?status.svg)](https://godoc.org/github.com/jaytaylor/html2text) -[![Build Status](https://travis-ci.org/jaytaylor/html2text.svg?branch=master)](https://travis-ci.org/jaytaylor/html2text) -[![Report Card](https://goreportcard.com/badge/github.com/jaytaylor/html2text)](https://goreportcard.com/report/github.com/jaytaylor/html2text) - -### Converts HTML into text of the markdown-flavored variety - - -## Introduction - -Ensure your emails are readable by all! - -Turns HTML into raw text, useful for sending fancy HTML emails with an equivalently nicely formatted TXT document as a fallback (e.g. for people who don't allow HTML emails or have other display issues). - -html2text is a simple golang package for rendering HTML into plaintext. - -There are still lots of improvements to be had, but FWIW this has worked fine for my [basic] HTML-2-text needs. - -It requires go 1.x or newer ;) - - -## Download the package - -```bash -go get jaytaylor.com/html2text -``` - -## Example usage - -```go -package main - -import ( - "fmt" - - "jaytaylor.com/html2text" -) - -func main() { - inputHTML := ` - - - My Mega Service - - - - - - - -

Welcome to your new account on my service!

- -

- Here is some more information: - -

-

- - - - - - - - - - - - -
Header 1Header 2
Footer 1Footer 2
Row 1 Col 1Row 1 Col 2
Row 2 Col 1Row 2 Col 2
- -` - - text, err := html2text.FromString(inputHTML, html2text.Options{PrettyTables: true}) - if err != nil { - panic(err) - } - fmt.Println(text) -} -``` - -Output: -``` -Mega Service ( http://jaytaylor.com/ ) - -****************************************** -Welcome to your new account on my service! -****************************************** - -Here is some more information: - -* Link 1: Example.com ( https://example.com ) -* Link 2: Example2.com ( https://example2.com ) -* Something else - -+-------------+-------------+ -| HEADER 1 | HEADER 2 | -+-------------+-------------+ -| Row 1 Col 1 | Row 1 Col 2 | -| Row 2 Col 1 | Row 2 Col 2 | -+-------------+-------------+ -| FOOTER 1 | FOOTER 2 | -+-------------+-------------+ -``` - - -## Unit-tests - -Running the unit-tests is straightforward and standard: - -```bash -go test -``` - - -# License - -Permissive MIT license. - - -## Contact - -You are more than welcome to open issues and send pull requests if you find a bug or want a new feature. - -If you appreciate this library please feel free to drop me a line and tell me! It's always nice to hear from people who have benefitted from my work. - -Email: jay at (my github username).com - -Twitter: [@jtaylor](https://twitter.com/jtaylor) - diff --git a/vendor/jaytaylor.com/html2text/html2text.go b/vendor/jaytaylor.com/html2text/html2text.go deleted file mode 100644 index 4398909..0000000 --- a/vendor/jaytaylor.com/html2text/html2text.go +++ /dev/null @@ -1,535 +0,0 @@ -package html2text - -import ( - "bytes" - "io" - "regexp" - "strings" - "unicode" - - "github.com/olekukonko/tablewriter" - "github.com/ssor/bom" - "golang.org/x/net/html" - "golang.org/x/net/html/atom" -) - -// Options provide toggles and overrides to control specific rendering behaviors. -type Options struct { - PrettyTables bool // Turns on pretty ASCII rendering for table elements. - PrettyTablesOptions *PrettyTablesOptions // Configures pretty ASCII rendering for table elements. - OmitLinks bool // Turns on omitting links -} - -// PrettyTablesOptions overrides tablewriter behaviors -type PrettyTablesOptions struct { - AutoFormatHeader bool - AutoWrapText bool - ReflowDuringAutoWrap bool - ColWidth int - ColumnSeparator string - RowSeparator string - CenterSeparator string - HeaderAlignment int - FooterAlignment int - Alignment int - ColumnAlignment []int - NewLine string - HeaderLine bool - RowLine bool - AutoMergeCells bool - Borders tablewriter.Border -} - -// NewPrettyTablesOptions creates PrettyTablesOptions with default settings -func NewPrettyTablesOptions() *PrettyTablesOptions { - return &PrettyTablesOptions{ - AutoFormatHeader: true, - AutoWrapText: true, - ReflowDuringAutoWrap: true, - ColWidth: tablewriter.MAX_ROW_WIDTH, - ColumnSeparator: tablewriter.COLUMN, - RowSeparator: tablewriter.ROW, - CenterSeparator: tablewriter.CENTER, - HeaderAlignment: tablewriter.ALIGN_DEFAULT, - FooterAlignment: tablewriter.ALIGN_DEFAULT, - Alignment: tablewriter.ALIGN_DEFAULT, - ColumnAlignment: []int{}, - NewLine: tablewriter.NEWLINE, - HeaderLine: true, - RowLine: false, - AutoMergeCells: false, - Borders: tablewriter.Border{Left: true, Right: true, Bottom: true, Top: true}, - } -} - -// FromHTMLNode renders text output from a pre-parsed HTML document. -func FromHTMLNode(doc *html.Node, o ...Options) (string, error) { - var options Options - if len(o) > 0 { - options = o[0] - } - - ctx := textifyTraverseContext{ - buf: bytes.Buffer{}, - options: options, - } - if err := ctx.traverse(doc); err != nil { - return "", err - } - - text := strings.TrimSpace(newlineRe.ReplaceAllString( - strings.Replace(ctx.buf.String(), "\n ", "\n", -1), "\n\n"), - ) - return text, nil -} - -// FromReader renders text output after parsing HTML for the specified -// io.Reader. -func FromReader(reader io.Reader, options ...Options) (string, error) { - newReader, err := bom.NewReaderWithoutBom(reader) - if err != nil { - return "", err - } - doc, err := html.Parse(newReader) - if err != nil { - return "", err - } - return FromHTMLNode(doc, options...) -} - -// FromString parses HTML from the input string, then renders the text form. -func FromString(input string, options ...Options) (string, error) { - bs := bom.CleanBom([]byte(input)) - text, err := FromReader(bytes.NewReader(bs), options...) - if err != nil { - return "", err - } - return text, nil -} - -var ( - spacingRe = regexp.MustCompile(`[ \r\n\t]+`) - newlineRe = regexp.MustCompile(`\n\n+`) -) - -// traverseTableCtx holds text-related context. -type textifyTraverseContext struct { - buf bytes.Buffer - - prefix string - tableCtx tableTraverseContext - options Options - endsWithSpace bool - justClosedDiv bool - blockquoteLevel int - lineLength int - isPre bool -} - -// tableTraverseContext holds table ASCII-form related context. -type tableTraverseContext struct { - header []string - body [][]string - footer []string - tmpRow int - isInFooter bool -} - -func (tableCtx *tableTraverseContext) init() { - tableCtx.body = [][]string{} - tableCtx.header = []string{} - tableCtx.footer = []string{} - tableCtx.isInFooter = false - tableCtx.tmpRow = 0 -} - -func (ctx *textifyTraverseContext) handleElement(node *html.Node) error { - ctx.justClosedDiv = false - - switch node.DataAtom { - case atom.Br: - return ctx.emit("\n") - - case atom.H1, atom.H2, atom.H3: - subCtx := textifyTraverseContext{} - if err := subCtx.traverseChildren(node); err != nil { - return err - } - - str := subCtx.buf.String() - dividerLen := 0 - for _, line := range strings.Split(str, "\n") { - if lineLen := len([]rune(line)); lineLen-1 > dividerLen { - dividerLen = lineLen - 1 - } - } - var divider string - if node.DataAtom == atom.H1 { - divider = strings.Repeat("*", dividerLen) - } else { - divider = strings.Repeat("-", dividerLen) - } - - if node.DataAtom == atom.H3 { - return ctx.emit("\n\n" + str + "\n" + divider + "\n\n") - } - return ctx.emit("\n\n" + divider + "\n" + str + "\n" + divider + "\n\n") - - case atom.Blockquote: - ctx.blockquoteLevel++ - ctx.prefix = strings.Repeat(">", ctx.blockquoteLevel) + " " - if err := ctx.emit("\n"); err != nil { - return err - } - if ctx.blockquoteLevel == 1 { - if err := ctx.emit("\n"); err != nil { - return err - } - } - if err := ctx.traverseChildren(node); err != nil { - return err - } - ctx.blockquoteLevel-- - ctx.prefix = strings.Repeat(">", ctx.blockquoteLevel) - if ctx.blockquoteLevel > 0 { - ctx.prefix += " " - } - return ctx.emit("\n\n") - - case atom.Div: - if ctx.lineLength > 0 { - if err := ctx.emit("\n"); err != nil { - return err - } - } - if err := ctx.traverseChildren(node); err != nil { - return err - } - var err error - if !ctx.justClosedDiv { - err = ctx.emit("\n") - } - ctx.justClosedDiv = true - return err - - case atom.Li: - if err := ctx.emit("* "); err != nil { - return err - } - - if err := ctx.traverseChildren(node); err != nil { - return err - } - - return ctx.emit("\n") - - case atom.B, atom.Strong: - subCtx := textifyTraverseContext{} - subCtx.endsWithSpace = true - if err := subCtx.traverseChildren(node); err != nil { - return err - } - str := subCtx.buf.String() - return ctx.emit("*" + str + "*") - - case atom.A: - linkText := "" - // For simple link element content with single text node only, peek at the link text. - if node.FirstChild != nil && node.FirstChild.NextSibling == nil && node.FirstChild.Type == html.TextNode { - linkText = node.FirstChild.Data - } - - // If image is the only child, take its alt text as the link text. - if img := node.FirstChild; img != nil && node.LastChild == img && img.DataAtom == atom.Img { - if altText := getAttrVal(img, "alt"); altText != "" { - if err := ctx.emit(altText); err != nil { - return err - } - } - } else if err := ctx.traverseChildren(node); err != nil { - return err - } - - hrefLink := "" - if attrVal := getAttrVal(node, "href"); attrVal != "" { - attrVal = ctx.normalizeHrefLink(attrVal) - // Don't print link href if it matches link element content or if the link is empty. - if !ctx.options.OmitLinks && attrVal != "" && linkText != attrVal { - hrefLink = "( " + attrVal + " )" - } - } - - return ctx.emit(hrefLink) - - case atom.P, atom.Ul: - return ctx.paragraphHandler(node) - - case atom.Table, atom.Tfoot, atom.Th, atom.Tr, atom.Td: - if ctx.options.PrettyTables { - return ctx.handleTableElement(node) - } else if node.DataAtom == atom.Table { - return ctx.paragraphHandler(node) - } - return ctx.traverseChildren(node) - - case atom.Pre: - ctx.isPre = true - err := ctx.traverseChildren(node) - ctx.isPre = false - return err - - case atom.Style, atom.Script, atom.Head: - // Ignore the subtree. - return nil - - default: - return ctx.traverseChildren(node) - } -} - -// paragraphHandler renders node children surrounded by double newlines. -func (ctx *textifyTraverseContext) paragraphHandler(node *html.Node) error { - if err := ctx.emit("\n\n"); err != nil { - return err - } - if err := ctx.traverseChildren(node); err != nil { - return err - } - return ctx.emit("\n\n") -} - -// handleTableElement is only to be invoked when options.PrettyTables is active. -func (ctx *textifyTraverseContext) handleTableElement(node *html.Node) error { - if !ctx.options.PrettyTables { - panic("handleTableElement invoked when PrettyTables not active") - } - - switch node.DataAtom { - case atom.Table: - if err := ctx.emit("\n\n"); err != nil { - return err - } - - // Re-intialize all table context. - ctx.tableCtx.init() - - // Browse children, enriching context with table data. - if err := ctx.traverseChildren(node); err != nil { - return err - } - - buf := &bytes.Buffer{} - table := tablewriter.NewWriter(buf) - if ctx.options.PrettyTablesOptions != nil { - options := ctx.options.PrettyTablesOptions - table.SetAutoFormatHeaders(options.AutoFormatHeader) - table.SetAutoWrapText(options.AutoWrapText) - table.SetReflowDuringAutoWrap(options.ReflowDuringAutoWrap) - table.SetColWidth(options.ColWidth) - table.SetColumnSeparator(options.ColumnSeparator) - table.SetRowSeparator(options.RowSeparator) - table.SetCenterSeparator(options.CenterSeparator) - table.SetHeaderAlignment(options.HeaderAlignment) - table.SetFooterAlignment(options.FooterAlignment) - table.SetAlignment(options.Alignment) - table.SetColumnAlignment(options.ColumnAlignment) - table.SetNewLine(options.NewLine) - table.SetHeaderLine(options.HeaderLine) - table.SetRowLine(options.RowLine) - table.SetAutoMergeCells(options.AutoMergeCells) - table.SetBorders(options.Borders) - } - table.SetHeader(ctx.tableCtx.header) - table.SetFooter(ctx.tableCtx.footer) - table.AppendBulk(ctx.tableCtx.body) - - // Render the table using ASCII. - table.Render() - if err := ctx.emit(buf.String()); err != nil { - return err - } - - return ctx.emit("\n\n") - - case atom.Tfoot: - ctx.tableCtx.isInFooter = true - if err := ctx.traverseChildren(node); err != nil { - return err - } - ctx.tableCtx.isInFooter = false - - case atom.Tr: - ctx.tableCtx.body = append(ctx.tableCtx.body, []string{}) - if err := ctx.traverseChildren(node); err != nil { - return err - } - ctx.tableCtx.tmpRow++ - - case atom.Th: - res, err := ctx.renderEachChild(node) - if err != nil { - return err - } - - ctx.tableCtx.header = append(ctx.tableCtx.header, res) - - case atom.Td: - res, err := ctx.renderEachChild(node) - if err != nil { - return err - } - - if ctx.tableCtx.isInFooter { - ctx.tableCtx.footer = append(ctx.tableCtx.footer, res) - } else { - ctx.tableCtx.body[ctx.tableCtx.tmpRow] = append(ctx.tableCtx.body[ctx.tableCtx.tmpRow], res) - } - - } - return nil -} - -func (ctx *textifyTraverseContext) traverse(node *html.Node) error { - switch node.Type { - default: - return ctx.traverseChildren(node) - - case html.TextNode: - var data string - if ctx.isPre { - data = node.Data - } else { - data = strings.TrimSpace(spacingRe.ReplaceAllString(node.Data, " ")) - } - return ctx.emit(data) - - case html.ElementNode: - return ctx.handleElement(node) - } -} - -func (ctx *textifyTraverseContext) traverseChildren(node *html.Node) error { - for c := node.FirstChild; c != nil; c = c.NextSibling { - if err := ctx.traverse(c); err != nil { - return err - } - } - - return nil -} - -func (ctx *textifyTraverseContext) emit(data string) error { - if data == "" { - return nil - } - var ( - lines = ctx.breakLongLines(data) - err error - ) - for _, line := range lines { - runes := []rune(line) - startsWithSpace := unicode.IsSpace(runes[0]) - if !startsWithSpace && !ctx.endsWithSpace && !strings.HasPrefix(data, ".") { - if err = ctx.buf.WriteByte(' '); err != nil { - return err - } - ctx.lineLength++ - } - ctx.endsWithSpace = unicode.IsSpace(runes[len(runes)-1]) - for _, c := range line { - if _, err = ctx.buf.WriteString(string(c)); err != nil { - return err - } - ctx.lineLength++ - if c == '\n' { - ctx.lineLength = 0 - if ctx.prefix != "" { - if _, err = ctx.buf.WriteString(ctx.prefix); err != nil { - return err - } - } - } - } - } - return nil -} - -const maxLineLen = 74 - -func (ctx *textifyTraverseContext) breakLongLines(data string) []string { - // Only break lines when in blockquotes. - if ctx.blockquoteLevel == 0 { - return []string{data} - } - var ( - ret = []string{} - runes = []rune(data) - l = len(runes) - existing = ctx.lineLength - ) - if existing >= maxLineLen { - ret = append(ret, "\n") - existing = 0 - } - for l+existing > maxLineLen { - i := maxLineLen - existing - for i >= 0 && !unicode.IsSpace(runes[i]) { - i-- - } - if i == -1 { - // No spaces, so go the other way. - i = maxLineLen - existing - for i < l && !unicode.IsSpace(runes[i]) { - i++ - } - } - ret = append(ret, string(runes[:i])+"\n") - for i < l && unicode.IsSpace(runes[i]) { - i++ - } - runes = runes[i:] - l = len(runes) - existing = 0 - } - if len(runes) > 0 { - ret = append(ret, string(runes)) - } - return ret -} - -func (ctx *textifyTraverseContext) normalizeHrefLink(link string) string { - link = strings.TrimSpace(link) - link = strings.TrimPrefix(link, "mailto:") - return link -} - -// renderEachChild visits each direct child of a node and collects the sequence of -// textuual representaitons separated by a single newline. -func (ctx *textifyTraverseContext) renderEachChild(node *html.Node) (string, error) { - buf := &bytes.Buffer{} - for c := node.FirstChild; c != nil; c = c.NextSibling { - s, err := FromHTMLNode(c, ctx.options) - if err != nil { - return "", err - } - if _, err = buf.WriteString(s); err != nil { - return "", err - } - if c.NextSibling != nil { - if err = buf.WriteByte('\n'); err != nil { - return "", err - } - } - } - return buf.String(), nil -} - -func getAttrVal(node *html.Node, attrName string) string { - for _, attr := range node.Attr { - if attr.Key == attrName { - return attr.Val - } - } - - return "" -} diff --git a/vendor/vendor.json b/vendor/vendor.json index e60f391..b22722f 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -15,10 +15,10 @@ "revisionTime": "2018-10-12T15:44:24Z" }, { - "checksumSHA1": "5UWAX/5F5bqC7tKtDb2QFFRqwAs=", + "checksumSHA1": "WoatyvsqqryIUsNP+2fXlbVtAVM=", "path": "github.com/chilts/sid", - "revision": "250d10e55bf450834d37cb13b7dae8816ada9b28", - "revisionTime": "2018-09-28T23:21:30Z" + "revision": "660e94789ec9b45634f588d40881e81b56de92a0", + "revisionTime": "2019-06-07T04:24:30Z" }, { "checksumSHA1": "qR7D38Zmn9TPUvGn64k+r0+Kq1c=", @@ -69,10 +69,10 @@ "revisionTime": "2018-10-12T15:49:47Z" }, { - "checksumSHA1": "HZJ2dhzXoMi8n+iY80A9vsnyQUk=", + "checksumSHA1": "C2jnBks3LctebwDmLMoq/zYZex0=", "path": "github.com/olekukonko/tablewriter", - "revision": "1c0837c15a0bac7871496dfce5dcdd308e0a330f", - "revisionTime": "2019-05-08T01:39:46Z" + "revision": "cc27d85e17cec9768d2ac401ea5d619a9628f16d", + "revisionTime": "2019-06-18T03:32:46Z" }, { "checksumSHA1": "qErubHtC7DAFBnEQkMTuKDtfFTU=", @@ -83,122 +83,122 @@ { "checksumSHA1": "bONEZcbkYKiPyABrecOLzHomjPU=", "path": "golang.org/x/net/html", - "revision": "f3200d17e092c607f615320ecaad13d87ad9a2b3", - "revisionTime": "2019-05-22T15:39:15Z" + "revision": "ba9fcec4b297b415637633c5a6e8fa592e4a16c3", + "revisionTime": "2019-08-26T16:14:39Z" }, { "checksumSHA1": "xwhqe/igHQrY3IhqDwzo6j7qpm8=", "path": "golang.org/x/net/html/atom", - "revision": "f3200d17e092c607f615320ecaad13d87ad9a2b3", - "revisionTime": "2019-05-22T15:39:15Z" + "revision": "ba9fcec4b297b415637633c5a6e8fa592e4a16c3", + "revisionTime": "2019-08-26T16:14:39Z" }, { "checksumSHA1": "barUU39reQ7LdgYLA323hQ/UGy4=", "path": "golang.org/x/net/html/charset", - "revision": "f3200d17e092c607f615320ecaad13d87ad9a2b3", - "revisionTime": "2019-05-22T15:39:15Z" + "revision": "ba9fcec4b297b415637633c5a6e8fa592e4a16c3", + "revisionTime": "2019-08-26T16:14:39Z" }, { "checksumSHA1": "tqqo7DEeFCclb58XbN44WwdpWww=", "path": "golang.org/x/text/encoding", - "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475", - "revisionTime": "2018-12-15T17:52:45Z" + "revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", + "revisionTime": "2019-08-29T15:11:34Z" }, { "checksumSHA1": "DSdlK4MKI/a3U8Zaee2XKBe01Fo=", "path": "golang.org/x/text/encoding/charmap", - "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475", - "revisionTime": "2018-12-15T17:52:45Z" + "revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", + "revisionTime": "2019-08-29T15:11:34Z" }, { "checksumSHA1": "SbJkfe5G/5tji96Pa15/ePDOCtk=", "path": "golang.org/x/text/encoding/htmlindex", - "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475", - "revisionTime": "2018-12-15T17:52:45Z" + "revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", + "revisionTime": "2019-08-29T15:11:34Z" }, { "checksumSHA1": "zeHyHebIZl1tGuwGllIhjfci+wI=", "path": "golang.org/x/text/encoding/internal", - "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475", - "revisionTime": "2018-12-15T17:52:45Z" + "revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", + "revisionTime": "2019-08-29T15:11:34Z" }, { "checksumSHA1": "hT7VaIBlkm2YpKulgnjqXNdicGQ=", "path": "golang.org/x/text/encoding/internal/identifier", - "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475", - "revisionTime": "2018-12-15T17:52:45Z" + "revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", + "revisionTime": "2019-08-29T15:11:34Z" }, { "checksumSHA1": "2YqVpmvjWGEBATyUphTP1MS34JE=", "path": "golang.org/x/text/encoding/japanese", - "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475", - "revisionTime": "2018-12-15T17:52:45Z" + "revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", + "revisionTime": "2019-08-29T15:11:34Z" }, { "checksumSHA1": "+ErWCAdaMwO4PLtrk9D/Hh+7oQM=", "path": "golang.org/x/text/encoding/korean", - "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475", - "revisionTime": "2018-12-15T17:52:45Z" + "revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", + "revisionTime": "2019-08-29T15:11:34Z" }, { "checksumSHA1": "mTuZi5urYwgDIO8+Gfql2pv8Vwg=", "path": "golang.org/x/text/encoding/simplifiedchinese", - "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475", - "revisionTime": "2018-12-15T17:52:45Z" + "revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", + "revisionTime": "2019-08-29T15:11:34Z" }, { "checksumSHA1": "D+VI4j0Wjzr8SeupWdOB5KBdFOw=", "path": "golang.org/x/text/encoding/traditionalchinese", - "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475", - "revisionTime": "2018-12-15T17:52:45Z" + "revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", + "revisionTime": "2019-08-29T15:11:34Z" }, { "checksumSHA1": "bAJTZJ3IGJdNmN/PSlRMRxWtxec=", "path": "golang.org/x/text/encoding/unicode", - "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475", - "revisionTime": "2018-12-15T17:52:45Z" + "revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", + "revisionTime": "2019-08-29T15:11:34Z" }, { "checksumSHA1": "ybE4kAPmNPV/dvShuG86AmLbhdE=", "path": "golang.org/x/text/internal/language", - "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475", - "revisionTime": "2018-12-15T17:52:45Z" + "revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", + "revisionTime": "2019-08-29T15:11:34Z" }, { "checksumSHA1": "VDwNSsZP6KShjTSwGUQUGJVrs1I=", "path": "golang.org/x/text/internal/language/compact", - "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475", - "revisionTime": "2018-12-15T17:52:45Z" + "revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", + "revisionTime": "2019-08-29T15:11:34Z" }, { "checksumSHA1": "hyNCcTwMQnV6/MK8uUW9E5H0J0M=", "path": "golang.org/x/text/internal/tag", - "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475", - "revisionTime": "2018-12-15T17:52:45Z" + "revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", + "revisionTime": "2019-08-29T15:11:34Z" }, { "checksumSHA1": "Qk7dljcrEK1BJkAEZguxAbG9dSo=", "path": "golang.org/x/text/internal/utf8internal", - "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475", - "revisionTime": "2018-12-15T17:52:45Z" + "revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", + "revisionTime": "2019-08-29T15:11:34Z" }, { "checksumSHA1": "oYNlkS+0TimKOScUz3Hn9QWyz6w=", "path": "golang.org/x/text/language", - "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475", - "revisionTime": "2018-12-15T17:52:45Z" + "revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", + "revisionTime": "2019-08-29T15:11:34Z" }, { "checksumSHA1": "IV4MN7KGBSocu/5NR3le3sxup4Y=", "path": "golang.org/x/text/runes", - "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475", - "revisionTime": "2018-12-15T17:52:45Z" + "revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", + "revisionTime": "2019-08-29T15:11:34Z" }, { "checksumSHA1": "R9iBDY+aPnT+8pyRcqGjXq5QixA=", "path": "golang.org/x/text/transform", - "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475", - "revisionTime": "2018-12-15T17:52:45Z" + "revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", + "revisionTime": "2019-08-29T15:11:34Z" }, { "checksumSHA1": "2/9hMw7Y4I42L/PTobKqVldWUAU=",