Compare commits
15 Commits
v1.14.0-rc
...
v1.14.0-rc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b0bc51183 | ||
|
|
53aa076555 | ||
|
|
f57370f33a | ||
|
|
c557d51b6f | ||
|
|
df3fdc26a0 | ||
|
|
af00c34aac | ||
|
|
120bf39f55 | ||
|
|
26a7e35f27 | ||
|
|
d44d2a5f00 | ||
|
|
7f1d86b338 | ||
|
|
d8816280f0 | ||
|
|
b09a73040f | ||
|
|
740b5f2602 | ||
|
|
96841c70c7 | ||
|
|
f92735d35d |
34
.goreleaser.yml
Normal file
34
.goreleaser.yml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
release:
|
||||||
|
prerelease: auto
|
||||||
|
name_template: "{{.ProjectName}} v{{.Version}}"
|
||||||
|
|
||||||
|
builds:
|
||||||
|
- env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
goos:
|
||||||
|
- freebsd
|
||||||
|
- windows
|
||||||
|
- darwin
|
||||||
|
- linux
|
||||||
|
- dragonfly
|
||||||
|
- netbsd
|
||||||
|
- openbsd
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
- arm
|
||||||
|
- arm64
|
||||||
|
- 386
|
||||||
|
ldflags:
|
||||||
|
- -s -w -X main.githash={{.ShortCommit}}
|
||||||
|
|
||||||
|
archive:
|
||||||
|
name_template: "{{ .Binary }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
|
||||||
|
format: binary
|
||||||
|
files:
|
||||||
|
- none*
|
||||||
|
replacements:
|
||||||
|
386: 32bit
|
||||||
|
amd64: 64bit
|
||||||
|
|
||||||
|
checksum:
|
||||||
|
name_template: 'checksums.txt'
|
||||||
@@ -48,10 +48,16 @@ after_script:
|
|||||||
- ./cc-test-reporter after-build --exit-code ${TRAVIS_TEST_RESULT}
|
- ./cc-test-reporter after-build --exit-code ${TRAVIS_TEST_RESULT}
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
|
on:
|
||||||
|
all_branches: true
|
||||||
provider: bintray
|
provider: bintray
|
||||||
|
on:
|
||||||
|
all_branches: true
|
||||||
edge:
|
edge:
|
||||||
branch: v1.8.47
|
branch: v1.8.47
|
||||||
file: ci/deploy.json
|
file: ci/deploy.json
|
||||||
user: 42wim
|
user: 42wim
|
||||||
|
on:
|
||||||
|
all_branches: true
|
||||||
key:
|
key:
|
||||||
secure: "CeXXe6JOmt7HYR81MdWLua0ltQHhDdkIeRGBFbgd7hkb1wi8eF9DgpAcQrTso8NIlHNZmSAP46uhFgsRvkuezzX0ygalZ7DCJyAyn3sAMEh+UQSHV1WGThRehTtidqRGjetzsIGSwdrJOWil+XTfbO1Z8DGzfakhSuAZka8CM4BAoe3YeP9rYK8h+84x0GHfczvsLtXZ3mWLvQuwe4pK6+ItBCUg0ae7O7ZUpWHy0xQQkkWztY/6RAzXfaG7DuGjIw+20fhx3WOXRNpHCtZ6Bc3qERCpk0s1HhlQWlrN9wDaFTBWYwlvSnNgvxxMbNXJ6RrRJ0l0bA7FUswYwyroxhzrGLdzWDg8dHaQkypocngdalfhpsnoO9j3ApJhomUFJ3UoEq5nOGRUrKn8MPi+dP0zE4kNQ3e4VNa1ufNrvfpWolMg3xh8OXuhQdD5wIM5zFAbRJLqWSCVAjPq4DDPecmvXBOlIial7oa312lN5qnBnUjvAcxszZ+FUyDHT1Grxzna4tMwxY9obPzZUzm7359AOCCwIQFVB8GLqD2nwIstcXS0zGRz+fhviPipHuBa02q5bGUZwmkvrSNab0s8Jo7pCrel2Rz3nWPKaiCfq2WjbW1CLheSMkOQrjsdUd1hhbqNWFPUjJPInTc77NAKCfm5runv5uyowRLh4NNd0sI="
|
secure: "CeXXe6JOmt7HYR81MdWLua0ltQHhDdkIeRGBFbgd7hkb1wi8eF9DgpAcQrTso8NIlHNZmSAP46uhFgsRvkuezzX0ygalZ7DCJyAyn3sAMEh+UQSHV1WGThRehTtidqRGjetzsIGSwdrJOWil+XTfbO1Z8DGzfakhSuAZka8CM4BAoe3YeP9rYK8h+84x0GHfczvsLtXZ3mWLvQuwe4pK6+ItBCUg0ae7O7ZUpWHy0xQQkkWztY/6RAzXfaG7DuGjIw+20fhx3WOXRNpHCtZ6Bc3qERCpk0s1HhlQWlrN9wDaFTBWYwlvSnNgvxxMbNXJ6RrRJ0l0bA7FUswYwyroxhzrGLdzWDg8dHaQkypocngdalfhpsnoO9j3ApJhomUFJ3UoEq5nOGRUrKn8MPi+dP0zE4kNQ3e4VNa1ufNrvfpWolMg3xh8OXuhQdD5wIM5zFAbRJLqWSCVAjPq4DDPecmvXBOlIial7oa312lN5qnBnUjvAcxszZ+FUyDHT1Grxzna4tMwxY9obPzZUzm7359AOCCwIQFVB8GLqD2nwIstcXS0zGRz+fhviPipHuBa02q5bGUZwmkvrSNab0s8Jo7pCrel2Rz3nWPKaiCfq2WjbW1CLheSMkOQrjsdUd1hhbqNWFPUjJPInTc77NAKCfm5runv5uyowRLh4NNd0sI="
|
||||||
|
|||||||
@@ -237,10 +237,6 @@ See [changelog.md](https://github.com/42wim/matterbridge/blob/master/changelog.m
|
|||||||
|
|
||||||
See [FAQ](https://github.com/42wim/matterbridge/wiki/FAQ)
|
See [FAQ](https://github.com/42wim/matterbridge/wiki/FAQ)
|
||||||
|
|
||||||
Want to tip ?
|
|
||||||
* eth: 0xb3f9b5387c66ad6be892bcb7bbc67862f3abc16f
|
|
||||||
* btc: 1N7cKHj5SfqBHBzDJ6kad4BzeqUBBS2zhs
|
|
||||||
|
|
||||||
## Related projects
|
## Related projects
|
||||||
* [FOSSRIT/infrastructure - roles/matterbridge](https://github.com/FOSSRIT/infrastructure/tree/master/roles/matterbridge) (Ansible role used to automate deployments of Matterbridge)
|
* [FOSSRIT/infrastructure - roles/matterbridge](https://github.com/FOSSRIT/infrastructure/tree/master/roles/matterbridge) (Ansible role used to automate deployments of Matterbridge)
|
||||||
* [matterbridge autoconfig](https://github.com/patcon/matterbridge-autoconfig)
|
* [matterbridge autoconfig](https://github.com/patcon/matterbridge-autoconfig)
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ type Protocol struct {
|
|||||||
MediaDownloadSize int // all protocols
|
MediaDownloadSize int // all protocols
|
||||||
MediaServerDownload string
|
MediaServerDownload string
|
||||||
MediaServerUpload string
|
MediaServerUpload string
|
||||||
|
MediaConvertWebPToPNG bool // telegram
|
||||||
MessageDelay int // IRC, time in millisecond to wait between messages
|
MessageDelay int // IRC, time in millisecond to wait between messages
|
||||||
MessageFormat string // telegram
|
MessageFormat string // telegram
|
||||||
MessageLength int // IRC, max length of a message allowed
|
MessageLength int // IRC, max length of a message allowed
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ func (b *Bdiscord) Send(msg config.Message) (string, error) {
|
|||||||
b.Log.Debugf("Setting webhook channel to \"%s\"", msg.Channel)
|
b.Log.Debugf("Setting webhook channel to \"%s\"", msg.Channel)
|
||||||
_, err := b.c.WebhookEdit(wID, "", "", channelID)
|
_, err := b.c.WebhookEdit(wID, "", "", channelID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Log.Errorf("Could not set webhook channel: %v", err)
|
b.Log.Errorf("Could not set webhook channel: %s", err)
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -278,7 +278,7 @@ func (b *Bdiscord) Send(msg config.Message) (string, error) {
|
|||||||
for _, rmsg := range helper.HandleExtra(&msg, b.General) {
|
for _, rmsg := range helper.HandleExtra(&msg, b.General) {
|
||||||
rmsg.Text = helper.ClipMessage(rmsg.Text, MessageLength)
|
rmsg.Text = helper.ClipMessage(rmsg.Text, MessageLength)
|
||||||
if _, err := b.c.ChannelMessageSend(channelID, rmsg.Username+rmsg.Text); err != nil {
|
if _, err := b.c.ChannelMessageSend(channelID, rmsg.Username+rmsg.Text); err != nil {
|
||||||
b.Log.Errorf("Could not send message %#v: %v", rmsg, err)
|
b.Log.Errorf("Could not send message %#v: %s", rmsg, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// check if we have files to upload (from slack, telegram or mattermost)
|
// check if we have files to upload (from slack, telegram or mattermost)
|
||||||
@@ -360,7 +360,7 @@ func (b *Bdiscord) handleUploadFile(msg *config.Message, channelID string) (stri
|
|||||||
}
|
}
|
||||||
_, err = b.c.ChannelMessageSendComplex(channelID, &m)
|
_, err = b.c.ChannelMessageSendComplex(channelID, &m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("file upload failed: %#v", err)
|
return "", fmt.Errorf("file upload failed: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "", nil
|
return "", nil
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ func (b *Bdiscord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreat
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// if using webhooks, do not relay if it's ours
|
// if using webhooks, do not relay if it's ours
|
||||||
if b.useWebhook() && m.Author.Bot && b.isWebhookID(m.Author.ID) {
|
if b.useWebhook() && m.Author.Bot { // && b.isWebhookID(m.Author.ID) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ func (b *Bdiscord) getNick(user *discordgo.User) string {
|
|||||||
// If we didn't find nick, search for it.
|
// If we didn't find nick, search for it.
|
||||||
member, err := b.c.GuildMember(b.guildID, user.ID)
|
member, err := b.c.GuildMember(b.guildID, user.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Log.Warnf("Failed to fetch information for member %#v: %#v", user, err)
|
b.Log.Warnf("Failed to fetch information for member %#v: %s", user, err)
|
||||||
return user.Username
|
return user.Username
|
||||||
} else if member == nil {
|
} else if member == nil {
|
||||||
b.Log.Warnf("Got no information for member %#v", user)
|
b.Log.Warnf("Got no information for member %#v", user)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package helper
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"image/png"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
@@ -10,6 +11,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"golang.org/x/image/webp"
|
||||||
|
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"gitlab.com/golang-commonmark/markdown"
|
"gitlab.com/golang-commonmark/markdown"
|
||||||
@@ -177,3 +180,19 @@ func ParseMarkdown(input string) string {
|
|||||||
md := markdown.New(markdown.XHTMLOutput(true), markdown.Breaks(true))
|
md := markdown.New(markdown.XHTMLOutput(true), markdown.Breaks(true))
|
||||||
return (md.RenderToString([]byte(input)))
|
return (md.RenderToString([]byte(input)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConvertWebPToPNG convert input data (which should be WebP format to PNG format)
|
||||||
|
func ConvertWebPToPNG(data *[]byte) error {
|
||||||
|
r := bytes.NewReader(*data)
|
||||||
|
m, err := webp.Decode(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var output []byte
|
||||||
|
w := bytes.NewBuffer(output)
|
||||||
|
if err := png.Encode(w, m); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*data = w.Bytes()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package helper
|
package helper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -103,3 +105,22 @@ func TestGetSubLines(t *testing.T) {
|
|||||||
assert.Equalf(t, testcase.nonSplitOutput, nonSplitLines, "'%s' testcase should give expected lines without splitting.", testname)
|
assert.Equalf(t, testcase.nonSplitOutput, nonSplitLines, "'%s' testcase should give expected lines without splitting.", testname)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConvertWebPToPNG(t *testing.T) {
|
||||||
|
if os.Getenv("LOCAL_TEST") == "" {
|
||||||
|
t.Skip()
|
||||||
|
}
|
||||||
|
input, err := ioutil.ReadFile("test.webp")
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
d := &input
|
||||||
|
err = ConvertWebPToPNG(d)
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile("test.png", *d, 0644)
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -40,6 +40,11 @@ func (b *Brocketchat) handleRocketHook(messages chan *config.Message) {
|
|||||||
|
|
||||||
func (b *Brocketchat) handleRocketClient(messages chan *config.Message) {
|
func (b *Brocketchat) handleRocketClient(messages chan *config.Message) {
|
||||||
for message := range b.messageChan {
|
for message := range b.messageChan {
|
||||||
|
// skip messages with same ID, apparently messages get duplicated for an unknown reason
|
||||||
|
if _, ok := b.cache.Get(message.ID); ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
b.cache.Add(message.ID, true)
|
||||||
b.Log.Debugf("message %#v", message)
|
b.Log.Debugf("message %#v", message)
|
||||||
m := message
|
m := message
|
||||||
if b.skipMessage(&m) {
|
if b.skipMessage(&m) {
|
||||||
|
|||||||
@@ -9,16 +9,18 @@ import (
|
|||||||
"github.com/42wim/matterbridge/bridge/helper"
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
"github.com/42wim/matterbridge/hook/rockethook"
|
"github.com/42wim/matterbridge/hook/rockethook"
|
||||||
"github.com/42wim/matterbridge/matterhook"
|
"github.com/42wim/matterbridge/matterhook"
|
||||||
|
lru "github.com/hashicorp/golang-lru"
|
||||||
"github.com/matterbridge/Rocket.Chat.Go.SDK/models"
|
"github.com/matterbridge/Rocket.Chat.Go.SDK/models"
|
||||||
"github.com/matterbridge/Rocket.Chat.Go.SDK/realtime"
|
"github.com/matterbridge/Rocket.Chat.Go.SDK/realtime"
|
||||||
"github.com/matterbridge/Rocket.Chat.Go.SDK/rest"
|
"github.com/matterbridge/Rocket.Chat.Go.SDK/rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Brocketchat struct {
|
type Brocketchat struct {
|
||||||
mh *matterhook.Client
|
mh *matterhook.Client
|
||||||
rh *rockethook.Client
|
rh *rockethook.Client
|
||||||
c *realtime.Client
|
c *realtime.Client
|
||||||
r *rest.Client
|
r *rest.Client
|
||||||
|
cache *lru.Cache
|
||||||
*bridge.Config
|
*bridge.Config
|
||||||
messageChan chan models.Message
|
messageChan chan models.Message
|
||||||
channelMap map[string]string
|
channelMap map[string]string
|
||||||
@@ -27,9 +29,16 @@ type Brocketchat struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func New(cfg *bridge.Config) bridge.Bridger {
|
func New(cfg *bridge.Config) bridge.Bridger {
|
||||||
b := &Brocketchat{Config: cfg}
|
newCache, err := lru.New(100)
|
||||||
b.messageChan = make(chan models.Message)
|
if err != nil {
|
||||||
b.channelMap = make(map[string]string)
|
cfg.Log.Fatalf("Could not create LRU cache for rocketchat bridge: %v", err)
|
||||||
|
}
|
||||||
|
b := &Brocketchat{
|
||||||
|
Config: cfg,
|
||||||
|
messageChan: make(chan models.Message),
|
||||||
|
channelMap: make(map[string]string),
|
||||||
|
cache: newCache,
|
||||||
|
}
|
||||||
b.Log.Debugf("enabling rocketchat")
|
b.Log.Debugf("enabling rocketchat")
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,6 +144,9 @@ func (b *Btelegram) handleRecv(updates <-chan tgbotapi.Update) {
|
|||||||
// quote the previous message
|
// quote the previous message
|
||||||
b.handleQuoting(&rmsg, message)
|
b.handleQuoting(&rmsg, message)
|
||||||
|
|
||||||
|
// handle entities (adding URLs)
|
||||||
|
b.handleEntities(&rmsg, message)
|
||||||
|
|
||||||
if rmsg.Text != "" || len(rmsg.Extra) > 0 {
|
if rmsg.Text != "" || len(rmsg.Extra) > 0 {
|
||||||
rmsg.Text = helper.RemoveEmptyNewLines(rmsg.Text)
|
rmsg.Text = helper.RemoveEmptyNewLines(rmsg.Text)
|
||||||
// channels don't have (always?) user information. see #410
|
// channels don't have (always?) user information. see #410
|
||||||
@@ -245,6 +248,15 @@ func (b *Btelegram) handleDownload(rmsg *config.Message, message *tgbotapi.Messa
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if strings.HasSuffix(name, ".webp") && b.GetBool("MediaConvertWebPToPNG") {
|
||||||
|
b.Log.Debugf("WebP to PNG conversion enabled, converting %s", name)
|
||||||
|
err := helper.ConvertWebPToPNG(data)
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Errorf("conversion failed: %s", err)
|
||||||
|
} else {
|
||||||
|
name = strings.Replace(name, ".webp", ".png", 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
helper.HandleDownloadData(b.Log, rmsg, name, message.Caption, "", data, b.General)
|
helper.HandleDownloadData(b.Log, rmsg, name, message.Caption, "", data, b.General)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -344,3 +356,22 @@ func (b *Btelegram) handleQuote(message, quoteNick, quoteMessage string) string
|
|||||||
format = strings.Replace(format, "{QUOTEMESSAGE}", quoteMessage, -1)
|
format = strings.Replace(format, "{QUOTEMESSAGE}", quoteMessage, -1)
|
||||||
return format
|
return format
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handleEntities handles messageEntities
|
||||||
|
func (b *Btelegram) handleEntities(rmsg *config.Message, message *tgbotapi.Message) {
|
||||||
|
if message.Entities == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// for now only do URL replacements
|
||||||
|
for _, e := range *message.Entities {
|
||||||
|
if e.Type == "text_link" {
|
||||||
|
url, err := e.ParseURL()
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Errorf("entity text_link url parse failed: %s", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
link := rmsg.Text[e.Offset : e.Offset+e.Length]
|
||||||
|
rmsg.Text = strings.Replace(rmsg.Text, link, url.String(), 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package btelegram
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"html"
|
"html"
|
||||||
"io"
|
|
||||||
|
|
||||||
"github.com/russross/blackfriday"
|
"github.com/russross/blackfriday"
|
||||||
)
|
)
|
||||||
@@ -33,7 +32,7 @@ func (options *customHTML) Header(out *bytes.Buffer, text func() bool, level int
|
|||||||
options.Paragraph(out, text)
|
options.Paragraph(out, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (options *customHTML) HRule(out io.ByteWriter) {
|
func (options *customHTML) HRule(out *bytes.Buffer) {
|
||||||
out.WriteByte('\n') //nolint:errcheck
|
out.WriteByte('\n') //nolint:errcheck
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,16 +53,13 @@ func (options *customHTML) ListItem(out *bytes.Buffer, text []byte, flags int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func makeHTML(input string) string {
|
func makeHTML(input string) string {
|
||||||
extensions := blackfriday.NoIntraEmphasis |
|
return string(blackfriday.Markdown([]byte(input),
|
||||||
blackfriday.FencedCode |
|
&customHTML{blackfriday.HtmlRenderer(blackfriday.HTML_USE_XHTML|blackfriday.HTML_SKIP_IMAGES, "", "")},
|
||||||
blackfriday.Autolink |
|
blackfriday.EXTENSION_NO_INTRA_EMPHASIS|
|
||||||
blackfriday.SpaceHeadings |
|
blackfriday.EXTENSION_FENCED_CODE|
|
||||||
blackfriday.HeadingIDs |
|
blackfriday.EXTENSION_AUTOLINK|
|
||||||
blackfriday.BackslashLineBreak |
|
blackfriday.EXTENSION_SPACE_HEADERS|
|
||||||
blackfriday.DefinitionLists
|
blackfriday.EXTENSION_HEADER_IDS|
|
||||||
|
blackfriday.EXTENSION_BACKSLASH_LINE_BREAK|
|
||||||
renderer := &customHTML{blackfriday.NewHTMLRenderer(blackfriday.HTMLRendererParameters{
|
blackfriday.EXTENSION_DEFINITION_LISTS))
|
||||||
Flags: blackfriday.UseXHTML | blackfriday.SkipImages,
|
|
||||||
})}
|
|
||||||
return string(blackfriday.Run([]byte(input), blackfriday.WithExtensions(extensions), blackfriday.WithRenderer(renderer)))
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ import (
|
|||||||
|
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
|
||||||
"github.com/Rhymen/go-whatsapp"
|
"github.com/matterbridge/go-whatsapp"
|
||||||
|
|
||||||
whatsappExt "maunium.net/go/mautrix-whatsapp/whatsapp-ext"
|
whatsappExt "github.com/matterbridge/mautrix-whatsapp/whatsapp-ext"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
qrcodeTerminal "github.com/Baozisoftware/qrcode-terminal-go"
|
qrcodeTerminal "github.com/Baozisoftware/qrcode-terminal-go"
|
||||||
"github.com/Rhymen/go-whatsapp"
|
"github.com/matterbridge/go-whatsapp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func qrFromTerminal(invert bool) chan string {
|
func qrFromTerminal(invert bool) chan string {
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ import (
|
|||||||
"github.com/42wim/matterbridge/bridge"
|
"github.com/42wim/matterbridge/bridge"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
|
||||||
"github.com/Rhymen/go-whatsapp"
|
"github.com/matterbridge/go-whatsapp"
|
||||||
|
|
||||||
whatsappExt "maunium.net/go/mautrix-whatsapp/whatsapp-ext"
|
whatsappExt "github.com/matterbridge/mautrix-whatsapp/whatsapp-ext"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -18,12 +19,11 @@ type Bzulip struct {
|
|||||||
bot *gzb.Bot
|
bot *gzb.Bot
|
||||||
streams map[int]string
|
streams map[int]string
|
||||||
*bridge.Config
|
*bridge.Config
|
||||||
channelToTopic map[string]string
|
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(cfg *bridge.Config) bridge.Bridger {
|
func New(cfg *bridge.Config) bridge.Bridger {
|
||||||
return &Bzulip{Config: cfg, streams: make(map[int]string), channelToTopic: make(map[string]string)}
|
return &Bzulip{Config: cfg, streams: make(map[int]string)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bzulip) Connect() error {
|
func (b *Bzulip) Connect() error {
|
||||||
@@ -48,9 +48,6 @@ func (b *Bzulip) Disconnect() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bzulip) JoinChannel(channel config.ChannelInfo) error {
|
func (b *Bzulip) JoinChannel(channel config.ChannelInfo) error {
|
||||||
b.Lock()
|
|
||||||
defer b.Unlock()
|
|
||||||
b.channelToTopic[channel.Name] = channel.Options.Topic
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,11 +113,13 @@ func (b *Bzulip) handleQueue() error {
|
|||||||
case gzb.BadEventQueueError:
|
case gzb.BadEventQueueError:
|
||||||
b.Log.Info("got a bad event queue id error, reconnecting")
|
b.Log.Info("got a bad event queue id error, reconnecting")
|
||||||
b.bot.Queues = nil
|
b.bot.Queues = nil
|
||||||
b.q, err = b.bot.RegisterAll()
|
for {
|
||||||
if err != nil {
|
b.q, err = b.bot.RegisterAll()
|
||||||
b.Log.Errorf("reconnecting failed: %s. Sleeping 10 seconds", err)
|
if err != nil {
|
||||||
time.Sleep(time.Second * 10)
|
b.Log.Errorf("reconnecting failed: %s. Sleeping 10 seconds", err)
|
||||||
continue
|
time.Sleep(time.Second * 10)
|
||||||
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
case gzb.HeartbeatError:
|
case gzb.HeartbeatError:
|
||||||
b.Log.Debug("heartbeat received.")
|
b.Log.Debug("heartbeat received.")
|
||||||
@@ -136,7 +135,14 @@ func (b *Bzulip) handleQueue() error {
|
|||||||
if m.SenderEmail == b.GetString("login") {
|
if m.SenderEmail == b.GetString("login") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
rmsg := config.Message{Username: m.SenderFullName, Text: m.Content, Channel: b.getChannel(m.StreamID), Account: b.Account, UserID: strconv.Itoa(m.SenderID), Avatar: m.AvatarURL}
|
rmsg := config.Message{
|
||||||
|
Username: m.SenderFullName,
|
||||||
|
Text: m.Content,
|
||||||
|
Channel: b.getChannel(m.StreamID) + "/topic:" + m.Subject,
|
||||||
|
Account: b.Account,
|
||||||
|
UserID: strconv.Itoa(m.SenderID),
|
||||||
|
Avatar: m.AvatarURL,
|
||||||
|
}
|
||||||
b.Log.Debugf("<= Sending message from %s on %s to gateway", rmsg.Username, b.Account)
|
b.Log.Debugf("<= Sending message from %s on %s to gateway", rmsg.Username, b.Account)
|
||||||
b.Log.Debugf("<= Message is %#v", rmsg)
|
b.Log.Debugf("<= Message is %#v", rmsg)
|
||||||
b.Remote <- rmsg
|
b.Remote <- rmsg
|
||||||
@@ -147,12 +153,11 @@ func (b *Bzulip) handleQueue() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bzulip) sendMessage(msg config.Message) (string, error) {
|
func (b *Bzulip) sendMessage(msg config.Message) (string, error) {
|
||||||
topic := "matterbridge"
|
topic := ""
|
||||||
if b.GetString("topic") != "" {
|
if strings.Contains(msg.Channel, "/topic:") {
|
||||||
topic = b.GetString("topic")
|
res := strings.Split(msg.Channel, "/topic:")
|
||||||
}
|
topic = res[1]
|
||||||
if res := b.getTopic(msg.Channel); res != "" {
|
msg.Channel = res[0]
|
||||||
topic = res
|
|
||||||
}
|
}
|
||||||
m := gzb.Message{
|
m := gzb.Message{
|
||||||
Stream: msg.Channel,
|
Stream: msg.Channel,
|
||||||
@@ -200,9 +205,3 @@ func (b *Bzulip) handleUploadFile(msg *config.Message) (string, error) {
|
|||||||
}
|
}
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bzulip) getTopic(channel string) string {
|
|
||||||
b.RLock()
|
|
||||||
defer b.RUnlock()
|
|
||||||
return b.channelToTopic[channel]
|
|
||||||
}
|
|
||||||
|
|||||||
16
changelog.md
16
changelog.md
@@ -1,4 +1,7 @@
|
|||||||
# v1.14.0-rc1
|
# v1.14.0
|
||||||
|
|
||||||
|
## Breaking
|
||||||
|
* zulip: Need to specify /topic:mytopic for channel configuration (zulip). (#751)
|
||||||
|
|
||||||
## New features
|
## New features
|
||||||
* whatsapp: new protocol added. Add initial WhatsApp support (#711) Thanks to @KrzysztofMadejski
|
* whatsapp: new protocol added. Add initial WhatsApp support (#711) Thanks to @KrzysztofMadejski
|
||||||
@@ -10,11 +13,17 @@
|
|||||||
* rocketchat: add support for the rocketchat API. Sending to rocketchat now supports uploading of files, editing and deleting of messages.
|
* rocketchat: add support for the rocketchat API. Sending to rocketchat now supports uploading of files, editing and deleting of messages.
|
||||||
* discord: Support join/leaves from discord. Closes #654 (#721)
|
* discord: Support join/leaves from discord. Closes #654 (#721)
|
||||||
* discord: Allow sending discriminator with Discord username (#726). See `UseDiscriminator` in matterbridge.toml.sample
|
* discord: Allow sending discriminator with Discord username (#726). See `UseDiscriminator` in matterbridge.toml.sample
|
||||||
* zulip: Allow zulip bridge to specify topic per channel. Closes #701 (#723). See `Topic` in matterbridge.toml.sample
|
|
||||||
* slack: Add extra debug option (slack). See `Debug` in the slack section in matterbridge.toml.sample
|
* slack: Add extra debug option (slack). See `Debug` in the slack section in matterbridge.toml.sample
|
||||||
|
* telegram: Add support for URL in messageEntities (telegram). Fixes #735 (#736)
|
||||||
|
* telegram: Add MediaConvertWebPToPNG option (telegram). (#741). See `MediaConvertWebPToPNG` in matterbridge.toml.sample
|
||||||
|
|
||||||
|
## Enhancements
|
||||||
|
* general: Fail gracefully on incorrect human input. Fixes #739 (#740)
|
||||||
|
|
||||||
## Bugfix
|
## Bugfix
|
||||||
|
* general: Handle file upload/download only once for each message (#742)
|
||||||
* zulip: Fix error handling on bad event queue id (zulip). Closes #694
|
* zulip: Fix error handling on bad event queue id (zulip). Closes #694
|
||||||
|
* zulip: Keep reconnecting until succeed (zulip) (#737)
|
||||||
* irc: add support for (older) unrealircd versions. #708
|
* irc: add support for (older) unrealircd versions. #708
|
||||||
* irc: Support quits from irc correctly. Fixes #722 (#724)
|
* irc: Support quits from irc correctly. Fixes #722 (#724)
|
||||||
* matrix: Send username when uploading video/images (matrix). Fixes #715 (#717)
|
* matrix: Send username when uploading video/images (matrix). Fixes #715 (#717)
|
||||||
@@ -22,6 +31,9 @@
|
|||||||
* matrix: Detect html nicks in RemoteNickFormat (matrix). Fixes #696 (#719)
|
* matrix: Detect html nicks in RemoteNickFormat (matrix). Fixes #696 (#719)
|
||||||
* slack: Hint at thread replies when messages are unthreaded (slack) (#684)
|
* slack: Hint at thread replies when messages are unthreaded (slack) (#684)
|
||||||
* xmpp: Do not send topic changes on connect (xmpp). Fixes #732 (#733)
|
* xmpp: Do not send topic changes on connect (xmpp). Fixes #732 (#733)
|
||||||
|
* telegram: Fix regression in HTML handling (telegram). Closes #734
|
||||||
|
* discord: Do not relay any bot messages (discord) (#743)
|
||||||
|
* rocketchat: Do not send duplicate messages (rocketchat). Fixes #745 (#752)
|
||||||
|
|
||||||
## Contributors
|
## Contributors
|
||||||
This release couldn't exist without the following contributors:
|
This release couldn't exist without the following contributors:
|
||||||
|
|||||||
@@ -92,6 +92,9 @@ func (gw *Gateway) AddBridge(cfg *config.Bridge) error {
|
|||||||
Bridge: br,
|
Bridge: br,
|
||||||
}
|
}
|
||||||
// add the actual bridger for this protocol to this bridge using the bridgeMap
|
// add the actual bridger for this protocol to this bridge using the bridgeMap
|
||||||
|
if _, ok := gw.Router.BridgeMap[br.Protocol]; !ok {
|
||||||
|
gw.logger.Fatalf("Incorrect protocol %s specified in gateway configuration %s, exiting.", br.Protocol, cfg.Account)
|
||||||
|
}
|
||||||
br.Bridger = gw.Router.BridgeMap[br.Protocol](brconfig)
|
br.Bridger = gw.Router.BridgeMap[br.Protocol](brconfig)
|
||||||
}
|
}
|
||||||
gw.mapChannelsToBridge(br)
|
gw.mapChannelsToBridge(br)
|
||||||
@@ -156,6 +159,10 @@ func (gw *Gateway) mapChannelConfig(cfg []config.Bridge, direction string) {
|
|||||||
gw.logger.Errorf("Mattermost channels do not start with a #: remove the # in %s", br.Channel)
|
gw.logger.Errorf("Mattermost channels do not start with a #: remove the # in %s", br.Channel)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
if strings.HasPrefix(br.Account, "zulip.") && !strings.Contains(br.Channel, "/topic:") {
|
||||||
|
gw.logger.Errorf("Breaking change, since matterbridge 1.14.0 zulip channels need to specify the topic with channel/topic:mytopic in %s of %s", br.Channel, br.Account)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
ID := br.Channel + br.Account
|
ID := br.Channel + br.Account
|
||||||
if _, ok := gw.Channels[ID]; !ok {
|
if _, ok := gw.Channels[ID]; !ok {
|
||||||
channel := &config.ChannelInfo{
|
channel := &config.ChannelInfo{
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ func (r *Router) handleReceive() {
|
|||||||
r.handleEventGetChannelMembers(&msg)
|
r.handleEventGetChannelMembers(&msg)
|
||||||
r.handleEventFailure(&msg)
|
r.handleEventFailure(&msg)
|
||||||
r.handleEventRejoinChannels(&msg)
|
r.handleEventRejoinChannels(&msg)
|
||||||
|
idx := 0
|
||||||
for _, gw := range r.Gateways {
|
for _, gw := range r.Gateways {
|
||||||
// record all the message ID's of the different bridges
|
// record all the message ID's of the different bridges
|
||||||
var msgIDs []*BrMsgID
|
var msgIDs []*BrMsgID
|
||||||
@@ -133,7 +134,9 @@ func (r *Router) handleReceive() {
|
|||||||
}
|
}
|
||||||
msg.Timestamp = time.Now()
|
msg.Timestamp = time.Now()
|
||||||
gw.modifyMessage(&msg)
|
gw.modifyMessage(&msg)
|
||||||
gw.handleFiles(&msg)
|
if idx == 0 {
|
||||||
|
gw.handleFiles(&msg)
|
||||||
|
}
|
||||||
for _, br := range gw.Bridges {
|
for _, br := range gw.Bridges {
|
||||||
msgIDs = append(msgIDs, gw.handleMessage(&msg, br)...)
|
msgIDs = append(msgIDs, gw.handleMessage(&msg, br)...)
|
||||||
}
|
}
|
||||||
@@ -141,6 +144,7 @@ func (r *Router) handleReceive() {
|
|||||||
if _, ok := gw.Messages.Get(msg.Protocol + " " + msg.ID); !ok && msg.ID != "" {
|
if _, ok := gw.Messages.Get(msg.Protocol + " " + msg.ID); !ok && msg.ID != "" {
|
||||||
gw.Messages.Add(msg.Protocol+" "+msg.ID, msgIDs)
|
gw.Messages.Add(msg.Protocol+" "+msg.ID, msgIDs)
|
||||||
}
|
}
|
||||||
|
idx++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
7
go.mod
7
go.mod
@@ -6,7 +6,6 @@ require (
|
|||||||
github.com/BurntSushi/toml v0.0.0-20170318202913-d94612f9fc14 // indirect
|
github.com/BurntSushi/toml v0.0.0-20170318202913-d94612f9fc14 // indirect
|
||||||
github.com/Jeffail/gabs v1.1.1 // indirect
|
github.com/Jeffail/gabs v1.1.1 // indirect
|
||||||
github.com/Philipp15b/go-steam v1.0.1-0.20180818081528-681bd9573329
|
github.com/Philipp15b/go-steam v1.0.1-0.20180818081528-681bd9573329
|
||||||
github.com/Rhymen/go-whatsapp v0.0.0-20190208184307-c9a81e957884
|
|
||||||
github.com/bwmarrin/discordgo v0.19.0
|
github.com/bwmarrin/discordgo v0.19.0
|
||||||
github.com/d5/tengo v1.9.2
|
github.com/d5/tengo v1.9.2
|
||||||
github.com/dfordsoft/golib v0.0.0-20180902042739-76ee6ab99bec
|
github.com/dfordsoft/golib v0.0.0-20180902042739-76ee6ab99bec
|
||||||
@@ -28,10 +27,12 @@ require (
|
|||||||
github.com/lusis/go-slackbot v0.0.0-20180109053408-401027ccfef5 // indirect
|
github.com/lusis/go-slackbot v0.0.0-20180109053408-401027ccfef5 // indirect
|
||||||
github.com/lusis/slack-test v0.0.0-20180109053238-3c758769bfa6 // indirect
|
github.com/lusis/slack-test v0.0.0-20180109053238-3c758769bfa6 // indirect
|
||||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20190210153444-cc9d05784d5d
|
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20190210153444-cc9d05784d5d
|
||||||
|
github.com/matterbridge/go-whatsapp v0.0.1-0.20190301204034-f2f1b29d441b
|
||||||
github.com/matterbridge/go-xmpp v0.0.0-20180529212104-cd19799fba91
|
github.com/matterbridge/go-xmpp v0.0.0-20180529212104-cd19799fba91
|
||||||
github.com/matterbridge/gomatrix v0.0.0-20190102230110-6f9631ca6dea
|
github.com/matterbridge/gomatrix v0.0.0-20190102230110-6f9631ca6dea
|
||||||
github.com/matterbridge/gozulipbot v0.0.0-20190212232658-7aa251978a18
|
github.com/matterbridge/gozulipbot v0.0.0-20190212232658-7aa251978a18
|
||||||
github.com/matterbridge/logrus-prefixed-formatter v0.0.0-20180806162718-01618749af61
|
github.com/matterbridge/logrus-prefixed-formatter v0.0.0-20180806162718-01618749af61
|
||||||
|
github.com/matterbridge/mautrix-whatsapp v0.0.0-20190301210046-3539cf52ed6e
|
||||||
github.com/mattermost/mattermost-server v5.5.0+incompatible
|
github.com/mattermost/mattermost-server v5.5.0+incompatible
|
||||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
|
||||||
github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474 // indirect
|
github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474 // indirect
|
||||||
@@ -46,7 +47,7 @@ require (
|
|||||||
github.com/peterhellberg/emojilib v0.0.0-20190124112554-c18758d55320
|
github.com/peterhellberg/emojilib v0.0.0-20190124112554-c18758d55320
|
||||||
github.com/pkg/errors v0.8.0 // indirect
|
github.com/pkg/errors v0.8.0 // indirect
|
||||||
github.com/rs/xid v1.2.1
|
github.com/rs/xid v1.2.1
|
||||||
github.com/russross/blackfriday v2.0.0+incompatible
|
github.com/russross/blackfriday v1.5.2
|
||||||
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca
|
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca
|
||||||
github.com/shazow/ssh-chat v0.0.0-20190125184227-81d7e1686296
|
github.com/shazow/ssh-chat v0.0.0-20190125184227-81d7e1686296
|
||||||
github.com/sirupsen/logrus v1.3.0
|
github.com/sirupsen/logrus v1.3.0
|
||||||
@@ -66,8 +67,8 @@ require (
|
|||||||
go.uber.org/atomic v1.3.2 // indirect
|
go.uber.org/atomic v1.3.2 // indirect
|
||||||
go.uber.org/multierr v1.1.0 // indirect
|
go.uber.org/multierr v1.1.0 // indirect
|
||||||
go.uber.org/zap v1.9.1 // indirect
|
go.uber.org/zap v1.9.1 // indirect
|
||||||
|
golang.org/x/image v0.0.0-20190220214146-31aff87c08e9
|
||||||
gopkg.in/fsnotify.v1 v1.4.7 // indirect
|
gopkg.in/fsnotify.v1 v1.4.7 // indirect
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||||
maunium.net/go/mautrix-whatsapp v0.0.0-20190127121751-281b3e8f77f3
|
|
||||||
)
|
)
|
||||||
|
|||||||
41
go.sum
41
go.sum
@@ -8,11 +8,6 @@ github.com/Jeffail/gabs v1.1.1 h1:V0uzR08Hj22EX8+8QMhyI9sX2hwRu+/RJhJUmnwda/E=
|
|||||||
github.com/Jeffail/gabs v1.1.1/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc=
|
github.com/Jeffail/gabs v1.1.1/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc=
|
||||||
github.com/Philipp15b/go-steam v1.0.1-0.20180818081528-681bd9573329 h1:xZBoq249G9MSt+XuY7sVQzcfONJ6IQuwpCK+KAaOpnY=
|
github.com/Philipp15b/go-steam v1.0.1-0.20180818081528-681bd9573329 h1:xZBoq249G9MSt+XuY7sVQzcfONJ6IQuwpCK+KAaOpnY=
|
||||||
github.com/Philipp15b/go-steam v1.0.1-0.20180818081528-681bd9573329/go.mod h1:HuVM+sZFzumUdKPWiz+IlCMb4RdsKdT3T+nQBKL+sYg=
|
github.com/Philipp15b/go-steam v1.0.1-0.20180818081528-681bd9573329/go.mod h1:HuVM+sZFzumUdKPWiz+IlCMb4RdsKdT3T+nQBKL+sYg=
|
||||||
github.com/Rhymen/go-whatsapp v0.0.0-20181218094654-2ca6af00572c h1:ldRXgMEfKmzBomrZusl3edG9AGEeztA7jovLEQy62us=
|
|
||||||
github.com/Rhymen/go-whatsapp v0.0.0-20181218094654-2ca6af00572c/go.mod h1:MSDmePOOkbFFbVW2WRRppBcbA+aabwpXRgyIIG7jDFQ=
|
|
||||||
github.com/Rhymen/go-whatsapp v0.0.0-20190208184307-c9a81e957884 h1:2AxfzkQi2L4QGBvUCZoWD6hQuUJa5MG54wiYyNqJlf4=
|
|
||||||
github.com/Rhymen/go-whatsapp v0.0.0-20190208184307-c9a81e957884/go.mod h1:rdQr95g2C1xcOfM7QGOhza58HeI3I+tZ/bbluv7VazA=
|
|
||||||
github.com/alexcesaro/log v0.0.0-20150915221235-61e686294e58 h1:MkpmYfld/S8kXqTYI68DfL8/hHXjHogL120Dy00TIxc=
|
|
||||||
github.com/alexcesaro/log v0.0.0-20150915221235-61e686294e58/go.mod h1:YNfsMyWSs+h+PaYkxGeMVmVCX75Zj/pqdjbu12ciCYE=
|
github.com/alexcesaro/log v0.0.0-20150915221235-61e686294e58/go.mod h1:YNfsMyWSs+h+PaYkxGeMVmVCX75Zj/pqdjbu12ciCYE=
|
||||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||||
github.com/bwmarrin/discordgo v0.19.0 h1:kMED/DB0NR1QhRcalb85w0Cu3Ep2OrGAqZH1R5awQiY=
|
github.com/bwmarrin/discordgo v0.19.0 h1:kMED/DB0NR1QhRcalb85w0Cu3Ep2OrGAqZH1R5awQiY=
|
||||||
@@ -43,6 +38,7 @@ github.com/gopackage/ddp v0.0.0-20170117053602-652027933df4/go.mod h1:lEO7XoHJ/x
|
|||||||
github.com/gopherjs/gopherjs v0.0.0-20180628210949-0892b62f0d9f h1:FDM3EtwZLyhW48YRiyqjivNlNZjAObv4xt4NnJaU+NQ=
|
github.com/gopherjs/gopherjs v0.0.0-20180628210949-0892b62f0d9f h1:FDM3EtwZLyhW48YRiyqjivNlNZjAObv4xt4NnJaU+NQ=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20180628210949-0892b62f0d9f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20180628210949-0892b62f0d9f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
|
github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
github.com/gorilla/schema v1.0.2 h1:sAgNfOcNYvdDSrzGHVy9nzCQahG+qmsg+nE8dK85QRA=
|
github.com/gorilla/schema v1.0.2 h1:sAgNfOcNYvdDSrzGHVy9nzCQahG+qmsg+nE8dK85QRA=
|
||||||
github.com/gorilla/schema v1.0.2/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
|
github.com/gorilla/schema v1.0.2/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
|
||||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||||
@@ -82,6 +78,8 @@ github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDe
|
|||||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20190210153444-cc9d05784d5d h1:F+Sr+C0ojSlYQ37BLylQtSFmyQULe3jbAygcyXQ9mVs=
|
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20190210153444-cc9d05784d5d h1:F+Sr+C0ojSlYQ37BLylQtSFmyQULe3jbAygcyXQ9mVs=
|
||||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20190210153444-cc9d05784d5d/go.mod h1:c6MxwqHD+0HvtAJjsHMIdPCiAwGiQwPRPTp69ACMg8A=
|
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20190210153444-cc9d05784d5d/go.mod h1:c6MxwqHD+0HvtAJjsHMIdPCiAwGiQwPRPTp69ACMg8A=
|
||||||
|
github.com/matterbridge/go-whatsapp v0.0.1-0.20190301204034-f2f1b29d441b h1:cO6Z+yj4Ivq/ay/IxSrV90oSIW/SSXWLa+XHsiLKMrw=
|
||||||
|
github.com/matterbridge/go-whatsapp v0.0.1-0.20190301204034-f2f1b29d441b/go.mod h1:dW19fYkkdUZsBAx7zv9fDh0n6NRqYIaKwB2JEBw8d0U=
|
||||||
github.com/matterbridge/go-xmpp v0.0.0-20180529212104-cd19799fba91 h1:KzDEcy8eDbTx881giW8a6llsAck3e2bJvMyKvh1IK+k=
|
github.com/matterbridge/go-xmpp v0.0.0-20180529212104-cd19799fba91 h1:KzDEcy8eDbTx881giW8a6llsAck3e2bJvMyKvh1IK+k=
|
||||||
github.com/matterbridge/go-xmpp v0.0.0-20180529212104-cd19799fba91/go.mod h1:ECDRehsR9TYTKCAsRS8/wLeOk6UUqDydw47ln7wG41Q=
|
github.com/matterbridge/go-xmpp v0.0.0-20180529212104-cd19799fba91/go.mod h1:ECDRehsR9TYTKCAsRS8/wLeOk6UUqDydw47ln7wG41Q=
|
||||||
github.com/matterbridge/gomatrix v0.0.0-20190102230110-6f9631ca6dea h1:kaADGqpK4gGO2BpzEyJrBxq2Jc57Rsar4i2EUxcACUc=
|
github.com/matterbridge/gomatrix v0.0.0-20190102230110-6f9631ca6dea h1:kaADGqpK4gGO2BpzEyJrBxq2Jc57Rsar4i2EUxcACUc=
|
||||||
@@ -90,12 +88,16 @@ github.com/matterbridge/gozulipbot v0.0.0-20190212232658-7aa251978a18 h1:fLhwXtW
|
|||||||
github.com/matterbridge/gozulipbot v0.0.0-20190212232658-7aa251978a18/go.mod h1:yAjnZ34DuDyPHMPHHjOsTk/FefW4JJjoMMCGt/8uuQA=
|
github.com/matterbridge/gozulipbot v0.0.0-20190212232658-7aa251978a18/go.mod h1:yAjnZ34DuDyPHMPHHjOsTk/FefW4JJjoMMCGt/8uuQA=
|
||||||
github.com/matterbridge/logrus-prefixed-formatter v0.0.0-20180806162718-01618749af61 h1:R/MgM/eUyRBQx2FiH6JVmXck8PaAuKfe2M1tWIzW7nE=
|
github.com/matterbridge/logrus-prefixed-formatter v0.0.0-20180806162718-01618749af61 h1:R/MgM/eUyRBQx2FiH6JVmXck8PaAuKfe2M1tWIzW7nE=
|
||||||
github.com/matterbridge/logrus-prefixed-formatter v0.0.0-20180806162718-01618749af61/go.mod h1:iXGEotOvwI1R1SjLxRc+BF5rUORTMtE0iMZBT2lxqAU=
|
github.com/matterbridge/logrus-prefixed-formatter v0.0.0-20180806162718-01618749af61/go.mod h1:iXGEotOvwI1R1SjLxRc+BF5rUORTMtE0iMZBT2lxqAU=
|
||||||
|
github.com/matterbridge/mautrix-whatsapp v0.0.0-20190301210046-3539cf52ed6e h1:1NqciL8sz+0UYeFrd/UQlL8tJPhFxOBmg+a94DN2sJU=
|
||||||
|
github.com/matterbridge/mautrix-whatsapp v0.0.0-20190301210046-3539cf52ed6e/go.mod h1:DrIFGcFumRlEW5k3PJjWGKPd4+w37d3SwOxlh1ZAL+4=
|
||||||
github.com/mattermost/mattermost-server v5.5.0+incompatible h1:0wcLGgYtd+YImtLDPf2AOfpBHxbU4suATx+6XKw1XbU=
|
github.com/mattermost/mattermost-server v5.5.0+incompatible h1:0wcLGgYtd+YImtLDPf2AOfpBHxbU4suATx+6XKw1XbU=
|
||||||
github.com/mattermost/mattermost-server v5.5.0+incompatible/go.mod h1:5L6MjAec+XXQwMIt791Ganu45GKsSiM+I0tLR9wUj8Y=
|
github.com/mattermost/mattermost-server v5.5.0+incompatible/go.mod h1:5L6MjAec+XXQwMIt791Ganu45GKsSiM+I0tLR9wUj8Y=
|
||||||
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
|
|
||||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
|
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
|
||||||
|
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
|
github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw=
|
||||||
|
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
||||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||||
@@ -129,8 +131,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc=
|
github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc=
|
||||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||||
github.com/russross/blackfriday v2.0.0+incompatible h1:cBXrhZNUf9C+La9/YpS+UHpUT8YD6Td9ZMSU9APFcsk=
|
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
|
||||||
github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca h1:NugYot0LIVPxTvN8n+Kvkn6TrbMyxQiuvKdEwFdR9vI=
|
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca h1:NugYot0LIVPxTvN8n+Kvkn6TrbMyxQiuvKdEwFdR9vI=
|
||||||
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
|
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
|
||||||
@@ -138,11 +140,9 @@ github.com/shazow/rateio v0.0.0-20150116013248-e8e00881e5c1 h1:Lx3BlDGFElJt4u/zK
|
|||||||
github.com/shazow/rateio v0.0.0-20150116013248-e8e00881e5c1/go.mod h1:vt2jWY/3Qw1bIzle5thrJWucsLuuX9iUNnp20CqCciI=
|
github.com/shazow/rateio v0.0.0-20150116013248-e8e00881e5c1/go.mod h1:vt2jWY/3Qw1bIzle5thrJWucsLuuX9iUNnp20CqCciI=
|
||||||
github.com/shazow/ssh-chat v0.0.0-20190125184227-81d7e1686296 h1:8RLq547MSVc6vhOuCl4Ca0TsAQknj6NX6ZLSZ3+xmio=
|
github.com/shazow/ssh-chat v0.0.0-20190125184227-81d7e1686296 h1:8RLq547MSVc6vhOuCl4Ca0TsAQknj6NX6ZLSZ3+xmio=
|
||||||
github.com/shazow/ssh-chat v0.0.0-20190125184227-81d7e1686296/go.mod h1:1GLXsL4esywkpNId3v4QWuMf3THtWGitWvtQ/L3aSA4=
|
github.com/shazow/ssh-chat v0.0.0-20190125184227-81d7e1686296/go.mod h1:1GLXsL4esywkpNId3v4QWuMf3THtWGitWvtQ/L3aSA4=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/sirupsen/logrus v1.3.0 h1:hI/7Q+DtNZ2kINb6qt/lS+IyXnHQe9e90POfeewL/ME=
|
github.com/sirupsen/logrus v1.3.0 h1:hI/7Q+DtNZ2kINb6qt/lS+IyXnHQe9e90POfeewL/ME=
|
||||||
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/skip2/go-qrcode v0.0.0-20171229120447-cf5f9fa2f0d8/go.mod h1:PLPIyL7ikehBD1OAjmKKiOEhbvWyHGaNDjquXMcYABo=
|
|
||||||
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9 h1:lpEzuenPuO1XNTeikEmvqYFcU37GVLl8SRNblzyvGBE=
|
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9 h1:lpEzuenPuO1XNTeikEmvqYFcU37GVLl8SRNblzyvGBE=
|
||||||
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9/go.mod h1:PLPIyL7ikehBD1OAjmKKiOEhbvWyHGaNDjquXMcYABo=
|
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9/go.mod h1:PLPIyL7ikehBD1OAjmKKiOEhbvWyHGaNDjquXMcYABo=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180803164922-886ec427f6b9 h1:lXQ+j+KwZcbwrbgU0Rp4Eglg3EJLHbuZU3BbOqAGBmg=
|
github.com/smartystreets/assertions v0.0.0-20180803164922-886ec427f6b9 h1:lXQ+j+KwZcbwrbgU0Rp4Eglg3EJLHbuZU3BbOqAGBmg=
|
||||||
@@ -160,9 +160,7 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
|
|||||||
github.com/spf13/viper v1.3.1 h1:5+8j8FTpnFV4nEImW/ofkzEt8VoOiLXxdYIDsB73T38=
|
github.com/spf13/viper v1.3.1 h1:5+8j8FTpnFV4nEImW/ofkzEt8VoOiLXxdYIDsB73T38=
|
||||||
github.com/spf13/viper v1.3.1/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
github.com/spf13/viper v1.3.1/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
@@ -197,25 +195,24 @@ go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/
|
|||||||
go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o=
|
go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o=
|
||||||
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16 h1:y6ce7gCWtnH+m3dCjzQ1PCuwl28DDIc3VNnvY29DlIA=
|
|
||||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
|
||||||
golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664 h1:YbZJ76lQ1BqNhVe7dKTSB67wDrc2VPRR75IyGyyPDX8=
|
|
||||||
golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613 h1:MQ/ZZiDsUapFFiMS+vzwXkCTeEKaum+Do5rINYJDmxc=
|
|
||||||
golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f h1:qWFY9ZxP3tfI37wYIs/MnIAqK0vlXp1xnYEa5HxFSSY=
|
||||||
|
golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
golang.org/x/image v0.0.0-20190220214146-31aff87c08e9 h1:+vH8qNweCrORN49012OX3h0oWEXO3p+rRnpAGQinddk=
|
||||||
|
golang.org/x/image v0.0.0-20190220214146-31aff87c08e9/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/net v0.0.0-20190110200230-915654e7eabc h1:Yx9JGxI1SBhVLFjpAkWMaO1TF+xyqtHLjZpvQboJGiM=
|
golang.org/x/net v0.0.0-20190110200230-915654e7eabc h1:Yx9JGxI1SBhVLFjpAkWMaO1TF+xyqtHLjZpvQboJGiM=
|
||||||
golang.org/x/net v0.0.0-20190110200230-915654e7eabc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190110200230-915654e7eabc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181212120007-b05ddf57801d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190109145017-48ac38b7c8cb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc h1:WiYx1rIFmx8c0mXAFtv5D/mHyKe1+jmuP7PViuwqwuQ=
|
|
||||||
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190222171317-cd391775e71e h1:oF7qaQxUH6KzFdKN4ww7NpPdo53SZi4UlcksLrb2y/o=
|
||||||
|
golang.org/x/sys v0.0.0-20190222171317-cd391775e71e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
@@ -233,5 +230,3 @@ maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfk
|
|||||||
maunium.net/go/maulogger/v2 v2.0.0/go.mod h1:Hbbkq3NV6jvJodByZu1mgEF3fpT7Kz9z0MjEZ3/BusI=
|
maunium.net/go/maulogger/v2 v2.0.0/go.mod h1:Hbbkq3NV6jvJodByZu1mgEF3fpT7Kz9z0MjEZ3/BusI=
|
||||||
maunium.net/go/mautrix v0.1.0-alpha.3/go.mod h1:GTVu6WDHR+98DKOrYetWsXorvUeKQV3jsSWO6ScbuFI=
|
maunium.net/go/mautrix v0.1.0-alpha.3/go.mod h1:GTVu6WDHR+98DKOrYetWsXorvUeKQV3jsSWO6ScbuFI=
|
||||||
maunium.net/go/mautrix-appservice v0.1.0-alpha.3/go.mod h1:wOnWOIuprYad7ly12rHIo3JLCPh4jwvx1prVrAB9RhM=
|
maunium.net/go/mautrix-appservice v0.1.0-alpha.3/go.mod h1:wOnWOIuprYad7ly12rHIo3JLCPh4jwvx1prVrAB9RhM=
|
||||||
maunium.net/go/mautrix-whatsapp v0.0.0-20190127121751-281b3e8f77f3 h1:A18t5Lp7I3aK0V7B7zdpb0hb/PBlu0X/Ai2AyU/XEk4=
|
|
||||||
maunium.net/go/mautrix-whatsapp v0.0.0-20190127121751-281b3e8f77f3/go.mod h1:r5E3J4urDEsjfui9OYZYMLBfCliaAqcCwM2xeczta6k=
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
version = "1.14.0-rc1"
|
version = "1.14.0-rc2"
|
||||||
githash string
|
githash string
|
||||||
|
|
||||||
flagConfig = flag.String("conf", "matterbridge.toml", "config file")
|
flagConfig = flag.String("conf", "matterbridge.toml", "config file")
|
||||||
|
|||||||
@@ -913,6 +913,11 @@ QuoteDisable=false
|
|||||||
#OPTIONAL (default "{MESSAGE} (re @{QUOTENICK}: {QUOTEMESSAGE})")
|
#OPTIONAL (default "{MESSAGE} (re @{QUOTENICK}: {QUOTEMESSAGE})")
|
||||||
QuoteFormat="{MESSAGE} (re @{QUOTENICK}: {QUOTEMESSAGE})"
|
QuoteFormat="{MESSAGE} (re @{QUOTENICK}: {QUOTEMESSAGE})"
|
||||||
|
|
||||||
|
#Convert WebP images to PNG before upload.
|
||||||
|
#https://github.com/42wim/matterbridge/issues/398
|
||||||
|
#OPTIONAL (default false)
|
||||||
|
MediaConvertWebPToPNG=false
|
||||||
|
|
||||||
#Disable sending of edits to other bridges
|
#Disable sending of edits to other bridges
|
||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
EditDisable=false
|
EditDisable=false
|
||||||
@@ -1358,12 +1363,6 @@ Login="yourbot-bot@yourserver.zulipchat.com"
|
|||||||
#REQUIRED
|
#REQUIRED
|
||||||
Server="https://yourserver.zulipchat.com"
|
Server="https://yourserver.zulipchat.com"
|
||||||
|
|
||||||
#Topic of the messages matterbridge will use
|
|
||||||
#OPTIONAL (default "matterbridge")
|
|
||||||
#You can specify a specific topic for each channel using [gateway.inout.options]
|
|
||||||
#See more information below at the gateway configuration
|
|
||||||
Topic="matterbridge"
|
|
||||||
|
|
||||||
## RELOADABLE SETTINGS
|
## RELOADABLE SETTINGS
|
||||||
## Settings below can be reloaded by editing the file
|
## Settings below can be reloaded by editing the file
|
||||||
|
|
||||||
@@ -1603,7 +1602,7 @@ enable=true
|
|||||||
# if you specify an empty string bridge will list all the possibilities
|
# if you specify an empty string bridge will list all the possibilities
|
||||||
# - "Group Name" if you specify a group name the bridge will hint its JID to specify
|
# - "Group Name" if you specify a group name the bridge will hint its JID to specify
|
||||||
# as group names might change in time and contain weird emoticons
|
# as group names might change in time and contain weird emoticons
|
||||||
# zulip - stream (without the #)
|
# zulip - stream/topic:topicname (without the #)
|
||||||
#
|
#
|
||||||
# REQUIRED
|
# REQUIRED
|
||||||
channel="#testing"
|
channel="#testing"
|
||||||
@@ -1645,10 +1644,7 @@ enable=true
|
|||||||
|
|
||||||
[[gateway.inout]]
|
[[gateway.inout]]
|
||||||
account="zulip.streamchat"
|
account="zulip.streamchat"
|
||||||
channel="general"
|
channel="general/topic:mytopic"
|
||||||
#OPTIONAL - topic only works for zulip
|
|
||||||
[gateway.inout.options]
|
|
||||||
topic="topic1"
|
|
||||||
|
|
||||||
#API example
|
#API example
|
||||||
#[[gateway.inout]]
|
#[[gateway.inout]]
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package binary
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/Rhymen/go-whatsapp/binary/token"
|
"github.com/matterbridge/go-whatsapp/binary/token"
|
||||||
"io"
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
@@ -2,7 +2,7 @@ package binary
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/Rhymen/go-whatsapp/binary/token"
|
"github.com/matterbridge/go-whatsapp/binary/token"
|
||||||
"math"
|
"math"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -2,7 +2,7 @@ package binary
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
pb "github.com/Rhymen/go-whatsapp/binary/proto"
|
pb "github.com/matterbridge/go-whatsapp/binary/proto"
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -14,9 +14,9 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Rhymen/go-whatsapp/binary"
|
|
||||||
"github.com/Rhymen/go-whatsapp/crypto/cbc"
|
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
|
"github.com/matterbridge/go-whatsapp/binary"
|
||||||
|
"github.com/matterbridge/go-whatsapp/crypto/cbc"
|
||||||
)
|
)
|
||||||
|
|
||||||
type metric byte
|
type metric byte
|
||||||
@@ -128,7 +128,7 @@ func NewConn(timeout time.Duration) (*Conn, error) {
|
|||||||
|
|
||||||
go wac.readPump()
|
go wac.readPump()
|
||||||
go wac.writePump()
|
go wac.writePump()
|
||||||
go wac.keepAlive(20000, 90000)
|
go wac.keepAlive(20000, 60000)
|
||||||
|
|
||||||
return wac, nil
|
return wac, nil
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@ package whatsapp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/Rhymen/go-whatsapp/binary"
|
"github.com/matterbridge/go-whatsapp/binary"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -13,8 +13,8 @@ const (
|
|||||||
PresenceAvailable = "available"
|
PresenceAvailable = "available"
|
||||||
PresenceUnavailable = "unavailable"
|
PresenceUnavailable = "unavailable"
|
||||||
PresenceComposing = "composing"
|
PresenceComposing = "composing"
|
||||||
PresenceRecording = "recording"
|
PresenceRecording = "recording"
|
||||||
PresencePaused = "paused"
|
PresencePaused = "paused"
|
||||||
)
|
)
|
||||||
|
|
||||||
//TODO: filename? WhatsApp uses Store.Contacts for these functions
|
//TODO: filename? WhatsApp uses Store.Contacts for these functions
|
||||||
@@ -30,44 +30,11 @@ func (wac *Conn) GetStatus(jid string) (<-chan string, error) {
|
|||||||
return wac.write(data)
|
return wac.write(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wac *Conn) GetGroupMetaData(jid string) (<-chan string, error) {
|
|
||||||
data := []interface{}{"query", "GroupMetadata", jid}
|
|
||||||
return wac.write(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wac *Conn) SubscribePresence(jid string) (<-chan string, error) {
|
func (wac *Conn) SubscribePresence(jid string) (<-chan string, error) {
|
||||||
data := []interface{}{"action", "presence", "subscribe", jid}
|
data := []interface{}{"action", "presence", "subscribe", jid}
|
||||||
return wac.write(data)
|
return wac.write(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wac *Conn) CreateGroup(subject string, participants []string) (<-chan string, error) {
|
|
||||||
return wac.setGroup("create", "", subject, participants)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wac *Conn) UpdateGroupSubject(subject string, jid string) (<-chan string, error) {
|
|
||||||
return wac.setGroup("subject", jid, subject, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wac *Conn) SetAdmin(jid string, participants []string) (<-chan string, error) {
|
|
||||||
return wac.setGroup("promote", jid, "", participants)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wac *Conn) RemoveAdmin(jid string, participants []string) (<-chan string, error) {
|
|
||||||
return wac.setGroup("demote", jid, "", participants)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wac *Conn) AddMember(jid string, participants []string) (<-chan string, error) {
|
|
||||||
return wac.setGroup("add", jid, "", participants)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wac *Conn) RemoveMember(jid string, participants []string) (<-chan string, error) {
|
|
||||||
return wac.setGroup("remove", jid, "", participants)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wac *Conn) LeaveGroup(jid string) (<-chan string, error) {
|
|
||||||
return wac.setGroup("leave", jid, "", nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wac *Conn) Search(search string, count, page int) (*binary.Node, error) {
|
func (wac *Conn) Search(search string, count, page int) (*binary.Node, error) {
|
||||||
return wac.query("search", "", "", "", "", search, count, page)
|
return wac.query("search", "", "", "", "", search, count, page)
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
module github.com/Rhymen/go-whatsapp
|
module github.com/matterbridge/go-whatsapp
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/golang/protobuf v1.2.0
|
github.com/golang/protobuf v1.2.0
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
|
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
|
golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613 h1:MQ/ZZiDsUapFFiMS+vzwXkCTeEKaum+Do5rINYJDmxc=
|
||||||
golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
65
vendor/github.com/matterbridge/go-whatsapp/group.go
generated
vendored
Normal file
65
vendor/github.com/matterbridge/go-whatsapp/group.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
package whatsapp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (wac *Conn) GetGroupMetaData(jid string) (<-chan string, error) {
|
||||||
|
data := []interface{}{"query", "GroupMetadata", jid}
|
||||||
|
return wac.write(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wac *Conn) CreateGroup(subject string, participants []string) (<-chan string, error) {
|
||||||
|
return wac.setGroup("create", "", subject, participants)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wac *Conn) UpdateGroupSubject(subject string, jid string) (<-chan string, error) {
|
||||||
|
return wac.setGroup("subject", jid, subject, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wac *Conn) SetAdmin(jid string, participants []string) (<-chan string, error) {
|
||||||
|
return wac.setGroup("promote", jid, "", participants)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wac *Conn) RemoveAdmin(jid string, participants []string) (<-chan string, error) {
|
||||||
|
return wac.setGroup("demote", jid, "", participants)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wac *Conn) AddMember(jid string, participants []string) (<-chan string, error) {
|
||||||
|
return wac.setGroup("add", jid, "", participants)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wac *Conn) RemoveMember(jid string, participants []string) (<-chan string, error) {
|
||||||
|
return wac.setGroup("remove", jid, "", participants)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wac *Conn) LeaveGroup(jid string) (<-chan string, error) {
|
||||||
|
return wac.setGroup("leave", jid, "", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wac *Conn) GroupInviteLink(jid string) (string, error) {
|
||||||
|
request := []interface{}{"query", "inviteCode", jid}
|
||||||
|
ch, err := wac.write(request)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
var response map[string]interface{}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case r := <-ch:
|
||||||
|
if err := json.Unmarshal([]byte(r), &response); err != nil {
|
||||||
|
return "", fmt.Errorf("error decoding response message: %v\n", err)
|
||||||
|
}
|
||||||
|
case <-time.After(wac.msgTimeout):
|
||||||
|
return "", fmt.Errorf("request timed out")
|
||||||
|
}
|
||||||
|
|
||||||
|
if int(response["status"].(float64)) != 200 {
|
||||||
|
return "", fmt.Errorf("request responded with %d", response["status"])
|
||||||
|
}
|
||||||
|
|
||||||
|
return response["code"].(string), nil
|
||||||
|
}
|
||||||
@@ -2,8 +2,8 @@ package whatsapp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/Rhymen/go-whatsapp/binary"
|
"github.com/matterbridge/go-whatsapp/binary"
|
||||||
"github.com/Rhymen/go-whatsapp/binary/proto"
|
"github.com/matterbridge/go-whatsapp/binary/proto"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -8,8 +8,8 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/Rhymen/go-whatsapp/crypto/cbc"
|
"github.com/matterbridge/go-whatsapp/crypto/cbc"
|
||||||
"github.com/Rhymen/go-whatsapp/crypto/hkdf"
|
"github.com/matterbridge/go-whatsapp/crypto/hkdf"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/Rhymen/go-whatsapp/binary"
|
"github.com/matterbridge/go-whatsapp/binary"
|
||||||
"github.com/Rhymen/go-whatsapp/binary/proto"
|
"github.com/matterbridge/go-whatsapp/binary/proto"
|
||||||
"io"
|
"io"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -363,6 +363,7 @@ type DocumentMessage struct {
|
|||||||
Title string
|
Title string
|
||||||
PageCount uint32
|
PageCount uint32
|
||||||
Type string
|
Type string
|
||||||
|
FileName string
|
||||||
Thumbnail []byte
|
Thumbnail []byte
|
||||||
Content io.Reader
|
Content io.Reader
|
||||||
url string
|
url string
|
||||||
@@ -376,15 +377,16 @@ func getDocumentMessage(msg *proto.WebMessageInfo) DocumentMessage {
|
|||||||
doc := msg.GetMessage().GetDocumentMessage()
|
doc := msg.GetMessage().GetDocumentMessage()
|
||||||
return DocumentMessage{
|
return DocumentMessage{
|
||||||
Info: getMessageInfo(msg),
|
Info: getMessageInfo(msg),
|
||||||
|
Title: doc.GetTitle(),
|
||||||
|
PageCount: doc.GetPageCount(),
|
||||||
|
Type: doc.GetMimetype(),
|
||||||
|
FileName: doc.GetFileName(),
|
||||||
Thumbnail: doc.GetJpegThumbnail(),
|
Thumbnail: doc.GetJpegThumbnail(),
|
||||||
url: doc.GetUrl(),
|
url: doc.GetUrl(),
|
||||||
mediaKey: doc.GetMediaKey(),
|
mediaKey: doc.GetMediaKey(),
|
||||||
fileEncSha256: doc.GetFileEncSha256(),
|
fileEncSha256: doc.GetFileEncSha256(),
|
||||||
fileSha256: doc.GetFileSha256(),
|
fileSha256: doc.GetFileSha256(),
|
||||||
fileLength: doc.GetFileLength(),
|
fileLength: doc.GetFileLength(),
|
||||||
PageCount: doc.GetPageCount(),
|
|
||||||
Title: doc.GetTitle(),
|
|
||||||
Type: doc.GetMimetype(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9,9 +9,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Rhymen/go-whatsapp/crypto/cbc"
|
"github.com/matterbridge/go-whatsapp/crypto/cbc"
|
||||||
"github.com/Rhymen/go-whatsapp/crypto/curve25519"
|
"github.com/matterbridge/go-whatsapp/crypto/curve25519"
|
||||||
"github.com/Rhymen/go-whatsapp/crypto/hkdf"
|
"github.com/matterbridge/go-whatsapp/crypto/hkdf"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package whatsapp
|
package whatsapp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/Rhymen/go-whatsapp/binary"
|
"github.com/matterbridge/go-whatsapp/binary"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/Rhymen/go-whatsapp"
|
"github.com/matterbridge/go-whatsapp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ChatUpdateCommand string
|
type ChatUpdateCommand string
|
||||||
@@ -20,7 +20,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/Rhymen/go-whatsapp"
|
"github.com/matterbridge/go-whatsapp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CommandType string
|
type CommandType string
|
||||||
@@ -19,7 +19,7 @@ package whatsappExt
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/Rhymen/go-whatsapp"
|
"github.com/matterbridge/go-whatsapp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ConnInfo struct {
|
type ConnInfo struct {
|
||||||
@@ -19,7 +19,7 @@ package whatsappExt
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/Rhymen/go-whatsapp"
|
"github.com/matterbridge/go-whatsapp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type JSONMessage []json.RawMessage
|
type JSONMessage []json.RawMessage
|
||||||
@@ -20,7 +20,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/Rhymen/go-whatsapp"
|
"github.com/matterbridge/go-whatsapp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MsgInfoCommand string
|
type MsgInfoCommand string
|
||||||
@@ -20,7 +20,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/Rhymen/go-whatsapp"
|
"github.com/matterbridge/go-whatsapp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PresenceType string
|
type PresenceType string
|
||||||
@@ -19,7 +19,7 @@ package whatsappExt
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/Rhymen/go-whatsapp"
|
"github.com/matterbridge/go-whatsapp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ProtocolProps struct {
|
type ProtocolProps struct {
|
||||||
@@ -19,7 +19,7 @@ package whatsappExt
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/Rhymen/go-whatsapp"
|
"github.com/matterbridge/go-whatsapp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StreamType string
|
type StreamType string
|
||||||
@@ -24,7 +24,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/Rhymen/go-whatsapp"
|
"github.com/matterbridge/go-whatsapp"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
214
vendor/github.com/mattn/go-colorable/colorable_windows.go
generated
vendored
214
vendor/github.com/mattn/go-colorable/colorable_windows.go
generated
vendored
@@ -29,6 +29,15 @@ const (
|
|||||||
backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity)
|
backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
genericRead = 0x80000000
|
||||||
|
genericWrite = 0x40000000
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
consoleTextmodeBuffer = 0x1
|
||||||
|
)
|
||||||
|
|
||||||
type wchar uint16
|
type wchar uint16
|
||||||
type short int16
|
type short int16
|
||||||
type dword uint32
|
type dword uint32
|
||||||
@@ -69,14 +78,17 @@ var (
|
|||||||
procGetConsoleCursorInfo = kernel32.NewProc("GetConsoleCursorInfo")
|
procGetConsoleCursorInfo = kernel32.NewProc("GetConsoleCursorInfo")
|
||||||
procSetConsoleCursorInfo = kernel32.NewProc("SetConsoleCursorInfo")
|
procSetConsoleCursorInfo = kernel32.NewProc("SetConsoleCursorInfo")
|
||||||
procSetConsoleTitle = kernel32.NewProc("SetConsoleTitleW")
|
procSetConsoleTitle = kernel32.NewProc("SetConsoleTitleW")
|
||||||
|
procCreateConsoleScreenBuffer = kernel32.NewProc("CreateConsoleScreenBuffer")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Writer provide colorable Writer to the console
|
// Writer provide colorable Writer to the console
|
||||||
type Writer struct {
|
type Writer struct {
|
||||||
out io.Writer
|
out io.Writer
|
||||||
handle syscall.Handle
|
handle syscall.Handle
|
||||||
oldattr word
|
althandle syscall.Handle
|
||||||
oldpos coord
|
oldattr word
|
||||||
|
oldpos coord
|
||||||
|
rest bytes.Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewColorable return new instance of Writer which handle escape sequence from File.
|
// NewColorable return new instance of Writer which handle escape sequence from File.
|
||||||
@@ -407,7 +419,18 @@ func (w *Writer) Write(data []byte) (n int, err error) {
|
|||||||
var csbi consoleScreenBufferInfo
|
var csbi consoleScreenBufferInfo
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
|
|
||||||
er := bytes.NewReader(data)
|
handle := w.handle
|
||||||
|
|
||||||
|
var er *bytes.Reader
|
||||||
|
if w.rest.Len() > 0 {
|
||||||
|
var rest bytes.Buffer
|
||||||
|
w.rest.WriteTo(&rest)
|
||||||
|
w.rest.Reset()
|
||||||
|
rest.Write(data)
|
||||||
|
er = bytes.NewReader(rest.Bytes())
|
||||||
|
} else {
|
||||||
|
er = bytes.NewReader(data)
|
||||||
|
}
|
||||||
var bw [1]byte
|
var bw [1]byte
|
||||||
loop:
|
loop:
|
||||||
for {
|
for {
|
||||||
@@ -425,29 +448,55 @@ loop:
|
|||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
|
|
||||||
if c2 == ']' {
|
switch c2 {
|
||||||
if err := doTitleSequence(er); err != nil {
|
case '>':
|
||||||
|
continue
|
||||||
|
case ']':
|
||||||
|
w.rest.WriteByte(c1)
|
||||||
|
w.rest.WriteByte(c2)
|
||||||
|
er.WriteTo(&w.rest)
|
||||||
|
if bytes.IndexByte(w.rest.Bytes(), 0x07) == -1 {
|
||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
continue
|
er = bytes.NewReader(w.rest.Bytes()[2:])
|
||||||
}
|
err := doTitleSequence(er)
|
||||||
if c2 != 0x5b {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
var m byte
|
|
||||||
for {
|
|
||||||
c, err := er.ReadByte()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
|
w.rest.Reset()
|
||||||
|
continue
|
||||||
|
// https://github.com/mattn/go-colorable/issues/27
|
||||||
|
case '7':
|
||||||
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
|
w.oldpos = csbi.cursorPosition
|
||||||
|
continue
|
||||||
|
case '8':
|
||||||
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos)))
|
||||||
|
continue
|
||||||
|
case 0x5b:
|
||||||
|
// execute part after switch
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
w.rest.WriteByte(c1)
|
||||||
|
w.rest.WriteByte(c2)
|
||||||
|
er.WriteTo(&w.rest)
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
var m byte
|
||||||
|
for i, c := range w.rest.Bytes()[2:] {
|
||||||
if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
|
if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
|
||||||
m = c
|
m = c
|
||||||
|
er = bytes.NewReader(w.rest.Bytes()[2+i+1:])
|
||||||
|
w.rest.Reset()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
buf.Write([]byte(string(c)))
|
buf.Write([]byte(string(c)))
|
||||||
}
|
}
|
||||||
|
if m == 0 {
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
|
||||||
switch m {
|
switch m {
|
||||||
case 'A':
|
case 'A':
|
||||||
@@ -455,61 +504,64 @@ loop:
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
csbi.cursorPosition.y -= short(n)
|
csbi.cursorPosition.y -= short(n)
|
||||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||||
case 'B':
|
case 'B':
|
||||||
n, err = strconv.Atoi(buf.String())
|
n, err = strconv.Atoi(buf.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
csbi.cursorPosition.y += short(n)
|
csbi.cursorPosition.y += short(n)
|
||||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||||
case 'C':
|
case 'C':
|
||||||
n, err = strconv.Atoi(buf.String())
|
n, err = strconv.Atoi(buf.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
csbi.cursorPosition.x += short(n)
|
csbi.cursorPosition.x += short(n)
|
||||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||||
case 'D':
|
case 'D':
|
||||||
n, err = strconv.Atoi(buf.String())
|
n, err = strconv.Atoi(buf.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
csbi.cursorPosition.x -= short(n)
|
csbi.cursorPosition.x -= short(n)
|
||||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
if csbi.cursorPosition.x < 0 {
|
||||||
|
csbi.cursorPosition.x = 0
|
||||||
|
}
|
||||||
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||||
case 'E':
|
case 'E':
|
||||||
n, err = strconv.Atoi(buf.String())
|
n, err = strconv.Atoi(buf.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
csbi.cursorPosition.x = 0
|
csbi.cursorPosition.x = 0
|
||||||
csbi.cursorPosition.y += short(n)
|
csbi.cursorPosition.y += short(n)
|
||||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||||
case 'F':
|
case 'F':
|
||||||
n, err = strconv.Atoi(buf.String())
|
n, err = strconv.Atoi(buf.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
csbi.cursorPosition.x = 0
|
csbi.cursorPosition.x = 0
|
||||||
csbi.cursorPosition.y -= short(n)
|
csbi.cursorPosition.y -= short(n)
|
||||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||||
case 'G':
|
case 'G':
|
||||||
n, err = strconv.Atoi(buf.String())
|
n, err = strconv.Atoi(buf.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
csbi.cursorPosition.x = short(n - 1)
|
csbi.cursorPosition.x = short(n - 1)
|
||||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||||
case 'H', 'f':
|
case 'H', 'f':
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
if buf.Len() > 0 {
|
if buf.Len() > 0 {
|
||||||
token := strings.Split(buf.String(), ";")
|
token := strings.Split(buf.String(), ";")
|
||||||
switch len(token) {
|
switch len(token) {
|
||||||
@@ -534,7 +586,7 @@ loop:
|
|||||||
} else {
|
} else {
|
||||||
csbi.cursorPosition.y = 0
|
csbi.cursorPosition.y = 0
|
||||||
}
|
}
|
||||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||||
case 'J':
|
case 'J':
|
||||||
n := 0
|
n := 0
|
||||||
if buf.Len() > 0 {
|
if buf.Len() > 0 {
|
||||||
@@ -545,20 +597,20 @@ loop:
|
|||||||
}
|
}
|
||||||
var count, written dword
|
var count, written dword
|
||||||
var cursor coord
|
var cursor coord
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
switch n {
|
switch n {
|
||||||
case 0:
|
case 0:
|
||||||
cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
|
cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
|
||||||
count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.size.y-csbi.cursorPosition.y)*csbi.size.x)
|
count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*dword(csbi.size.x)
|
||||||
case 1:
|
case 1:
|
||||||
cursor = coord{x: csbi.window.left, y: csbi.window.top}
|
cursor = coord{x: csbi.window.left, y: csbi.window.top}
|
||||||
count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.window.top-csbi.cursorPosition.y)*csbi.size.x)
|
count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.window.top-csbi.cursorPosition.y)*dword(csbi.size.x)
|
||||||
case 2:
|
case 2:
|
||||||
cursor = coord{x: csbi.window.left, y: csbi.window.top}
|
cursor = coord{x: csbi.window.left, y: csbi.window.top}
|
||||||
count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.size.y-csbi.cursorPosition.y)*csbi.size.x)
|
count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*dword(csbi.size.x)
|
||||||
}
|
}
|
||||||
procFillConsoleOutputCharacter.Call(uintptr(w.handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
||||||
procFillConsoleOutputAttribute.Call(uintptr(w.handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
||||||
case 'K':
|
case 'K':
|
||||||
n := 0
|
n := 0
|
||||||
if buf.Len() > 0 {
|
if buf.Len() > 0 {
|
||||||
@@ -567,28 +619,28 @@ loop:
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
var cursor coord
|
var cursor coord
|
||||||
var count, written dword
|
var count, written dword
|
||||||
switch n {
|
switch n {
|
||||||
case 0:
|
case 0:
|
||||||
cursor = coord{x: csbi.cursorPosition.x + 1, y: csbi.cursorPosition.y}
|
cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
|
||||||
count = dword(csbi.size.x - csbi.cursorPosition.x - 1)
|
count = dword(csbi.size.x - csbi.cursorPosition.x)
|
||||||
case 1:
|
case 1:
|
||||||
cursor = coord{x: csbi.window.left, y: csbi.window.top + csbi.cursorPosition.y}
|
cursor = coord{x: csbi.window.left, y: csbi.cursorPosition.y}
|
||||||
count = dword(csbi.size.x - csbi.cursorPosition.x)
|
count = dword(csbi.size.x - csbi.cursorPosition.x)
|
||||||
case 2:
|
case 2:
|
||||||
cursor = coord{x: csbi.window.left, y: csbi.window.top + csbi.cursorPosition.y}
|
cursor = coord{x: csbi.window.left, y: csbi.cursorPosition.y}
|
||||||
count = dword(csbi.size.x)
|
count = dword(csbi.size.x)
|
||||||
}
|
}
|
||||||
procFillConsoleOutputCharacter.Call(uintptr(w.handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
||||||
procFillConsoleOutputAttribute.Call(uintptr(w.handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
||||||
case 'm':
|
case 'm':
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
attr := csbi.attributes
|
attr := csbi.attributes
|
||||||
cs := buf.String()
|
cs := buf.String()
|
||||||
if cs == "" {
|
if cs == "" {
|
||||||
procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(w.oldattr))
|
procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(w.oldattr))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
token := strings.Split(cs, ";")
|
token := strings.Split(cs, ";")
|
||||||
@@ -627,6 +679,21 @@ loop:
|
|||||||
attr |= n256foreAttr[n256]
|
attr |= n256foreAttr[n256]
|
||||||
i += 2
|
i += 2
|
||||||
}
|
}
|
||||||
|
} else if len(token) == 5 && token[i+1] == "2" {
|
||||||
|
var r, g, b int
|
||||||
|
r, _ = strconv.Atoi(token[i+2])
|
||||||
|
g, _ = strconv.Atoi(token[i+3])
|
||||||
|
b, _ = strconv.Atoi(token[i+4])
|
||||||
|
i += 4
|
||||||
|
if r > 127 {
|
||||||
|
attr |= foregroundRed
|
||||||
|
}
|
||||||
|
if g > 127 {
|
||||||
|
attr |= foregroundGreen
|
||||||
|
}
|
||||||
|
if b > 127 {
|
||||||
|
attr |= foregroundBlue
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
attr = attr & (w.oldattr & backgroundMask)
|
attr = attr & (w.oldattr & backgroundMask)
|
||||||
}
|
}
|
||||||
@@ -654,6 +721,21 @@ loop:
|
|||||||
attr |= n256backAttr[n256]
|
attr |= n256backAttr[n256]
|
||||||
i += 2
|
i += 2
|
||||||
}
|
}
|
||||||
|
} else if len(token) == 5 && token[i+1] == "2" {
|
||||||
|
var r, g, b int
|
||||||
|
r, _ = strconv.Atoi(token[i+2])
|
||||||
|
g, _ = strconv.Atoi(token[i+3])
|
||||||
|
b, _ = strconv.Atoi(token[i+4])
|
||||||
|
i += 4
|
||||||
|
if r > 127 {
|
||||||
|
attr |= backgroundRed
|
||||||
|
}
|
||||||
|
if g > 127 {
|
||||||
|
attr |= backgroundGreen
|
||||||
|
}
|
||||||
|
if b > 127 {
|
||||||
|
attr |= backgroundBlue
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
attr = attr & (w.oldattr & foregroundMask)
|
attr = attr & (w.oldattr & foregroundMask)
|
||||||
}
|
}
|
||||||
@@ -685,38 +767,52 @@ loop:
|
|||||||
attr |= backgroundBlue
|
attr |= backgroundBlue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(attr))
|
procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(attr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 'h':
|
case 'h':
|
||||||
var ci consoleCursorInfo
|
var ci consoleCursorInfo
|
||||||
cs := buf.String()
|
cs := buf.String()
|
||||||
if cs == "5>" {
|
if cs == "5>" {
|
||||||
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
||||||
ci.visible = 0
|
ci.visible = 0
|
||||||
procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
||||||
} else if cs == "?25" {
|
} else if cs == "?25" {
|
||||||
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
||||||
ci.visible = 1
|
ci.visible = 1
|
||||||
procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
||||||
|
} else if cs == "?1049" {
|
||||||
|
if w.althandle == 0 {
|
||||||
|
h, _, _ := procCreateConsoleScreenBuffer.Call(uintptr(genericRead|genericWrite), 0, 0, uintptr(consoleTextmodeBuffer), 0, 0)
|
||||||
|
w.althandle = syscall.Handle(h)
|
||||||
|
if w.althandle != 0 {
|
||||||
|
handle = w.althandle
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case 'l':
|
case 'l':
|
||||||
var ci consoleCursorInfo
|
var ci consoleCursorInfo
|
||||||
cs := buf.String()
|
cs := buf.String()
|
||||||
if cs == "5>" {
|
if cs == "5>" {
|
||||||
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
||||||
ci.visible = 1
|
ci.visible = 1
|
||||||
procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
||||||
} else if cs == "?25" {
|
} else if cs == "?25" {
|
||||||
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
||||||
ci.visible = 0
|
ci.visible = 0
|
||||||
procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
||||||
|
} else if cs == "?1049" {
|
||||||
|
if w.althandle != 0 {
|
||||||
|
syscall.CloseHandle(w.althandle)
|
||||||
|
w.althandle = 0
|
||||||
|
handle = w.handle
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case 's':
|
case 's':
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
w.oldpos = csbi.cursorPosition
|
w.oldpos = csbi.cursorPosition
|
||||||
case 'u':
|
case 'u':
|
||||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&w.oldpos)))
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
3
vendor/github.com/mattn/go-colorable/go.mod
generated
vendored
Normal file
3
vendor/github.com/mattn/go-colorable/go.mod
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module github.com/mattn/go-colorable
|
||||||
|
|
||||||
|
require github.com/mattn/go-isatty v0.0.5
|
||||||
4
vendor/github.com/mattn/go-colorable/go.sum
generated
vendored
Normal file
4
vendor/github.com/mattn/go-colorable/go.sum
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw=
|
||||||
|
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
|
||||||
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
3
vendor/github.com/mattn/go-isatty/go.mod
generated
vendored
Normal file
3
vendor/github.com/mattn/go-isatty/go.mod
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module github.com/mattn/go-isatty
|
||||||
|
|
||||||
|
require golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223
|
||||||
2
vendor/github.com/mattn/go-isatty/go.sum
generated
vendored
Normal file
2
vendor/github.com/mattn/go-isatty/go.sum
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
|
||||||
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
15
vendor/github.com/mattn/go-isatty/isatty_appengine.go
generated
vendored
15
vendor/github.com/mattn/go-isatty/isatty_appengine.go
generated
vendored
@@ -1,15 +0,0 @@
|
|||||||
// +build appengine
|
|
||||||
|
|
||||||
package isatty
|
|
||||||
|
|
||||||
// IsTerminal returns true if the file descriptor is terminal which
|
|
||||||
// is always false on on appengine classic which is a sandboxed PaaS.
|
|
||||||
func IsTerminal(fd uintptr) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
|
|
||||||
// terminal. This is also always false on this environment.
|
|
||||||
func IsCygwinTerminal(fd uintptr) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
6
vendor/github.com/mattn/go-isatty/isatty_bsd.go
generated
vendored
6
vendor/github.com/mattn/go-isatty/isatty_bsd.go
generated
vendored
@@ -16,3 +16,9 @@ func IsTerminal(fd uintptr) bool {
|
|||||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
||||||
return err == 0
|
return err == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
|
||||||
|
// terminal. This is also always false on this environment.
|
||||||
|
func IsCygwinTerminal(fd uintptr) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
20
vendor/github.com/mattn/go-isatty/isatty_linux.go
generated
vendored
20
vendor/github.com/mattn/go-isatty/isatty_linux.go
generated
vendored
@@ -1,18 +1,18 @@
|
|||||||
// +build linux
|
// +build linux
|
||||||
// +build !appengine,!ppc64,!ppc64le
|
// +build !appengine
|
||||||
|
|
||||||
package isatty
|
package isatty
|
||||||
|
|
||||||
import (
|
import "golang.org/x/sys/unix"
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
const ioctlReadTermios = syscall.TCGETS
|
|
||||||
|
|
||||||
// IsTerminal return true if the file descriptor is terminal.
|
// IsTerminal return true if the file descriptor is terminal.
|
||||||
func IsTerminal(fd uintptr) bool {
|
func IsTerminal(fd uintptr) bool {
|
||||||
var termios syscall.Termios
|
_, err := unix.IoctlGetTermios(int(fd), unix.TCGETS)
|
||||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
return err == nil
|
||||||
return err == 0
|
}
|
||||||
|
|
||||||
|
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
|
||||||
|
// terminal. This is also always false on this environment.
|
||||||
|
func IsCygwinTerminal(fd uintptr) bool {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
19
vendor/github.com/mattn/go-isatty/isatty_linux_ppc64x.go
generated
vendored
19
vendor/github.com/mattn/go-isatty/isatty_linux_ppc64x.go
generated
vendored
@@ -1,19 +0,0 @@
|
|||||||
// +build linux
|
|
||||||
// +build ppc64 ppc64le
|
|
||||||
|
|
||||||
package isatty
|
|
||||||
|
|
||||||
import (
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
syscall "golang.org/x/sys/unix"
|
|
||||||
)
|
|
||||||
|
|
||||||
const ioctlReadTermios = syscall.TCGETS
|
|
||||||
|
|
||||||
// IsTerminal return true if the file descriptor is terminal.
|
|
||||||
func IsTerminal(fd uintptr) bool {
|
|
||||||
var termios syscall.Termios
|
|
||||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
|
||||||
return err == 0
|
|
||||||
}
|
|
||||||
11
vendor/github.com/mattn/go-isatty/isatty_others.go
generated
vendored
11
vendor/github.com/mattn/go-isatty/isatty_others.go
generated
vendored
@@ -1,9 +1,14 @@
|
|||||||
// +build !windows
|
// +build appengine js
|
||||||
// +build !appengine
|
|
||||||
|
|
||||||
package isatty
|
package isatty
|
||||||
|
|
||||||
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
|
// IsTerminal returns true if the file descriptor is terminal which
|
||||||
|
// is always false on js and appengine classic which is a sandboxed PaaS.
|
||||||
|
func IsTerminal(fd uintptr) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
|
||||||
// terminal. This is also always false on this environment.
|
// terminal. This is also always false on this environment.
|
||||||
func IsCygwinTerminal(fd uintptr) bool {
|
func IsCygwinTerminal(fd uintptr) bool {
|
||||||
return false
|
return false
|
||||||
|
|||||||
6
vendor/github.com/mattn/go-isatty/isatty_solaris.go
generated
vendored
6
vendor/github.com/mattn/go-isatty/isatty_solaris.go
generated
vendored
@@ -14,3 +14,9 @@ func IsTerminal(fd uintptr) bool {
|
|||||||
err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio)
|
err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio)
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
|
||||||
|
// terminal. This is also always false on this environment.
|
||||||
|
func IsCygwinTerminal(fd uintptr) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
27
vendor/github.com/russross/blackfriday/.travis.yml
generated
vendored
27
vendor/github.com/russross/blackfriday/.travis.yml
generated
vendored
@@ -1,18 +1,17 @@
|
|||||||
# Travis CI (http://travis-ci.org/) is a continuous integration service for
|
sudo: false
|
||||||
# open source projects. This file configures it to run unit tests for
|
|
||||||
# blackfriday.
|
|
||||||
|
|
||||||
language: go
|
language: go
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.5
|
- "1.9.x"
|
||||||
- 1.6
|
- "1.10.x"
|
||||||
- 1.7
|
- tip
|
||||||
|
matrix:
|
||||||
|
fast_finish: true
|
||||||
|
allow_failures:
|
||||||
|
- go: tip
|
||||||
install:
|
install:
|
||||||
- go get -d -t -v ./...
|
- # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step).
|
||||||
- go build -v ./...
|
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- go test -v ./...
|
- go get -t -v ./...
|
||||||
- go test -run=^$ -bench=BenchmarkReference -benchmem
|
- diff -u <(echo -n) <(gofmt -d -s .)
|
||||||
|
- go tool vet .
|
||||||
|
- go test -v -race ./...
|
||||||
|
|||||||
130
vendor/github.com/russross/blackfriday/README.md
generated
vendored
130
vendor/github.com/russross/blackfriday/README.md
generated
vendored
@@ -1,4 +1,6 @@
|
|||||||
Blackfriday [](https://travis-ci.org/russross/blackfriday)
|
Blackfriday
|
||||||
|
[![Build Status][BuildSVG]][BuildURL]
|
||||||
|
[![Godoc][GodocV2SVG]][GodocV2URL]
|
||||||
===========
|
===========
|
||||||
|
|
||||||
Blackfriday is a [Markdown][1] processor implemented in [Go][2]. It
|
Blackfriday is a [Markdown][1] processor implemented in [Go][2]. It
|
||||||
@@ -16,27 +18,27 @@ It started as a translation from C of [Sundown][3].
|
|||||||
Installation
|
Installation
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Blackfriday is compatible with any modern Go release. With Go 1.7 and git
|
Blackfriday is compatible with any modern Go release. With Go and git installed:
|
||||||
installed:
|
|
||||||
|
|
||||||
go get gopkg.in/russross/blackfriday.v2
|
go get -u gopkg.in/russross/blackfriday.v2
|
||||||
|
|
||||||
will download, compile, and install the package into your `$GOPATH`
|
will download, compile, and install the package into your `$GOPATH` directory
|
||||||
directory hierarchy. Alternatively, you can achieve the same if you
|
hierarchy.
|
||||||
import it into a project:
|
|
||||||
|
|
||||||
import "gopkg.in/russross/blackfriday.v2"
|
|
||||||
|
|
||||||
and `go get` without parameters.
|
|
||||||
|
|
||||||
|
|
||||||
Versions
|
Versions
|
||||||
--------
|
--------
|
||||||
|
|
||||||
Currently maintained and recommended version of Blackfriday is `v2`. It's being
|
Currently maintained and recommended version of Blackfriday is `v2`. It's being
|
||||||
developed on its own branch: https://github.com/russross/blackfriday/v2. You
|
developed on its own branch: https://github.com/russross/blackfriday/tree/v2 and the
|
||||||
should install and import it via [gopkg.in][6] at
|
documentation is available at
|
||||||
`gopkg.in/russross/blackfriday.v2`.
|
https://godoc.org/gopkg.in/russross/blackfriday.v2.
|
||||||
|
|
||||||
|
It is `go get`-able via [gopkg.in][6] at `gopkg.in/russross/blackfriday.v2`,
|
||||||
|
but we highly recommend using package management tool like [dep][7] or
|
||||||
|
[Glide][8] and make use of semantic versioning. With package management you
|
||||||
|
should import `github.com/russross/blackfriday` and specify that you're using
|
||||||
|
version 2.0.0.
|
||||||
|
|
||||||
Version 2 offers a number of improvements over v1:
|
Version 2 offers a number of improvements over v1:
|
||||||
|
|
||||||
@@ -56,9 +58,43 @@ Potential drawbacks:
|
|||||||
v2. See issue [#348](https://github.com/russross/blackfriday/issues/348) for
|
v2. See issue [#348](https://github.com/russross/blackfriday/issues/348) for
|
||||||
tracking.
|
tracking.
|
||||||
|
|
||||||
|
If you are still interested in the legacy `v1`, you can import it from
|
||||||
|
`github.com/russross/blackfriday`. Documentation for the legacy v1 can be found
|
||||||
|
here: https://godoc.org/github.com/russross/blackfriday
|
||||||
|
|
||||||
|
### Known issue with `dep`
|
||||||
|
|
||||||
|
There is a known problem with using Blackfriday v1 _transitively_ and `dep`.
|
||||||
|
Currently `dep` prioritizes semver versions over anything else, and picks the
|
||||||
|
latest one, plus it does not apply a `[[constraint]]` specifier to transitively
|
||||||
|
pulled in packages. So if you're using something that uses Blackfriday v1, but
|
||||||
|
that something does not use `dep` yet, you will get Blackfriday v2 pulled in and
|
||||||
|
your first dependency will fail to build.
|
||||||
|
|
||||||
|
There are couple of fixes for it, documented here:
|
||||||
|
https://github.com/golang/dep/blob/master/docs/FAQ.md#how-do-i-constrain-a-transitive-dependencys-version
|
||||||
|
|
||||||
|
Meanwhile, `dep` team is working on a more general solution to the constraints
|
||||||
|
on transitive dependencies problem: https://github.com/golang/dep/issues/1124.
|
||||||
|
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
### v1
|
||||||
|
|
||||||
|
For basic usage, it is as simple as getting your input into a byte
|
||||||
|
slice and calling:
|
||||||
|
|
||||||
|
output := blackfriday.MarkdownBasic(input)
|
||||||
|
|
||||||
|
This renders it with no extensions enabled. To get a more useful
|
||||||
|
feature set, use this instead:
|
||||||
|
|
||||||
|
output := blackfriday.MarkdownCommon(input)
|
||||||
|
|
||||||
|
### v2
|
||||||
|
|
||||||
For the most sensible markdown processing, it is as simple as getting your input
|
For the most sensible markdown processing, it is as simple as getting your input
|
||||||
into a byte slice and calling:
|
into a byte slice and calling:
|
||||||
|
|
||||||
@@ -85,7 +121,7 @@ Here's an example of simple usage of Blackfriday together with Bluemonday:
|
|||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"github.com/microcosm-cc/bluemonday"
|
"github.com/microcosm-cc/bluemonday"
|
||||||
"github.com/russross/blackfriday"
|
"gopkg.in/russross/blackfriday.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
@@ -93,11 +129,21 @@ unsafe := blackfriday.Run(input)
|
|||||||
html := bluemonday.UGCPolicy().SanitizeBytes(unsafe)
|
html := bluemonday.UGCPolicy().SanitizeBytes(unsafe)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Custom options
|
### Custom options, v1
|
||||||
|
|
||||||
|
If you want to customize the set of options, first get a renderer
|
||||||
|
(currently only the HTML output engine), then use it to
|
||||||
|
call the more general `Markdown` function. For examples, see the
|
||||||
|
implementations of `MarkdownBasic` and `MarkdownCommon` in
|
||||||
|
`markdown.go`.
|
||||||
|
|
||||||
|
### Custom options, v2
|
||||||
|
|
||||||
If you want to customize the set of options, use `blackfriday.WithExtensions`,
|
If you want to customize the set of options, use `blackfriday.WithExtensions`,
|
||||||
`blackfriday.WithRenderer` and `blackfriday.WithRefOverride`.
|
`blackfriday.WithRenderer` and `blackfriday.WithRefOverride`.
|
||||||
|
|
||||||
|
### `blackfriday-tool`
|
||||||
|
|
||||||
You can also check out `blackfriday-tool` for a more complete example
|
You can also check out `blackfriday-tool` for a more complete example
|
||||||
of how to use it. Download and install it using:
|
of how to use it. Download and install it using:
|
||||||
|
|
||||||
@@ -117,6 +163,22 @@ installed in `$GOPATH/bin`. This is a statically-linked binary that
|
|||||||
can be copied to wherever you need it without worrying about
|
can be copied to wherever you need it without worrying about
|
||||||
dependencies and library versions.
|
dependencies and library versions.
|
||||||
|
|
||||||
|
### Sanitized anchor names
|
||||||
|
|
||||||
|
Blackfriday includes an algorithm for creating sanitized anchor names
|
||||||
|
corresponding to a given input text. This algorithm is used to create
|
||||||
|
anchors for headings when `EXTENSION_AUTO_HEADER_IDS` is enabled. The
|
||||||
|
algorithm has a specification, so that other packages can create
|
||||||
|
compatible anchor names and links to those anchors.
|
||||||
|
|
||||||
|
The specification is located at https://godoc.org/github.com/russross/blackfriday#hdr-Sanitized_Anchor_Names.
|
||||||
|
|
||||||
|
[`SanitizedAnchorName`](https://godoc.org/github.com/russross/blackfriday#SanitizedAnchorName) exposes this functionality, and can be used to
|
||||||
|
create compatible links to the anchor names generated by blackfriday.
|
||||||
|
This algorithm is also implemented in a small standalone package at
|
||||||
|
[`github.com/shurcooL/sanitized_anchor_name`](https://godoc.org/github.com/shurcooL/sanitized_anchor_name). It can be useful for clients
|
||||||
|
that want a small package and don't need full functionality of blackfriday.
|
||||||
|
|
||||||
|
|
||||||
Features
|
Features
|
||||||
--------
|
--------
|
||||||
@@ -184,7 +246,7 @@ implements the following extensions:
|
|||||||
and supply a language (to make syntax highlighting simple). Just
|
and supply a language (to make syntax highlighting simple). Just
|
||||||
mark it like this:
|
mark it like this:
|
||||||
|
|
||||||
```go
|
``` go
|
||||||
func getTrue() bool {
|
func getTrue() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -193,6 +255,15 @@ implements the following extensions:
|
|||||||
You can use 3 or more backticks to mark the beginning of the
|
You can use 3 or more backticks to mark the beginning of the
|
||||||
block, and the same number to mark the end of the block.
|
block, and the same number to mark the end of the block.
|
||||||
|
|
||||||
|
To preserve classes of fenced code blocks while using the bluemonday
|
||||||
|
HTML sanitizer, use the following policy:
|
||||||
|
|
||||||
|
``` go
|
||||||
|
p := bluemonday.UGCPolicy()
|
||||||
|
p.AllowAttrs("class").Matching(regexp.MustCompile("^language-[a-zA-Z0-9]+$")).OnElements("code")
|
||||||
|
html := p.SanitizeBytes(unsafe)
|
||||||
|
```
|
||||||
|
|
||||||
* **Definition lists**. A simple definition list is made of a single-line
|
* **Definition lists**. A simple definition list is made of a single-line
|
||||||
term followed by a colon and the definition for that term.
|
term followed by a colon and the definition for that term.
|
||||||
|
|
||||||
@@ -218,8 +289,10 @@ implements the following extensions:
|
|||||||
* **Strikethrough**. Use two tildes (`~~`) to mark text that
|
* **Strikethrough**. Use two tildes (`~~`) to mark text that
|
||||||
should be crossed out.
|
should be crossed out.
|
||||||
|
|
||||||
* **Hard line breaks**. With this extension enabled newlines in the input
|
* **Hard line breaks**. With this extension enabled (it is off by
|
||||||
translate into line breaks in the output. This extension is off by default.
|
default in the `MarkdownBasic` and `MarkdownCommon` convenience
|
||||||
|
functions), newlines in the input translate into line breaks in
|
||||||
|
the output.
|
||||||
|
|
||||||
* **Smart quotes**. Smartypants-style punctuation substitution is
|
* **Smart quotes**. Smartypants-style punctuation substitution is
|
||||||
supported, turning normal double- and single-quote marks into
|
supported, turning normal double- and single-quote marks into
|
||||||
@@ -258,15 +331,21 @@ are a few of note:
|
|||||||
* [LaTeX output](https://bitbucket.org/ambrevar/blackfriday-latex):
|
* [LaTeX output](https://bitbucket.org/ambrevar/blackfriday-latex):
|
||||||
renders output as LaTeX.
|
renders output as LaTeX.
|
||||||
|
|
||||||
|
* [bfchroma](https://github.com/Depado/bfchroma/): provides convenience
|
||||||
|
integration with the [Chroma](https://github.com/alecthomas/chroma) code
|
||||||
|
highlighting library. bfchroma is only compatible with v2 of Blackfriday and
|
||||||
|
provides a drop-in renderer ready to use with Blackfriday, as well as
|
||||||
|
options and means for further customization.
|
||||||
|
|
||||||
Todo
|
|
||||||
|
TODO
|
||||||
----
|
----
|
||||||
|
|
||||||
* More unit testing
|
* More unit testing
|
||||||
* Improve unicode support. It does not understand all unicode
|
* Improve Unicode support. It does not understand all Unicode
|
||||||
rules (about what constitutes a letter, a punctuation symbol,
|
rules (about what constitutes a letter, a punctuation symbol,
|
||||||
etc.), so it may fail to detect word boundaries correctly in
|
etc.), so it may fail to detect word boundaries correctly in
|
||||||
some instances. It is safe on all utf-8 input.
|
some instances. It is safe on all UTF-8 input.
|
||||||
|
|
||||||
|
|
||||||
License
|
License
|
||||||
@@ -281,3 +360,10 @@ License
|
|||||||
[4]: https://godoc.org/gopkg.in/russross/blackfriday.v2#Parse "Parse func"
|
[4]: https://godoc.org/gopkg.in/russross/blackfriday.v2#Parse "Parse func"
|
||||||
[5]: https://github.com/microcosm-cc/bluemonday "Bluemonday"
|
[5]: https://github.com/microcosm-cc/bluemonday "Bluemonday"
|
||||||
[6]: https://labix.org/gopkg.in "gopkg.in"
|
[6]: https://labix.org/gopkg.in "gopkg.in"
|
||||||
|
[7]: https://github.com/golang/dep/ "dep"
|
||||||
|
[8]: https://github.com/Masterminds/glide "Glide"
|
||||||
|
|
||||||
|
[BuildSVG]: https://travis-ci.org/russross/blackfriday.svg?branch=master
|
||||||
|
[BuildURL]: https://travis-ci.org/russross/blackfriday
|
||||||
|
[GodocV2SVG]: https://godoc.org/gopkg.in/russross/blackfriday.v2?status.svg
|
||||||
|
[GodocV2URL]: https://godoc.org/gopkg.in/russross/blackfriday.v2
|
||||||
|
|||||||
851
vendor/github.com/russross/blackfriday/block.go
generated
vendored
851
vendor/github.com/russross/blackfriday/block.go
generated
vendored
File diff suppressed because it is too large
Load Diff
40
vendor/github.com/russross/blackfriday/doc.go
generated
vendored
40
vendor/github.com/russross/blackfriday/doc.go
generated
vendored
@@ -1,18 +1,32 @@
|
|||||||
// Package blackfriday is a markdown processor.
|
// Package blackfriday is a Markdown processor.
|
||||||
//
|
//
|
||||||
// It translates plain text with simple formatting rules into an AST, which can
|
// It translates plain text with simple formatting rules into HTML or LaTeX.
|
||||||
// then be further processed to HTML (provided by Blackfriday itself) or other
|
|
||||||
// formats (provided by the community).
|
|
||||||
//
|
//
|
||||||
// The simplest way to invoke Blackfriday is to call the Run function. It will
|
// Sanitized Anchor Names
|
||||||
// take a text input and produce a text output in HTML (or other format).
|
|
||||||
//
|
//
|
||||||
// A slightly more sophisticated way to use Blackfriday is to create a Markdown
|
// Blackfriday includes an algorithm for creating sanitized anchor names
|
||||||
// processor and to call Parse, which returns a syntax tree for the input
|
// corresponding to a given input text. This algorithm is used to create
|
||||||
// document. You can leverage Blackfriday's parsing for content extraction from
|
// anchors for headings when EXTENSION_AUTO_HEADER_IDS is enabled. The
|
||||||
// markdown documents. You can assign a custom renderer and set various options
|
// algorithm is specified below, so that other packages can create
|
||||||
// to the Markdown processor.
|
// compatible anchor names and links to those anchors.
|
||||||
//
|
//
|
||||||
// If you're interested in calling Blackfriday from command line, see
|
// The algorithm iterates over the input text, interpreted as UTF-8,
|
||||||
// https://github.com/russross/blackfriday-tool.
|
// one Unicode code point (rune) at a time. All runes that are letters (category L)
|
||||||
|
// or numbers (category N) are considered valid characters. They are mapped to
|
||||||
|
// lower case, and included in the output. All other runes are considered
|
||||||
|
// invalid characters. Invalid characters that preceed the first valid character,
|
||||||
|
// as well as invalid character that follow the last valid character
|
||||||
|
// are dropped completely. All other sequences of invalid characters
|
||||||
|
// between two valid characters are replaced with a single dash character '-'.
|
||||||
|
//
|
||||||
|
// SanitizedAnchorName exposes this functionality, and can be used to
|
||||||
|
// create compatible links to the anchor names generated by blackfriday.
|
||||||
|
// This algorithm is also implemented in a small standalone package at
|
||||||
|
// github.com/shurcooL/sanitized_anchor_name. It can be useful for clients
|
||||||
|
// that want a small package and don't need full functionality of blackfriday.
|
||||||
package blackfriday
|
package blackfriday
|
||||||
|
|
||||||
|
// NOTE: Keep Sanitized Anchor Name algorithm in sync with package
|
||||||
|
// github.com/shurcooL/sanitized_anchor_name.
|
||||||
|
// Otherwise, users of sanitized_anchor_name will get anchor names
|
||||||
|
// that are incompatible with those generated by blackfriday.
|
||||||
|
|||||||
34
vendor/github.com/russross/blackfriday/esc.go
generated
vendored
34
vendor/github.com/russross/blackfriday/esc.go
generated
vendored
@@ -1,34 +0,0 @@
|
|||||||
package blackfriday
|
|
||||||
|
|
||||||
import (
|
|
||||||
"html"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
var htmlEscaper = [256][]byte{
|
|
||||||
'&': []byte("&"),
|
|
||||||
'<': []byte("<"),
|
|
||||||
'>': []byte(">"),
|
|
||||||
'"': []byte("""),
|
|
||||||
}
|
|
||||||
|
|
||||||
func escapeHTML(w io.Writer, s []byte) {
|
|
||||||
var start, end int
|
|
||||||
for end < len(s) {
|
|
||||||
escSeq := htmlEscaper[s[end]]
|
|
||||||
if escSeq != nil {
|
|
||||||
w.Write(s[start:end])
|
|
||||||
w.Write(escSeq)
|
|
||||||
start = end + 1
|
|
||||||
}
|
|
||||||
end++
|
|
||||||
}
|
|
||||||
if start < len(s) && end <= len(s) {
|
|
||||||
w.Write(s[start:end])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func escLink(w io.Writer, text []byte) {
|
|
||||||
unesc := html.UnescapeString(string(text))
|
|
||||||
escapeHTML(w, []byte(unesc))
|
|
||||||
}
|
|
||||||
1
vendor/github.com/russross/blackfriday/go.mod
generated
vendored
Normal file
1
vendor/github.com/russross/blackfriday/go.mod
generated
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
module github.com/russross/blackfriday
|
||||||
1530
vendor/github.com/russross/blackfriday/html.go
generated
vendored
1530
vendor/github.com/russross/blackfriday/html.go
generated
vendored
File diff suppressed because it is too large
Load Diff
554
vendor/github.com/russross/blackfriday/inline.go
generated
vendored
554
vendor/github.com/russross/blackfriday/inline.go
generated
vendored
File diff suppressed because it is too large
Load Diff
334
vendor/github.com/russross/blackfriday/latex.go
generated
vendored
Normal file
334
vendor/github.com/russross/blackfriday/latex.go
generated
vendored
Normal file
@@ -0,0 +1,334 @@
|
|||||||
|
//
|
||||||
|
// Blackfriday Markdown Processor
|
||||||
|
// Available at http://github.com/russross/blackfriday
|
||||||
|
//
|
||||||
|
// Copyright © 2011 Russ Ross <russ@russross.com>.
|
||||||
|
// Distributed under the Simplified BSD License.
|
||||||
|
// See README.md for details.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// LaTeX rendering backend
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
package blackfriday
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Latex is a type that implements the Renderer interface for LaTeX output.
|
||||||
|
//
|
||||||
|
// Do not create this directly, instead use the LatexRenderer function.
|
||||||
|
type Latex struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// LatexRenderer creates and configures a Latex object, which
|
||||||
|
// satisfies the Renderer interface.
|
||||||
|
//
|
||||||
|
// flags is a set of LATEX_* options ORed together (currently no such options
|
||||||
|
// are defined).
|
||||||
|
func LatexRenderer(flags int) Renderer {
|
||||||
|
return &Latex{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) GetFlags() int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// render code chunks using verbatim, or listings if we have a language
|
||||||
|
func (options *Latex) BlockCode(out *bytes.Buffer, text []byte, info string) {
|
||||||
|
if info == "" {
|
||||||
|
out.WriteString("\n\\begin{verbatim}\n")
|
||||||
|
} else {
|
||||||
|
lang := strings.Fields(info)[0]
|
||||||
|
out.WriteString("\n\\begin{lstlisting}[language=")
|
||||||
|
out.WriteString(lang)
|
||||||
|
out.WriteString("]\n")
|
||||||
|
}
|
||||||
|
out.Write(text)
|
||||||
|
if info == "" {
|
||||||
|
out.WriteString("\n\\end{verbatim}\n")
|
||||||
|
} else {
|
||||||
|
out.WriteString("\n\\end{lstlisting}\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) TitleBlock(out *bytes.Buffer, text []byte) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) BlockQuote(out *bytes.Buffer, text []byte) {
|
||||||
|
out.WriteString("\n\\begin{quotation}\n")
|
||||||
|
out.Write(text)
|
||||||
|
out.WriteString("\n\\end{quotation}\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) BlockHtml(out *bytes.Buffer, text []byte) {
|
||||||
|
// a pretty lame thing to do...
|
||||||
|
out.WriteString("\n\\begin{verbatim}\n")
|
||||||
|
out.Write(text)
|
||||||
|
out.WriteString("\n\\end{verbatim}\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) Header(out *bytes.Buffer, text func() bool, level int, id string) {
|
||||||
|
marker := out.Len()
|
||||||
|
|
||||||
|
switch level {
|
||||||
|
case 1:
|
||||||
|
out.WriteString("\n\\section{")
|
||||||
|
case 2:
|
||||||
|
out.WriteString("\n\\subsection{")
|
||||||
|
case 3:
|
||||||
|
out.WriteString("\n\\subsubsection{")
|
||||||
|
case 4:
|
||||||
|
out.WriteString("\n\\paragraph{")
|
||||||
|
case 5:
|
||||||
|
out.WriteString("\n\\subparagraph{")
|
||||||
|
case 6:
|
||||||
|
out.WriteString("\n\\textbf{")
|
||||||
|
}
|
||||||
|
if !text() {
|
||||||
|
out.Truncate(marker)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
out.WriteString("}\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) HRule(out *bytes.Buffer) {
|
||||||
|
out.WriteString("\n\\HRule\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) List(out *bytes.Buffer, text func() bool, flags int) {
|
||||||
|
marker := out.Len()
|
||||||
|
if flags&LIST_TYPE_ORDERED != 0 {
|
||||||
|
out.WriteString("\n\\begin{enumerate}\n")
|
||||||
|
} else {
|
||||||
|
out.WriteString("\n\\begin{itemize}\n")
|
||||||
|
}
|
||||||
|
if !text() {
|
||||||
|
out.Truncate(marker)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if flags&LIST_TYPE_ORDERED != 0 {
|
||||||
|
out.WriteString("\n\\end{enumerate}\n")
|
||||||
|
} else {
|
||||||
|
out.WriteString("\n\\end{itemize}\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) ListItem(out *bytes.Buffer, text []byte, flags int) {
|
||||||
|
out.WriteString("\n\\item ")
|
||||||
|
out.Write(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) Paragraph(out *bytes.Buffer, text func() bool) {
|
||||||
|
marker := out.Len()
|
||||||
|
out.WriteString("\n")
|
||||||
|
if !text() {
|
||||||
|
out.Truncate(marker)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
out.WriteString("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) Table(out *bytes.Buffer, header []byte, body []byte, columnData []int) {
|
||||||
|
out.WriteString("\n\\begin{tabular}{")
|
||||||
|
for _, elt := range columnData {
|
||||||
|
switch elt {
|
||||||
|
case TABLE_ALIGNMENT_LEFT:
|
||||||
|
out.WriteByte('l')
|
||||||
|
case TABLE_ALIGNMENT_RIGHT:
|
||||||
|
out.WriteByte('r')
|
||||||
|
default:
|
||||||
|
out.WriteByte('c')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.WriteString("}\n")
|
||||||
|
out.Write(header)
|
||||||
|
out.WriteString(" \\\\\n\\hline\n")
|
||||||
|
out.Write(body)
|
||||||
|
out.WriteString("\n\\end{tabular}\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) TableRow(out *bytes.Buffer, text []byte) {
|
||||||
|
if out.Len() > 0 {
|
||||||
|
out.WriteString(" \\\\\n")
|
||||||
|
}
|
||||||
|
out.Write(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) TableHeaderCell(out *bytes.Buffer, text []byte, align int) {
|
||||||
|
if out.Len() > 0 {
|
||||||
|
out.WriteString(" & ")
|
||||||
|
}
|
||||||
|
out.Write(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) TableCell(out *bytes.Buffer, text []byte, align int) {
|
||||||
|
if out.Len() > 0 {
|
||||||
|
out.WriteString(" & ")
|
||||||
|
}
|
||||||
|
out.Write(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: this
|
||||||
|
func (options *Latex) Footnotes(out *bytes.Buffer, text func() bool) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) FootnoteItem(out *bytes.Buffer, name, text []byte, flags int) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) AutoLink(out *bytes.Buffer, link []byte, kind int) {
|
||||||
|
out.WriteString("\\href{")
|
||||||
|
if kind == LINK_TYPE_EMAIL {
|
||||||
|
out.WriteString("mailto:")
|
||||||
|
}
|
||||||
|
out.Write(link)
|
||||||
|
out.WriteString("}{")
|
||||||
|
out.Write(link)
|
||||||
|
out.WriteString("}")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) CodeSpan(out *bytes.Buffer, text []byte) {
|
||||||
|
out.WriteString("\\texttt{")
|
||||||
|
escapeSpecialChars(out, text)
|
||||||
|
out.WriteString("}")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) DoubleEmphasis(out *bytes.Buffer, text []byte) {
|
||||||
|
out.WriteString("\\textbf{")
|
||||||
|
out.Write(text)
|
||||||
|
out.WriteString("}")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) Emphasis(out *bytes.Buffer, text []byte) {
|
||||||
|
out.WriteString("\\textit{")
|
||||||
|
out.Write(text)
|
||||||
|
out.WriteString("}")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) {
|
||||||
|
if bytes.HasPrefix(link, []byte("http://")) || bytes.HasPrefix(link, []byte("https://")) {
|
||||||
|
// treat it like a link
|
||||||
|
out.WriteString("\\href{")
|
||||||
|
out.Write(link)
|
||||||
|
out.WriteString("}{")
|
||||||
|
out.Write(alt)
|
||||||
|
out.WriteString("}")
|
||||||
|
} else {
|
||||||
|
out.WriteString("\\includegraphics{")
|
||||||
|
out.Write(link)
|
||||||
|
out.WriteString("}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) LineBreak(out *bytes.Buffer) {
|
||||||
|
out.WriteString(" \\\\\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) Link(out *bytes.Buffer, link []byte, title []byte, content []byte) {
|
||||||
|
out.WriteString("\\href{")
|
||||||
|
out.Write(link)
|
||||||
|
out.WriteString("}{")
|
||||||
|
out.Write(content)
|
||||||
|
out.WriteString("}")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) RawHtmlTag(out *bytes.Buffer, tag []byte) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) TripleEmphasis(out *bytes.Buffer, text []byte) {
|
||||||
|
out.WriteString("\\textbf{\\textit{")
|
||||||
|
out.Write(text)
|
||||||
|
out.WriteString("}}")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) StrikeThrough(out *bytes.Buffer, text []byte) {
|
||||||
|
out.WriteString("\\sout{")
|
||||||
|
out.Write(text)
|
||||||
|
out.WriteString("}")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: this
|
||||||
|
func (options *Latex) FootnoteRef(out *bytes.Buffer, ref []byte, id int) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func needsBackslash(c byte) bool {
|
||||||
|
for _, r := range []byte("_{}%$&\\~#") {
|
||||||
|
if c == r {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func escapeSpecialChars(out *bytes.Buffer, text []byte) {
|
||||||
|
for i := 0; i < len(text); i++ {
|
||||||
|
// directly copy normal characters
|
||||||
|
org := i
|
||||||
|
|
||||||
|
for i < len(text) && !needsBackslash(text[i]) {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if i > org {
|
||||||
|
out.Write(text[org:i])
|
||||||
|
}
|
||||||
|
|
||||||
|
// escape a character
|
||||||
|
if i >= len(text) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
out.WriteByte('\\')
|
||||||
|
out.WriteByte(text[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) Entity(out *bytes.Buffer, entity []byte) {
|
||||||
|
// TODO: convert this into a unicode character or something
|
||||||
|
out.Write(entity)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) NormalText(out *bytes.Buffer, text []byte) {
|
||||||
|
escapeSpecialChars(out, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
// header and footer
|
||||||
|
func (options *Latex) DocumentHeader(out *bytes.Buffer) {
|
||||||
|
out.WriteString("\\documentclass{article}\n")
|
||||||
|
out.WriteString("\n")
|
||||||
|
out.WriteString("\\usepackage{graphicx}\n")
|
||||||
|
out.WriteString("\\usepackage{listings}\n")
|
||||||
|
out.WriteString("\\usepackage[margin=1in]{geometry}\n")
|
||||||
|
out.WriteString("\\usepackage[utf8]{inputenc}\n")
|
||||||
|
out.WriteString("\\usepackage{verbatim}\n")
|
||||||
|
out.WriteString("\\usepackage[normalem]{ulem}\n")
|
||||||
|
out.WriteString("\\usepackage{hyperref}\n")
|
||||||
|
out.WriteString("\n")
|
||||||
|
out.WriteString("\\hypersetup{colorlinks,%\n")
|
||||||
|
out.WriteString(" citecolor=black,%\n")
|
||||||
|
out.WriteString(" filecolor=black,%\n")
|
||||||
|
out.WriteString(" linkcolor=black,%\n")
|
||||||
|
out.WriteString(" urlcolor=black,%\n")
|
||||||
|
out.WriteString(" pdfstartview=FitH,%\n")
|
||||||
|
out.WriteString(" breaklinks=true,%\n")
|
||||||
|
out.WriteString(" pdfauthor={Blackfriday Markdown Processor v")
|
||||||
|
out.WriteString(VERSION)
|
||||||
|
out.WriteString("}}\n")
|
||||||
|
out.WriteString("\n")
|
||||||
|
out.WriteString("\\newcommand{\\HRule}{\\rule{\\linewidth}{0.5mm}}\n")
|
||||||
|
out.WriteString("\\addtolength{\\parskip}{0.5\\baselineskip}\n")
|
||||||
|
out.WriteString("\\parindent=0pt\n")
|
||||||
|
out.WriteString("\n")
|
||||||
|
out.WriteString("\\begin{document}\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options *Latex) DocumentFooter(out *bytes.Buffer) {
|
||||||
|
out.WriteString("\n\\end{document}\n")
|
||||||
|
}
|
||||||
765
vendor/github.com/russross/blackfriday/markdown.go
generated
vendored
765
vendor/github.com/russross/blackfriday/markdown.go
generated
vendored
@@ -1,200 +1,230 @@
|
|||||||
|
//
|
||||||
// Blackfriday Markdown Processor
|
// Blackfriday Markdown Processor
|
||||||
// Available at http://github.com/russross/blackfriday
|
// Available at http://github.com/russross/blackfriday
|
||||||
//
|
//
|
||||||
// Copyright © 2011 Russ Ross <russ@russross.com>.
|
// Copyright © 2011 Russ Ross <russ@russross.com>.
|
||||||
// Distributed under the Simplified BSD License.
|
// Distributed under the Simplified BSD License.
|
||||||
// See README.md for details.
|
// See README.md for details.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Markdown parsing and processing
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
package blackfriday
|
package blackfriday
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
//
|
const VERSION = "1.5"
|
||||||
// Markdown parsing and processing
|
|
||||||
//
|
|
||||||
|
|
||||||
// Version string of the package. Appears in the rendered document when
|
|
||||||
// CompletePage flag is on.
|
|
||||||
const Version = "2.0"
|
|
||||||
|
|
||||||
// Extensions is a bitwise or'ed collection of enabled Blackfriday's
|
|
||||||
// extensions.
|
|
||||||
type Extensions int
|
|
||||||
|
|
||||||
// These are the supported markdown parsing extensions.
|
// These are the supported markdown parsing extensions.
|
||||||
// OR these values together to select multiple extensions.
|
// OR these values together to select multiple extensions.
|
||||||
const (
|
const (
|
||||||
NoExtensions Extensions = 0
|
EXTENSION_NO_INTRA_EMPHASIS = 1 << iota // ignore emphasis markers inside words
|
||||||
NoIntraEmphasis Extensions = 1 << iota // Ignore emphasis markers inside words
|
EXTENSION_TABLES // render tables
|
||||||
Tables // Render tables
|
EXTENSION_FENCED_CODE // render fenced code blocks
|
||||||
FencedCode // Render fenced code blocks
|
EXTENSION_AUTOLINK // detect embedded URLs that are not explicitly marked
|
||||||
Autolink // Detect embedded URLs that are not explicitly marked
|
EXTENSION_STRIKETHROUGH // strikethrough text using ~~test~~
|
||||||
Strikethrough // Strikethrough text using ~~test~~
|
EXTENSION_LAX_HTML_BLOCKS // loosen up HTML block parsing rules
|
||||||
LaxHTMLBlocks // Loosen up HTML block parsing rules
|
EXTENSION_SPACE_HEADERS // be strict about prefix header rules
|
||||||
SpaceHeadings // Be strict about prefix heading rules
|
EXTENSION_HARD_LINE_BREAK // translate newlines into line breaks
|
||||||
HardLineBreak // Translate newlines into line breaks
|
EXTENSION_TAB_SIZE_EIGHT // expand tabs to eight spaces instead of four
|
||||||
TabSizeEight // Expand tabs to eight spaces instead of four
|
EXTENSION_FOOTNOTES // Pandoc-style footnotes
|
||||||
Footnotes // Pandoc-style footnotes
|
EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK // No need to insert an empty line to start a (code, quote, ordered list, unordered list) block
|
||||||
NoEmptyLineBeforeBlock // No need to insert an empty line to start a (code, quote, ordered list, unordered list) block
|
EXTENSION_HEADER_IDS // specify header IDs with {#id}
|
||||||
HeadingIDs // specify heading IDs with {#id}
|
EXTENSION_TITLEBLOCK // Titleblock ala pandoc
|
||||||
Titleblock // Titleblock ala pandoc
|
EXTENSION_AUTO_HEADER_IDS // Create the header ID from the text
|
||||||
AutoHeadingIDs // Create the heading ID from the text
|
EXTENSION_BACKSLASH_LINE_BREAK // translate trailing backslashes into line breaks
|
||||||
BackslashLineBreak // Translate trailing backslashes into line breaks
|
EXTENSION_DEFINITION_LISTS // render definition lists
|
||||||
DefinitionLists // Render definition lists
|
EXTENSION_JOIN_LINES // delete newline and join lines
|
||||||
|
|
||||||
CommonHTMLFlags HTMLFlags = UseXHTML | Smartypants |
|
commonHtmlFlags = 0 |
|
||||||
SmartypantsFractions | SmartypantsDashes | SmartypantsLatexDashes
|
HTML_USE_XHTML |
|
||||||
|
HTML_USE_SMARTYPANTS |
|
||||||
|
HTML_SMARTYPANTS_FRACTIONS |
|
||||||
|
HTML_SMARTYPANTS_DASHES |
|
||||||
|
HTML_SMARTYPANTS_LATEX_DASHES
|
||||||
|
|
||||||
CommonExtensions Extensions = NoIntraEmphasis | Tables | FencedCode |
|
commonExtensions = 0 |
|
||||||
Autolink | Strikethrough | SpaceHeadings | HeadingIDs |
|
EXTENSION_NO_INTRA_EMPHASIS |
|
||||||
BackslashLineBreak | DefinitionLists
|
EXTENSION_TABLES |
|
||||||
|
EXTENSION_FENCED_CODE |
|
||||||
|
EXTENSION_AUTOLINK |
|
||||||
|
EXTENSION_STRIKETHROUGH |
|
||||||
|
EXTENSION_SPACE_HEADERS |
|
||||||
|
EXTENSION_HEADER_IDS |
|
||||||
|
EXTENSION_BACKSLASH_LINE_BREAK |
|
||||||
|
EXTENSION_DEFINITION_LISTS
|
||||||
)
|
)
|
||||||
|
|
||||||
// ListType contains bitwise or'ed flags for list and list item objects.
|
// These are the possible flag values for the link renderer.
|
||||||
type ListType int
|
// Only a single one of these values will be used; they are not ORed together.
|
||||||
|
// These are mostly of interest if you are writing a new output format.
|
||||||
|
const (
|
||||||
|
LINK_TYPE_NOT_AUTOLINK = iota
|
||||||
|
LINK_TYPE_NORMAL
|
||||||
|
LINK_TYPE_EMAIL
|
||||||
|
)
|
||||||
|
|
||||||
// These are the possible flag values for the ListItem renderer.
|
// These are the possible flag values for the ListItem renderer.
|
||||||
// Multiple flag values may be ORed together.
|
// Multiple flag values may be ORed together.
|
||||||
// These are mostly of interest if you are writing a new output format.
|
// These are mostly of interest if you are writing a new output format.
|
||||||
const (
|
const (
|
||||||
ListTypeOrdered ListType = 1 << iota
|
LIST_TYPE_ORDERED = 1 << iota
|
||||||
ListTypeDefinition
|
LIST_TYPE_DEFINITION
|
||||||
ListTypeTerm
|
LIST_TYPE_TERM
|
||||||
|
LIST_ITEM_CONTAINS_BLOCK
|
||||||
ListItemContainsBlock
|
LIST_ITEM_BEGINNING_OF_LIST
|
||||||
ListItemBeginningOfList // TODO: figure out if this is of any use now
|
LIST_ITEM_END_OF_LIST
|
||||||
ListItemEndOfList
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CellAlignFlags holds a type of alignment in a table cell.
|
|
||||||
type CellAlignFlags int
|
|
||||||
|
|
||||||
// These are the possible flag values for the table cell renderer.
|
// These are the possible flag values for the table cell renderer.
|
||||||
// Only a single one of these values will be used; they are not ORed together.
|
// Only a single one of these values will be used; they are not ORed together.
|
||||||
// These are mostly of interest if you are writing a new output format.
|
// These are mostly of interest if you are writing a new output format.
|
||||||
const (
|
const (
|
||||||
TableAlignmentLeft CellAlignFlags = 1 << iota
|
TABLE_ALIGNMENT_LEFT = 1 << iota
|
||||||
TableAlignmentRight
|
TABLE_ALIGNMENT_RIGHT
|
||||||
TableAlignmentCenter = (TableAlignmentLeft | TableAlignmentRight)
|
TABLE_ALIGNMENT_CENTER = (TABLE_ALIGNMENT_LEFT | TABLE_ALIGNMENT_RIGHT)
|
||||||
)
|
)
|
||||||
|
|
||||||
// The size of a tab stop.
|
// The size of a tab stop.
|
||||||
const (
|
const (
|
||||||
TabSizeDefault = 4
|
TAB_SIZE_DEFAULT = 4
|
||||||
TabSizeDouble = 8
|
TAB_SIZE_EIGHT = 8
|
||||||
)
|
)
|
||||||
|
|
||||||
// blockTags is a set of tags that are recognized as HTML block tags.
|
// blockTags is a set of tags that are recognized as HTML block tags.
|
||||||
// Any of these can be included in markdown text without special escaping.
|
// Any of these can be included in markdown text without special escaping.
|
||||||
var blockTags = map[string]struct{}{
|
var blockTags = map[string]struct{}{
|
||||||
"blockquote": struct{}{},
|
"blockquote": {},
|
||||||
"del": struct{}{},
|
"del": {},
|
||||||
"div": struct{}{},
|
"div": {},
|
||||||
"dl": struct{}{},
|
"dl": {},
|
||||||
"fieldset": struct{}{},
|
"fieldset": {},
|
||||||
"form": struct{}{},
|
"form": {},
|
||||||
"h1": struct{}{},
|
"h1": {},
|
||||||
"h2": struct{}{},
|
"h2": {},
|
||||||
"h3": struct{}{},
|
"h3": {},
|
||||||
"h4": struct{}{},
|
"h4": {},
|
||||||
"h5": struct{}{},
|
"h5": {},
|
||||||
"h6": struct{}{},
|
"h6": {},
|
||||||
"iframe": struct{}{},
|
"iframe": {},
|
||||||
"ins": struct{}{},
|
"ins": {},
|
||||||
"math": struct{}{},
|
"math": {},
|
||||||
"noscript": struct{}{},
|
"noscript": {},
|
||||||
"ol": struct{}{},
|
"ol": {},
|
||||||
"pre": struct{}{},
|
"pre": {},
|
||||||
"p": struct{}{},
|
"p": {},
|
||||||
"script": struct{}{},
|
"script": {},
|
||||||
"style": struct{}{},
|
"style": {},
|
||||||
"table": struct{}{},
|
"table": {},
|
||||||
"ul": struct{}{},
|
"ul": {},
|
||||||
|
|
||||||
// HTML5
|
// HTML5
|
||||||
"address": struct{}{},
|
"address": {},
|
||||||
"article": struct{}{},
|
"article": {},
|
||||||
"aside": struct{}{},
|
"aside": {},
|
||||||
"canvas": struct{}{},
|
"canvas": {},
|
||||||
"figcaption": struct{}{},
|
"figcaption": {},
|
||||||
"figure": struct{}{},
|
"figure": {},
|
||||||
"footer": struct{}{},
|
"footer": {},
|
||||||
"header": struct{}{},
|
"header": {},
|
||||||
"hgroup": struct{}{},
|
"hgroup": {},
|
||||||
"main": struct{}{},
|
"main": {},
|
||||||
"nav": struct{}{},
|
"nav": {},
|
||||||
"output": struct{}{},
|
"output": {},
|
||||||
"progress": struct{}{},
|
"progress": {},
|
||||||
"section": struct{}{},
|
"section": {},
|
||||||
"video": struct{}{},
|
"video": {},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Renderer is the rendering interface. This is mostly of interest if you are
|
// Renderer is the rendering interface.
|
||||||
// implementing a new rendering format.
|
// This is mostly of interest if you are implementing a new rendering format.
|
||||||
//
|
//
|
||||||
// Only an HTML implementation is provided in this repository, see the README
|
// When a byte slice is provided, it contains the (rendered) contents of the
|
||||||
// for external implementations.
|
// element.
|
||||||
|
//
|
||||||
|
// When a callback is provided instead, it will write the contents of the
|
||||||
|
// respective element directly to the output buffer and return true on success.
|
||||||
|
// If the callback returns false, the rendering function should reset the
|
||||||
|
// output buffer as though it had never been called.
|
||||||
|
//
|
||||||
|
// Currently Html and Latex implementations are provided
|
||||||
type Renderer interface {
|
type Renderer interface {
|
||||||
// RenderNode is the main rendering method. It will be called once for
|
// block-level callbacks
|
||||||
// every leaf node and twice for every non-leaf node (first with
|
BlockCode(out *bytes.Buffer, text []byte, infoString string)
|
||||||
// entering=true, then with entering=false). The method should write its
|
BlockQuote(out *bytes.Buffer, text []byte)
|
||||||
// rendition of the node to the supplied writer w.
|
BlockHtml(out *bytes.Buffer, text []byte)
|
||||||
RenderNode(w io.Writer, node *Node, entering bool) WalkStatus
|
Header(out *bytes.Buffer, text func() bool, level int, id string)
|
||||||
|
HRule(out *bytes.Buffer)
|
||||||
|
List(out *bytes.Buffer, text func() bool, flags int)
|
||||||
|
ListItem(out *bytes.Buffer, text []byte, flags int)
|
||||||
|
Paragraph(out *bytes.Buffer, text func() bool)
|
||||||
|
Table(out *bytes.Buffer, header []byte, body []byte, columnData []int)
|
||||||
|
TableRow(out *bytes.Buffer, text []byte)
|
||||||
|
TableHeaderCell(out *bytes.Buffer, text []byte, flags int)
|
||||||
|
TableCell(out *bytes.Buffer, text []byte, flags int)
|
||||||
|
Footnotes(out *bytes.Buffer, text func() bool)
|
||||||
|
FootnoteItem(out *bytes.Buffer, name, text []byte, flags int)
|
||||||
|
TitleBlock(out *bytes.Buffer, text []byte)
|
||||||
|
|
||||||
// RenderHeader is a method that allows the renderer to produce some
|
// Span-level callbacks
|
||||||
// content preceding the main body of the output document. The header is
|
AutoLink(out *bytes.Buffer, link []byte, kind int)
|
||||||
// understood in the broad sense here. For example, the default HTML
|
CodeSpan(out *bytes.Buffer, text []byte)
|
||||||
// renderer will write not only the HTML document preamble, but also the
|
DoubleEmphasis(out *bytes.Buffer, text []byte)
|
||||||
// table of contents if it was requested.
|
Emphasis(out *bytes.Buffer, text []byte)
|
||||||
//
|
Image(out *bytes.Buffer, link []byte, title []byte, alt []byte)
|
||||||
// The method will be passed an entire document tree, in case a particular
|
LineBreak(out *bytes.Buffer)
|
||||||
// implementation needs to inspect it to produce output.
|
Link(out *bytes.Buffer, link []byte, title []byte, content []byte)
|
||||||
//
|
RawHtmlTag(out *bytes.Buffer, tag []byte)
|
||||||
// The output should be written to the supplied writer w. If your
|
TripleEmphasis(out *bytes.Buffer, text []byte)
|
||||||
// implementation has no header to write, supply an empty implementation.
|
StrikeThrough(out *bytes.Buffer, text []byte)
|
||||||
RenderHeader(w io.Writer, ast *Node)
|
FootnoteRef(out *bytes.Buffer, ref []byte, id int)
|
||||||
|
|
||||||
// RenderFooter is a symmetric counterpart of RenderHeader.
|
// Low-level callbacks
|
||||||
RenderFooter(w io.Writer, ast *Node)
|
Entity(out *bytes.Buffer, entity []byte)
|
||||||
|
NormalText(out *bytes.Buffer, text []byte)
|
||||||
|
|
||||||
|
// Header and footer
|
||||||
|
DocumentHeader(out *bytes.Buffer)
|
||||||
|
DocumentFooter(out *bytes.Buffer)
|
||||||
|
|
||||||
|
GetFlags() int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Callback functions for inline parsing. One such function is defined
|
// Callback functions for inline parsing. One such function is defined
|
||||||
// for each character that triggers a response when parsing inline data.
|
// for each character that triggers a response when parsing inline data.
|
||||||
type inlineParser func(p *Markdown, data []byte, offset int) (int, *Node)
|
type inlineParser func(p *parser, out *bytes.Buffer, data []byte, offset int) int
|
||||||
|
|
||||||
// Markdown is a type that holds extensions and the runtime state used by
|
// Parser holds runtime state used by the parser.
|
||||||
// Parse, and the renderer. You can not use it directly, construct it with New.
|
// This is constructed by the Markdown function.
|
||||||
type Markdown struct {
|
type parser struct {
|
||||||
renderer Renderer
|
r Renderer
|
||||||
referenceOverride ReferenceOverrideFunc
|
refOverride ReferenceOverrideFunc
|
||||||
refs map[string]*reference
|
refs map[string]*reference
|
||||||
inlineCallback [256]inlineParser
|
inlineCallback [256]inlineParser
|
||||||
extensions Extensions
|
flags int
|
||||||
nesting int
|
nesting int
|
||||||
maxNesting int
|
maxNesting int
|
||||||
insideLink bool
|
insideLink bool
|
||||||
|
|
||||||
// Footnotes need to be ordered as well as available to quickly check for
|
// Footnotes need to be ordered as well as available to quickly check for
|
||||||
// presence. If a ref is also a footnote, it's stored both in refs and here
|
// presence. If a ref is also a footnote, it's stored both in refs and here
|
||||||
// in notes. Slice is nil if footnotes not enabled.
|
// in notes. Slice is nil if footnotes not enabled.
|
||||||
notes []*reference
|
notes []*reference
|
||||||
|
notesRecord map[string]struct{}
|
||||||
doc *Node
|
|
||||||
tip *Node // = doc
|
|
||||||
oldTip *Node
|
|
||||||
lastMatchedContainer *Node // = doc
|
|
||||||
allClosed bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Markdown) getRef(refid string) (ref *reference, found bool) {
|
func (p *parser) getRef(refid string) (ref *reference, found bool) {
|
||||||
if p.referenceOverride != nil {
|
if p.refOverride != nil {
|
||||||
r, overridden := p.referenceOverride(refid)
|
r, overridden := p.refOverride(refid)
|
||||||
if overridden {
|
if overridden {
|
||||||
if r == nil {
|
if r == nil {
|
||||||
return nil, false
|
return nil, false
|
||||||
@@ -202,7 +232,7 @@ func (p *Markdown) getRef(refid string) (ref *reference, found bool) {
|
|||||||
return &reference{
|
return &reference{
|
||||||
link: []byte(r.Link),
|
link: []byte(r.Link),
|
||||||
title: []byte(r.Title),
|
title: []byte(r.Title),
|
||||||
noteID: 0,
|
noteId: 0,
|
||||||
hasBlock: false,
|
hasBlock: false,
|
||||||
text: []byte(r.Text)}, true
|
text: []byte(r.Text)}, true
|
||||||
}
|
}
|
||||||
@@ -212,34 +242,9 @@ func (p *Markdown) getRef(refid string) (ref *reference, found bool) {
|
|||||||
return ref, found
|
return ref, found
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Markdown) finalize(block *Node) {
|
func (p *parser) isFootnote(ref *reference) bool {
|
||||||
above := block.Parent
|
_, ok := p.notesRecord[string(ref.link)]
|
||||||
block.open = false
|
return ok
|
||||||
p.tip = above
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Markdown) addChild(node NodeType, offset uint32) *Node {
|
|
||||||
return p.addExistingChild(NewNode(node), offset)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Markdown) addExistingChild(node *Node, offset uint32) *Node {
|
|
||||||
for !p.tip.canContain(node.Type) {
|
|
||||||
p.finalize(p.tip)
|
|
||||||
}
|
|
||||||
p.tip.AppendChild(node)
|
|
||||||
p.tip = node
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Markdown) closeUnmatchedBlocks() {
|
|
||||||
if !p.allClosed {
|
|
||||||
for p.oldTip != p.lastMatchedContainer {
|
|
||||||
parent := p.oldTip.Parent
|
|
||||||
p.finalize(p.oldTip)
|
|
||||||
p.oldTip = parent
|
|
||||||
}
|
|
||||||
p.allClosed = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -266,27 +271,102 @@ type Reference struct {
|
|||||||
// See the documentation in Options for more details on use-case.
|
// See the documentation in Options for more details on use-case.
|
||||||
type ReferenceOverrideFunc func(reference string) (ref *Reference, overridden bool)
|
type ReferenceOverrideFunc func(reference string) (ref *Reference, overridden bool)
|
||||||
|
|
||||||
// New constructs a Markdown processor. You can use the same With* functions as
|
// Options represents configurable overrides and callbacks (in addition to the
|
||||||
// for Run() to customize parser's behavior and the renderer.
|
// extension flag set) for configuring a Markdown parse.
|
||||||
func New(opts ...Option) *Markdown {
|
type Options struct {
|
||||||
var p Markdown
|
// Extensions is a flag set of bit-wise ORed extension bits. See the
|
||||||
for _, opt := range opts {
|
// EXTENSION_* flags defined in this package.
|
||||||
opt(&p)
|
Extensions int
|
||||||
|
|
||||||
|
// ReferenceOverride is an optional function callback that is called every
|
||||||
|
// time a reference is resolved.
|
||||||
|
//
|
||||||
|
// In Markdown, the link reference syntax can be made to resolve a link to
|
||||||
|
// a reference instead of an inline URL, in one of the following ways:
|
||||||
|
//
|
||||||
|
// * [link text][refid]
|
||||||
|
// * [refid][]
|
||||||
|
//
|
||||||
|
// Usually, the refid is defined at the bottom of the Markdown document. If
|
||||||
|
// this override function is provided, the refid is passed to the override
|
||||||
|
// function first, before consulting the defined refids at the bottom. If
|
||||||
|
// the override function indicates an override did not occur, the refids at
|
||||||
|
// the bottom will be used to fill in the link details.
|
||||||
|
ReferenceOverride ReferenceOverrideFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarkdownBasic is a convenience function for simple rendering.
|
||||||
|
// It processes markdown input with no extensions enabled.
|
||||||
|
func MarkdownBasic(input []byte) []byte {
|
||||||
|
// set up the HTML renderer
|
||||||
|
htmlFlags := HTML_USE_XHTML
|
||||||
|
renderer := HtmlRenderer(htmlFlags, "", "")
|
||||||
|
|
||||||
|
// set up the parser
|
||||||
|
return MarkdownOptions(input, renderer, Options{Extensions: 0})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call Markdown with most useful extensions enabled
|
||||||
|
// MarkdownCommon is a convenience function for simple rendering.
|
||||||
|
// It processes markdown input with common extensions enabled, including:
|
||||||
|
//
|
||||||
|
// * Smartypants processing with smart fractions and LaTeX dashes
|
||||||
|
//
|
||||||
|
// * Intra-word emphasis suppression
|
||||||
|
//
|
||||||
|
// * Tables
|
||||||
|
//
|
||||||
|
// * Fenced code blocks
|
||||||
|
//
|
||||||
|
// * Autolinking
|
||||||
|
//
|
||||||
|
// * Strikethrough support
|
||||||
|
//
|
||||||
|
// * Strict header parsing
|
||||||
|
//
|
||||||
|
// * Custom Header IDs
|
||||||
|
func MarkdownCommon(input []byte) []byte {
|
||||||
|
// set up the HTML renderer
|
||||||
|
renderer := HtmlRenderer(commonHtmlFlags, "", "")
|
||||||
|
return MarkdownOptions(input, renderer, Options{
|
||||||
|
Extensions: commonExtensions})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Markdown is the main rendering function.
|
||||||
|
// It parses and renders a block of markdown-encoded text.
|
||||||
|
// The supplied Renderer is used to format the output, and extensions dictates
|
||||||
|
// which non-standard extensions are enabled.
|
||||||
|
//
|
||||||
|
// To use the supplied Html or LaTeX renderers, see HtmlRenderer and
|
||||||
|
// LatexRenderer, respectively.
|
||||||
|
func Markdown(input []byte, renderer Renderer, extensions int) []byte {
|
||||||
|
return MarkdownOptions(input, renderer, Options{
|
||||||
|
Extensions: extensions})
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarkdownOptions is just like Markdown but takes additional options through
|
||||||
|
// the Options struct.
|
||||||
|
func MarkdownOptions(input []byte, renderer Renderer, opts Options) []byte {
|
||||||
|
// no point in parsing if we can't render
|
||||||
|
if renderer == nil {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extensions := opts.Extensions
|
||||||
|
|
||||||
|
// fill in the render structure
|
||||||
|
p := new(parser)
|
||||||
|
p.r = renderer
|
||||||
|
p.flags = extensions
|
||||||
|
p.refOverride = opts.ReferenceOverride
|
||||||
p.refs = make(map[string]*reference)
|
p.refs = make(map[string]*reference)
|
||||||
p.maxNesting = 16
|
p.maxNesting = 16
|
||||||
p.insideLink = false
|
p.insideLink = false
|
||||||
docNode := NewNode(Document)
|
|
||||||
p.doc = docNode
|
|
||||||
p.tip = docNode
|
|
||||||
p.oldTip = docNode
|
|
||||||
p.lastMatchedContainer = docNode
|
|
||||||
p.allClosed = true
|
|
||||||
// register inline parsers
|
// register inline parsers
|
||||||
p.inlineCallback[' '] = maybeLineBreak
|
|
||||||
p.inlineCallback['*'] = emphasis
|
p.inlineCallback['*'] = emphasis
|
||||||
p.inlineCallback['_'] = emphasis
|
p.inlineCallback['_'] = emphasis
|
||||||
if p.extensions&Strikethrough != 0 {
|
if extensions&EXTENSION_STRIKETHROUGH != 0 {
|
||||||
p.inlineCallback['~'] = emphasis
|
p.inlineCallback['~'] = emphasis
|
||||||
}
|
}
|
||||||
p.inlineCallback['`'] = codeSpan
|
p.inlineCallback['`'] = codeSpan
|
||||||
@@ -295,166 +375,116 @@ func New(opts ...Option) *Markdown {
|
|||||||
p.inlineCallback['<'] = leftAngle
|
p.inlineCallback['<'] = leftAngle
|
||||||
p.inlineCallback['\\'] = escape
|
p.inlineCallback['\\'] = escape
|
||||||
p.inlineCallback['&'] = entity
|
p.inlineCallback['&'] = entity
|
||||||
p.inlineCallback['!'] = maybeImage
|
|
||||||
p.inlineCallback['^'] = maybeInlineFootnote
|
if extensions&EXTENSION_AUTOLINK != 0 {
|
||||||
if p.extensions&Autolink != 0 {
|
p.inlineCallback[':'] = autoLink
|
||||||
p.inlineCallback['h'] = maybeAutoLink
|
|
||||||
p.inlineCallback['m'] = maybeAutoLink
|
|
||||||
p.inlineCallback['f'] = maybeAutoLink
|
|
||||||
p.inlineCallback['H'] = maybeAutoLink
|
|
||||||
p.inlineCallback['M'] = maybeAutoLink
|
|
||||||
p.inlineCallback['F'] = maybeAutoLink
|
|
||||||
}
|
}
|
||||||
if p.extensions&Footnotes != 0 {
|
|
||||||
|
if extensions&EXTENSION_FOOTNOTES != 0 {
|
||||||
p.notes = make([]*reference, 0)
|
p.notes = make([]*reference, 0)
|
||||||
|
p.notesRecord = make(map[string]struct{})
|
||||||
}
|
}
|
||||||
return &p
|
|
||||||
|
first := firstPass(p, input)
|
||||||
|
second := secondPass(p, first)
|
||||||
|
return second
|
||||||
}
|
}
|
||||||
|
|
||||||
// Option customizes the Markdown processor's default behavior.
|
// first pass:
|
||||||
type Option func(*Markdown)
|
// - normalize newlines
|
||||||
|
// - extract references (outside of fenced code blocks)
|
||||||
// WithRenderer allows you to override the default renderer.
|
// - expand tabs (outside of fenced code blocks)
|
||||||
func WithRenderer(r Renderer) Option {
|
// - copy everything else
|
||||||
return func(p *Markdown) {
|
func firstPass(p *parser, input []byte) []byte {
|
||||||
p.renderer = r
|
var out bytes.Buffer
|
||||||
|
tabSize := TAB_SIZE_DEFAULT
|
||||||
|
if p.flags&EXTENSION_TAB_SIZE_EIGHT != 0 {
|
||||||
|
tabSize = TAB_SIZE_EIGHT
|
||||||
}
|
}
|
||||||
|
beg := 0
|
||||||
|
lastFencedCodeBlockEnd := 0
|
||||||
|
for beg < len(input) {
|
||||||
|
// Find end of this line, then process the line.
|
||||||
|
end := beg
|
||||||
|
for end < len(input) && input[end] != '\n' && input[end] != '\r' {
|
||||||
|
end++
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.flags&EXTENSION_FENCED_CODE != 0 {
|
||||||
|
// track fenced code block boundaries to suppress tab expansion
|
||||||
|
// and reference extraction inside them:
|
||||||
|
if beg >= lastFencedCodeBlockEnd {
|
||||||
|
if i := p.fencedCodeBlock(&out, input[beg:], false); i > 0 {
|
||||||
|
lastFencedCodeBlockEnd = beg + i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the line body if present
|
||||||
|
if end > beg {
|
||||||
|
if end < lastFencedCodeBlockEnd { // Do not expand tabs while inside fenced code blocks.
|
||||||
|
out.Write(input[beg:end])
|
||||||
|
} else if refEnd := isReference(p, input[beg:], tabSize); refEnd > 0 {
|
||||||
|
beg += refEnd
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
expandTabs(&out, input[beg:end], tabSize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if end < len(input) && input[end] == '\r' {
|
||||||
|
end++
|
||||||
|
}
|
||||||
|
if end < len(input) && input[end] == '\n' {
|
||||||
|
end++
|
||||||
|
}
|
||||||
|
out.WriteByte('\n')
|
||||||
|
|
||||||
|
beg = end
|
||||||
|
}
|
||||||
|
|
||||||
|
// empty input?
|
||||||
|
if out.Len() == 0 {
|
||||||
|
out.WriteByte('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
return out.Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithExtensions allows you to pick some of the many extensions provided by
|
// second pass: actual rendering
|
||||||
// Blackfriday. You can bitwise OR them.
|
func secondPass(p *parser, input []byte) []byte {
|
||||||
func WithExtensions(e Extensions) Option {
|
var output bytes.Buffer
|
||||||
return func(p *Markdown) {
|
|
||||||
p.extensions = e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithNoExtensions turns off all extensions and custom behavior.
|
p.r.DocumentHeader(&output)
|
||||||
func WithNoExtensions() Option {
|
p.block(&output, input)
|
||||||
return func(p *Markdown) {
|
|
||||||
p.extensions = NoExtensions
|
if p.flags&EXTENSION_FOOTNOTES != 0 && len(p.notes) > 0 {
|
||||||
p.renderer = NewHTMLRenderer(HTMLRendererParameters{
|
p.r.Footnotes(&output, func() bool {
|
||||||
Flags: HTMLFlagsNone,
|
flags := LIST_ITEM_BEGINNING_OF_LIST
|
||||||
|
for i := 0; i < len(p.notes); i += 1 {
|
||||||
|
ref := p.notes[i]
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if ref.hasBlock {
|
||||||
|
flags |= LIST_ITEM_CONTAINS_BLOCK
|
||||||
|
p.block(&buf, ref.title)
|
||||||
|
} else {
|
||||||
|
p.inline(&buf, ref.title)
|
||||||
|
}
|
||||||
|
p.r.FootnoteItem(&output, ref.link, buf.Bytes(), flags)
|
||||||
|
flags &^= LIST_ITEM_BEGINNING_OF_LIST | LIST_ITEM_CONTAINS_BLOCK
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// WithRefOverride sets an optional function callback that is called every
|
p.r.DocumentFooter(&output)
|
||||||
// time a reference is resolved.
|
|
||||||
//
|
|
||||||
// In Markdown, the link reference syntax can be made to resolve a link to
|
|
||||||
// a reference instead of an inline URL, in one of the following ways:
|
|
||||||
//
|
|
||||||
// * [link text][refid]
|
|
||||||
// * [refid][]
|
|
||||||
//
|
|
||||||
// Usually, the refid is defined at the bottom of the Markdown document. If
|
|
||||||
// this override function is provided, the refid is passed to the override
|
|
||||||
// function first, before consulting the defined refids at the bottom. If
|
|
||||||
// the override function indicates an override did not occur, the refids at
|
|
||||||
// the bottom will be used to fill in the link details.
|
|
||||||
func WithRefOverride(o ReferenceOverrideFunc) Option {
|
|
||||||
return func(p *Markdown) {
|
|
||||||
p.referenceOverride = o
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run is the main entry point to Blackfriday. It parses and renders a
|
if p.nesting != 0 {
|
||||||
// block of markdown-encoded text.
|
panic("Nesting level did not end at zero")
|
||||||
//
|
}
|
||||||
// The simplest invocation of Run takes one argument, input:
|
|
||||||
// output := Run(input)
|
|
||||||
// This will parse the input with CommonExtensions enabled and render it with
|
|
||||||
// the default HTMLRenderer (with CommonHTMLFlags).
|
|
||||||
//
|
|
||||||
// Variadic arguments opts can customize the default behavior. Since Markdown
|
|
||||||
// type does not contain exported fields, you can not use it directly. Instead,
|
|
||||||
// use the With* functions. For example, this will call the most basic
|
|
||||||
// functionality, with no extensions:
|
|
||||||
// output := Run(input, WithNoExtensions())
|
|
||||||
//
|
|
||||||
// You can use any number of With* arguments, even contradicting ones. They
|
|
||||||
// will be applied in order of appearance and the latter will override the
|
|
||||||
// former:
|
|
||||||
// output := Run(input, WithNoExtensions(), WithExtensions(exts),
|
|
||||||
// WithRenderer(yourRenderer))
|
|
||||||
func Run(input []byte, opts ...Option) []byte {
|
|
||||||
r := NewHTMLRenderer(HTMLRendererParameters{
|
|
||||||
Flags: CommonHTMLFlags,
|
|
||||||
})
|
|
||||||
optList := []Option{WithRenderer(r), WithExtensions(CommonExtensions)}
|
|
||||||
optList = append(optList, opts...)
|
|
||||||
parser := New(optList...)
|
|
||||||
ast := parser.Parse(input)
|
|
||||||
var buf bytes.Buffer
|
|
||||||
parser.renderer.RenderHeader(&buf, ast)
|
|
||||||
ast.Walk(func(node *Node, entering bool) WalkStatus {
|
|
||||||
return parser.renderer.RenderNode(&buf, node, entering)
|
|
||||||
})
|
|
||||||
parser.renderer.RenderFooter(&buf, ast)
|
|
||||||
return buf.Bytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse is an entry point to the parsing part of Blackfriday. It takes an
|
return output.Bytes()
|
||||||
// input markdown document and produces a syntax tree for its contents. This
|
|
||||||
// tree can then be rendered with a default or custom renderer, or
|
|
||||||
// analyzed/transformed by the caller to whatever non-standard needs they have.
|
|
||||||
// The return value is the root node of the syntax tree.
|
|
||||||
func (p *Markdown) Parse(input []byte) *Node {
|
|
||||||
p.block(input)
|
|
||||||
// Walk the tree and finish up some of unfinished blocks
|
|
||||||
for p.tip != nil {
|
|
||||||
p.finalize(p.tip)
|
|
||||||
}
|
|
||||||
// Walk the tree again and process inline markdown in each block
|
|
||||||
p.doc.Walk(func(node *Node, entering bool) WalkStatus {
|
|
||||||
if node.Type == Paragraph || node.Type == Heading || node.Type == TableCell {
|
|
||||||
p.inline(node, node.content)
|
|
||||||
node.content = nil
|
|
||||||
}
|
|
||||||
return GoToNext
|
|
||||||
})
|
|
||||||
p.parseRefsToAST()
|
|
||||||
return p.doc
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Markdown) parseRefsToAST() {
|
|
||||||
if p.extensions&Footnotes == 0 || len(p.notes) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.tip = p.doc
|
|
||||||
block := p.addBlock(List, nil)
|
|
||||||
block.IsFootnotesList = true
|
|
||||||
block.ListFlags = ListTypeOrdered
|
|
||||||
flags := ListItemBeginningOfList
|
|
||||||
// Note: this loop is intentionally explicit, not range-form. This is
|
|
||||||
// because the body of the loop will append nested footnotes to p.notes and
|
|
||||||
// we need to process those late additions. Range form would only walk over
|
|
||||||
// the fixed initial set.
|
|
||||||
for i := 0; i < len(p.notes); i++ {
|
|
||||||
ref := p.notes[i]
|
|
||||||
p.addExistingChild(ref.footnote, 0)
|
|
||||||
block := ref.footnote
|
|
||||||
block.ListFlags = flags | ListTypeOrdered
|
|
||||||
block.RefLink = ref.link
|
|
||||||
if ref.hasBlock {
|
|
||||||
flags |= ListItemContainsBlock
|
|
||||||
p.block(ref.title)
|
|
||||||
} else {
|
|
||||||
p.inline(block, ref.title)
|
|
||||||
}
|
|
||||||
flags &^= ListItemBeginningOfList | ListItemContainsBlock
|
|
||||||
}
|
|
||||||
above := block.Parent
|
|
||||||
finalizeList(block)
|
|
||||||
p.tip = above
|
|
||||||
block.Walk(func(node *Node, entering bool) WalkStatus {
|
|
||||||
if node.Type == Paragraph || node.Type == Heading {
|
|
||||||
p.inline(node, node.content)
|
|
||||||
node.content = nil
|
|
||||||
}
|
|
||||||
return GoToNext
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -486,56 +516,18 @@ func (p *Markdown) parseRefsToAST() {
|
|||||||
//
|
//
|
||||||
// are not yet supported.
|
// are not yet supported.
|
||||||
|
|
||||||
// reference holds all information necessary for a reference-style links or
|
// References are parsed and stored in this struct.
|
||||||
// footnotes.
|
|
||||||
//
|
|
||||||
// Consider this markdown with reference-style links:
|
|
||||||
//
|
|
||||||
// [link][ref]
|
|
||||||
//
|
|
||||||
// [ref]: /url/ "tooltip title"
|
|
||||||
//
|
|
||||||
// It will be ultimately converted to this HTML:
|
|
||||||
//
|
|
||||||
// <p><a href=\"/url/\" title=\"title\">link</a></p>
|
|
||||||
//
|
|
||||||
// And a reference structure will be populated as follows:
|
|
||||||
//
|
|
||||||
// p.refs["ref"] = &reference{
|
|
||||||
// link: "/url/",
|
|
||||||
// title: "tooltip title",
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Alternatively, reference can contain information about a footnote. Consider
|
|
||||||
// this markdown:
|
|
||||||
//
|
|
||||||
// Text needing a footnote.[^a]
|
|
||||||
//
|
|
||||||
// [^a]: This is the note
|
|
||||||
//
|
|
||||||
// A reference structure will be populated as follows:
|
|
||||||
//
|
|
||||||
// p.refs["a"] = &reference{
|
|
||||||
// link: "a",
|
|
||||||
// title: "This is the note",
|
|
||||||
// noteID: <some positive int>,
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// TODO: As you can see, it begs for splitting into two dedicated structures
|
|
||||||
// for refs and for footnotes.
|
|
||||||
type reference struct {
|
type reference struct {
|
||||||
link []byte
|
link []byte
|
||||||
title []byte
|
title []byte
|
||||||
noteID int // 0 if not a footnote ref
|
noteId int // 0 if not a footnote ref
|
||||||
hasBlock bool
|
hasBlock bool
|
||||||
footnote *Node // a link to the Item node within a list of footnotes
|
text []byte
|
||||||
|
|
||||||
text []byte // only gets populated by refOverride feature with Reference.Text
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *reference) String() string {
|
func (r *reference) String() string {
|
||||||
return fmt.Sprintf("{link: %q, title: %q, text: %q, noteID: %d, hasBlock: %v}",
|
return fmt.Sprintf("{link: %q, title: %q, text: %q, noteId: %d, hasBlock: %v}",
|
||||||
r.link, r.title, r.text, r.noteID, r.hasBlock)
|
r.link, r.title, r.text, r.noteId, r.hasBlock)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether or not data starts with a reference link.
|
// Check whether or not data starts with a reference link.
|
||||||
@@ -543,7 +535,7 @@ func (r *reference) String() string {
|
|||||||
// (in the render struct).
|
// (in the render struct).
|
||||||
// Returns the number of bytes to skip to move past it,
|
// Returns the number of bytes to skip to move past it,
|
||||||
// or zero if the first line is not a reference.
|
// or zero if the first line is not a reference.
|
||||||
func isReference(p *Markdown, data []byte, tabSize int) int {
|
func isReference(p *parser, data []byte, tabSize int) int {
|
||||||
// up to 3 optional leading spaces
|
// up to 3 optional leading spaces
|
||||||
if len(data) < 4 {
|
if len(data) < 4 {
|
||||||
return 0
|
return 0
|
||||||
@@ -553,18 +545,18 @@ func isReference(p *Markdown, data []byte, tabSize int) int {
|
|||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
noteID := 0
|
noteId := 0
|
||||||
|
|
||||||
// id part: anything but a newline between brackets
|
// id part: anything but a newline between brackets
|
||||||
if data[i] != '[' {
|
if data[i] != '[' {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
if p.extensions&Footnotes != 0 {
|
if p.flags&EXTENSION_FOOTNOTES != 0 {
|
||||||
if i < len(data) && data[i] == '^' {
|
if i < len(data) && data[i] == '^' {
|
||||||
// we can set it to anything here because the proper noteIds will
|
// we can set it to anything here because the proper noteIds will
|
||||||
// be assigned later during the second pass. It just has to be != 0
|
// be assigned later during the second pass. It just has to be != 0
|
||||||
noteID = 1
|
noteId = 1
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -576,11 +568,7 @@ func isReference(p *Markdown, data []byte, tabSize int) int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
idEnd := i
|
idEnd := i
|
||||||
// footnotes can have empty ID, like this: [^], but a reference can not be
|
|
||||||
// empty like this: []. Break early if it's not a footnote and there's no ID
|
|
||||||
if noteID == 0 && idOffset == idEnd {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
// spacer: colon (space | tab)* newline? (space | tab)*
|
// spacer: colon (space | tab)* newline? (space | tab)*
|
||||||
i++
|
i++
|
||||||
if i >= len(data) || data[i] != ':' {
|
if i >= len(data) || data[i] != ':' {
|
||||||
@@ -611,7 +599,7 @@ func isReference(p *Markdown, data []byte, tabSize int) int {
|
|||||||
hasBlock bool
|
hasBlock bool
|
||||||
)
|
)
|
||||||
|
|
||||||
if p.extensions&Footnotes != 0 && noteID != 0 {
|
if p.flags&EXTENSION_FOOTNOTES != 0 && noteId != 0 {
|
||||||
linkOffset, linkEnd, raw, hasBlock = scanFootnote(p, data, i, tabSize)
|
linkOffset, linkEnd, raw, hasBlock = scanFootnote(p, data, i, tabSize)
|
||||||
lineEnd = linkEnd
|
lineEnd = linkEnd
|
||||||
} else {
|
} else {
|
||||||
@@ -624,11 +612,11 @@ func isReference(p *Markdown, data []byte, tabSize int) int {
|
|||||||
// a valid ref has been found
|
// a valid ref has been found
|
||||||
|
|
||||||
ref := &reference{
|
ref := &reference{
|
||||||
noteID: noteID,
|
noteId: noteId,
|
||||||
hasBlock: hasBlock,
|
hasBlock: hasBlock,
|
||||||
}
|
}
|
||||||
|
|
||||||
if noteID > 0 {
|
if noteId > 0 {
|
||||||
// reusing the link field for the id since footnotes don't have links
|
// reusing the link field for the id since footnotes don't have links
|
||||||
ref.link = data[idOffset:idEnd]
|
ref.link = data[idOffset:idEnd]
|
||||||
// if footnote, it's not really a title, it's the contained text
|
// if footnote, it's not really a title, it's the contained text
|
||||||
@@ -646,12 +634,15 @@ func isReference(p *Markdown, data []byte, tabSize int) int {
|
|||||||
return lineEnd
|
return lineEnd
|
||||||
}
|
}
|
||||||
|
|
||||||
func scanLinkRef(p *Markdown, data []byte, i int) (linkOffset, linkEnd, titleOffset, titleEnd, lineEnd int) {
|
func scanLinkRef(p *parser, data []byte, i int) (linkOffset, linkEnd, titleOffset, titleEnd, lineEnd int) {
|
||||||
// link: whitespace-free sequence, optionally between angle brackets
|
// link: whitespace-free sequence, optionally between angle brackets
|
||||||
if data[i] == '<' {
|
if data[i] == '<' {
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
linkOffset = i
|
linkOffset = i
|
||||||
|
if i == len(data) {
|
||||||
|
return
|
||||||
|
}
|
||||||
for i < len(data) && data[i] != ' ' && data[i] != '\t' && data[i] != '\n' && data[i] != '\r' {
|
for i < len(data) && data[i] != ' ' && data[i] != '\t' && data[i] != '\n' && data[i] != '\r' {
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
@@ -714,13 +705,13 @@ func scanLinkRef(p *Markdown, data []byte, i int) (linkOffset, linkEnd, titleOff
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// The first bit of this logic is the same as Parser.listItem, but the rest
|
// The first bit of this logic is the same as (*parser).listItem, but the rest
|
||||||
// is much simpler. This function simply finds the entire block and shifts it
|
// is much simpler. This function simply finds the entire block and shifts it
|
||||||
// over by one tab if it is indeed a block (just returns the line if it's not).
|
// over by one tab if it is indeed a block (just returns the line if it's not).
|
||||||
// blockEnd is the end of the section in the input buffer, and contents is the
|
// blockEnd is the end of the section in the input buffer, and contents is the
|
||||||
// extracted text that was shifted over one tab. It will need to be rendered at
|
// extracted text that was shifted over one tab. It will need to be rendered at
|
||||||
// the end of the document.
|
// the end of the document.
|
||||||
func scanFootnote(p *Markdown, data []byte, i, indentSize int) (blockStart, blockEnd int, contents []byte, hasBlock bool) {
|
func scanFootnote(p *parser, data []byte, i, indentSize int) (blockStart, blockEnd int, contents []byte, hasBlock bool) {
|
||||||
if i == 0 || len(data) == 0 {
|
if i == 0 || len(data) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -813,7 +804,17 @@ func ispunct(c byte) bool {
|
|||||||
|
|
||||||
// Test if a character is a whitespace character.
|
// Test if a character is a whitespace character.
|
||||||
func isspace(c byte) bool {
|
func isspace(c byte) bool {
|
||||||
return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v'
|
return ishorizontalspace(c) || isverticalspace(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test if a character is a horizontal whitespace character.
|
||||||
|
func ishorizontalspace(c byte) bool {
|
||||||
|
return c == ' ' || c == '\t'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test if a character is a vertical whitespace character.
|
||||||
|
func isverticalspace(c byte) bool {
|
||||||
|
return c == '\n' || c == '\r' || c == '\f' || c == '\v'
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if a character is letter.
|
// Test if a character is letter.
|
||||||
|
|||||||
354
vendor/github.com/russross/blackfriday/node.go
generated
vendored
354
vendor/github.com/russross/blackfriday/node.go
generated
vendored
@@ -1,354 +0,0 @@
|
|||||||
package blackfriday
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NodeType specifies a type of a single node of a syntax tree. Usually one
|
|
||||||
// node (and its type) corresponds to a single markdown feature, e.g. emphasis
|
|
||||||
// or code block.
|
|
||||||
type NodeType int
|
|
||||||
|
|
||||||
// Constants for identifying different types of nodes. See NodeType.
|
|
||||||
const (
|
|
||||||
Document NodeType = iota
|
|
||||||
BlockQuote
|
|
||||||
List
|
|
||||||
Item
|
|
||||||
Paragraph
|
|
||||||
Heading
|
|
||||||
HorizontalRule
|
|
||||||
Emph
|
|
||||||
Strong
|
|
||||||
Del
|
|
||||||
Link
|
|
||||||
Image
|
|
||||||
Text
|
|
||||||
HTMLBlock
|
|
||||||
CodeBlock
|
|
||||||
Softbreak
|
|
||||||
Hardbreak
|
|
||||||
Code
|
|
||||||
HTMLSpan
|
|
||||||
Table
|
|
||||||
TableCell
|
|
||||||
TableHead
|
|
||||||
TableBody
|
|
||||||
TableRow
|
|
||||||
)
|
|
||||||
|
|
||||||
var nodeTypeNames = []string{
|
|
||||||
Document: "Document",
|
|
||||||
BlockQuote: "BlockQuote",
|
|
||||||
List: "List",
|
|
||||||
Item: "Item",
|
|
||||||
Paragraph: "Paragraph",
|
|
||||||
Heading: "Heading",
|
|
||||||
HorizontalRule: "HorizontalRule",
|
|
||||||
Emph: "Emph",
|
|
||||||
Strong: "Strong",
|
|
||||||
Del: "Del",
|
|
||||||
Link: "Link",
|
|
||||||
Image: "Image",
|
|
||||||
Text: "Text",
|
|
||||||
HTMLBlock: "HTMLBlock",
|
|
||||||
CodeBlock: "CodeBlock",
|
|
||||||
Softbreak: "Softbreak",
|
|
||||||
Hardbreak: "Hardbreak",
|
|
||||||
Code: "Code",
|
|
||||||
HTMLSpan: "HTMLSpan",
|
|
||||||
Table: "Table",
|
|
||||||
TableCell: "TableCell",
|
|
||||||
TableHead: "TableHead",
|
|
||||||
TableBody: "TableBody",
|
|
||||||
TableRow: "TableRow",
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t NodeType) String() string {
|
|
||||||
return nodeTypeNames[t]
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListData contains fields relevant to a List and Item node type.
|
|
||||||
type ListData struct {
|
|
||||||
ListFlags ListType
|
|
||||||
Tight bool // Skip <p>s around list item data if true
|
|
||||||
BulletChar byte // '*', '+' or '-' in bullet lists
|
|
||||||
Delimiter byte // '.' or ')' after the number in ordered lists
|
|
||||||
RefLink []byte // If not nil, turns this list item into a footnote item and triggers different rendering
|
|
||||||
IsFootnotesList bool // This is a list of footnotes
|
|
||||||
}
|
|
||||||
|
|
||||||
// LinkData contains fields relevant to a Link node type.
|
|
||||||
type LinkData struct {
|
|
||||||
Destination []byte // Destination is what goes into a href
|
|
||||||
Title []byte // Title is the tooltip thing that goes in a title attribute
|
|
||||||
NoteID int // NoteID contains a serial number of a footnote, zero if it's not a footnote
|
|
||||||
Footnote *Node // If it's a footnote, this is a direct link to the footnote Node. Otherwise nil.
|
|
||||||
}
|
|
||||||
|
|
||||||
// CodeBlockData contains fields relevant to a CodeBlock node type.
|
|
||||||
type CodeBlockData struct {
|
|
||||||
IsFenced bool // Specifies whether it's a fenced code block or an indented one
|
|
||||||
Info []byte // This holds the info string
|
|
||||||
FenceChar byte
|
|
||||||
FenceLength int
|
|
||||||
FenceOffset int
|
|
||||||
}
|
|
||||||
|
|
||||||
// TableCellData contains fields relevant to a TableCell node type.
|
|
||||||
type TableCellData struct {
|
|
||||||
IsHeader bool // This tells if it's under the header row
|
|
||||||
Align CellAlignFlags // This holds the value for align attribute
|
|
||||||
}
|
|
||||||
|
|
||||||
// HeadingData contains fields relevant to a Heading node type.
|
|
||||||
type HeadingData struct {
|
|
||||||
Level int // This holds the heading level number
|
|
||||||
HeadingID string // This might hold heading ID, if present
|
|
||||||
IsTitleblock bool // Specifies whether it's a title block
|
|
||||||
}
|
|
||||||
|
|
||||||
// Node is a single element in the abstract syntax tree of the parsed document.
|
|
||||||
// It holds connections to the structurally neighboring nodes and, for certain
|
|
||||||
// types of nodes, additional information that might be needed when rendering.
|
|
||||||
type Node struct {
|
|
||||||
Type NodeType // Determines the type of the node
|
|
||||||
Parent *Node // Points to the parent
|
|
||||||
FirstChild *Node // Points to the first child, if any
|
|
||||||
LastChild *Node // Points to the last child, if any
|
|
||||||
Prev *Node // Previous sibling; nil if it's the first child
|
|
||||||
Next *Node // Next sibling; nil if it's the last child
|
|
||||||
|
|
||||||
Literal []byte // Text contents of the leaf nodes
|
|
||||||
|
|
||||||
HeadingData // Populated if Type is Heading
|
|
||||||
ListData // Populated if Type is List
|
|
||||||
CodeBlockData // Populated if Type is CodeBlock
|
|
||||||
LinkData // Populated if Type is Link
|
|
||||||
TableCellData // Populated if Type is TableCell
|
|
||||||
|
|
||||||
content []byte // Markdown content of the block nodes
|
|
||||||
open bool // Specifies an open block node that has not been finished to process yet
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNode allocates a node of a specified type.
|
|
||||||
func NewNode(typ NodeType) *Node {
|
|
||||||
return &Node{
|
|
||||||
Type: typ,
|
|
||||||
open: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *Node) String() string {
|
|
||||||
ellipsis := ""
|
|
||||||
snippet := n.Literal
|
|
||||||
if len(snippet) > 16 {
|
|
||||||
snippet = snippet[:16]
|
|
||||||
ellipsis = "..."
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%s: '%s%s'", n.Type, snippet, ellipsis)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unlink removes node 'n' from the tree.
|
|
||||||
// It panics if the node is nil.
|
|
||||||
func (n *Node) Unlink() {
|
|
||||||
if n.Prev != nil {
|
|
||||||
n.Prev.Next = n.Next
|
|
||||||
} else if n.Parent != nil {
|
|
||||||
n.Parent.FirstChild = n.Next
|
|
||||||
}
|
|
||||||
if n.Next != nil {
|
|
||||||
n.Next.Prev = n.Prev
|
|
||||||
} else if n.Parent != nil {
|
|
||||||
n.Parent.LastChild = n.Prev
|
|
||||||
}
|
|
||||||
n.Parent = nil
|
|
||||||
n.Next = nil
|
|
||||||
n.Prev = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AppendChild adds a node 'child' as a child of 'n'.
|
|
||||||
// It panics if either node is nil.
|
|
||||||
func (n *Node) AppendChild(child *Node) {
|
|
||||||
child.Unlink()
|
|
||||||
child.Parent = n
|
|
||||||
if n.LastChild != nil {
|
|
||||||
n.LastChild.Next = child
|
|
||||||
child.Prev = n.LastChild
|
|
||||||
n.LastChild = child
|
|
||||||
} else {
|
|
||||||
n.FirstChild = child
|
|
||||||
n.LastChild = child
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertBefore inserts 'sibling' immediately before 'n'.
|
|
||||||
// It panics if either node is nil.
|
|
||||||
func (n *Node) InsertBefore(sibling *Node) {
|
|
||||||
sibling.Unlink()
|
|
||||||
sibling.Prev = n.Prev
|
|
||||||
if sibling.Prev != nil {
|
|
||||||
sibling.Prev.Next = sibling
|
|
||||||
}
|
|
||||||
sibling.Next = n
|
|
||||||
n.Prev = sibling
|
|
||||||
sibling.Parent = n.Parent
|
|
||||||
if sibling.Prev == nil {
|
|
||||||
sibling.Parent.FirstChild = sibling
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *Node) isContainer() bool {
|
|
||||||
switch n.Type {
|
|
||||||
case Document:
|
|
||||||
fallthrough
|
|
||||||
case BlockQuote:
|
|
||||||
fallthrough
|
|
||||||
case List:
|
|
||||||
fallthrough
|
|
||||||
case Item:
|
|
||||||
fallthrough
|
|
||||||
case Paragraph:
|
|
||||||
fallthrough
|
|
||||||
case Heading:
|
|
||||||
fallthrough
|
|
||||||
case Emph:
|
|
||||||
fallthrough
|
|
||||||
case Strong:
|
|
||||||
fallthrough
|
|
||||||
case Del:
|
|
||||||
fallthrough
|
|
||||||
case Link:
|
|
||||||
fallthrough
|
|
||||||
case Image:
|
|
||||||
fallthrough
|
|
||||||
case Table:
|
|
||||||
fallthrough
|
|
||||||
case TableHead:
|
|
||||||
fallthrough
|
|
||||||
case TableBody:
|
|
||||||
fallthrough
|
|
||||||
case TableRow:
|
|
||||||
fallthrough
|
|
||||||
case TableCell:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *Node) canContain(t NodeType) bool {
|
|
||||||
if n.Type == List {
|
|
||||||
return t == Item
|
|
||||||
}
|
|
||||||
if n.Type == Document || n.Type == BlockQuote || n.Type == Item {
|
|
||||||
return t != Item
|
|
||||||
}
|
|
||||||
if n.Type == Table {
|
|
||||||
return t == TableHead || t == TableBody
|
|
||||||
}
|
|
||||||
if n.Type == TableHead || n.Type == TableBody {
|
|
||||||
return t == TableRow
|
|
||||||
}
|
|
||||||
if n.Type == TableRow {
|
|
||||||
return t == TableCell
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// WalkStatus allows NodeVisitor to have some control over the tree traversal.
|
|
||||||
// It is returned from NodeVisitor and different values allow Node.Walk to
|
|
||||||
// decide which node to go to next.
|
|
||||||
type WalkStatus int
|
|
||||||
|
|
||||||
const (
|
|
||||||
// GoToNext is the default traversal of every node.
|
|
||||||
GoToNext WalkStatus = iota
|
|
||||||
// SkipChildren tells walker to skip all children of current node.
|
|
||||||
SkipChildren
|
|
||||||
// Terminate tells walker to terminate the traversal.
|
|
||||||
Terminate
|
|
||||||
)
|
|
||||||
|
|
||||||
// NodeVisitor is a callback to be called when traversing the syntax tree.
|
|
||||||
// Called twice for every node: once with entering=true when the branch is
|
|
||||||
// first visited, then with entering=false after all the children are done.
|
|
||||||
type NodeVisitor func(node *Node, entering bool) WalkStatus
|
|
||||||
|
|
||||||
// Walk is a convenience method that instantiates a walker and starts a
|
|
||||||
// traversal of subtree rooted at n.
|
|
||||||
func (n *Node) Walk(visitor NodeVisitor) {
|
|
||||||
w := newNodeWalker(n)
|
|
||||||
for w.current != nil {
|
|
||||||
status := visitor(w.current, w.entering)
|
|
||||||
switch status {
|
|
||||||
case GoToNext:
|
|
||||||
w.next()
|
|
||||||
case SkipChildren:
|
|
||||||
w.entering = false
|
|
||||||
w.next()
|
|
||||||
case Terminate:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type nodeWalker struct {
|
|
||||||
current *Node
|
|
||||||
root *Node
|
|
||||||
entering bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func newNodeWalker(root *Node) *nodeWalker {
|
|
||||||
return &nodeWalker{
|
|
||||||
current: root,
|
|
||||||
root: root,
|
|
||||||
entering: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (nw *nodeWalker) next() {
|
|
||||||
if (!nw.current.isContainer() || !nw.entering) && nw.current == nw.root {
|
|
||||||
nw.current = nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if nw.entering && nw.current.isContainer() {
|
|
||||||
if nw.current.FirstChild != nil {
|
|
||||||
nw.current = nw.current.FirstChild
|
|
||||||
nw.entering = true
|
|
||||||
} else {
|
|
||||||
nw.entering = false
|
|
||||||
}
|
|
||||||
} else if nw.current.Next == nil {
|
|
||||||
nw.current = nw.current.Parent
|
|
||||||
nw.entering = false
|
|
||||||
} else {
|
|
||||||
nw.current = nw.current.Next
|
|
||||||
nw.entering = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func dump(ast *Node) {
|
|
||||||
fmt.Println(dumpString(ast))
|
|
||||||
}
|
|
||||||
|
|
||||||
func dumpR(ast *Node, depth int) string {
|
|
||||||
if ast == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
indent := bytes.Repeat([]byte("\t"), depth)
|
|
||||||
content := ast.Literal
|
|
||||||
if content == nil {
|
|
||||||
content = ast.content
|
|
||||||
}
|
|
||||||
result := fmt.Sprintf("%s%s(%q)\n", indent, ast.Type, content)
|
|
||||||
for n := ast.FirstChild; n != nil; n = n.Next {
|
|
||||||
result += dumpR(n, depth+1)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func dumpString(ast *Node) string {
|
|
||||||
return dumpR(ast, 0)
|
|
||||||
}
|
|
||||||
139
vendor/github.com/russross/blackfriday/smartypants.go
generated
vendored
139
vendor/github.com/russross/blackfriday/smartypants.go
generated
vendored
@@ -17,14 +17,11 @@ package blackfriday
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// SPRenderer is a struct containing state of a Smartypants renderer.
|
type smartypantsData struct {
|
||||||
type SPRenderer struct {
|
|
||||||
inSingleQuote bool
|
inSingleQuote bool
|
||||||
inDoubleQuote bool
|
inDoubleQuote bool
|
||||||
callbacks [256]smartCallback
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func wordBoundary(c byte) bool {
|
func wordBoundary(c byte) bool {
|
||||||
@@ -121,7 +118,7 @@ func smartQuoteHelper(out *bytes.Buffer, previousChar byte, nextChar byte, quote
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *SPRenderer) smartSingleQuote(out *bytes.Buffer, previousChar byte, text []byte) int {
|
func smartSingleQuote(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int {
|
||||||
if len(text) >= 2 {
|
if len(text) >= 2 {
|
||||||
t1 := tolower(text[1])
|
t1 := tolower(text[1])
|
||||||
|
|
||||||
@@ -130,7 +127,7 @@ func (r *SPRenderer) smartSingleQuote(out *bytes.Buffer, previousChar byte, text
|
|||||||
if len(text) >= 3 {
|
if len(text) >= 3 {
|
||||||
nextChar = text[2]
|
nextChar = text[2]
|
||||||
}
|
}
|
||||||
if smartQuoteHelper(out, previousChar, nextChar, 'd', &r.inDoubleQuote, false) {
|
if smartQuoteHelper(out, previousChar, nextChar, 'd', &smrt.inDoubleQuote, false) {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,7 +152,7 @@ func (r *SPRenderer) smartSingleQuote(out *bytes.Buffer, previousChar byte, text
|
|||||||
if len(text) > 1 {
|
if len(text) > 1 {
|
||||||
nextChar = text[1]
|
nextChar = text[1]
|
||||||
}
|
}
|
||||||
if smartQuoteHelper(out, previousChar, nextChar, 's', &r.inSingleQuote, false) {
|
if smartQuoteHelper(out, previousChar, nextChar, 's', &smrt.inSingleQuote, false) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,7 +160,7 @@ func (r *SPRenderer) smartSingleQuote(out *bytes.Buffer, previousChar byte, text
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *SPRenderer) smartParens(out *bytes.Buffer, previousChar byte, text []byte) int {
|
func smartParens(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int {
|
||||||
if len(text) >= 3 {
|
if len(text) >= 3 {
|
||||||
t1 := tolower(text[1])
|
t1 := tolower(text[1])
|
||||||
t2 := tolower(text[2])
|
t2 := tolower(text[2])
|
||||||
@@ -188,7 +185,7 @@ func (r *SPRenderer) smartParens(out *bytes.Buffer, previousChar byte, text []by
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *SPRenderer) smartDash(out *bytes.Buffer, previousChar byte, text []byte) int {
|
func smartDash(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int {
|
||||||
if len(text) >= 2 {
|
if len(text) >= 2 {
|
||||||
if text[1] == '-' {
|
if text[1] == '-' {
|
||||||
out.WriteString("—")
|
out.WriteString("—")
|
||||||
@@ -205,7 +202,7 @@ func (r *SPRenderer) smartDash(out *bytes.Buffer, previousChar byte, text []byte
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *SPRenderer) smartDashLatex(out *bytes.Buffer, previousChar byte, text []byte) int {
|
func smartDashLatex(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int {
|
||||||
if len(text) >= 3 && text[1] == '-' && text[2] == '-' {
|
if len(text) >= 3 && text[1] == '-' && text[2] == '-' {
|
||||||
out.WriteString("—")
|
out.WriteString("—")
|
||||||
return 2
|
return 2
|
||||||
@@ -219,13 +216,13 @@ func (r *SPRenderer) smartDashLatex(out *bytes.Buffer, previousChar byte, text [
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *SPRenderer) smartAmpVariant(out *bytes.Buffer, previousChar byte, text []byte, quote byte, addNBSP bool) int {
|
func smartAmpVariant(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte, quote byte, addNBSP bool) int {
|
||||||
if bytes.HasPrefix(text, []byte(""")) {
|
if bytes.HasPrefix(text, []byte(""")) {
|
||||||
nextChar := byte(0)
|
nextChar := byte(0)
|
||||||
if len(text) >= 7 {
|
if len(text) >= 7 {
|
||||||
nextChar = text[6]
|
nextChar = text[6]
|
||||||
}
|
}
|
||||||
if smartQuoteHelper(out, previousChar, nextChar, quote, &r.inDoubleQuote, addNBSP) {
|
if smartQuoteHelper(out, previousChar, nextChar, quote, &smrt.inDoubleQuote, addNBSP) {
|
||||||
return 5
|
return 5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,18 +235,18 @@ func (r *SPRenderer) smartAmpVariant(out *bytes.Buffer, previousChar byte, text
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *SPRenderer) smartAmp(angledQuotes, addNBSP bool) func(*bytes.Buffer, byte, []byte) int {
|
func smartAmp(angledQuotes, addNBSP bool) func(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int {
|
||||||
var quote byte = 'd'
|
var quote byte = 'd'
|
||||||
if angledQuotes {
|
if angledQuotes {
|
||||||
quote = 'a'
|
quote = 'a'
|
||||||
}
|
}
|
||||||
|
|
||||||
return func(out *bytes.Buffer, previousChar byte, text []byte) int {
|
return func(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int {
|
||||||
return r.smartAmpVariant(out, previousChar, text, quote, addNBSP)
|
return smartAmpVariant(out, smrt, previousChar, text, quote, addNBSP)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *SPRenderer) smartPeriod(out *bytes.Buffer, previousChar byte, text []byte) int {
|
func smartPeriod(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int {
|
||||||
if len(text) >= 3 && text[1] == '.' && text[2] == '.' {
|
if len(text) >= 3 && text[1] == '.' && text[2] == '.' {
|
||||||
out.WriteString("…")
|
out.WriteString("…")
|
||||||
return 2
|
return 2
|
||||||
@@ -264,13 +261,13 @@ func (r *SPRenderer) smartPeriod(out *bytes.Buffer, previousChar byte, text []by
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *SPRenderer) smartBacktick(out *bytes.Buffer, previousChar byte, text []byte) int {
|
func smartBacktick(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int {
|
||||||
if len(text) >= 2 && text[1] == '`' {
|
if len(text) >= 2 && text[1] == '`' {
|
||||||
nextChar := byte(0)
|
nextChar := byte(0)
|
||||||
if len(text) >= 3 {
|
if len(text) >= 3 {
|
||||||
nextChar = text[2]
|
nextChar = text[2]
|
||||||
}
|
}
|
||||||
if smartQuoteHelper(out, previousChar, nextChar, 'd', &r.inDoubleQuote, false) {
|
if smartQuoteHelper(out, previousChar, nextChar, 'd', &smrt.inDoubleQuote, false) {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -279,7 +276,7 @@ func (r *SPRenderer) smartBacktick(out *bytes.Buffer, previousChar byte, text []
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *SPRenderer) smartNumberGeneric(out *bytes.Buffer, previousChar byte, text []byte) int {
|
func smartNumberGeneric(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int {
|
||||||
if wordBoundary(previousChar) && previousChar != '/' && len(text) >= 3 {
|
if wordBoundary(previousChar) && previousChar != '/' && len(text) >= 3 {
|
||||||
// is it of the form digits/digits(word boundary)?, i.e., \d+/\d+\b
|
// is it of the form digits/digits(word boundary)?, i.e., \d+/\d+\b
|
||||||
// note: check for regular slash (/) or fraction slash (⁄, 0x2044, or 0xe2 81 84 in utf-8)
|
// note: check for regular slash (/) or fraction slash (⁄, 0x2044, or 0xe2 81 84 in utf-8)
|
||||||
@@ -321,7 +318,7 @@ func (r *SPRenderer) smartNumberGeneric(out *bytes.Buffer, previousChar byte, te
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *SPRenderer) smartNumber(out *bytes.Buffer, previousChar byte, text []byte) int {
|
func smartNumber(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int {
|
||||||
if wordBoundary(previousChar) && previousChar != '/' && len(text) >= 3 {
|
if wordBoundary(previousChar) && previousChar != '/' && len(text) >= 3 {
|
||||||
if text[0] == '1' && text[1] == '/' && text[2] == '2' {
|
if text[0] == '1' && text[1] == '/' && text[2] == '2' {
|
||||||
if len(text) < 4 || wordBoundary(text[3]) && text[3] != '/' {
|
if len(text) < 4 || wordBoundary(text[3]) && text[3] != '/' {
|
||||||
@@ -349,27 +346,27 @@ func (r *SPRenderer) smartNumber(out *bytes.Buffer, previousChar byte, text []by
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *SPRenderer) smartDoubleQuoteVariant(out *bytes.Buffer, previousChar byte, text []byte, quote byte) int {
|
func smartDoubleQuoteVariant(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte, quote byte) int {
|
||||||
nextChar := byte(0)
|
nextChar := byte(0)
|
||||||
if len(text) > 1 {
|
if len(text) > 1 {
|
||||||
nextChar = text[1]
|
nextChar = text[1]
|
||||||
}
|
}
|
||||||
if !smartQuoteHelper(out, previousChar, nextChar, quote, &r.inDoubleQuote, false) {
|
if !smartQuoteHelper(out, previousChar, nextChar, quote, &smrt.inDoubleQuote, false) {
|
||||||
out.WriteString(""")
|
out.WriteString(""")
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *SPRenderer) smartDoubleQuote(out *bytes.Buffer, previousChar byte, text []byte) int {
|
func smartDoubleQuote(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int {
|
||||||
return r.smartDoubleQuoteVariant(out, previousChar, text, 'd')
|
return smartDoubleQuoteVariant(out, smrt, previousChar, text, 'd')
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *SPRenderer) smartAngledDoubleQuote(out *bytes.Buffer, previousChar byte, text []byte) int {
|
func smartAngledDoubleQuote(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int {
|
||||||
return r.smartDoubleQuoteVariant(out, previousChar, text, 'a')
|
return smartDoubleQuoteVariant(out, smrt, previousChar, text, 'a')
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *SPRenderer) smartLeftAngle(out *bytes.Buffer, previousChar byte, text []byte) int {
|
func smartLeftAngle(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int {
|
||||||
i := 0
|
i := 0
|
||||||
|
|
||||||
for i < len(text) && text[i] != '>' {
|
for i < len(text) && text[i] != '>' {
|
||||||
@@ -380,78 +377,54 @@ func (r *SPRenderer) smartLeftAngle(out *bytes.Buffer, previousChar byte, text [
|
|||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
type smartCallback func(out *bytes.Buffer, previousChar byte, text []byte) int
|
type smartCallback func(out *bytes.Buffer, smrt *smartypantsData, previousChar byte, text []byte) int
|
||||||
|
|
||||||
// NewSmartypantsRenderer constructs a Smartypants renderer object.
|
type smartypantsRenderer [256]smartCallback
|
||||||
func NewSmartypantsRenderer(flags HTMLFlags) *SPRenderer {
|
|
||||||
var (
|
|
||||||
r SPRenderer
|
|
||||||
|
|
||||||
smartAmpAngled = r.smartAmp(true, false)
|
var (
|
||||||
smartAmpAngledNBSP = r.smartAmp(true, true)
|
smartAmpAngled = smartAmp(true, false)
|
||||||
smartAmpRegular = r.smartAmp(false, false)
|
smartAmpAngledNBSP = smartAmp(true, true)
|
||||||
smartAmpRegularNBSP = r.smartAmp(false, true)
|
smartAmpRegular = smartAmp(false, false)
|
||||||
|
smartAmpRegularNBSP = smartAmp(false, true)
|
||||||
|
)
|
||||||
|
|
||||||
addNBSP = flags&SmartypantsQuotesNBSP != 0
|
func smartypants(flags int) *smartypantsRenderer {
|
||||||
)
|
r := new(smartypantsRenderer)
|
||||||
|
addNBSP := flags&HTML_SMARTYPANTS_QUOTES_NBSP != 0
|
||||||
if flags&SmartypantsAngledQuotes == 0 {
|
if flags&HTML_SMARTYPANTS_ANGLED_QUOTES == 0 {
|
||||||
r.callbacks['"'] = r.smartDoubleQuote
|
r['"'] = smartDoubleQuote
|
||||||
if !addNBSP {
|
if !addNBSP {
|
||||||
r.callbacks['&'] = smartAmpRegular
|
r['&'] = smartAmpRegular
|
||||||
} else {
|
} else {
|
||||||
r.callbacks['&'] = smartAmpRegularNBSP
|
r['&'] = smartAmpRegularNBSP
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
r.callbacks['"'] = r.smartAngledDoubleQuote
|
r['"'] = smartAngledDoubleQuote
|
||||||
if !addNBSP {
|
if !addNBSP {
|
||||||
r.callbacks['&'] = smartAmpAngled
|
r['&'] = smartAmpAngled
|
||||||
} else {
|
} else {
|
||||||
r.callbacks['&'] = smartAmpAngledNBSP
|
r['&'] = smartAmpAngledNBSP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r.callbacks['\''] = r.smartSingleQuote
|
r['\''] = smartSingleQuote
|
||||||
r.callbacks['('] = r.smartParens
|
r['('] = smartParens
|
||||||
if flags&SmartypantsDashes != 0 {
|
if flags&HTML_SMARTYPANTS_DASHES != 0 {
|
||||||
if flags&SmartypantsLatexDashes == 0 {
|
if flags&HTML_SMARTYPANTS_LATEX_DASHES == 0 {
|
||||||
r.callbacks['-'] = r.smartDash
|
r['-'] = smartDash
|
||||||
} else {
|
} else {
|
||||||
r.callbacks['-'] = r.smartDashLatex
|
r['-'] = smartDashLatex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r.callbacks['.'] = r.smartPeriod
|
r['.'] = smartPeriod
|
||||||
if flags&SmartypantsFractions == 0 {
|
if flags&HTML_SMARTYPANTS_FRACTIONS == 0 {
|
||||||
r.callbacks['1'] = r.smartNumber
|
r['1'] = smartNumber
|
||||||
r.callbacks['3'] = r.smartNumber
|
r['3'] = smartNumber
|
||||||
} else {
|
} else {
|
||||||
for ch := '1'; ch <= '9'; ch++ {
|
for ch := '1'; ch <= '9'; ch++ {
|
||||||
r.callbacks[ch] = r.smartNumberGeneric
|
r[ch] = smartNumberGeneric
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r.callbacks['<'] = r.smartLeftAngle
|
r['<'] = smartLeftAngle
|
||||||
r.callbacks['`'] = r.smartBacktick
|
r['`'] = smartBacktick
|
||||||
return &r
|
return r
|
||||||
}
|
|
||||||
|
|
||||||
// Process is the entry point of the Smartypants renderer.
|
|
||||||
func (r *SPRenderer) Process(w io.Writer, text []byte) {
|
|
||||||
mark := 0
|
|
||||||
for i := 0; i < len(text); i++ {
|
|
||||||
if action := r.callbacks[text[i]]; action != nil {
|
|
||||||
if i > mark {
|
|
||||||
w.Write(text[mark:i])
|
|
||||||
}
|
|
||||||
previousChar := byte(0)
|
|
||||||
if i > 0 {
|
|
||||||
previousChar = text[i-1]
|
|
||||||
}
|
|
||||||
var tmp bytes.Buffer
|
|
||||||
i += action(&tmp, previousChar, text[i:])
|
|
||||||
w.Write(tmp.Bytes())
|
|
||||||
mark = i + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if mark < len(text) {
|
|
||||||
w.Write(text[mark:])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
16
vendor/github.com/shurcooL/sanitized_anchor_name/.travis.yml
generated
vendored
16
vendor/github.com/shurcooL/sanitized_anchor_name/.travis.yml
generated
vendored
@@ -1,16 +0,0 @@
|
|||||||
sudo: false
|
|
||||||
language: go
|
|
||||||
go:
|
|
||||||
- 1.x
|
|
||||||
- master
|
|
||||||
matrix:
|
|
||||||
allow_failures:
|
|
||||||
- go: master
|
|
||||||
fast_finish: true
|
|
||||||
install:
|
|
||||||
- # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step).
|
|
||||||
script:
|
|
||||||
- go get -t -v ./...
|
|
||||||
- diff -u <(echo -n) <(gofmt -d -s .)
|
|
||||||
- go tool vet .
|
|
||||||
- go test -v -race ./...
|
|
||||||
21
vendor/github.com/shurcooL/sanitized_anchor_name/LICENSE
generated
vendored
21
vendor/github.com/shurcooL/sanitized_anchor_name/LICENSE
generated
vendored
@@ -1,21 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2015 Dmitri Shuralyov
|
|
||||||
|
|
||||||
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.
|
|
||||||
36
vendor/github.com/shurcooL/sanitized_anchor_name/README.md
generated
vendored
36
vendor/github.com/shurcooL/sanitized_anchor_name/README.md
generated
vendored
@@ -1,36 +0,0 @@
|
|||||||
sanitized_anchor_name
|
|
||||||
=====================
|
|
||||||
|
|
||||||
[](https://travis-ci.org/shurcooL/sanitized_anchor_name) [](https://godoc.org/github.com/shurcooL/sanitized_anchor_name)
|
|
||||||
|
|
||||||
Package sanitized_anchor_name provides a func to create sanitized anchor names.
|
|
||||||
|
|
||||||
Its logic can be reused by multiple packages to create interoperable anchor names
|
|
||||||
and links to those anchors.
|
|
||||||
|
|
||||||
At this time, it does not try to ensure that generated anchor names
|
|
||||||
are unique, that responsibility falls on the caller.
|
|
||||||
|
|
||||||
Installation
|
|
||||||
------------
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go get -u github.com/shurcooL/sanitized_anchor_name
|
|
||||||
```
|
|
||||||
|
|
||||||
Example
|
|
||||||
-------
|
|
||||||
|
|
||||||
```Go
|
|
||||||
anchorName := sanitized_anchor_name.Create("This is a header")
|
|
||||||
|
|
||||||
fmt.Println(anchorName)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// this-is-a-header
|
|
||||||
```
|
|
||||||
|
|
||||||
License
|
|
||||||
-------
|
|
||||||
|
|
||||||
- [MIT License](LICENSE)
|
|
||||||
1
vendor/github.com/shurcooL/sanitized_anchor_name/go.mod
generated
vendored
1
vendor/github.com/shurcooL/sanitized_anchor_name/go.mod
generated
vendored
@@ -1 +0,0 @@
|
|||||||
module github.com/shurcooL/sanitized_anchor_name
|
|
||||||
29
vendor/github.com/shurcooL/sanitized_anchor_name/main.go
generated
vendored
29
vendor/github.com/shurcooL/sanitized_anchor_name/main.go
generated
vendored
@@ -1,29 +0,0 @@
|
|||||||
// Package sanitized_anchor_name provides a func to create sanitized anchor names.
|
|
||||||
//
|
|
||||||
// Its logic can be reused by multiple packages to create interoperable anchor names
|
|
||||||
// and links to those anchors.
|
|
||||||
//
|
|
||||||
// At this time, it does not try to ensure that generated anchor names
|
|
||||||
// are unique, that responsibility falls on the caller.
|
|
||||||
package sanitized_anchor_name // import "github.com/shurcooL/sanitized_anchor_name"
|
|
||||||
|
|
||||||
import "unicode"
|
|
||||||
|
|
||||||
// Create returns a sanitized anchor name for the given text.
|
|
||||||
func Create(text string) string {
|
|
||||||
var anchorName []rune
|
|
||||||
var futureDash = false
|
|
||||||
for _, r := range text {
|
|
||||||
switch {
|
|
||||||
case unicode.IsLetter(r) || unicode.IsNumber(r):
|
|
||||||
if futureDash && len(anchorName) > 0 {
|
|
||||||
anchorName = append(anchorName, '-')
|
|
||||||
}
|
|
||||||
futureDash = false
|
|
||||||
anchorName = append(anchorName, unicode.ToLower(r))
|
|
||||||
default:
|
|
||||||
futureDash = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return string(anchorName)
|
|
||||||
}
|
|
||||||
23
vendor/golang.org/x/crypto/acme/acme.go
generated
vendored
23
vendor/golang.org/x/crypto/acme/acme.go
generated
vendored
@@ -128,11 +128,7 @@ func (c *Client) Discover(ctx context.Context) (Directory, error) {
|
|||||||
return *c.dir, nil
|
return *c.dir, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
dirURL := c.DirectoryURL
|
res, err := c.get(ctx, c.directoryURL(), wantStatus(http.StatusOK))
|
||||||
if dirURL == "" {
|
|
||||||
dirURL = LetsEncryptURL
|
|
||||||
}
|
|
||||||
res, err := c.get(ctx, dirURL, wantStatus(http.StatusOK))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Directory{}, err
|
return Directory{}, err
|
||||||
}
|
}
|
||||||
@@ -165,6 +161,13 @@ func (c *Client) Discover(ctx context.Context) (Directory, error) {
|
|||||||
return *c.dir, nil
|
return *c.dir, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) directoryURL() string {
|
||||||
|
if c.DirectoryURL != "" {
|
||||||
|
return c.DirectoryURL
|
||||||
|
}
|
||||||
|
return LetsEncryptURL
|
||||||
|
}
|
||||||
|
|
||||||
// CreateCert requests a new certificate using the Certificate Signing Request csr encoded in DER format.
|
// CreateCert requests a new certificate using the Certificate Signing Request csr encoded in DER format.
|
||||||
// The exp argument indicates the desired certificate validity duration. CA may issue a certificate
|
// The exp argument indicates the desired certificate validity duration. CA may issue a certificate
|
||||||
// with a different duration.
|
// with a different duration.
|
||||||
@@ -711,12 +714,18 @@ func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Accoun
|
|||||||
}
|
}
|
||||||
|
|
||||||
// popNonce returns a nonce value previously stored with c.addNonce
|
// popNonce returns a nonce value previously stored with c.addNonce
|
||||||
// or fetches a fresh one from the given URL.
|
// or fetches a fresh one from a URL by issuing a HEAD request.
|
||||||
|
// It first tries c.directoryURL() and then the provided url if the former fails.
|
||||||
func (c *Client) popNonce(ctx context.Context, url string) (string, error) {
|
func (c *Client) popNonce(ctx context.Context, url string) (string, error) {
|
||||||
c.noncesMu.Lock()
|
c.noncesMu.Lock()
|
||||||
defer c.noncesMu.Unlock()
|
defer c.noncesMu.Unlock()
|
||||||
if len(c.nonces) == 0 {
|
if len(c.nonces) == 0 {
|
||||||
return c.fetchNonce(ctx, url)
|
dirURL := c.directoryURL()
|
||||||
|
v, err := c.fetchNonce(ctx, dirURL)
|
||||||
|
if err != nil && url != dirURL {
|
||||||
|
v, err = c.fetchNonce(ctx, url)
|
||||||
|
}
|
||||||
|
return v, err
|
||||||
}
|
}
|
||||||
var nonce string
|
var nonce string
|
||||||
for nonce = range c.nonces {
|
for nonce = range c.nonces {
|
||||||
|
|||||||
8
vendor/golang.org/x/crypto/blowfish/cipher.go
generated
vendored
8
vendor/golang.org/x/crypto/blowfish/cipher.go
generated
vendored
@@ -3,6 +3,14 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Package blowfish implements Bruce Schneier's Blowfish encryption algorithm.
|
// Package blowfish implements Bruce Schneier's Blowfish encryption algorithm.
|
||||||
|
//
|
||||||
|
// Blowfish is a legacy cipher and its short block size makes it vulnerable to
|
||||||
|
// birthday bound attacks (see https://sweet32.info). It should only be used
|
||||||
|
// where compatibility with legacy systems, not security, is the goal.
|
||||||
|
//
|
||||||
|
// Deprecated: any new system should use AES (from crypto/aes, if necessary in
|
||||||
|
// an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from
|
||||||
|
// golang.org/x/crypto/chacha20poly1305).
|
||||||
package blowfish // import "golang.org/x/crypto/blowfish"
|
package blowfish // import "golang.org/x/crypto/blowfish"
|
||||||
|
|
||||||
// The code is a port of Bruce Schneier's C implementation.
|
// The code is a port of Bruce Schneier's C implementation.
|
||||||
|
|||||||
2
vendor/golang.org/x/crypto/curve25519/curve25519.go
generated
vendored
2
vendor/golang.org/x/crypto/curve25519/curve25519.go
generated
vendored
@@ -86,7 +86,7 @@ func feFromBytes(dst *fieldElement, src *[32]byte) {
|
|||||||
h6 := load3(src[20:]) << 7
|
h6 := load3(src[20:]) << 7
|
||||||
h7 := load3(src[23:]) << 5
|
h7 := load3(src[23:]) << 5
|
||||||
h8 := load3(src[26:]) << 4
|
h8 := load3(src[26:]) << 4
|
||||||
h9 := load3(src[29:]) << 2
|
h9 := (load3(src[29:]) & 0x7fffff) << 2
|
||||||
|
|
||||||
var carry [10]int64
|
var carry [10]int64
|
||||||
carry[9] = (h9 + 1<<24) >> 25
|
carry[9] = (h9 + 1<<24) >> 25
|
||||||
|
|||||||
308
vendor/golang.org/x/crypto/internal/chacha20/asm_arm64.s
generated
vendored
Normal file
308
vendor/golang.org/x/crypto/internal/chacha20/asm_arm64.s
generated
vendored
Normal file
@@ -0,0 +1,308 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.11
|
||||||
|
// +build !gccgo,!appengine
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
#define NUM_ROUNDS 10
|
||||||
|
|
||||||
|
// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
|
||||||
|
TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0
|
||||||
|
MOVD dst+0(FP), R1
|
||||||
|
MOVD src+24(FP), R2
|
||||||
|
MOVD src_len+32(FP), R3
|
||||||
|
MOVD key+48(FP), R4
|
||||||
|
MOVD nonce+56(FP), R6
|
||||||
|
MOVD counter+64(FP), R7
|
||||||
|
|
||||||
|
MOVD $·constants(SB), R10
|
||||||
|
MOVD $·incRotMatrix(SB), R11
|
||||||
|
|
||||||
|
MOVW (R7), R20
|
||||||
|
|
||||||
|
AND $~255, R3, R13
|
||||||
|
ADD R2, R13, R12 // R12 for block end
|
||||||
|
AND $255, R3, R13
|
||||||
|
loop:
|
||||||
|
MOVD $NUM_ROUNDS, R21
|
||||||
|
VLD1 (R11), [V30.S4, V31.S4]
|
||||||
|
|
||||||
|
// load contants
|
||||||
|
// VLD4R (R10), [V0.S4, V1.S4, V2.S4, V3.S4]
|
||||||
|
WORD $0x4D60E940
|
||||||
|
|
||||||
|
// load keys
|
||||||
|
// VLD4R 16(R4), [V4.S4, V5.S4, V6.S4, V7.S4]
|
||||||
|
WORD $0x4DFFE884
|
||||||
|
// VLD4R 16(R4), [V8.S4, V9.S4, V10.S4, V11.S4]
|
||||||
|
WORD $0x4DFFE888
|
||||||
|
SUB $32, R4
|
||||||
|
|
||||||
|
// load counter + nonce
|
||||||
|
// VLD1R (R7), [V12.S4]
|
||||||
|
WORD $0x4D40C8EC
|
||||||
|
|
||||||
|
// VLD3R (R6), [V13.S4, V14.S4, V15.S4]
|
||||||
|
WORD $0x4D40E8CD
|
||||||
|
|
||||||
|
// update counter
|
||||||
|
VADD V30.S4, V12.S4, V12.S4
|
||||||
|
|
||||||
|
chacha:
|
||||||
|
// V0..V3 += V4..V7
|
||||||
|
// V12..V15 <<<= ((V12..V15 XOR V0..V3), 16)
|
||||||
|
VADD V0.S4, V4.S4, V0.S4
|
||||||
|
VADD V1.S4, V5.S4, V1.S4
|
||||||
|
VADD V2.S4, V6.S4, V2.S4
|
||||||
|
VADD V3.S4, V7.S4, V3.S4
|
||||||
|
VEOR V12.B16, V0.B16, V12.B16
|
||||||
|
VEOR V13.B16, V1.B16, V13.B16
|
||||||
|
VEOR V14.B16, V2.B16, V14.B16
|
||||||
|
VEOR V15.B16, V3.B16, V15.B16
|
||||||
|
VREV32 V12.H8, V12.H8
|
||||||
|
VREV32 V13.H8, V13.H8
|
||||||
|
VREV32 V14.H8, V14.H8
|
||||||
|
VREV32 V15.H8, V15.H8
|
||||||
|
// V8..V11 += V12..V15
|
||||||
|
// V4..V7 <<<= ((V4..V7 XOR V8..V11), 12)
|
||||||
|
VADD V8.S4, V12.S4, V8.S4
|
||||||
|
VADD V9.S4, V13.S4, V9.S4
|
||||||
|
VADD V10.S4, V14.S4, V10.S4
|
||||||
|
VADD V11.S4, V15.S4, V11.S4
|
||||||
|
VEOR V8.B16, V4.B16, V16.B16
|
||||||
|
VEOR V9.B16, V5.B16, V17.B16
|
||||||
|
VEOR V10.B16, V6.B16, V18.B16
|
||||||
|
VEOR V11.B16, V7.B16, V19.B16
|
||||||
|
VSHL $12, V16.S4, V4.S4
|
||||||
|
VSHL $12, V17.S4, V5.S4
|
||||||
|
VSHL $12, V18.S4, V6.S4
|
||||||
|
VSHL $12, V19.S4, V7.S4
|
||||||
|
VSRI $20, V16.S4, V4.S4
|
||||||
|
VSRI $20, V17.S4, V5.S4
|
||||||
|
VSRI $20, V18.S4, V6.S4
|
||||||
|
VSRI $20, V19.S4, V7.S4
|
||||||
|
|
||||||
|
// V0..V3 += V4..V7
|
||||||
|
// V12..V15 <<<= ((V12..V15 XOR V0..V3), 8)
|
||||||
|
VADD V0.S4, V4.S4, V0.S4
|
||||||
|
VADD V1.S4, V5.S4, V1.S4
|
||||||
|
VADD V2.S4, V6.S4, V2.S4
|
||||||
|
VADD V3.S4, V7.S4, V3.S4
|
||||||
|
VEOR V12.B16, V0.B16, V12.B16
|
||||||
|
VEOR V13.B16, V1.B16, V13.B16
|
||||||
|
VEOR V14.B16, V2.B16, V14.B16
|
||||||
|
VEOR V15.B16, V3.B16, V15.B16
|
||||||
|
VTBL V31.B16, [V12.B16], V12.B16
|
||||||
|
VTBL V31.B16, [V13.B16], V13.B16
|
||||||
|
VTBL V31.B16, [V14.B16], V14.B16
|
||||||
|
VTBL V31.B16, [V15.B16], V15.B16
|
||||||
|
|
||||||
|
// V8..V11 += V12..V15
|
||||||
|
// V4..V7 <<<= ((V4..V7 XOR V8..V11), 7)
|
||||||
|
VADD V12.S4, V8.S4, V8.S4
|
||||||
|
VADD V13.S4, V9.S4, V9.S4
|
||||||
|
VADD V14.S4, V10.S4, V10.S4
|
||||||
|
VADD V15.S4, V11.S4, V11.S4
|
||||||
|
VEOR V8.B16, V4.B16, V16.B16
|
||||||
|
VEOR V9.B16, V5.B16, V17.B16
|
||||||
|
VEOR V10.B16, V6.B16, V18.B16
|
||||||
|
VEOR V11.B16, V7.B16, V19.B16
|
||||||
|
VSHL $7, V16.S4, V4.S4
|
||||||
|
VSHL $7, V17.S4, V5.S4
|
||||||
|
VSHL $7, V18.S4, V6.S4
|
||||||
|
VSHL $7, V19.S4, V7.S4
|
||||||
|
VSRI $25, V16.S4, V4.S4
|
||||||
|
VSRI $25, V17.S4, V5.S4
|
||||||
|
VSRI $25, V18.S4, V6.S4
|
||||||
|
VSRI $25, V19.S4, V7.S4
|
||||||
|
|
||||||
|
// V0..V3 += V5..V7, V4
|
||||||
|
// V15,V12-V14 <<<= ((V15,V12-V14 XOR V0..V3), 16)
|
||||||
|
VADD V0.S4, V5.S4, V0.S4
|
||||||
|
VADD V1.S4, V6.S4, V1.S4
|
||||||
|
VADD V2.S4, V7.S4, V2.S4
|
||||||
|
VADD V3.S4, V4.S4, V3.S4
|
||||||
|
VEOR V15.B16, V0.B16, V15.B16
|
||||||
|
VEOR V12.B16, V1.B16, V12.B16
|
||||||
|
VEOR V13.B16, V2.B16, V13.B16
|
||||||
|
VEOR V14.B16, V3.B16, V14.B16
|
||||||
|
VREV32 V12.H8, V12.H8
|
||||||
|
VREV32 V13.H8, V13.H8
|
||||||
|
VREV32 V14.H8, V14.H8
|
||||||
|
VREV32 V15.H8, V15.H8
|
||||||
|
|
||||||
|
// V10 += V15; V5 <<<= ((V10 XOR V5), 12)
|
||||||
|
// ...
|
||||||
|
VADD V15.S4, V10.S4, V10.S4
|
||||||
|
VADD V12.S4, V11.S4, V11.S4
|
||||||
|
VADD V13.S4, V8.S4, V8.S4
|
||||||
|
VADD V14.S4, V9.S4, V9.S4
|
||||||
|
VEOR V10.B16, V5.B16, V16.B16
|
||||||
|
VEOR V11.B16, V6.B16, V17.B16
|
||||||
|
VEOR V8.B16, V7.B16, V18.B16
|
||||||
|
VEOR V9.B16, V4.B16, V19.B16
|
||||||
|
VSHL $12, V16.S4, V5.S4
|
||||||
|
VSHL $12, V17.S4, V6.S4
|
||||||
|
VSHL $12, V18.S4, V7.S4
|
||||||
|
VSHL $12, V19.S4, V4.S4
|
||||||
|
VSRI $20, V16.S4, V5.S4
|
||||||
|
VSRI $20, V17.S4, V6.S4
|
||||||
|
VSRI $20, V18.S4, V7.S4
|
||||||
|
VSRI $20, V19.S4, V4.S4
|
||||||
|
|
||||||
|
// V0 += V5; V15 <<<= ((V0 XOR V15), 8)
|
||||||
|
// ...
|
||||||
|
VADD V5.S4, V0.S4, V0.S4
|
||||||
|
VADD V6.S4, V1.S4, V1.S4
|
||||||
|
VADD V7.S4, V2.S4, V2.S4
|
||||||
|
VADD V4.S4, V3.S4, V3.S4
|
||||||
|
VEOR V0.B16, V15.B16, V15.B16
|
||||||
|
VEOR V1.B16, V12.B16, V12.B16
|
||||||
|
VEOR V2.B16, V13.B16, V13.B16
|
||||||
|
VEOR V3.B16, V14.B16, V14.B16
|
||||||
|
VTBL V31.B16, [V12.B16], V12.B16
|
||||||
|
VTBL V31.B16, [V13.B16], V13.B16
|
||||||
|
VTBL V31.B16, [V14.B16], V14.B16
|
||||||
|
VTBL V31.B16, [V15.B16], V15.B16
|
||||||
|
|
||||||
|
// V10 += V15; V5 <<<= ((V10 XOR V5), 7)
|
||||||
|
// ...
|
||||||
|
VADD V15.S4, V10.S4, V10.S4
|
||||||
|
VADD V12.S4, V11.S4, V11.S4
|
||||||
|
VADD V13.S4, V8.S4, V8.S4
|
||||||
|
VADD V14.S4, V9.S4, V9.S4
|
||||||
|
VEOR V10.B16, V5.B16, V16.B16
|
||||||
|
VEOR V11.B16, V6.B16, V17.B16
|
||||||
|
VEOR V8.B16, V7.B16, V18.B16
|
||||||
|
VEOR V9.B16, V4.B16, V19.B16
|
||||||
|
VSHL $7, V16.S4, V5.S4
|
||||||
|
VSHL $7, V17.S4, V6.S4
|
||||||
|
VSHL $7, V18.S4, V7.S4
|
||||||
|
VSHL $7, V19.S4, V4.S4
|
||||||
|
VSRI $25, V16.S4, V5.S4
|
||||||
|
VSRI $25, V17.S4, V6.S4
|
||||||
|
VSRI $25, V18.S4, V7.S4
|
||||||
|
VSRI $25, V19.S4, V4.S4
|
||||||
|
|
||||||
|
SUB $1, R21
|
||||||
|
CBNZ R21, chacha
|
||||||
|
|
||||||
|
// VLD4R (R10), [V16.S4, V17.S4, V18.S4, V19.S4]
|
||||||
|
WORD $0x4D60E950
|
||||||
|
|
||||||
|
// VLD4R 16(R4), [V20.S4, V21.S4, V22.S4, V23.S4]
|
||||||
|
WORD $0x4DFFE894
|
||||||
|
VADD V30.S4, V12.S4, V12.S4
|
||||||
|
VADD V16.S4, V0.S4, V0.S4
|
||||||
|
VADD V17.S4, V1.S4, V1.S4
|
||||||
|
VADD V18.S4, V2.S4, V2.S4
|
||||||
|
VADD V19.S4, V3.S4, V3.S4
|
||||||
|
// VLD4R 16(R4), [V24.S4, V25.S4, V26.S4, V27.S4]
|
||||||
|
WORD $0x4DFFE898
|
||||||
|
// restore R4
|
||||||
|
SUB $32, R4
|
||||||
|
|
||||||
|
// load counter + nonce
|
||||||
|
// VLD1R (R7), [V28.S4]
|
||||||
|
WORD $0x4D40C8FC
|
||||||
|
// VLD3R (R6), [V29.S4, V30.S4, V31.S4]
|
||||||
|
WORD $0x4D40E8DD
|
||||||
|
|
||||||
|
VADD V20.S4, V4.S4, V4.S4
|
||||||
|
VADD V21.S4, V5.S4, V5.S4
|
||||||
|
VADD V22.S4, V6.S4, V6.S4
|
||||||
|
VADD V23.S4, V7.S4, V7.S4
|
||||||
|
VADD V24.S4, V8.S4, V8.S4
|
||||||
|
VADD V25.S4, V9.S4, V9.S4
|
||||||
|
VADD V26.S4, V10.S4, V10.S4
|
||||||
|
VADD V27.S4, V11.S4, V11.S4
|
||||||
|
VADD V28.S4, V12.S4, V12.S4
|
||||||
|
VADD V29.S4, V13.S4, V13.S4
|
||||||
|
VADD V30.S4, V14.S4, V14.S4
|
||||||
|
VADD V31.S4, V15.S4, V15.S4
|
||||||
|
|
||||||
|
VZIP1 V1.S4, V0.S4, V16.S4
|
||||||
|
VZIP2 V1.S4, V0.S4, V17.S4
|
||||||
|
VZIP1 V3.S4, V2.S4, V18.S4
|
||||||
|
VZIP2 V3.S4, V2.S4, V19.S4
|
||||||
|
VZIP1 V5.S4, V4.S4, V20.S4
|
||||||
|
VZIP2 V5.S4, V4.S4, V21.S4
|
||||||
|
VZIP1 V7.S4, V6.S4, V22.S4
|
||||||
|
VZIP2 V7.S4, V6.S4, V23.S4
|
||||||
|
VZIP1 V9.S4, V8.S4, V24.S4
|
||||||
|
VZIP2 V9.S4, V8.S4, V25.S4
|
||||||
|
VZIP1 V11.S4, V10.S4, V26.S4
|
||||||
|
VZIP2 V11.S4, V10.S4, V27.S4
|
||||||
|
VZIP1 V13.S4, V12.S4, V28.S4
|
||||||
|
VZIP2 V13.S4, V12.S4, V29.S4
|
||||||
|
VZIP1 V15.S4, V14.S4, V30.S4
|
||||||
|
VZIP2 V15.S4, V14.S4, V31.S4
|
||||||
|
VZIP1 V18.D2, V16.D2, V0.D2
|
||||||
|
VZIP2 V18.D2, V16.D2, V4.D2
|
||||||
|
VZIP1 V19.D2, V17.D2, V8.D2
|
||||||
|
VZIP2 V19.D2, V17.D2, V12.D2
|
||||||
|
VLD1.P 64(R2), [V16.B16, V17.B16, V18.B16, V19.B16]
|
||||||
|
|
||||||
|
VZIP1 V22.D2, V20.D2, V1.D2
|
||||||
|
VZIP2 V22.D2, V20.D2, V5.D2
|
||||||
|
VZIP1 V23.D2, V21.D2, V9.D2
|
||||||
|
VZIP2 V23.D2, V21.D2, V13.D2
|
||||||
|
VLD1.P 64(R2), [V20.B16, V21.B16, V22.B16, V23.B16]
|
||||||
|
VZIP1 V26.D2, V24.D2, V2.D2
|
||||||
|
VZIP2 V26.D2, V24.D2, V6.D2
|
||||||
|
VZIP1 V27.D2, V25.D2, V10.D2
|
||||||
|
VZIP2 V27.D2, V25.D2, V14.D2
|
||||||
|
VLD1.P 64(R2), [V24.B16, V25.B16, V26.B16, V27.B16]
|
||||||
|
VZIP1 V30.D2, V28.D2, V3.D2
|
||||||
|
VZIP2 V30.D2, V28.D2, V7.D2
|
||||||
|
VZIP1 V31.D2, V29.D2, V11.D2
|
||||||
|
VZIP2 V31.D2, V29.D2, V15.D2
|
||||||
|
VLD1.P 64(R2), [V28.B16, V29.B16, V30.B16, V31.B16]
|
||||||
|
VEOR V0.B16, V16.B16, V16.B16
|
||||||
|
VEOR V1.B16, V17.B16, V17.B16
|
||||||
|
VEOR V2.B16, V18.B16, V18.B16
|
||||||
|
VEOR V3.B16, V19.B16, V19.B16
|
||||||
|
VST1.P [V16.B16, V17.B16, V18.B16, V19.B16], 64(R1)
|
||||||
|
VEOR V4.B16, V20.B16, V20.B16
|
||||||
|
VEOR V5.B16, V21.B16, V21.B16
|
||||||
|
VEOR V6.B16, V22.B16, V22.B16
|
||||||
|
VEOR V7.B16, V23.B16, V23.B16
|
||||||
|
VST1.P [V20.B16, V21.B16, V22.B16, V23.B16], 64(R1)
|
||||||
|
VEOR V8.B16, V24.B16, V24.B16
|
||||||
|
VEOR V9.B16, V25.B16, V25.B16
|
||||||
|
VEOR V10.B16, V26.B16, V26.B16
|
||||||
|
VEOR V11.B16, V27.B16, V27.B16
|
||||||
|
VST1.P [V24.B16, V25.B16, V26.B16, V27.B16], 64(R1)
|
||||||
|
VEOR V12.B16, V28.B16, V28.B16
|
||||||
|
VEOR V13.B16, V29.B16, V29.B16
|
||||||
|
VEOR V14.B16, V30.B16, V30.B16
|
||||||
|
VEOR V15.B16, V31.B16, V31.B16
|
||||||
|
VST1.P [V28.B16, V29.B16, V30.B16, V31.B16], 64(R1)
|
||||||
|
|
||||||
|
ADD $4, R20
|
||||||
|
MOVW R20, (R7) // update counter
|
||||||
|
|
||||||
|
CMP R2, R12
|
||||||
|
BGT loop
|
||||||
|
|
||||||
|
RET
|
||||||
|
|
||||||
|
|
||||||
|
DATA ·constants+0x00(SB)/4, $0x61707865
|
||||||
|
DATA ·constants+0x04(SB)/4, $0x3320646e
|
||||||
|
DATA ·constants+0x08(SB)/4, $0x79622d32
|
||||||
|
DATA ·constants+0x0c(SB)/4, $0x6b206574
|
||||||
|
GLOBL ·constants(SB), NOPTR|RODATA, $32
|
||||||
|
|
||||||
|
DATA ·incRotMatrix+0x00(SB)/4, $0x00000000
|
||||||
|
DATA ·incRotMatrix+0x04(SB)/4, $0x00000001
|
||||||
|
DATA ·incRotMatrix+0x08(SB)/4, $0x00000002
|
||||||
|
DATA ·incRotMatrix+0x0c(SB)/4, $0x00000003
|
||||||
|
DATA ·incRotMatrix+0x10(SB)/4, $0x02010003
|
||||||
|
DATA ·incRotMatrix+0x14(SB)/4, $0x06050407
|
||||||
|
DATA ·incRotMatrix+0x18(SB)/4, $0x0A09080B
|
||||||
|
DATA ·incRotMatrix+0x1c(SB)/4, $0x0E0D0C0F
|
||||||
|
GLOBL ·incRotMatrix(SB), NOPTR|RODATA, $32
|
||||||
31
vendor/golang.org/x/crypto/internal/chacha20/chacha_arm64.go
generated
vendored
Normal file
31
vendor/golang.org/x/crypto/internal/chacha20/chacha_arm64.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.11
|
||||||
|
// +build !gccgo
|
||||||
|
|
||||||
|
package chacha20
|
||||||
|
|
||||||
|
const (
|
||||||
|
haveAsm = true
|
||||||
|
bufSize = 256
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
|
||||||
|
|
||||||
|
func (c *Cipher) xorKeyStreamAsm(dst, src []byte) {
|
||||||
|
|
||||||
|
if len(src) >= bufSize {
|
||||||
|
xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(src)%bufSize != 0 {
|
||||||
|
i := len(src) - len(src)%bufSize
|
||||||
|
c.buf = [bufSize]byte{}
|
||||||
|
copy(c.buf[:], src[i:])
|
||||||
|
xorKeyStreamVX(c.buf[:], c.buf[:], &c.key, &c.nonce, &c.counter)
|
||||||
|
c.len = bufSize - copy(dst[i:], c.buf[:len(src)%bufSize])
|
||||||
|
}
|
||||||
|
}
|
||||||
2
vendor/golang.org/x/crypto/internal/chacha20/chacha_noasm.go
generated
vendored
2
vendor/golang.org/x/crypto/internal/chacha20/chacha_noasm.go
generated
vendored
@@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build !s390x gccgo appengine
|
// +build !arm64,!s390x arm64,!go1.11 gccgo appengine
|
||||||
|
|
||||||
package chacha20
|
package chacha20
|
||||||
|
|
||||||
|
|||||||
3
vendor/golang.org/x/image/AUTHORS
generated
vendored
Normal file
3
vendor/golang.org/x/image/AUTHORS
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# This source code refers to The Go Authors for copyright purposes.
|
||||||
|
# The master list of authors is in the main Go distribution,
|
||||||
|
# visible at http://tip.golang.org/AUTHORS.
|
||||||
3
vendor/golang.org/x/image/CONTRIBUTORS
generated
vendored
Normal file
3
vendor/golang.org/x/image/CONTRIBUTORS
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# This source code was written by the Go contributors.
|
||||||
|
# The master list of contributors is in the main Go distribution,
|
||||||
|
# visible at http://tip.golang.org/CONTRIBUTORS.
|
||||||
27
vendor/golang.org/x/image/LICENSE
generated
vendored
Normal file
27
vendor/golang.org/x/image/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
22
vendor/golang.org/x/image/PATENTS
generated
vendored
Normal file
22
vendor/golang.org/x/image/PATENTS
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
Additional IP Rights Grant (Patents)
|
||||||
|
|
||||||
|
"This implementation" means the copyrightable works distributed by
|
||||||
|
Google as part of the Go project.
|
||||||
|
|
||||||
|
Google hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||||
|
no-charge, royalty-free, irrevocable (except as stated in this section)
|
||||||
|
patent license to make, have made, use, offer to sell, sell, import,
|
||||||
|
transfer and otherwise run, modify and propagate the contents of this
|
||||||
|
implementation of Go, where such license applies only to those patent
|
||||||
|
claims, both currently owned or controlled by Google and acquired in
|
||||||
|
the future, licensable by Google that are necessarily infringed by this
|
||||||
|
implementation of Go. This grant does not include claims that would be
|
||||||
|
infringed only as a consequence of further modification of this
|
||||||
|
implementation. If you or your agent or exclusive licensee institute or
|
||||||
|
order or agree to the institution of patent litigation against any
|
||||||
|
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||||
|
that this implementation of Go or any code incorporated within this
|
||||||
|
implementation of Go constitutes direct or contributory patent
|
||||||
|
infringement, or inducement of patent infringement, then any patent
|
||||||
|
rights granted to you under this License for this implementation of Go
|
||||||
|
shall terminate as of the date such litigation is filed.
|
||||||
193
vendor/golang.org/x/image/riff/riff.go
generated
vendored
Normal file
193
vendor/golang.org/x/image/riff/riff.go
generated
vendored
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package riff implements the Resource Interchange File Format, used by media
|
||||||
|
// formats such as AVI, WAVE and WEBP.
|
||||||
|
//
|
||||||
|
// A RIFF stream contains a sequence of chunks. Each chunk consists of an 8-byte
|
||||||
|
// header (containing a 4-byte chunk type and a 4-byte chunk length), the chunk
|
||||||
|
// data (presented as an io.Reader), and some padding bytes.
|
||||||
|
//
|
||||||
|
// A detailed description of the format is at
|
||||||
|
// http://www.tactilemedia.com/info/MCI_Control_Info.html
|
||||||
|
package riff // import "golang.org/x/image/riff"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errMissingPaddingByte = errors.New("riff: missing padding byte")
|
||||||
|
errMissingRIFFChunkHeader = errors.New("riff: missing RIFF chunk header")
|
||||||
|
errListSubchunkTooLong = errors.New("riff: list subchunk too long")
|
||||||
|
errShortChunkData = errors.New("riff: short chunk data")
|
||||||
|
errShortChunkHeader = errors.New("riff: short chunk header")
|
||||||
|
errStaleReader = errors.New("riff: stale reader")
|
||||||
|
)
|
||||||
|
|
||||||
|
// u32 decodes the first four bytes of b as a little-endian integer.
|
||||||
|
func u32(b []byte) uint32 {
|
||||||
|
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
|
||||||
|
}
|
||||||
|
|
||||||
|
const chunkHeaderSize = 8
|
||||||
|
|
||||||
|
// FourCC is a four character code.
|
||||||
|
type FourCC [4]byte
|
||||||
|
|
||||||
|
// LIST is the "LIST" FourCC.
|
||||||
|
var LIST = FourCC{'L', 'I', 'S', 'T'}
|
||||||
|
|
||||||
|
// NewReader returns the RIFF stream's form type, such as "AVI " or "WAVE", and
|
||||||
|
// its chunks as a *Reader.
|
||||||
|
func NewReader(r io.Reader) (formType FourCC, data *Reader, err error) {
|
||||||
|
var buf [chunkHeaderSize]byte
|
||||||
|
if _, err := io.ReadFull(r, buf[:]); err != nil {
|
||||||
|
if err == io.EOF || err == io.ErrUnexpectedEOF {
|
||||||
|
err = errMissingRIFFChunkHeader
|
||||||
|
}
|
||||||
|
return FourCC{}, nil, err
|
||||||
|
}
|
||||||
|
if buf[0] != 'R' || buf[1] != 'I' || buf[2] != 'F' || buf[3] != 'F' {
|
||||||
|
return FourCC{}, nil, errMissingRIFFChunkHeader
|
||||||
|
}
|
||||||
|
return NewListReader(u32(buf[4:]), r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewListReader returns a LIST chunk's list type, such as "movi" or "wavl",
|
||||||
|
// and its chunks as a *Reader.
|
||||||
|
func NewListReader(chunkLen uint32, chunkData io.Reader) (listType FourCC, data *Reader, err error) {
|
||||||
|
if chunkLen < 4 {
|
||||||
|
return FourCC{}, nil, errShortChunkData
|
||||||
|
}
|
||||||
|
z := &Reader{r: chunkData}
|
||||||
|
if _, err := io.ReadFull(chunkData, z.buf[:4]); err != nil {
|
||||||
|
if err == io.EOF || err == io.ErrUnexpectedEOF {
|
||||||
|
err = errShortChunkData
|
||||||
|
}
|
||||||
|
return FourCC{}, nil, err
|
||||||
|
}
|
||||||
|
z.totalLen = chunkLen - 4
|
||||||
|
return FourCC{z.buf[0], z.buf[1], z.buf[2], z.buf[3]}, z, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reader reads chunks from an underlying io.Reader.
|
||||||
|
type Reader struct {
|
||||||
|
r io.Reader
|
||||||
|
err error
|
||||||
|
|
||||||
|
totalLen uint32
|
||||||
|
chunkLen uint32
|
||||||
|
|
||||||
|
chunkReader *chunkReader
|
||||||
|
buf [chunkHeaderSize]byte
|
||||||
|
padded bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next returns the next chunk's ID, length and data. It returns io.EOF if there
|
||||||
|
// are no more chunks. The io.Reader returned becomes stale after the next Next
|
||||||
|
// call, and should no longer be used.
|
||||||
|
//
|
||||||
|
// It is valid to call Next even if all of the previous chunk's data has not
|
||||||
|
// been read.
|
||||||
|
func (z *Reader) Next() (chunkID FourCC, chunkLen uint32, chunkData io.Reader, err error) {
|
||||||
|
if z.err != nil {
|
||||||
|
return FourCC{}, 0, nil, z.err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drain the rest of the previous chunk.
|
||||||
|
if z.chunkLen != 0 {
|
||||||
|
want := z.chunkLen
|
||||||
|
var got int64
|
||||||
|
got, z.err = io.Copy(ioutil.Discard, z.chunkReader)
|
||||||
|
if z.err == nil && uint32(got) != want {
|
||||||
|
z.err = errShortChunkData
|
||||||
|
}
|
||||||
|
if z.err != nil {
|
||||||
|
return FourCC{}, 0, nil, z.err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
z.chunkReader = nil
|
||||||
|
if z.padded {
|
||||||
|
if z.totalLen == 0 {
|
||||||
|
z.err = errListSubchunkTooLong
|
||||||
|
return FourCC{}, 0, nil, z.err
|
||||||
|
}
|
||||||
|
z.totalLen--
|
||||||
|
_, z.err = io.ReadFull(z.r, z.buf[:1])
|
||||||
|
if z.err != nil {
|
||||||
|
if z.err == io.EOF {
|
||||||
|
z.err = errMissingPaddingByte
|
||||||
|
}
|
||||||
|
return FourCC{}, 0, nil, z.err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We are done if we have no more data.
|
||||||
|
if z.totalLen == 0 {
|
||||||
|
z.err = io.EOF
|
||||||
|
return FourCC{}, 0, nil, z.err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the next chunk header.
|
||||||
|
if z.totalLen < chunkHeaderSize {
|
||||||
|
z.err = errShortChunkHeader
|
||||||
|
return FourCC{}, 0, nil, z.err
|
||||||
|
}
|
||||||
|
z.totalLen -= chunkHeaderSize
|
||||||
|
if _, z.err = io.ReadFull(z.r, z.buf[:chunkHeaderSize]); z.err != nil {
|
||||||
|
if z.err == io.EOF || z.err == io.ErrUnexpectedEOF {
|
||||||
|
z.err = errShortChunkHeader
|
||||||
|
}
|
||||||
|
return FourCC{}, 0, nil, z.err
|
||||||
|
}
|
||||||
|
chunkID = FourCC{z.buf[0], z.buf[1], z.buf[2], z.buf[3]}
|
||||||
|
z.chunkLen = u32(z.buf[4:])
|
||||||
|
if z.chunkLen > z.totalLen {
|
||||||
|
z.err = errListSubchunkTooLong
|
||||||
|
return FourCC{}, 0, nil, z.err
|
||||||
|
}
|
||||||
|
z.padded = z.chunkLen&1 == 1
|
||||||
|
z.chunkReader = &chunkReader{z}
|
||||||
|
return chunkID, z.chunkLen, z.chunkReader, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type chunkReader struct {
|
||||||
|
z *Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *chunkReader) Read(p []byte) (int, error) {
|
||||||
|
if c != c.z.chunkReader {
|
||||||
|
return 0, errStaleReader
|
||||||
|
}
|
||||||
|
z := c.z
|
||||||
|
if z.err != nil {
|
||||||
|
if z.err == io.EOF {
|
||||||
|
return 0, errStaleReader
|
||||||
|
}
|
||||||
|
return 0, z.err
|
||||||
|
}
|
||||||
|
|
||||||
|
n := int(z.chunkLen)
|
||||||
|
if n == 0 {
|
||||||
|
return 0, io.EOF
|
||||||
|
}
|
||||||
|
if n < 0 {
|
||||||
|
// Converting uint32 to int overflowed.
|
||||||
|
n = math.MaxInt32
|
||||||
|
}
|
||||||
|
if n > len(p) {
|
||||||
|
n = len(p)
|
||||||
|
}
|
||||||
|
n, err := z.r.Read(p[:n])
|
||||||
|
z.totalLen -= uint32(n)
|
||||||
|
z.chunkLen -= uint32(n)
|
||||||
|
if err != io.EOF {
|
||||||
|
z.err = err
|
||||||
|
}
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
403
vendor/golang.org/x/image/vp8/decode.go
generated
vendored
Normal file
403
vendor/golang.org/x/image/vp8/decode.go
generated
vendored
Normal file
@@ -0,0 +1,403 @@
|
|||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package vp8 implements a decoder for the VP8 lossy image format.
|
||||||
|
//
|
||||||
|
// The VP8 specification is RFC 6386.
|
||||||
|
package vp8 // import "golang.org/x/image/vp8"
|
||||||
|
|
||||||
|
// This file implements the top-level decoding algorithm.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"image"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// limitReader wraps an io.Reader to read at most n bytes from it.
|
||||||
|
type limitReader struct {
|
||||||
|
r io.Reader
|
||||||
|
n int
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadFull reads exactly len(p) bytes into p.
|
||||||
|
func (r *limitReader) ReadFull(p []byte) error {
|
||||||
|
if len(p) > r.n {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
n, err := io.ReadFull(r.r, p)
|
||||||
|
r.n -= n
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// FrameHeader is a frame header, as specified in section 9.1.
|
||||||
|
type FrameHeader struct {
|
||||||
|
KeyFrame bool
|
||||||
|
VersionNumber uint8
|
||||||
|
ShowFrame bool
|
||||||
|
FirstPartitionLen uint32
|
||||||
|
Width int
|
||||||
|
Height int
|
||||||
|
XScale uint8
|
||||||
|
YScale uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
nSegment = 4
|
||||||
|
nSegmentProb = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
// segmentHeader holds segment-related header information.
|
||||||
|
type segmentHeader struct {
|
||||||
|
useSegment bool
|
||||||
|
updateMap bool
|
||||||
|
relativeDelta bool
|
||||||
|
quantizer [nSegment]int8
|
||||||
|
filterStrength [nSegment]int8
|
||||||
|
prob [nSegmentProb]uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
nRefLFDelta = 4
|
||||||
|
nModeLFDelta = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
// filterHeader holds filter-related header information.
|
||||||
|
type filterHeader struct {
|
||||||
|
simple bool
|
||||||
|
level int8
|
||||||
|
sharpness uint8
|
||||||
|
useLFDelta bool
|
||||||
|
refLFDelta [nRefLFDelta]int8
|
||||||
|
modeLFDelta [nModeLFDelta]int8
|
||||||
|
perSegmentLevel [nSegment]int8
|
||||||
|
}
|
||||||
|
|
||||||
|
// mb is the per-macroblock decode state. A decoder maintains mbw+1 of these
|
||||||
|
// as it is decoding macroblocks left-to-right and top-to-bottom: mbw for the
|
||||||
|
// macroblocks in the row above, and one for the macroblock to the left.
|
||||||
|
type mb struct {
|
||||||
|
// pred is the predictor mode for the 4 bottom or right 4x4 luma regions.
|
||||||
|
pred [4]uint8
|
||||||
|
// nzMask is a mask of 8 bits: 4 for the bottom or right 4x4 luma regions,
|
||||||
|
// and 2 + 2 for the bottom or right 4x4 chroma regions. A 1 bit indicates
|
||||||
|
// that region has non-zero coefficients.
|
||||||
|
nzMask uint8
|
||||||
|
// nzY16 is a 0/1 value that is 1 if the macroblock used Y16 prediction and
|
||||||
|
// had non-zero coefficients.
|
||||||
|
nzY16 uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decoder decodes VP8 bitstreams into frames. Decoding one frame consists of
|
||||||
|
// calling Init, DecodeFrameHeader and then DecodeFrame in that order.
|
||||||
|
// A Decoder can be re-used to decode multiple frames.
|
||||||
|
type Decoder struct {
|
||||||
|
// r is the input bitsream.
|
||||||
|
r limitReader
|
||||||
|
// scratch is a scratch buffer.
|
||||||
|
scratch [8]byte
|
||||||
|
// img is the YCbCr image to decode into.
|
||||||
|
img *image.YCbCr
|
||||||
|
// mbw and mbh are the number of 16x16 macroblocks wide and high the image is.
|
||||||
|
mbw, mbh int
|
||||||
|
// frameHeader is the frame header. When decoding multiple frames,
|
||||||
|
// frames that aren't key frames will inherit the Width, Height,
|
||||||
|
// XScale and YScale of the most recent key frame.
|
||||||
|
frameHeader FrameHeader
|
||||||
|
// Other headers.
|
||||||
|
segmentHeader segmentHeader
|
||||||
|
filterHeader filterHeader
|
||||||
|
// The image data is divided into a number of independent partitions.
|
||||||
|
// There is 1 "first partition" and between 1 and 8 "other partitions"
|
||||||
|
// for coefficient data.
|
||||||
|
fp partition
|
||||||
|
op [8]partition
|
||||||
|
nOP int
|
||||||
|
// Quantization factors.
|
||||||
|
quant [nSegment]quant
|
||||||
|
// DCT/WHT coefficient decoding probabilities.
|
||||||
|
tokenProb [nPlane][nBand][nContext][nProb]uint8
|
||||||
|
useSkipProb bool
|
||||||
|
skipProb uint8
|
||||||
|
// Loop filter parameters.
|
||||||
|
filterParams [nSegment][2]filterParam
|
||||||
|
perMBFilterParams []filterParam
|
||||||
|
|
||||||
|
// The eight fields below relate to the current macroblock being decoded.
|
||||||
|
//
|
||||||
|
// Segment-based adjustments.
|
||||||
|
segment int
|
||||||
|
// Per-macroblock state for the macroblock immediately left of and those
|
||||||
|
// macroblocks immediately above the current macroblock.
|
||||||
|
leftMB mb
|
||||||
|
upMB []mb
|
||||||
|
// Bitmasks for which 4x4 regions of coeff contain non-zero coefficients.
|
||||||
|
nzDCMask, nzACMask uint32
|
||||||
|
// Predictor modes.
|
||||||
|
usePredY16 bool // The libwebp C code calls this !is_i4x4_.
|
||||||
|
predY16 uint8
|
||||||
|
predC8 uint8
|
||||||
|
predY4 [4][4]uint8
|
||||||
|
|
||||||
|
// The two fields below form a workspace for reconstructing a macroblock.
|
||||||
|
// Their specific sizes are documented in reconstruct.go.
|
||||||
|
coeff [1*16*16 + 2*8*8 + 1*4*4]int16
|
||||||
|
ybr [1 + 16 + 1 + 8][32]uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDecoder returns a new Decoder.
|
||||||
|
func NewDecoder() *Decoder {
|
||||||
|
return &Decoder{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init initializes the decoder to read at most n bytes from r.
|
||||||
|
func (d *Decoder) Init(r io.Reader, n int) {
|
||||||
|
d.r = limitReader{r, n}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeFrameHeader decodes the frame header.
|
||||||
|
func (d *Decoder) DecodeFrameHeader() (fh FrameHeader, err error) {
|
||||||
|
// All frame headers are at least 3 bytes long.
|
||||||
|
b := d.scratch[:3]
|
||||||
|
if err = d.r.ReadFull(b); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
d.frameHeader.KeyFrame = (b[0] & 1) == 0
|
||||||
|
d.frameHeader.VersionNumber = (b[0] >> 1) & 7
|
||||||
|
d.frameHeader.ShowFrame = (b[0]>>4)&1 == 1
|
||||||
|
d.frameHeader.FirstPartitionLen = uint32(b[0])>>5 | uint32(b[1])<<3 | uint32(b[2])<<11
|
||||||
|
if !d.frameHeader.KeyFrame {
|
||||||
|
return d.frameHeader, nil
|
||||||
|
}
|
||||||
|
// Frame headers for key frames are an additional 7 bytes long.
|
||||||
|
b = d.scratch[:7]
|
||||||
|
if err = d.r.ReadFull(b); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Check the magic sync code.
|
||||||
|
if b[0] != 0x9d || b[1] != 0x01 || b[2] != 0x2a {
|
||||||
|
err = errors.New("vp8: invalid format")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
d.frameHeader.Width = int(b[4]&0x3f)<<8 | int(b[3])
|
||||||
|
d.frameHeader.Height = int(b[6]&0x3f)<<8 | int(b[5])
|
||||||
|
d.frameHeader.XScale = b[4] >> 6
|
||||||
|
d.frameHeader.YScale = b[6] >> 6
|
||||||
|
d.mbw = (d.frameHeader.Width + 0x0f) >> 4
|
||||||
|
d.mbh = (d.frameHeader.Height + 0x0f) >> 4
|
||||||
|
d.segmentHeader = segmentHeader{
|
||||||
|
prob: [3]uint8{0xff, 0xff, 0xff},
|
||||||
|
}
|
||||||
|
d.tokenProb = defaultTokenProb
|
||||||
|
d.segment = 0
|
||||||
|
return d.frameHeader, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensureImg ensures that d.img is large enough to hold the decoded frame.
|
||||||
|
func (d *Decoder) ensureImg() {
|
||||||
|
if d.img != nil {
|
||||||
|
p0, p1 := d.img.Rect.Min, d.img.Rect.Max
|
||||||
|
if p0.X == 0 && p0.Y == 0 && p1.X >= 16*d.mbw && p1.Y >= 16*d.mbh {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m := image.NewYCbCr(image.Rect(0, 0, 16*d.mbw, 16*d.mbh), image.YCbCrSubsampleRatio420)
|
||||||
|
d.img = m.SubImage(image.Rect(0, 0, d.frameHeader.Width, d.frameHeader.Height)).(*image.YCbCr)
|
||||||
|
d.perMBFilterParams = make([]filterParam, d.mbw*d.mbh)
|
||||||
|
d.upMB = make([]mb, d.mbw)
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseSegmentHeader parses the segment header, as specified in section 9.3.
|
||||||
|
func (d *Decoder) parseSegmentHeader() {
|
||||||
|
d.segmentHeader.useSegment = d.fp.readBit(uniformProb)
|
||||||
|
if !d.segmentHeader.useSegment {
|
||||||
|
d.segmentHeader.updateMap = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
d.segmentHeader.updateMap = d.fp.readBit(uniformProb)
|
||||||
|
if d.fp.readBit(uniformProb) {
|
||||||
|
d.segmentHeader.relativeDelta = !d.fp.readBit(uniformProb)
|
||||||
|
for i := range d.segmentHeader.quantizer {
|
||||||
|
d.segmentHeader.quantizer[i] = int8(d.fp.readOptionalInt(uniformProb, 7))
|
||||||
|
}
|
||||||
|
for i := range d.segmentHeader.filterStrength {
|
||||||
|
d.segmentHeader.filterStrength[i] = int8(d.fp.readOptionalInt(uniformProb, 6))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !d.segmentHeader.updateMap {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for i := range d.segmentHeader.prob {
|
||||||
|
if d.fp.readBit(uniformProb) {
|
||||||
|
d.segmentHeader.prob[i] = uint8(d.fp.readUint(uniformProb, 8))
|
||||||
|
} else {
|
||||||
|
d.segmentHeader.prob[i] = 0xff
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseFilterHeader parses the filter header, as specified in section 9.4.
|
||||||
|
func (d *Decoder) parseFilterHeader() {
|
||||||
|
d.filterHeader.simple = d.fp.readBit(uniformProb)
|
||||||
|
d.filterHeader.level = int8(d.fp.readUint(uniformProb, 6))
|
||||||
|
d.filterHeader.sharpness = uint8(d.fp.readUint(uniformProb, 3))
|
||||||
|
d.filterHeader.useLFDelta = d.fp.readBit(uniformProb)
|
||||||
|
if d.filterHeader.useLFDelta && d.fp.readBit(uniformProb) {
|
||||||
|
for i := range d.filterHeader.refLFDelta {
|
||||||
|
d.filterHeader.refLFDelta[i] = int8(d.fp.readOptionalInt(uniformProb, 6))
|
||||||
|
}
|
||||||
|
for i := range d.filterHeader.modeLFDelta {
|
||||||
|
d.filterHeader.modeLFDelta[i] = int8(d.fp.readOptionalInt(uniformProb, 6))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if d.filterHeader.level == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if d.segmentHeader.useSegment {
|
||||||
|
for i := range d.filterHeader.perSegmentLevel {
|
||||||
|
strength := d.segmentHeader.filterStrength[i]
|
||||||
|
if d.segmentHeader.relativeDelta {
|
||||||
|
strength += d.filterHeader.level
|
||||||
|
}
|
||||||
|
d.filterHeader.perSegmentLevel[i] = strength
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
d.filterHeader.perSegmentLevel[0] = d.filterHeader.level
|
||||||
|
}
|
||||||
|
d.computeFilterParams()
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseOtherPartitions parses the other partitions, as specified in section 9.5.
|
||||||
|
func (d *Decoder) parseOtherPartitions() error {
|
||||||
|
const maxNOP = 1 << 3
|
||||||
|
var partLens [maxNOP]int
|
||||||
|
d.nOP = 1 << d.fp.readUint(uniformProb, 2)
|
||||||
|
|
||||||
|
// The final partition length is implied by the remaining chunk data
|
||||||
|
// (d.r.n) and the other d.nOP-1 partition lengths. Those d.nOP-1 partition
|
||||||
|
// lengths are stored as 24-bit uints, i.e. up to 16 MiB per partition.
|
||||||
|
n := 3 * (d.nOP - 1)
|
||||||
|
partLens[d.nOP-1] = d.r.n - n
|
||||||
|
if partLens[d.nOP-1] < 0 {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
if n > 0 {
|
||||||
|
buf := make([]byte, n)
|
||||||
|
if err := d.r.ReadFull(buf); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for i := 0; i < d.nOP-1; i++ {
|
||||||
|
pl := int(buf[3*i+0]) | int(buf[3*i+1])<<8 | int(buf[3*i+2])<<16
|
||||||
|
if pl > partLens[d.nOP-1] {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
partLens[i] = pl
|
||||||
|
partLens[d.nOP-1] -= pl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We check if the final partition length can also fit into a 24-bit uint.
|
||||||
|
// Strictly speaking, this isn't part of the spec, but it guards against a
|
||||||
|
// malicious WEBP image that is too large to ReadFull the encoded DCT
|
||||||
|
// coefficients into memory, whether that's because the actual WEBP file is
|
||||||
|
// too large, or whether its RIFF metadata lists too large a chunk.
|
||||||
|
if 1<<24 <= partLens[d.nOP-1] {
|
||||||
|
return errors.New("vp8: too much data to decode")
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]byte, d.r.n)
|
||||||
|
if err := d.r.ReadFull(buf); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for i, pl := range partLens {
|
||||||
|
if i == d.nOP {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
d.op[i].init(buf[:pl])
|
||||||
|
buf = buf[pl:]
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseOtherHeaders parses header information other than the frame header.
|
||||||
|
func (d *Decoder) parseOtherHeaders() error {
|
||||||
|
// Initialize and parse the first partition.
|
||||||
|
firstPartition := make([]byte, d.frameHeader.FirstPartitionLen)
|
||||||
|
if err := d.r.ReadFull(firstPartition); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
d.fp.init(firstPartition)
|
||||||
|
if d.frameHeader.KeyFrame {
|
||||||
|
// Read and ignore the color space and pixel clamp values. They are
|
||||||
|
// specified in section 9.2, but are unimplemented.
|
||||||
|
d.fp.readBit(uniformProb)
|
||||||
|
d.fp.readBit(uniformProb)
|
||||||
|
}
|
||||||
|
d.parseSegmentHeader()
|
||||||
|
d.parseFilterHeader()
|
||||||
|
if err := d.parseOtherPartitions(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
d.parseQuant()
|
||||||
|
if !d.frameHeader.KeyFrame {
|
||||||
|
// Golden and AltRef frames are specified in section 9.7.
|
||||||
|
// TODO(nigeltao): implement. Note that they are only used for video, not still images.
|
||||||
|
return errors.New("vp8: Golden / AltRef frames are not implemented")
|
||||||
|
}
|
||||||
|
// Read and ignore the refreshLastFrameBuffer bit, specified in section 9.8.
|
||||||
|
// It applies only to video, and not still images.
|
||||||
|
d.fp.readBit(uniformProb)
|
||||||
|
d.parseTokenProb()
|
||||||
|
d.useSkipProb = d.fp.readBit(uniformProb)
|
||||||
|
if d.useSkipProb {
|
||||||
|
d.skipProb = uint8(d.fp.readUint(uniformProb, 8))
|
||||||
|
}
|
||||||
|
if d.fp.unexpectedEOF {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeFrame decodes the frame and returns it as an YCbCr image.
|
||||||
|
// The image's contents are valid up until the next call to Decoder.Init.
|
||||||
|
func (d *Decoder) DecodeFrame() (*image.YCbCr, error) {
|
||||||
|
d.ensureImg()
|
||||||
|
if err := d.parseOtherHeaders(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Reconstruct the rows.
|
||||||
|
for mbx := 0; mbx < d.mbw; mbx++ {
|
||||||
|
d.upMB[mbx] = mb{}
|
||||||
|
}
|
||||||
|
for mby := 0; mby < d.mbh; mby++ {
|
||||||
|
d.leftMB = mb{}
|
||||||
|
for mbx := 0; mbx < d.mbw; mbx++ {
|
||||||
|
skip := d.reconstruct(mbx, mby)
|
||||||
|
fs := d.filterParams[d.segment][btou(!d.usePredY16)]
|
||||||
|
fs.inner = fs.inner || !skip
|
||||||
|
d.perMBFilterParams[d.mbw*mby+mbx] = fs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if d.fp.unexpectedEOF {
|
||||||
|
return nil, io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
for i := 0; i < d.nOP; i++ {
|
||||||
|
if d.op[i].unexpectedEOF {
|
||||||
|
return nil, io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Apply the loop filter.
|
||||||
|
//
|
||||||
|
// Even if we are using per-segment levels, section 15 says that "loop
|
||||||
|
// filtering must be skipped entirely if loop_filter_level at either the
|
||||||
|
// frame header level or macroblock override level is 0".
|
||||||
|
if d.filterHeader.level != 0 {
|
||||||
|
if d.filterHeader.simple {
|
||||||
|
d.simpleFilter()
|
||||||
|
} else {
|
||||||
|
d.normalFilter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return d.img, nil
|
||||||
|
}
|
||||||
273
vendor/golang.org/x/image/vp8/filter.go
generated
vendored
Normal file
273
vendor/golang.org/x/image/vp8/filter.go
generated
vendored
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package vp8
|
||||||
|
|
||||||
|
// filter2 modifies a 2-pixel wide or 2-pixel high band along an edge.
|
||||||
|
func filter2(pix []byte, level, index, iStep, jStep int) {
|
||||||
|
for n := 16; n > 0; n, index = n-1, index+iStep {
|
||||||
|
p1 := int(pix[index-2*jStep])
|
||||||
|
p0 := int(pix[index-1*jStep])
|
||||||
|
q0 := int(pix[index+0*jStep])
|
||||||
|
q1 := int(pix[index+1*jStep])
|
||||||
|
if abs(p0-q0)<<1+abs(p1-q1)>>1 > level {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
a := 3*(q0-p0) + clamp127(p1-q1)
|
||||||
|
a1 := clamp15((a + 4) >> 3)
|
||||||
|
a2 := clamp15((a + 3) >> 3)
|
||||||
|
pix[index-1*jStep] = clamp255(p0 + a2)
|
||||||
|
pix[index+0*jStep] = clamp255(q0 - a1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// filter246 modifies a 2-, 4- or 6-pixel wide or high band along an edge.
|
||||||
|
func filter246(pix []byte, n, level, ilevel, hlevel, index, iStep, jStep int, fourNotSix bool) {
|
||||||
|
for ; n > 0; n, index = n-1, index+iStep {
|
||||||
|
p3 := int(pix[index-4*jStep])
|
||||||
|
p2 := int(pix[index-3*jStep])
|
||||||
|
p1 := int(pix[index-2*jStep])
|
||||||
|
p0 := int(pix[index-1*jStep])
|
||||||
|
q0 := int(pix[index+0*jStep])
|
||||||
|
q1 := int(pix[index+1*jStep])
|
||||||
|
q2 := int(pix[index+2*jStep])
|
||||||
|
q3 := int(pix[index+3*jStep])
|
||||||
|
if abs(p0-q0)<<1+abs(p1-q1)>>1 > level {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if abs(p3-p2) > ilevel ||
|
||||||
|
abs(p2-p1) > ilevel ||
|
||||||
|
abs(p1-p0) > ilevel ||
|
||||||
|
abs(q1-q0) > ilevel ||
|
||||||
|
abs(q2-q1) > ilevel ||
|
||||||
|
abs(q3-q2) > ilevel {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if abs(p1-p0) > hlevel || abs(q1-q0) > hlevel {
|
||||||
|
// Filter 2 pixels.
|
||||||
|
a := 3*(q0-p0) + clamp127(p1-q1)
|
||||||
|
a1 := clamp15((a + 4) >> 3)
|
||||||
|
a2 := clamp15((a + 3) >> 3)
|
||||||
|
pix[index-1*jStep] = clamp255(p0 + a2)
|
||||||
|
pix[index+0*jStep] = clamp255(q0 - a1)
|
||||||
|
} else if fourNotSix {
|
||||||
|
// Filter 4 pixels.
|
||||||
|
a := 3 * (q0 - p0)
|
||||||
|
a1 := clamp15((a + 4) >> 3)
|
||||||
|
a2 := clamp15((a + 3) >> 3)
|
||||||
|
a3 := (a1 + 1) >> 1
|
||||||
|
pix[index-2*jStep] = clamp255(p1 + a3)
|
||||||
|
pix[index-1*jStep] = clamp255(p0 + a2)
|
||||||
|
pix[index+0*jStep] = clamp255(q0 - a1)
|
||||||
|
pix[index+1*jStep] = clamp255(q1 - a3)
|
||||||
|
} else {
|
||||||
|
// Filter 6 pixels.
|
||||||
|
a := clamp127(3*(q0-p0) + clamp127(p1-q1))
|
||||||
|
a1 := (27*a + 63) >> 7
|
||||||
|
a2 := (18*a + 63) >> 7
|
||||||
|
a3 := (9*a + 63) >> 7
|
||||||
|
pix[index-3*jStep] = clamp255(p2 + a3)
|
||||||
|
pix[index-2*jStep] = clamp255(p1 + a2)
|
||||||
|
pix[index-1*jStep] = clamp255(p0 + a1)
|
||||||
|
pix[index+0*jStep] = clamp255(q0 - a1)
|
||||||
|
pix[index+1*jStep] = clamp255(q1 - a2)
|
||||||
|
pix[index+2*jStep] = clamp255(q2 - a3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// simpleFilter implements the simple filter, as specified in section 15.2.
|
||||||
|
func (d *Decoder) simpleFilter() {
|
||||||
|
for mby := 0; mby < d.mbh; mby++ {
|
||||||
|
for mbx := 0; mbx < d.mbw; mbx++ {
|
||||||
|
f := d.perMBFilterParams[d.mbw*mby+mbx]
|
||||||
|
if f.level == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
l := int(f.level)
|
||||||
|
yIndex := (mby*d.img.YStride + mbx) * 16
|
||||||
|
if mbx > 0 {
|
||||||
|
filter2(d.img.Y, l+4, yIndex, d.img.YStride, 1)
|
||||||
|
}
|
||||||
|
if f.inner {
|
||||||
|
filter2(d.img.Y, l, yIndex+0x4, d.img.YStride, 1)
|
||||||
|
filter2(d.img.Y, l, yIndex+0x8, d.img.YStride, 1)
|
||||||
|
filter2(d.img.Y, l, yIndex+0xc, d.img.YStride, 1)
|
||||||
|
}
|
||||||
|
if mby > 0 {
|
||||||
|
filter2(d.img.Y, l+4, yIndex, 1, d.img.YStride)
|
||||||
|
}
|
||||||
|
if f.inner {
|
||||||
|
filter2(d.img.Y, l, yIndex+d.img.YStride*0x4, 1, d.img.YStride)
|
||||||
|
filter2(d.img.Y, l, yIndex+d.img.YStride*0x8, 1, d.img.YStride)
|
||||||
|
filter2(d.img.Y, l, yIndex+d.img.YStride*0xc, 1, d.img.YStride)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// normalFilter implements the normal filter, as specified in section 15.3.
|
||||||
|
func (d *Decoder) normalFilter() {
|
||||||
|
for mby := 0; mby < d.mbh; mby++ {
|
||||||
|
for mbx := 0; mbx < d.mbw; mbx++ {
|
||||||
|
f := d.perMBFilterParams[d.mbw*mby+mbx]
|
||||||
|
if f.level == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
l, il, hl := int(f.level), int(f.ilevel), int(f.hlevel)
|
||||||
|
yIndex := (mby*d.img.YStride + mbx) * 16
|
||||||
|
cIndex := (mby*d.img.CStride + mbx) * 8
|
||||||
|
if mbx > 0 {
|
||||||
|
filter246(d.img.Y, 16, l+4, il, hl, yIndex, d.img.YStride, 1, false)
|
||||||
|
filter246(d.img.Cb, 8, l+4, il, hl, cIndex, d.img.CStride, 1, false)
|
||||||
|
filter246(d.img.Cr, 8, l+4, il, hl, cIndex, d.img.CStride, 1, false)
|
||||||
|
}
|
||||||
|
if f.inner {
|
||||||
|
filter246(d.img.Y, 16, l, il, hl, yIndex+0x4, d.img.YStride, 1, true)
|
||||||
|
filter246(d.img.Y, 16, l, il, hl, yIndex+0x8, d.img.YStride, 1, true)
|
||||||
|
filter246(d.img.Y, 16, l, il, hl, yIndex+0xc, d.img.YStride, 1, true)
|
||||||
|
filter246(d.img.Cb, 8, l, il, hl, cIndex+0x4, d.img.CStride, 1, true)
|
||||||
|
filter246(d.img.Cr, 8, l, il, hl, cIndex+0x4, d.img.CStride, 1, true)
|
||||||
|
}
|
||||||
|
if mby > 0 {
|
||||||
|
filter246(d.img.Y, 16, l+4, il, hl, yIndex, 1, d.img.YStride, false)
|
||||||
|
filter246(d.img.Cb, 8, l+4, il, hl, cIndex, 1, d.img.CStride, false)
|
||||||
|
filter246(d.img.Cr, 8, l+4, il, hl, cIndex, 1, d.img.CStride, false)
|
||||||
|
}
|
||||||
|
if f.inner {
|
||||||
|
filter246(d.img.Y, 16, l, il, hl, yIndex+d.img.YStride*0x4, 1, d.img.YStride, true)
|
||||||
|
filter246(d.img.Y, 16, l, il, hl, yIndex+d.img.YStride*0x8, 1, d.img.YStride, true)
|
||||||
|
filter246(d.img.Y, 16, l, il, hl, yIndex+d.img.YStride*0xc, 1, d.img.YStride, true)
|
||||||
|
filter246(d.img.Cb, 8, l, il, hl, cIndex+d.img.CStride*0x4, 1, d.img.CStride, true)
|
||||||
|
filter246(d.img.Cr, 8, l, il, hl, cIndex+d.img.CStride*0x4, 1, d.img.CStride, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// filterParam holds the loop filter parameters for a macroblock.
|
||||||
|
type filterParam struct {
|
||||||
|
// The first three fields are thresholds used by the loop filter to smooth
|
||||||
|
// over the edges and interior of a macroblock. level is used by both the
|
||||||
|
// simple and normal filters. The inner level and high edge variance level
|
||||||
|
// are only used by the normal filter.
|
||||||
|
level, ilevel, hlevel uint8
|
||||||
|
// inner is whether the inner loop filter cannot be optimized out as a
|
||||||
|
// no-op for this particular macroblock.
|
||||||
|
inner bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// computeFilterParams computes the loop filter parameters, as specified in
|
||||||
|
// section 15.4.
|
||||||
|
func (d *Decoder) computeFilterParams() {
|
||||||
|
for i := range d.filterParams {
|
||||||
|
baseLevel := d.filterHeader.level
|
||||||
|
if d.segmentHeader.useSegment {
|
||||||
|
baseLevel = d.segmentHeader.filterStrength[i]
|
||||||
|
if d.segmentHeader.relativeDelta {
|
||||||
|
baseLevel += d.filterHeader.level
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for j := range d.filterParams[i] {
|
||||||
|
p := &d.filterParams[i][j]
|
||||||
|
p.inner = j != 0
|
||||||
|
level := baseLevel
|
||||||
|
if d.filterHeader.useLFDelta {
|
||||||
|
// The libwebp C code has a "TODO: only CURRENT is handled for now."
|
||||||
|
level += d.filterHeader.refLFDelta[0]
|
||||||
|
if j != 0 {
|
||||||
|
level += d.filterHeader.modeLFDelta[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if level <= 0 {
|
||||||
|
p.level = 0
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if level > 63 {
|
||||||
|
level = 63
|
||||||
|
}
|
||||||
|
ilevel := level
|
||||||
|
if d.filterHeader.sharpness > 0 {
|
||||||
|
if d.filterHeader.sharpness > 4 {
|
||||||
|
ilevel >>= 2
|
||||||
|
} else {
|
||||||
|
ilevel >>= 1
|
||||||
|
}
|
||||||
|
if x := int8(9 - d.filterHeader.sharpness); ilevel > x {
|
||||||
|
ilevel = x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ilevel < 1 {
|
||||||
|
ilevel = 1
|
||||||
|
}
|
||||||
|
p.ilevel = uint8(ilevel)
|
||||||
|
p.level = uint8(2*level + ilevel)
|
||||||
|
if d.frameHeader.KeyFrame {
|
||||||
|
if level < 15 {
|
||||||
|
p.hlevel = 0
|
||||||
|
} else if level < 40 {
|
||||||
|
p.hlevel = 1
|
||||||
|
} else {
|
||||||
|
p.hlevel = 2
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if level < 15 {
|
||||||
|
p.hlevel = 0
|
||||||
|
} else if level < 20 {
|
||||||
|
p.hlevel = 1
|
||||||
|
} else if level < 40 {
|
||||||
|
p.hlevel = 2
|
||||||
|
} else {
|
||||||
|
p.hlevel = 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// intSize is either 32 or 64.
|
||||||
|
const intSize = 32 << (^uint(0) >> 63)
|
||||||
|
|
||||||
|
func abs(x int) int {
|
||||||
|
// m := -1 if x < 0. m := 0 otherwise.
|
||||||
|
m := x >> (intSize - 1)
|
||||||
|
|
||||||
|
// In two's complement representation, the negative number
|
||||||
|
// of any number (except the smallest one) can be computed
|
||||||
|
// by flipping all the bits and add 1. This is faster than
|
||||||
|
// code with a branch.
|
||||||
|
// See Hacker's Delight, section 2-4.
|
||||||
|
return (x ^ m) - m
|
||||||
|
}
|
||||||
|
|
||||||
|
func clamp15(x int) int {
|
||||||
|
if x < -16 {
|
||||||
|
return -16
|
||||||
|
}
|
||||||
|
if x > 15 {
|
||||||
|
return 15
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func clamp127(x int) int {
|
||||||
|
if x < -128 {
|
||||||
|
return -128
|
||||||
|
}
|
||||||
|
if x > 127 {
|
||||||
|
return 127
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func clamp255(x int) uint8 {
|
||||||
|
if x < 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if x > 255 {
|
||||||
|
return 255
|
||||||
|
}
|
||||||
|
return uint8(x)
|
||||||
|
}
|
||||||
98
vendor/golang.org/x/image/vp8/idct.go
generated
vendored
Normal file
98
vendor/golang.org/x/image/vp8/idct.go
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package vp8
|
||||||
|
|
||||||
|
// This file implements the inverse Discrete Cosine Transform and the inverse
|
||||||
|
// Walsh Hadamard Transform (WHT), as specified in sections 14.3 and 14.4.
|
||||||
|
|
||||||
|
func clip8(i int32) uint8 {
|
||||||
|
if i < 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if i > 255 {
|
||||||
|
return 255
|
||||||
|
}
|
||||||
|
return uint8(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *Decoder) inverseDCT4(y, x, coeffBase int) {
|
||||||
|
const (
|
||||||
|
c1 = 85627 // 65536 * cos(pi/8) * sqrt(2).
|
||||||
|
c2 = 35468 // 65536 * sin(pi/8) * sqrt(2).
|
||||||
|
)
|
||||||
|
var m [4][4]int32
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
a := int32(z.coeff[coeffBase+0]) + int32(z.coeff[coeffBase+8])
|
||||||
|
b := int32(z.coeff[coeffBase+0]) - int32(z.coeff[coeffBase+8])
|
||||||
|
c := (int32(z.coeff[coeffBase+4])*c2)>>16 - (int32(z.coeff[coeffBase+12])*c1)>>16
|
||||||
|
d := (int32(z.coeff[coeffBase+4])*c1)>>16 + (int32(z.coeff[coeffBase+12])*c2)>>16
|
||||||
|
m[i][0] = a + d
|
||||||
|
m[i][1] = b + c
|
||||||
|
m[i][2] = b - c
|
||||||
|
m[i][3] = a - d
|
||||||
|
coeffBase++
|
||||||
|
}
|
||||||
|
for j := 0; j < 4; j++ {
|
||||||
|
dc := m[0][j] + 4
|
||||||
|
a := dc + m[2][j]
|
||||||
|
b := dc - m[2][j]
|
||||||
|
c := (m[1][j]*c2)>>16 - (m[3][j]*c1)>>16
|
||||||
|
d := (m[1][j]*c1)>>16 + (m[3][j]*c2)>>16
|
||||||
|
z.ybr[y+j][x+0] = clip8(int32(z.ybr[y+j][x+0]) + (a+d)>>3)
|
||||||
|
z.ybr[y+j][x+1] = clip8(int32(z.ybr[y+j][x+1]) + (b+c)>>3)
|
||||||
|
z.ybr[y+j][x+2] = clip8(int32(z.ybr[y+j][x+2]) + (b-c)>>3)
|
||||||
|
z.ybr[y+j][x+3] = clip8(int32(z.ybr[y+j][x+3]) + (a-d)>>3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *Decoder) inverseDCT4DCOnly(y, x, coeffBase int) {
|
||||||
|
dc := (int32(z.coeff[coeffBase+0]) + 4) >> 3
|
||||||
|
for j := 0; j < 4; j++ {
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
z.ybr[y+j][x+i] = clip8(int32(z.ybr[y+j][x+i]) + dc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *Decoder) inverseDCT8(y, x, coeffBase int) {
|
||||||
|
z.inverseDCT4(y+0, x+0, coeffBase+0*16)
|
||||||
|
z.inverseDCT4(y+0, x+4, coeffBase+1*16)
|
||||||
|
z.inverseDCT4(y+4, x+0, coeffBase+2*16)
|
||||||
|
z.inverseDCT4(y+4, x+4, coeffBase+3*16)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *Decoder) inverseDCT8DCOnly(y, x, coeffBase int) {
|
||||||
|
z.inverseDCT4DCOnly(y+0, x+0, coeffBase+0*16)
|
||||||
|
z.inverseDCT4DCOnly(y+0, x+4, coeffBase+1*16)
|
||||||
|
z.inverseDCT4DCOnly(y+4, x+0, coeffBase+2*16)
|
||||||
|
z.inverseDCT4DCOnly(y+4, x+4, coeffBase+3*16)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Decoder) inverseWHT16() {
|
||||||
|
var m [16]int32
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
a0 := int32(d.coeff[384+0+i]) + int32(d.coeff[384+12+i])
|
||||||
|
a1 := int32(d.coeff[384+4+i]) + int32(d.coeff[384+8+i])
|
||||||
|
a2 := int32(d.coeff[384+4+i]) - int32(d.coeff[384+8+i])
|
||||||
|
a3 := int32(d.coeff[384+0+i]) - int32(d.coeff[384+12+i])
|
||||||
|
m[0+i] = a0 + a1
|
||||||
|
m[8+i] = a0 - a1
|
||||||
|
m[4+i] = a3 + a2
|
||||||
|
m[12+i] = a3 - a2
|
||||||
|
}
|
||||||
|
out := 0
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
dc := m[0+i*4] + 3
|
||||||
|
a0 := dc + m[3+i*4]
|
||||||
|
a1 := m[1+i*4] + m[2+i*4]
|
||||||
|
a2 := m[1+i*4] - m[2+i*4]
|
||||||
|
a3 := dc - m[3+i*4]
|
||||||
|
d.coeff[out+0] = int16((a0 + a1) >> 3)
|
||||||
|
d.coeff[out+16] = int16((a3 + a2) >> 3)
|
||||||
|
d.coeff[out+32] = int16((a0 - a1) >> 3)
|
||||||
|
d.coeff[out+48] = int16((a3 - a2) >> 3)
|
||||||
|
out += 64
|
||||||
|
}
|
||||||
|
}
|
||||||
129
vendor/golang.org/x/image/vp8/partition.go
generated
vendored
Normal file
129
vendor/golang.org/x/image/vp8/partition.go
generated
vendored
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package vp8
|
||||||
|
|
||||||
|
// Each VP8 frame consists of between 2 and 9 bitstream partitions.
|
||||||
|
// Each partition is byte-aligned and is independently arithmetic-encoded.
|
||||||
|
//
|
||||||
|
// This file implements decoding a partition's bitstream, as specified in
|
||||||
|
// chapter 7. The implementation follows libwebp's approach instead of the
|
||||||
|
// specification's reference C implementation. For example, we use a look-up
|
||||||
|
// table instead of a for loop to recalibrate the encoded range.
|
||||||
|
|
||||||
|
var (
|
||||||
|
lutShift = [127]uint8{
|
||||||
|
7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||||
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||||
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
}
|
||||||
|
lutRangeM1 = [127]uint8{
|
||||||
|
127,
|
||||||
|
127, 191,
|
||||||
|
127, 159, 191, 223,
|
||||||
|
127, 143, 159, 175, 191, 207, 223, 239,
|
||||||
|
127, 135, 143, 151, 159, 167, 175, 183, 191, 199, 207, 215, 223, 231, 239, 247,
|
||||||
|
127, 131, 135, 139, 143, 147, 151, 155, 159, 163, 167, 171, 175, 179, 183, 187,
|
||||||
|
191, 195, 199, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251,
|
||||||
|
127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157,
|
||||||
|
159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189,
|
||||||
|
191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221,
|
||||||
|
223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// uniformProb represents a 50% probability that the next bit is 0.
|
||||||
|
const uniformProb = 128
|
||||||
|
|
||||||
|
// partition holds arithmetic-coded bits.
|
||||||
|
type partition struct {
|
||||||
|
// buf is the input bytes.
|
||||||
|
buf []byte
|
||||||
|
// r is how many of buf's bytes have been consumed.
|
||||||
|
r int
|
||||||
|
// rangeM1 is range minus 1, where range is in the arithmetic coding sense,
|
||||||
|
// not the Go language sense.
|
||||||
|
rangeM1 uint32
|
||||||
|
// bits and nBits hold those bits shifted out of buf but not yet consumed.
|
||||||
|
bits uint32
|
||||||
|
nBits uint8
|
||||||
|
// unexpectedEOF tells whether we tried to read past buf.
|
||||||
|
unexpectedEOF bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// init initializes the partition.
|
||||||
|
func (p *partition) init(buf []byte) {
|
||||||
|
p.buf = buf
|
||||||
|
p.r = 0
|
||||||
|
p.rangeM1 = 254
|
||||||
|
p.bits = 0
|
||||||
|
p.nBits = 0
|
||||||
|
p.unexpectedEOF = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// readBit returns the next bit.
|
||||||
|
func (p *partition) readBit(prob uint8) bool {
|
||||||
|
if p.nBits < 8 {
|
||||||
|
if p.r >= len(p.buf) {
|
||||||
|
p.unexpectedEOF = true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Expression split for 386 compiler.
|
||||||
|
x := uint32(p.buf[p.r])
|
||||||
|
p.bits |= x << (8 - p.nBits)
|
||||||
|
p.r++
|
||||||
|
p.nBits += 8
|
||||||
|
}
|
||||||
|
split := (p.rangeM1*uint32(prob))>>8 + 1
|
||||||
|
bit := p.bits >= split<<8
|
||||||
|
if bit {
|
||||||
|
p.rangeM1 -= split
|
||||||
|
p.bits -= split << 8
|
||||||
|
} else {
|
||||||
|
p.rangeM1 = split - 1
|
||||||
|
}
|
||||||
|
if p.rangeM1 < 127 {
|
||||||
|
shift := lutShift[p.rangeM1]
|
||||||
|
p.rangeM1 = uint32(lutRangeM1[p.rangeM1])
|
||||||
|
p.bits <<= shift
|
||||||
|
p.nBits -= shift
|
||||||
|
}
|
||||||
|
return bit
|
||||||
|
}
|
||||||
|
|
||||||
|
// readUint returns the next n-bit unsigned integer.
|
||||||
|
func (p *partition) readUint(prob, n uint8) uint32 {
|
||||||
|
var u uint32
|
||||||
|
for n > 0 {
|
||||||
|
n--
|
||||||
|
if p.readBit(prob) {
|
||||||
|
u |= 1 << n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// readInt returns the next n-bit signed integer.
|
||||||
|
func (p *partition) readInt(prob, n uint8) int32 {
|
||||||
|
u := p.readUint(prob, n)
|
||||||
|
b := p.readBit(prob)
|
||||||
|
if b {
|
||||||
|
return -int32(u)
|
||||||
|
}
|
||||||
|
return int32(u)
|
||||||
|
}
|
||||||
|
|
||||||
|
// readOptionalInt returns the next n-bit signed integer in an encoding
|
||||||
|
// where the likely result is zero.
|
||||||
|
func (p *partition) readOptionalInt(prob, n uint8) int32 {
|
||||||
|
if !p.readBit(prob) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return p.readInt(prob, n)
|
||||||
|
}
|
||||||
201
vendor/golang.org/x/image/vp8/pred.go
generated
vendored
Normal file
201
vendor/golang.org/x/image/vp8/pred.go
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package vp8
|
||||||
|
|
||||||
|
// This file implements parsing the predictor modes, as specified in chapter
|
||||||
|
// 11.
|
||||||
|
|
||||||
|
func (d *Decoder) parsePredModeY16(mbx int) {
|
||||||
|
var p uint8
|
||||||
|
if !d.fp.readBit(156) {
|
||||||
|
if !d.fp.readBit(163) {
|
||||||
|
p = predDC
|
||||||
|
} else {
|
||||||
|
p = predVE
|
||||||
|
}
|
||||||
|
} else if !d.fp.readBit(128) {
|
||||||
|
p = predHE
|
||||||
|
} else {
|
||||||
|
p = predTM
|
||||||
|
}
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
d.upMB[mbx].pred[i] = p
|
||||||
|
d.leftMB.pred[i] = p
|
||||||
|
}
|
||||||
|
d.predY16 = p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Decoder) parsePredModeC8() {
|
||||||
|
if !d.fp.readBit(142) {
|
||||||
|
d.predC8 = predDC
|
||||||
|
} else if !d.fp.readBit(114) {
|
||||||
|
d.predC8 = predVE
|
||||||
|
} else if !d.fp.readBit(183) {
|
||||||
|
d.predC8 = predHE
|
||||||
|
} else {
|
||||||
|
d.predC8 = predTM
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Decoder) parsePredModeY4(mbx int) {
|
||||||
|
for j := 0; j < 4; j++ {
|
||||||
|
p := d.leftMB.pred[j]
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
prob := &predProb[d.upMB[mbx].pred[i]][p]
|
||||||
|
if !d.fp.readBit(prob[0]) {
|
||||||
|
p = predDC
|
||||||
|
} else if !d.fp.readBit(prob[1]) {
|
||||||
|
p = predTM
|
||||||
|
} else if !d.fp.readBit(prob[2]) {
|
||||||
|
p = predVE
|
||||||
|
} else if !d.fp.readBit(prob[3]) {
|
||||||
|
if !d.fp.readBit(prob[4]) {
|
||||||
|
p = predHE
|
||||||
|
} else if !d.fp.readBit(prob[5]) {
|
||||||
|
p = predRD
|
||||||
|
} else {
|
||||||
|
p = predVR
|
||||||
|
}
|
||||||
|
} else if !d.fp.readBit(prob[6]) {
|
||||||
|
p = predLD
|
||||||
|
} else if !d.fp.readBit(prob[7]) {
|
||||||
|
p = predVL
|
||||||
|
} else if !d.fp.readBit(prob[8]) {
|
||||||
|
p = predHD
|
||||||
|
} else {
|
||||||
|
p = predHU
|
||||||
|
}
|
||||||
|
d.predY4[j][i] = p
|
||||||
|
d.upMB[mbx].pred[i] = p
|
||||||
|
}
|
||||||
|
d.leftMB.pred[j] = p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// predProb are the probabilities to decode a 4x4 region's predictor mode given
|
||||||
|
// the predictor modes of the regions above and left of it.
|
||||||
|
// These values are specified in section 11.5.
|
||||||
|
var predProb = [nPred][nPred][9]uint8{
|
||||||
|
{
|
||||||
|
{231, 120, 48, 89, 115, 113, 120, 152, 112},
|
||||||
|
{152, 179, 64, 126, 170, 118, 46, 70, 95},
|
||||||
|
{175, 69, 143, 80, 85, 82, 72, 155, 103},
|
||||||
|
{56, 58, 10, 171, 218, 189, 17, 13, 152},
|
||||||
|
{114, 26, 17, 163, 44, 195, 21, 10, 173},
|
||||||
|
{121, 24, 80, 195, 26, 62, 44, 64, 85},
|
||||||
|
{144, 71, 10, 38, 171, 213, 144, 34, 26},
|
||||||
|
{170, 46, 55, 19, 136, 160, 33, 206, 71},
|
||||||
|
{63, 20, 8, 114, 114, 208, 12, 9, 226},
|
||||||
|
{81, 40, 11, 96, 182, 84, 29, 16, 36},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{134, 183, 89, 137, 98, 101, 106, 165, 148},
|
||||||
|
{72, 187, 100, 130, 157, 111, 32, 75, 80},
|
||||||
|
{66, 102, 167, 99, 74, 62, 40, 234, 128},
|
||||||
|
{41, 53, 9, 178, 241, 141, 26, 8, 107},
|
||||||
|
{74, 43, 26, 146, 73, 166, 49, 23, 157},
|
||||||
|
{65, 38, 105, 160, 51, 52, 31, 115, 128},
|
||||||
|
{104, 79, 12, 27, 217, 255, 87, 17, 7},
|
||||||
|
{87, 68, 71, 44, 114, 51, 15, 186, 23},
|
||||||
|
{47, 41, 14, 110, 182, 183, 21, 17, 194},
|
||||||
|
{66, 45, 25, 102, 197, 189, 23, 18, 22},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{88, 88, 147, 150, 42, 46, 45, 196, 205},
|
||||||
|
{43, 97, 183, 117, 85, 38, 35, 179, 61},
|
||||||
|
{39, 53, 200, 87, 26, 21, 43, 232, 171},
|
||||||
|
{56, 34, 51, 104, 114, 102, 29, 93, 77},
|
||||||
|
{39, 28, 85, 171, 58, 165, 90, 98, 64},
|
||||||
|
{34, 22, 116, 206, 23, 34, 43, 166, 73},
|
||||||
|
{107, 54, 32, 26, 51, 1, 81, 43, 31},
|
||||||
|
{68, 25, 106, 22, 64, 171, 36, 225, 114},
|
||||||
|
{34, 19, 21, 102, 132, 188, 16, 76, 124},
|
||||||
|
{62, 18, 78, 95, 85, 57, 50, 48, 51},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{193, 101, 35, 159, 215, 111, 89, 46, 111},
|
||||||
|
{60, 148, 31, 172, 219, 228, 21, 18, 111},
|
||||||
|
{112, 113, 77, 85, 179, 255, 38, 120, 114},
|
||||||
|
{40, 42, 1, 196, 245, 209, 10, 25, 109},
|
||||||
|
{88, 43, 29, 140, 166, 213, 37, 43, 154},
|
||||||
|
{61, 63, 30, 155, 67, 45, 68, 1, 209},
|
||||||
|
{100, 80, 8, 43, 154, 1, 51, 26, 71},
|
||||||
|
{142, 78, 78, 16, 255, 128, 34, 197, 171},
|
||||||
|
{41, 40, 5, 102, 211, 183, 4, 1, 221},
|
||||||
|
{51, 50, 17, 168, 209, 192, 23, 25, 82},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{138, 31, 36, 171, 27, 166, 38, 44, 229},
|
||||||
|
{67, 87, 58, 169, 82, 115, 26, 59, 179},
|
||||||
|
{63, 59, 90, 180, 59, 166, 93, 73, 154},
|
||||||
|
{40, 40, 21, 116, 143, 209, 34, 39, 175},
|
||||||
|
{47, 15, 16, 183, 34, 223, 49, 45, 183},
|
||||||
|
{46, 17, 33, 183, 6, 98, 15, 32, 183},
|
||||||
|
{57, 46, 22, 24, 128, 1, 54, 17, 37},
|
||||||
|
{65, 32, 73, 115, 28, 128, 23, 128, 205},
|
||||||
|
{40, 3, 9, 115, 51, 192, 18, 6, 223},
|
||||||
|
{87, 37, 9, 115, 59, 77, 64, 21, 47},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{104, 55, 44, 218, 9, 54, 53, 130, 226},
|
||||||
|
{64, 90, 70, 205, 40, 41, 23, 26, 57},
|
||||||
|
{54, 57, 112, 184, 5, 41, 38, 166, 213},
|
||||||
|
{30, 34, 26, 133, 152, 116, 10, 32, 134},
|
||||||
|
{39, 19, 53, 221, 26, 114, 32, 73, 255},
|
||||||
|
{31, 9, 65, 234, 2, 15, 1, 118, 73},
|
||||||
|
{75, 32, 12, 51, 192, 255, 160, 43, 51},
|
||||||
|
{88, 31, 35, 67, 102, 85, 55, 186, 85},
|
||||||
|
{56, 21, 23, 111, 59, 205, 45, 37, 192},
|
||||||
|
{55, 38, 70, 124, 73, 102, 1, 34, 98},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{125, 98, 42, 88, 104, 85, 117, 175, 82},
|
||||||
|
{95, 84, 53, 89, 128, 100, 113, 101, 45},
|
||||||
|
{75, 79, 123, 47, 51, 128, 81, 171, 1},
|
||||||
|
{57, 17, 5, 71, 102, 57, 53, 41, 49},
|
||||||
|
{38, 33, 13, 121, 57, 73, 26, 1, 85},
|
||||||
|
{41, 10, 67, 138, 77, 110, 90, 47, 114},
|
||||||
|
{115, 21, 2, 10, 102, 255, 166, 23, 6},
|
||||||
|
{101, 29, 16, 10, 85, 128, 101, 196, 26},
|
||||||
|
{57, 18, 10, 102, 102, 213, 34, 20, 43},
|
||||||
|
{117, 20, 15, 36, 163, 128, 68, 1, 26},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{102, 61, 71, 37, 34, 53, 31, 243, 192},
|
||||||
|
{69, 60, 71, 38, 73, 119, 28, 222, 37},
|
||||||
|
{68, 45, 128, 34, 1, 47, 11, 245, 171},
|
||||||
|
{62, 17, 19, 70, 146, 85, 55, 62, 70},
|
||||||
|
{37, 43, 37, 154, 100, 163, 85, 160, 1},
|
||||||
|
{63, 9, 92, 136, 28, 64, 32, 201, 85},
|
||||||
|
{75, 15, 9, 9, 64, 255, 184, 119, 16},
|
||||||
|
{86, 6, 28, 5, 64, 255, 25, 248, 1},
|
||||||
|
{56, 8, 17, 132, 137, 255, 55, 116, 128},
|
||||||
|
{58, 15, 20, 82, 135, 57, 26, 121, 40},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{164, 50, 31, 137, 154, 133, 25, 35, 218},
|
||||||
|
{51, 103, 44, 131, 131, 123, 31, 6, 158},
|
||||||
|
{86, 40, 64, 135, 148, 224, 45, 183, 128},
|
||||||
|
{22, 26, 17, 131, 240, 154, 14, 1, 209},
|
||||||
|
{45, 16, 21, 91, 64, 222, 7, 1, 197},
|
||||||
|
{56, 21, 39, 155, 60, 138, 23, 102, 213},
|
||||||
|
{83, 12, 13, 54, 192, 255, 68, 47, 28},
|
||||||
|
{85, 26, 85, 85, 128, 128, 32, 146, 171},
|
||||||
|
{18, 11, 7, 63, 144, 171, 4, 4, 246},
|
||||||
|
{35, 27, 10, 146, 174, 171, 12, 26, 128},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{190, 80, 35, 99, 180, 80, 126, 54, 45},
|
||||||
|
{85, 126, 47, 87, 176, 51, 41, 20, 32},
|
||||||
|
{101, 75, 128, 139, 118, 146, 116, 128, 85},
|
||||||
|
{56, 41, 15, 176, 236, 85, 37, 9, 62},
|
||||||
|
{71, 30, 17, 119, 118, 255, 17, 18, 138},
|
||||||
|
{101, 38, 60, 138, 55, 70, 43, 26, 142},
|
||||||
|
{146, 36, 19, 30, 171, 255, 97, 27, 20},
|
||||||
|
{138, 45, 61, 62, 219, 1, 81, 188, 64},
|
||||||
|
{32, 41, 20, 117, 151, 142, 20, 21, 163},
|
||||||
|
{112, 19, 12, 61, 195, 128, 48, 4, 24},
|
||||||
|
},
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user