From 795a8705c3fdc5bf55e83d382e7d3ff233896a0b Mon Sep 17 00:00:00 2001
From: Wim <wim@42.be>
Date: Thu, 26 Dec 2019 23:12:28 +0100
Subject: Add initial Microsoft Teams support

Documentation on https://github.com/42wim/matterbridge/wiki/MS-Teams-setup
---
 vendor/github.com/mattn/godown/.gitignore  |   2 +
 vendor/github.com/mattn/godown/.travis.yml |  14 ++
 vendor/github.com/mattn/godown/LICENSE     |  21 ++
 vendor/github.com/mattn/godown/README.md   |  42 ++++
 vendor/github.com/mattn/godown/godown.go   | 372 +++++++++++++++++++++++++++++
 5 files changed, 451 insertions(+)
 create mode 100644 vendor/github.com/mattn/godown/.gitignore
 create mode 100644 vendor/github.com/mattn/godown/.travis.yml
 create mode 100644 vendor/github.com/mattn/godown/LICENSE
 create mode 100644 vendor/github.com/mattn/godown/README.md
 create mode 100644 vendor/github.com/mattn/godown/godown.go

(limited to 'vendor/github.com/mattn/godown')

diff --git a/vendor/github.com/mattn/godown/.gitignore b/vendor/github.com/mattn/godown/.gitignore
new file mode 100644
index 00000000..2c77a177
--- /dev/null
+++ b/vendor/github.com/mattn/godown/.gitignore
@@ -0,0 +1,2 @@
+*.swp
+godown
diff --git a/vendor/github.com/mattn/godown/.travis.yml b/vendor/github.com/mattn/godown/.travis.yml
new file mode 100644
index 00000000..4a9344d1
--- /dev/null
+++ b/vendor/github.com/mattn/godown/.travis.yml
@@ -0,0 +1,14 @@
+language: go
+
+go:
+  - 1.8
+  - 1.9.3
+
+env:
+  secure: "sssm68fvzltcAnFd0Vc+OJV0eOicaTUO4I/CRX9LsnqzSsiNmaFT5o1O0Mx622ApYxCfiG3G53B8wuPzSMQxdPaSiMqzoXNLjD8gURaZBWTXc+kj9WFUoS4KW5L8KF3zrmS1u6Ja9U/elIpNqbpuwqT7sZUUJJM1JR50uEVmtP9oc/iqTKh3JK1HZCkb/PDVKs7xY5AEOhx1x0QOn9SegMUK2b83WeuSbta3Z6Rp4EW3p3WwI1WHZmm8+IYjvbwu18foQSetfro+pXCyDBpw1zLbBTDR8W02VwkH2vECMm4N7GYPmHWNx2lZFqoFp9zY5zCRUQG9KmxqbappalBCsT1ZyesUt7Wp/qYw5W+1Np7/vQhe8eeyyKMzsS7FBq8Imn4JiBPbj/1KAhVoZZKyv0qU4hgxHPZMC/JtVoTkIH3IXvTE88P92z9pFL30afQ692BXPe+XmCBph4zBdH88vksdiky9DWuXJ+O0rDCcLes45ij/wk6psdTPx3IXuMohfkO81F0pveksBYFkff8dXXxCABUzZbPaawEDnLAQKJ1m+oF3UYhPzVwrelNjFDOUq3mxsTU36uyhB9fb8sJ+BmorTD9AvqNvobcwKlQ6TaVJEhHjDJRxho82OG2gof9UbsJF3+6IM8uuUVy3TP7b1o+t8PQ3iNKTB4RUzGjJCOs="
+
+script:
+  go test -v -race -coverprofile=coverage.txt -covermode=atomic
+
+after_success:
+  - bash <(curl -s https://codecov.io/bash)
diff --git a/vendor/github.com/mattn/godown/LICENSE b/vendor/github.com/mattn/godown/LICENSE
new file mode 100644
index 00000000..e364750d
--- /dev/null
+++ b/vendor/github.com/mattn/godown/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2018 Yasuhiro Matsumoto
+
+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/mattn/godown/README.md b/vendor/github.com/mattn/godown/README.md
new file mode 100644
index 00000000..a94f4157
--- /dev/null
+++ b/vendor/github.com/mattn/godown/README.md
@@ -0,0 +1,42 @@
+# godown
+
+[![Build Status](https://travis-ci.org/mattn/godown.png?branch=master)](https://travis-ci.org/mattn/godown)
+[![Codecov](https://codecov.io/gh/mattn/godown/branch/master/graph/badge.svg)](https://codecov.io/gh/mattn/godown)
+[![GoDoc](https://godoc.org/github.com/mattn/godown?status.svg)](http://godoc.org/github.com/mattn/godown)
+[![Go Report Card](https://goreportcard.com/badge/github.com/mattn/godown)](https://goreportcard.com/report/github.com/mattn/godown)
+
+Convert HTML into Markdown
+
+This is work in progress.
+
+## Usage
+
+```
+err := godown.Convert(w, r)
+checkError(err)
+```
+
+
+## Command Line
+
+```
+$ godown < index.html > index.md
+```
+
+## Installation
+
+```
+$ go get github.com/mattn/godown/cmd/godown
+```
+
+## TODO
+
+* escape strings in HTML
+
+## License
+
+MIT
+
+## Author
+
+Yasuhiro Matsumoto (a.k.a. mattn)
diff --git a/vendor/github.com/mattn/godown/godown.go b/vendor/github.com/mattn/godown/godown.go
new file mode 100644
index 00000000..10423be9
--- /dev/null
+++ b/vendor/github.com/mattn/godown/godown.go
@@ -0,0 +1,372 @@
+package godown
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"regexp"
+	"strings"
+
+	"github.com/mattn/go-runewidth"
+
+	"golang.org/x/net/html"
+)
+
+func isChildOf(node *html.Node, name string) bool {
+	node = node.Parent
+	return node != nil && node.Type == html.ElementNode && strings.ToLower(node.Data) == name
+}
+
+func hasClass(node *html.Node, clazz string) bool {
+	for _, attr := range node.Attr {
+		if attr.Key == "class" {
+			for _, c := range strings.Fields(attr.Val) {
+				if c == clazz {
+					return true
+				}
+			}
+		}
+	}
+	return false
+}
+
+func attr(node *html.Node, key string) string {
+	for _, attr := range node.Attr {
+		if attr.Key == key {
+			return attr.Val
+		}
+	}
+	return ""
+}
+
+func br(node *html.Node, w io.Writer, option *Option) {
+	node = node.PrevSibling
+	if node == nil {
+		return
+	}
+	switch node.Type {
+	case html.TextNode:
+		text := strings.Trim(node.Data, " \t")
+		if text != "" && !strings.HasSuffix(text, "\n") {
+			fmt.Fprint(w, "\n")
+		}
+	case html.ElementNode:
+		switch strings.ToLower(node.Data) {
+		case "br", "p", "ul", "ol", "div", "blockquote", "h1", "h2", "h3", "h4", "h5", "h6":
+			fmt.Fprint(w, "\n")
+		}
+	}
+}
+
+func table(node *html.Node, w io.Writer, option *Option) {
+	for tr := node.FirstChild; tr != nil; tr = tr.NextSibling {
+		if tr.Type == html.ElementNode && strings.ToLower(tr.Data) == "tbody" {
+			node = tr
+			break
+		}
+	}
+	var header bool
+	var rows [][]string
+	for tr := node.FirstChild; tr != nil; tr = tr.NextSibling {
+		if tr.Type != html.ElementNode || strings.ToLower(tr.Data) != "tr" {
+			continue
+		}
+		var cols []string
+		if !header {
+			for th := tr.FirstChild; th != nil; th = th.NextSibling {
+				if th.Type != html.ElementNode || strings.ToLower(th.Data) != "th" {
+					continue
+				}
+				var buf bytes.Buffer
+				walk(th, &buf, 0, option)
+				cols = append(cols, buf.String())
+			}
+			if len(cols) > 0 {
+				rows = append(rows, cols)
+				header = true
+				continue
+			}
+		}
+		for td := tr.FirstChild; td != nil; td = td.NextSibling {
+			if td.Type != html.ElementNode || strings.ToLower(td.Data) != "td" {
+				continue
+			}
+			var buf bytes.Buffer
+			walk(td, &buf, 0, option)
+			cols = append(cols, buf.String())
+		}
+		rows = append(rows, cols)
+	}
+	maxcol := 0
+	for _, cols := range rows {
+		if len(cols) > maxcol {
+			maxcol = len(cols)
+		}
+	}
+	widths := make([]int, maxcol)
+	for _, cols := range rows {
+		for i := 0; i < maxcol; i++ {
+			if i < len(cols) {
+				width := runewidth.StringWidth(cols[i])
+				if widths[i] < width {
+					widths[i] = width
+				}
+			}
+		}
+	}
+	for i, cols := range rows {
+		for j := 0; j < maxcol; j++ {
+			fmt.Fprint(w, "|")
+			if j < len(cols) {
+				width := runewidth.StringWidth(cols[j])
+				fmt.Fprint(w, cols[j])
+				fmt.Fprint(w, strings.Repeat(" ", widths[j]-width))
+			} else {
+				fmt.Fprint(w, strings.Repeat(" ", widths[j]))
+			}
+		}
+		fmt.Fprint(w, "|\n")
+		if i == 0 && header {
+			for j := 0; j < maxcol; j++ {
+				fmt.Fprint(w, "|")
+				fmt.Fprint(w, strings.Repeat("-", widths[j]))
+			}
+			fmt.Fprint(w, "|\n")
+		}
+	}
+	fmt.Fprint(w, "\n")
+}
+
+var emptyElements = []string{
+	"area",
+	"base",
+	"br",
+	"col",
+	"embed",
+	"hr",
+	"img",
+	"input",
+	"keygen",
+	"link",
+	"meta",
+	"param",
+	"source",
+	"track",
+	"wbr",
+}
+
+func raw(node *html.Node, w io.Writer, option *Option) {
+	switch node.Type {
+	case html.ElementNode:
+		fmt.Fprintf(w, "<%s", node.Data)
+		for _, attr := range node.Attr {
+			fmt.Fprintf(w, " %s=%q", attr.Key, attr.Val)
+		}
+		found := false
+		tag := strings.ToLower(node.Data)
+		for _, e := range emptyElements {
+			if e == tag {
+				found = true
+				break
+			}
+		}
+		if found {
+			fmt.Fprint(w, "/>")
+		} else {
+			fmt.Fprint(w, ">")
+			for c := node.FirstChild; c != nil; c = c.NextSibling {
+				raw(c, w, option)
+			}
+			fmt.Fprintf(w, "</%s>", node.Data)
+		}
+	case html.TextNode:
+		fmt.Fprint(w, node.Data)
+	}
+}
+
+func bq(node *html.Node, w io.Writer, option *Option) {
+	if node.Type == html.TextNode {
+		fmt.Fprint(w, strings.Replace(node.Data, "\u00a0", " ", -1))
+	} else {
+		for c := node.FirstChild; c != nil; c = c.NextSibling {
+			bq(c, w, option)
+		}
+	}
+}
+
+func pre(node *html.Node, w io.Writer, option *Option) {
+	if node.Type == html.TextNode {
+		fmt.Fprint(w, node.Data)
+	} else {
+		for c := node.FirstChild; c != nil; c = c.NextSibling {
+			pre(c, w, option)
+		}
+	}
+}
+
+func walk(node *html.Node, w io.Writer, nest int, option *Option) {
+	if node.Type == html.TextNode {
+		if strings.TrimSpace(node.Data) != "" {
+			text := regexp.MustCompile(`[[:space:]][[:space:]]*`).ReplaceAllString(strings.Trim(node.Data, "\t\r\n"), " ")
+			fmt.Fprint(w, text)
+		}
+	}
+	n := 0
+	for c := node.FirstChild; c != nil; c = c.NextSibling {
+		switch c.Type {
+		case html.CommentNode:
+			fmt.Fprint(w, "<!--")
+			fmt.Fprint(w, c.Data)
+			fmt.Fprint(w, "-->\n")
+		case html.ElementNode:
+			switch strings.ToLower(c.Data) {
+			case "a":
+				fmt.Fprint(w, "[")
+				walk(c, w, nest, option)
+				fmt.Fprint(w, "]("+attr(c, "href")+")")
+			case "b", "strong":
+				fmt.Fprint(w, "**")
+				walk(c, w, nest, option)
+				fmt.Fprint(w, "**")
+			case "i", "em":
+				fmt.Fprint(w, "_")
+				walk(c, w, nest, option)
+				fmt.Fprint(w, "_")
+			case "del":
+				fmt.Fprint(w, "~~")
+				walk(c, w, nest, option)
+				fmt.Fprint(w, "~~")
+			case "br":
+				br(c, w, option)
+				fmt.Fprint(w, "\n\n")
+			case "p":
+				br(c, w, option)
+				walk(c, w, nest, option)
+				br(c, w, option)
+				fmt.Fprint(w, "\n\n")
+			case "code":
+				if !isChildOf(c, "pre") {
+					fmt.Fprint(w, "`")
+					pre(c, w, option)
+					fmt.Fprint(w, "`")
+				}
+			case "pre":
+				br(c, w, option)
+				var buf bytes.Buffer
+				pre(c, &buf, option)
+				var lang string
+				if option != nil && option.GuessLang != nil {
+					if guess, err := option.GuessLang(buf.String()); err == nil {
+						lang = guess
+					}
+				}
+				fmt.Fprint(w, "```"+lang+"\n")
+				fmt.Fprint(w, buf.String())
+				if !strings.HasSuffix(buf.String(), "\n") {
+					fmt.Fprint(w, "\n")
+				}
+				fmt.Fprint(w, "```\n\n")
+			case "div":
+				br(c, w, option)
+				walk(c, w, nest, option)
+				fmt.Fprint(w, "\n")
+			case "blockquote":
+				br(c, w, option)
+				var buf bytes.Buffer
+				if hasClass(c, "code") {
+					bq(c, &buf, option)
+					var lang string
+					if option != nil && option.GuessLang != nil {
+						if guess, err := option.GuessLang(buf.String()); err == nil {
+							lang = guess
+						}
+					}
+					fmt.Fprint(w, "```"+lang+"\n")
+					fmt.Fprint(w, strings.TrimLeft(buf.String(), "\n"))
+					if !strings.HasSuffix(buf.String(), "\n") {
+						fmt.Fprint(w, "\n")
+					}
+					fmt.Fprint(w, "```\n\n")
+				} else {
+					walk(c, &buf, nest+1, option)
+
+					if lines := strings.Split(strings.TrimSpace(buf.String()), "\n"); len(lines) > 0 {
+						for _, l := range lines {
+							fmt.Fprint(w, "> "+strings.TrimSpace(l)+"\n")
+						}
+						fmt.Fprint(w, "\n")
+					}
+				}
+			case "ul", "ol":
+				br(c, w, option)
+				var buf bytes.Buffer
+				walk(c, &buf, 1, option)
+				if lines := strings.Split(strings.TrimSpace(buf.String()), "\n"); len(lines) > 0 {
+					for i, l := range lines {
+						if i > 0 || nest > 0 {
+							fmt.Fprint(w, "\n")
+						}
+						fmt.Fprint(w, strings.Repeat("    ", nest)+strings.TrimSpace(l))
+					}
+					fmt.Fprint(w, "\n")
+				}
+			case "li":
+				br(c, w, option)
+				if isChildOf(c, "ul") {
+					fmt.Fprint(w, "* ")
+				} else if isChildOf(c, "ol") {
+					n++
+					fmt.Fprint(w, fmt.Sprintf("%d. ", n))
+				}
+				walk(c, w, nest, option)
+				fmt.Fprint(w, "\n")
+			case "h1", "h2", "h3", "h4", "h5", "h6":
+				br(c, w, option)
+				fmt.Fprint(w, strings.Repeat("#", int(rune(c.Data[1])-rune('0')))+" ")
+				walk(c, w, nest, option)
+				fmt.Fprint(w, "\n\n")
+			case "img":
+				fmt.Fprint(w, "!["+attr(c, "alt")+"]("+attr(c, "src")+")")
+			case "hr":
+				br(c, w, option)
+				fmt.Fprint(w, "\n---\n\n")
+			case "table":
+				br(c, w, option)
+				table(c, w, option)
+			case "style":
+				if option != nil && option.Style {
+					br(c, w, option)
+					raw(c, w, option)
+					fmt.Fprint(w, "\n\n")
+				}
+			case "script":
+				if option != nil && option.Script {
+					br(c, w, option)
+					raw(c, w, option)
+					fmt.Fprint(w, "\n\n")
+				}
+			default:
+				walk(c, w, nest, option)
+			}
+		default:
+			walk(c, w, nest, option)
+		}
+	}
+}
+
+type Option struct {
+	GuessLang func(string) (string, error)
+	Script    bool
+	Style     bool
+}
+
+// Convert convert HTML to Markdown. Read HTML from r and write to w.
+func Convert(w io.Writer, r io.Reader, option *Option) error {
+	doc, err := html.Parse(r)
+	if err != nil {
+		return err
+	}
+	walk(doc, w, 0, option)
+	fmt.Fprint(w, "\n")
+	return nil
+}
-- 
cgit v1.2.3