Revert "Updated vendor packages."

This reverts commit 3d981156fe.
This commit is contained in:
Martin Dosch 2019-08-30 09:44:03 +02:00
parent 3d981156fe
commit 96fd8cf3f6
11 changed files with 754 additions and 160 deletions

View file

@ -20,19 +20,13 @@ go get github.com/chilts/sid
``` ```
id1 := sid.Id() id1 := sid.Id()
id2 := sid.IdHex() id2 := sid.Id()
id3 := sid.IdBase32()
id4 := sid.IdBase64()
fmt.Printf("id1 = %s\n", id1) fmt.Printf("id1 = %s\n", id1)
fmt.Printf("id2 = %s\n", id2) fmt.Printf("id2 = %s\n", id2)
fmt.Printf("id3 = %s\n", id3)
fmt.Printf("id4 = %s\n", id4)
// -> "id1 = 1559872035903071353-1186579057231285506" // -> "id1 = 1IeSBAWW83j-2wgJ4PUtlAr"
// -> "id2 = 15a5cf57e7d2a837-6eaafe687e7b3ec3" // -> "id2 = 1IeSBAWW9kK-0cDG64GQgGJ"
// -> "id3 = 1b9efqnl51jj7-4u66ikpfq9ugm"
// -> "id4 = 1IeSBAWW9kK-0cDG64GQgGJ"
``` ```
## Author ## Author
@ -43,6 +37,6 @@ For [AppsAttic](https://appsattic.com/), [@AppsAttic](https://twitter.com/AppsAt
## License ## License
[MIT](https://chilts.mit-license.org/2017/) [MIT](https://publish.li/mit-qLQqmVTO).
(Ends) (Ends)

View file

@ -1,3 +0,0 @@
module github.com/chilts/sid
go 1.12

93
vendor/github.com/chilts/sid/sid.go generated vendored
View file

@ -12,7 +12,6 @@
package sid package sid
import ( import (
"fmt"
"math/rand" "math/rand"
"strconv" "strconv"
"strings" "strings"
@ -33,39 +32,17 @@ var chars = make([]string, 11, 11)
// 64 chars but ordered by ASCII // 64 chars but ordered by ASCII
const base64 string = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~" const base64 string = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"
func toStr(n int64) string { func toStr(now int64) string {
// now do the generation (backwards, so we just %64 then /64 along the way) // now do the generation (backwards, so we just %64 then /64 along the way)
for i := 10; i >= 0; i-- { for i := 10; i >= 0; i-- {
index := n % 64 index := now % 64
chars[i] = string(base64[index]) chars[i] = string(base64[index])
n = n / 64 now = now / 64
} }
return strings.Join(chars, "") 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" // 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 // 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 // random number is incremented instead of a new one being generated. This makes sure that two consecutive Ids
@ -94,66 +71,10 @@ func IdBase64() string {
return toStr(now) + "-" + toStr(r) return toStr(now) + "-" + toStr(r)
} }
// IdBase32 returns a 27 char string based on timestamp and a random number. The format is // Id returns a 23 char string based on timestamp and a random number. The format is "XXXXXXXXXXX-YYYYYYYYYYY" where X
// "XXXXXXXXXXXXX-YYYYYYYYYYYYY" where X is the timestamp and Y is the random number. If (by any chance) this is called // is the timestamp and Y is the random number. If (by any chance) this is called in the same nanosecond, the random
// in the same nanosecond, the random number is incremented instead of a new one being generated. This makes sure that // number is incremented instead of a new one being generated. This makes sure that two consecutive Ids generated in
// two consecutive Ids generated in the same goroutine also ensure those Ids are also sortable. // 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. // It is safe to call from different goroutines since it has it's own locking.
func Id() string { func Id() string {

View file

@ -1,8 +0,0 @@
module github.com/olekukonko/tablewriter
go 1.12
require (
github.com/mattn/go-runewidth v0.0.4
github.com/olekukonko/tablewriter v0.0.1
)

View file

@ -1,4 +0,0 @@
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=

View file

@ -766,7 +766,7 @@ func (t *Table) printRowMergeCells(writer io.Writer, columns [][]string, rowIdx
if t.autoMergeCells { if t.autoMergeCells {
//Store the full line to merge mutli-lines cells //Store the full line to merge mutli-lines cells
fullLine := strings.TrimRight(strings.Join(columns[y], " "), " ") fullLine := strings.Join(columns[y], " ")
if len(previousLine) > y && fullLine == previousLine[y] && fullLine != "" { 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. // 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) 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 //The new previous line is the current one
previousLine = make([]string, total) previousLine = make([]string, total)
for y := 0; y < total; y++ { for y := 0; y < total; y++ {
previousLine[y] = strings.TrimRight(strings.Join(columns[y], " ")," ") //Store the full line for multi-lines cells previousLine[y] = 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. //Returns the newly added line and wether or not a border should be displayed above.
return previousLine, displayCellBorder return previousLine, displayCellBorder

22
vendor/jaytaylor.com/html2text/LICENSE generated vendored Normal file
View file

@ -0,0 +1,22 @@
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.

137
vendor/jaytaylor.com/html2text/README.md generated vendored Normal file
View file

@ -0,0 +1,137 @@
# 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 := `
<html>
<head>
<title>My Mega Service</title>
<link rel=\"stylesheet\" href=\"main.css\">
<style type=\"text/css\">body { color: #fff; }</style>
</head>
<body>
<div class="logo">
<a href="http://jaytaylor.com/"><img src="/logo-image.jpg" alt="Mega Service"/></a>
</div>
<h1>Welcome to your new account on my service!</h1>
<p>
Here is some more information:
<ul>
<li>Link 1: <a href="https://example.com">Example.com</a></li>
<li>Link 2: <a href="https://example2.com">Example2.com</a></li>
<li>Something else</li>
</ul>
</p>
<table>
<thead>
<tr><th>Header 1</th><th>Header 2</th></tr>
</thead>
<tfoot>
<tr><td>Footer 1</td><td>Footer 2</td></tr>
</tfoot>
<tbody>
<tr><td>Row 1 Col 1</td><td>Row 1 Col 2</td></tr>
<tr><td>Row 2 Col 1</td><td>Row 2 Col 2</td></tr>
</tbody>
</table>
</body>
</html>`
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)

535
vendor/jaytaylor.com/html2text/html2text.go generated vendored Normal file
View file

@ -0,0 +1,535 @@
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 ""
}

92
vendor/vendor.json vendored
View file

@ -15,10 +15,10 @@
"revisionTime": "2018-10-12T15:44:24Z" "revisionTime": "2018-10-12T15:44:24Z"
}, },
{ {
"checksumSHA1": "WoatyvsqqryIUsNP+2fXlbVtAVM=", "checksumSHA1": "5UWAX/5F5bqC7tKtDb2QFFRqwAs=",
"path": "github.com/chilts/sid", "path": "github.com/chilts/sid",
"revision": "660e94789ec9b45634f588d40881e81b56de92a0", "revision": "250d10e55bf450834d37cb13b7dae8816ada9b28",
"revisionTime": "2019-06-07T04:24:30Z" "revisionTime": "2018-09-28T23:21:30Z"
}, },
{ {
"checksumSHA1": "qR7D38Zmn9TPUvGn64k+r0+Kq1c=", "checksumSHA1": "qR7D38Zmn9TPUvGn64k+r0+Kq1c=",
@ -69,10 +69,10 @@
"revisionTime": "2018-10-12T15:49:47Z" "revisionTime": "2018-10-12T15:49:47Z"
}, },
{ {
"checksumSHA1": "C2jnBks3LctebwDmLMoq/zYZex0=", "checksumSHA1": "HZJ2dhzXoMi8n+iY80A9vsnyQUk=",
"path": "github.com/olekukonko/tablewriter", "path": "github.com/olekukonko/tablewriter",
"revision": "cc27d85e17cec9768d2ac401ea5d619a9628f16d", "revision": "1c0837c15a0bac7871496dfce5dcdd308e0a330f",
"revisionTime": "2019-06-18T03:32:46Z" "revisionTime": "2019-05-08T01:39:46Z"
}, },
{ {
"checksumSHA1": "qErubHtC7DAFBnEQkMTuKDtfFTU=", "checksumSHA1": "qErubHtC7DAFBnEQkMTuKDtfFTU=",
@ -83,122 +83,122 @@
{ {
"checksumSHA1": "bONEZcbkYKiPyABrecOLzHomjPU=", "checksumSHA1": "bONEZcbkYKiPyABrecOLzHomjPU=",
"path": "golang.org/x/net/html", "path": "golang.org/x/net/html",
"revision": "ba9fcec4b297b415637633c5a6e8fa592e4a16c3", "revision": "f3200d17e092c607f615320ecaad13d87ad9a2b3",
"revisionTime": "2019-08-26T16:14:39Z" "revisionTime": "2019-05-22T15:39:15Z"
}, },
{ {
"checksumSHA1": "xwhqe/igHQrY3IhqDwzo6j7qpm8=", "checksumSHA1": "xwhqe/igHQrY3IhqDwzo6j7qpm8=",
"path": "golang.org/x/net/html/atom", "path": "golang.org/x/net/html/atom",
"revision": "ba9fcec4b297b415637633c5a6e8fa592e4a16c3", "revision": "f3200d17e092c607f615320ecaad13d87ad9a2b3",
"revisionTime": "2019-08-26T16:14:39Z" "revisionTime": "2019-05-22T15:39:15Z"
}, },
{ {
"checksumSHA1": "barUU39reQ7LdgYLA323hQ/UGy4=", "checksumSHA1": "barUU39reQ7LdgYLA323hQ/UGy4=",
"path": "golang.org/x/net/html/charset", "path": "golang.org/x/net/html/charset",
"revision": "ba9fcec4b297b415637633c5a6e8fa592e4a16c3", "revision": "f3200d17e092c607f615320ecaad13d87ad9a2b3",
"revisionTime": "2019-08-26T16:14:39Z" "revisionTime": "2019-05-22T15:39:15Z"
}, },
{ {
"checksumSHA1": "tqqo7DEeFCclb58XbN44WwdpWww=", "checksumSHA1": "tqqo7DEeFCclb58XbN44WwdpWww=",
"path": "golang.org/x/text/encoding", "path": "golang.org/x/text/encoding",
"revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475",
"revisionTime": "2019-08-29T15:11:34Z" "revisionTime": "2018-12-15T17:52:45Z"
}, },
{ {
"checksumSHA1": "DSdlK4MKI/a3U8Zaee2XKBe01Fo=", "checksumSHA1": "DSdlK4MKI/a3U8Zaee2XKBe01Fo=",
"path": "golang.org/x/text/encoding/charmap", "path": "golang.org/x/text/encoding/charmap",
"revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475",
"revisionTime": "2019-08-29T15:11:34Z" "revisionTime": "2018-12-15T17:52:45Z"
}, },
{ {
"checksumSHA1": "SbJkfe5G/5tji96Pa15/ePDOCtk=", "checksumSHA1": "SbJkfe5G/5tji96Pa15/ePDOCtk=",
"path": "golang.org/x/text/encoding/htmlindex", "path": "golang.org/x/text/encoding/htmlindex",
"revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475",
"revisionTime": "2019-08-29T15:11:34Z" "revisionTime": "2018-12-15T17:52:45Z"
}, },
{ {
"checksumSHA1": "zeHyHebIZl1tGuwGllIhjfci+wI=", "checksumSHA1": "zeHyHebIZl1tGuwGllIhjfci+wI=",
"path": "golang.org/x/text/encoding/internal", "path": "golang.org/x/text/encoding/internal",
"revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475",
"revisionTime": "2019-08-29T15:11:34Z" "revisionTime": "2018-12-15T17:52:45Z"
}, },
{ {
"checksumSHA1": "hT7VaIBlkm2YpKulgnjqXNdicGQ=", "checksumSHA1": "hT7VaIBlkm2YpKulgnjqXNdicGQ=",
"path": "golang.org/x/text/encoding/internal/identifier", "path": "golang.org/x/text/encoding/internal/identifier",
"revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475",
"revisionTime": "2019-08-29T15:11:34Z" "revisionTime": "2018-12-15T17:52:45Z"
}, },
{ {
"checksumSHA1": "2YqVpmvjWGEBATyUphTP1MS34JE=", "checksumSHA1": "2YqVpmvjWGEBATyUphTP1MS34JE=",
"path": "golang.org/x/text/encoding/japanese", "path": "golang.org/x/text/encoding/japanese",
"revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475",
"revisionTime": "2019-08-29T15:11:34Z" "revisionTime": "2018-12-15T17:52:45Z"
}, },
{ {
"checksumSHA1": "+ErWCAdaMwO4PLtrk9D/Hh+7oQM=", "checksumSHA1": "+ErWCAdaMwO4PLtrk9D/Hh+7oQM=",
"path": "golang.org/x/text/encoding/korean", "path": "golang.org/x/text/encoding/korean",
"revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475",
"revisionTime": "2019-08-29T15:11:34Z" "revisionTime": "2018-12-15T17:52:45Z"
}, },
{ {
"checksumSHA1": "mTuZi5urYwgDIO8+Gfql2pv8Vwg=", "checksumSHA1": "mTuZi5urYwgDIO8+Gfql2pv8Vwg=",
"path": "golang.org/x/text/encoding/simplifiedchinese", "path": "golang.org/x/text/encoding/simplifiedchinese",
"revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475",
"revisionTime": "2019-08-29T15:11:34Z" "revisionTime": "2018-12-15T17:52:45Z"
}, },
{ {
"checksumSHA1": "D+VI4j0Wjzr8SeupWdOB5KBdFOw=", "checksumSHA1": "D+VI4j0Wjzr8SeupWdOB5KBdFOw=",
"path": "golang.org/x/text/encoding/traditionalchinese", "path": "golang.org/x/text/encoding/traditionalchinese",
"revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475",
"revisionTime": "2019-08-29T15:11:34Z" "revisionTime": "2018-12-15T17:52:45Z"
}, },
{ {
"checksumSHA1": "bAJTZJ3IGJdNmN/PSlRMRxWtxec=", "checksumSHA1": "bAJTZJ3IGJdNmN/PSlRMRxWtxec=",
"path": "golang.org/x/text/encoding/unicode", "path": "golang.org/x/text/encoding/unicode",
"revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475",
"revisionTime": "2019-08-29T15:11:34Z" "revisionTime": "2018-12-15T17:52:45Z"
}, },
{ {
"checksumSHA1": "ybE4kAPmNPV/dvShuG86AmLbhdE=", "checksumSHA1": "ybE4kAPmNPV/dvShuG86AmLbhdE=",
"path": "golang.org/x/text/internal/language", "path": "golang.org/x/text/internal/language",
"revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475",
"revisionTime": "2019-08-29T15:11:34Z" "revisionTime": "2018-12-15T17:52:45Z"
}, },
{ {
"checksumSHA1": "VDwNSsZP6KShjTSwGUQUGJVrs1I=", "checksumSHA1": "VDwNSsZP6KShjTSwGUQUGJVrs1I=",
"path": "golang.org/x/text/internal/language/compact", "path": "golang.org/x/text/internal/language/compact",
"revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475",
"revisionTime": "2019-08-29T15:11:34Z" "revisionTime": "2018-12-15T17:52:45Z"
}, },
{ {
"checksumSHA1": "hyNCcTwMQnV6/MK8uUW9E5H0J0M=", "checksumSHA1": "hyNCcTwMQnV6/MK8uUW9E5H0J0M=",
"path": "golang.org/x/text/internal/tag", "path": "golang.org/x/text/internal/tag",
"revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475",
"revisionTime": "2019-08-29T15:11:34Z" "revisionTime": "2018-12-15T17:52:45Z"
}, },
{ {
"checksumSHA1": "Qk7dljcrEK1BJkAEZguxAbG9dSo=", "checksumSHA1": "Qk7dljcrEK1BJkAEZguxAbG9dSo=",
"path": "golang.org/x/text/internal/utf8internal", "path": "golang.org/x/text/internal/utf8internal",
"revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475",
"revisionTime": "2019-08-29T15:11:34Z" "revisionTime": "2018-12-15T17:52:45Z"
}, },
{ {
"checksumSHA1": "oYNlkS+0TimKOScUz3Hn9QWyz6w=", "checksumSHA1": "oYNlkS+0TimKOScUz3Hn9QWyz6w=",
"path": "golang.org/x/text/language", "path": "golang.org/x/text/language",
"revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475",
"revisionTime": "2019-08-29T15:11:34Z" "revisionTime": "2018-12-15T17:52:45Z"
}, },
{ {
"checksumSHA1": "IV4MN7KGBSocu/5NR3le3sxup4Y=", "checksumSHA1": "IV4MN7KGBSocu/5NR3le3sxup4Y=",
"path": "golang.org/x/text/runes", "path": "golang.org/x/text/runes",
"revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475",
"revisionTime": "2019-08-29T15:11:34Z" "revisionTime": "2018-12-15T17:52:45Z"
}, },
{ {
"checksumSHA1": "R9iBDY+aPnT+8pyRcqGjXq5QixA=", "checksumSHA1": "R9iBDY+aPnT+8pyRcqGjXq5QixA=",
"path": "golang.org/x/text/transform", "path": "golang.org/x/text/transform",
"revision": "3d0f7978add91030e5e8976ff65ccdd828286cba", "revision": "342b2e1fbaa52c93f31447ad2c6abc048c63e475",
"revisionTime": "2019-08-29T15:11:34Z" "revisionTime": "2018-12-15T17:52:45Z"
}, },
{ {
"checksumSHA1": "2/9hMw7Y4I42L/PTobKqVldWUAU=", "checksumSHA1": "2/9hMw7Y4I42L/PTobKqVldWUAU=",