diff options
author | Thomas Boerger <thomas@webhippie.de> | 2016-11-03 23:16:01 +0100 |
---|---|---|
committer | Thomas Boerger <thomas@webhippie.de> | 2016-11-04 08:43:11 +0100 |
commit | 1ebb35b98889ff77299f24d82da426b434b0cca0 (patch) | |
tree | 6dcb814d6df4d11c7e7a0ba6da8a6945628e2c5d /vendor/github.com/jaytaylor | |
parent | 78f86abba45cb35018c58b8bd5f4c48a86cc8634 (diff) | |
download | gitea-1ebb35b98889ff77299f24d82da426b434b0cca0.tar.gz gitea-1ebb35b98889ff77299f24d82da426b434b0cca0.zip |
Added all required dependencies
Diffstat (limited to 'vendor/github.com/jaytaylor')
-rw-r--r-- | vendor/github.com/jaytaylor/html2text/LICENSE | 22 | ||||
-rw-r--r-- | vendor/github.com/jaytaylor/html2text/README.md | 112 | ||||
-rw-r--r-- | vendor/github.com/jaytaylor/html2text/html2text.go | 300 |
3 files changed, 434 insertions, 0 deletions
diff --git a/vendor/github.com/jaytaylor/html2text/LICENSE b/vendor/github.com/jaytaylor/html2text/LICENSE new file mode 100644 index 0000000000..24dc4abecc --- /dev/null +++ b/vendor/github.com/jaytaylor/html2text/LICENSE @@ -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. + diff --git a/vendor/github.com/jaytaylor/html2text/README.md b/vendor/github.com/jaytaylor/html2text/README.md new file mode 100644 index 0000000000..6e67dbcc6a --- /dev/null +++ b/vendor/github.com/jaytaylor/html2text/README.md @@ -0,0 +1,112 @@ +# 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 + + +## Introduction + +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 github.com/jaytaylor/html2text +``` + +## Example usage + +```go +package main + +import ( + "fmt" + + "github.com/jaytaylor/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://mymegaservice.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> + </body> + </html> + ` + + text, err := html2text.FromString(inputHtml) + if err != nil { + panic(err) + } + fmt.Println(text) +} +``` + +Output: +``` +Mega Service ( http://mymegaservice.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 +``` + + +## 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/github.com/jaytaylor/html2text/html2text.go b/vendor/github.com/jaytaylor/html2text/html2text.go new file mode 100644 index 0000000000..66454cfcac --- /dev/null +++ b/vendor/github.com/jaytaylor/html2text/html2text.go @@ -0,0 +1,300 @@ +package html2text + +import ( + "bytes" + "io" + "regexp" + "strings" + "unicode" + + "golang.org/x/net/html" + "golang.org/x/net/html/atom" +) + +var ( + spacingRe = regexp.MustCompile(`[ \r\n\t]+`) + newlineRe = regexp.MustCompile(`\n\n+`) +) + +type textifyTraverseCtx struct { + Buf bytes.Buffer + + prefix string + blockquoteLevel int + lineLength int + endsWithSpace bool + endsWithNewline bool + justClosedDiv bool +} + +func (ctx *textifyTraverseCtx) traverse(node *html.Node) error { + switch node.Type { + + default: + return ctx.traverseChildren(node) + + case html.TextNode: + data := strings.Trim(spacingRe.ReplaceAllString(node.Data, " "), " ") + return ctx.emit(data) + + case html.ElementNode: + + ctx.justClosedDiv = false + switch node.DataAtom { + case atom.Br: + return ctx.emit("\n") + + case atom.H1, atom.H2, atom.H3: + subCtx := textifyTraverseCtx{} + 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 + } + } + divider := "" + 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 == false { + 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 := textifyTraverseCtx{} + subCtx.endsWithSpace = true + if err := subCtx.traverseChildren(node); err != nil { + return err + } + str := subCtx.Buf.String() + return ctx.emit("*" + str + "*") + + case atom.A: + // 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 != "" { + ctx.emit(altText) + } + } else if err := ctx.traverseChildren(node); err != nil { + return err + } + + hrefLink := "" + if attrVal := getAttrVal(node, "href"); attrVal != "" { + attrVal = ctx.normalizeHrefLink(attrVal) + if attrVal != "" { + hrefLink = "( " + attrVal + " )" + } + } + + return ctx.emit(hrefLink) + + case atom.P, atom.Ul, atom.Table: + if err := ctx.emit("\n\n"); err != nil { + return err + } + + if err := ctx.traverseChildren(node); err != nil { + return err + } + + return ctx.emit("\n\n") + + case atom.Tr: + if err := ctx.traverseChildren(node); err != nil { + return err + } + + return ctx.emit("\n") + + case atom.Style, atom.Script, atom.Head: + // Ignore the subtree + return nil + + default: + return ctx.traverseChildren(node) + } + } +} + +func (ctx *textifyTraverseCtx) 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 *textifyTraverseCtx) emit(data string) error { + if len(data) == 0 { + return nil + } + lines := ctx.breakLongLines(data) + var err error + for _, line := range lines { + runes := []rune(line) + startsWithSpace := unicode.IsSpace(runes[0]) + if !startsWithSpace && !ctx.endsWithSpace { + ctx.Buf.WriteByte(' ') + ctx.lineLength++ + } + ctx.endsWithSpace = unicode.IsSpace(runes[len(runes)-1]) + for _, c := range line { + _, err = ctx.Buf.WriteString(string(c)) + if err != nil { + return err + } + ctx.lineLength++ + if c == '\n' { + ctx.lineLength = 0 + if ctx.prefix != "" { + _, err = ctx.Buf.WriteString(ctx.prefix) + if err != nil { + return err + } + } + } + } + } + return nil +} + +func (ctx *textifyTraverseCtx) breakLongLines(data string) []string { + // only break lines when we are in blockquotes + if ctx.blockquoteLevel == 0 { + return []string{data} + } + var ret []string + runes := []rune(data) + l := len(runes) + existing := ctx.lineLength + if existing >= 74 { + ret = append(ret, "\n") + existing = 0 + } + for l+existing > 74 { + i := 74 - existing + for i >= 0 && !unicode.IsSpace(runes[i]) { + i-- + } + if i == -1 { + // no spaces, so go the other way + i = 74 - 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 *textifyTraverseCtx) normalizeHrefLink(link string) string { + link = strings.TrimSpace(link) + link = strings.TrimPrefix(link, "mailto:") + return link +} + +func getAttrVal(node *html.Node, attrName string) string { + for _, attr := range node.Attr { + if attr.Key == attrName { + return attr.Val + } + } + + return "" +} + +func FromReader(reader io.Reader) (string, error) { + doc, err := html.Parse(reader) + if err != nil { + return "", err + } + + ctx := textifyTraverseCtx{ + Buf: bytes.Buffer{}, + } + 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 +} + +func FromString(input string) (string, error) { + text, err := FromReader(strings.NewReader(input)) + if err != nil { + return "", err + } + return text, nil +} |