mirror of
https://github.com/cwinfo/matterbridge.git
synced 2024-11-22 09:20:27 +00:00
Update dependencies (#1610)
* Update dependencies * Update module to go 1.17
This commit is contained in:
parent
7ae45c42e7
commit
4dd8bae5c9
107
go.mod
107
go.mod
@ -4,38 +4,34 @@ require (
|
|||||||
github.com/42wim/go-gitter v0.0.0-20170828205020-017310c2d557
|
github.com/42wim/go-gitter v0.0.0-20170828205020-017310c2d557
|
||||||
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f
|
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f
|
||||||
github.com/Benau/tgsconverter v0.0.0-20210809170556-99f4a4f6337f
|
github.com/Benau/tgsconverter v0.0.0-20210809170556-99f4a4f6337f
|
||||||
github.com/Jeffail/gabs v1.4.0 // indirect
|
|
||||||
github.com/Philipp15b/go-steam v1.0.1-0.20200727090957-6ae9b3c0a560
|
github.com/Philipp15b/go-steam v1.0.1-0.20200727090957-6ae9b3c0a560
|
||||||
github.com/Rhymen/go-whatsapp v0.1.2-0.20210615184944-2b8a3e9b8aa2
|
github.com/Rhymen/go-whatsapp v0.1.2-0.20210615184944-2b8a3e9b8aa2
|
||||||
github.com/SevereCloud/vksdk/v2 v2.10.0
|
github.com/SevereCloud/vksdk/v2 v2.10.0
|
||||||
github.com/d5/tengo/v2 v2.8.0
|
github.com/d5/tengo/v2 v2.8.0
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/fsnotify/fsnotify v1.4.9
|
github.com/fsnotify/fsnotify v1.5.1
|
||||||
github.com/go-telegram-bot-api/telegram-bot-api v1.0.1-0.20200524105306-7434b0456e81
|
github.com/go-telegram-bot-api/telegram-bot-api v1.0.1-0.20200524105306-7434b0456e81
|
||||||
github.com/gomarkdown/markdown v0.0.0-20210514010506-3b9f47219fe7
|
github.com/gomarkdown/markdown v0.0.0-20210918233619-6c1113f12c4a
|
||||||
github.com/google/gops v0.3.19
|
github.com/google/gops v0.3.21
|
||||||
github.com/gopackage/ddp v0.0.0-20170117053602-652027933df4 // indirect
|
|
||||||
github.com/gorilla/schema v1.2.0
|
github.com/gorilla/schema v1.2.0
|
||||||
github.com/gorilla/websocket v1.4.2
|
github.com/gorilla/websocket v1.4.2
|
||||||
github.com/hashicorp/golang-lru v0.5.4
|
github.com/hashicorp/golang-lru v0.5.4
|
||||||
github.com/jpillora/backoff v1.0.0
|
github.com/jpillora/backoff v1.0.0
|
||||||
github.com/keybase/go-keybase-chat-bot v0.0.0-20200505163032-5cacf52379da
|
github.com/keybase/go-keybase-chat-bot v0.0.0-20211004153716-fd2ee4d6be11
|
||||||
github.com/kyokomi/emoji/v2 v2.2.8
|
github.com/kyokomi/emoji/v2 v2.2.8
|
||||||
github.com/labstack/echo/v4 v4.4.0
|
github.com/labstack/echo/v4 v4.6.1
|
||||||
github.com/lrstanley/girc v0.0.0-20210611213246-771323f1624b
|
github.com/lrstanley/girc v0.0.0-20210611213246-771323f1624b
|
||||||
github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16
|
github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16
|
||||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20210403163225-761e8622445d
|
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20211016222428-79310a412696
|
||||||
github.com/matterbridge/discordgo v0.21.2-0.20210201201054-fb39a175b4f7
|
github.com/matterbridge/discordgo v0.21.2-0.20210201201054-fb39a175b4f7
|
||||||
github.com/matterbridge/go-xmpp v0.0.0-20210731150933-5702291c239f
|
github.com/matterbridge/go-xmpp v0.0.0-20210731150933-5702291c239f
|
||||||
github.com/matterbridge/gozulipbot v0.0.0-20200820220548-be5824faa913
|
github.com/matterbridge/gozulipbot v0.0.0-20200820220548-be5824faa913
|
||||||
github.com/matterbridge/logrus-prefixed-formatter v0.5.3-0.20200523233437-d971309a77ba
|
github.com/matterbridge/logrus-prefixed-formatter v0.5.3-0.20200523233437-d971309a77ba
|
||||||
github.com/matterbridge/matterclient v0.0.0-20211016195328-346acac403d8
|
github.com/matterbridge/matterclient v0.0.0-20211016195328-346acac403d8
|
||||||
github.com/mattermost/mattermost-server/v5 v5.30.1
|
github.com/mattermost/mattermost-server/v5 v5.39.0
|
||||||
github.com/mattermost/mattermost-server/v6 v6.0.0
|
github.com/mattermost/mattermost-server/v6 v6.0.0
|
||||||
github.com/mattn/godown v0.0.1
|
github.com/mattn/godown v0.0.1
|
||||||
github.com/missdeer/golib v1.0.4
|
github.com/missdeer/golib v1.0.4
|
||||||
github.com/mreiferson/go-httpclient v0.0.0-20201222173833-5e475fde3a4d // indirect
|
|
||||||
github.com/mrexodia/wray v0.0.0-20160318003008-78a2c1f284ff // indirect
|
|
||||||
github.com/nelsonken/gomf v0.0.0-20180504123937-a9dd2f9deae9
|
github.com/nelsonken/gomf v0.0.0-20180504123937-a9dd2f9deae9
|
||||||
github.com/paulrosania/go-charset v0.0.0-20190326053356-55c9d7a5834c
|
github.com/paulrosania/go-charset v0.0.0-20190326053356-55c9d7a5834c
|
||||||
github.com/rs/xid v1.3.0
|
github.com/rs/xid v1.3.0
|
||||||
@ -43,19 +39,98 @@ require (
|
|||||||
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca
|
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca
|
||||||
github.com/shazow/ssh-chat v1.10.1
|
github.com/shazow/ssh-chat v1.10.1
|
||||||
github.com/sirupsen/logrus v1.8.1
|
github.com/sirupsen/logrus v1.8.1
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
|
github.com/slack-go/slack v0.9.5
|
||||||
github.com/slack-go/slack v0.9.3
|
github.com/spf13/viper v1.9.0
|
||||||
github.com/spf13/viper v1.8.1
|
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
github.com/vincent-petithory/dataurl v0.0.0-20191104211930-d1553a71de50
|
github.com/vincent-petithory/dataurl v0.0.0-20191104211930-d1553a71de50
|
||||||
github.com/writeas/go-strip-markdown v2.0.1+incompatible
|
github.com/writeas/go-strip-markdown v2.0.1+incompatible
|
||||||
github.com/yaegashi/msgraph.go v0.1.4
|
github.com/yaegashi/msgraph.go v0.1.4
|
||||||
github.com/zfjagann/golang-ring v0.0.0-20210116075443-7c86fdb43134
|
github.com/zfjagann/golang-ring v0.0.0-20210116075443-7c86fdb43134
|
||||||
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d
|
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d
|
||||||
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914
|
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1
|
||||||
gomod.garykim.dev/nc-talk v0.3.0
|
gomod.garykim.dev/nc-talk v0.3.0
|
||||||
gopkg.in/olahol/melody.v1 v1.0.0-20170518105555-d52139073376
|
gopkg.in/olahol/melody.v1 v1.0.0-20170518105555-d52139073376
|
||||||
layeh.com/gumble v0.0.0-20200818122324-146f9205029b
|
layeh.com/gumble v0.0.0-20200818122324-146f9205029b
|
||||||
)
|
)
|
||||||
|
|
||||||
go 1.15
|
require (
|
||||||
|
github.com/Benau/go_rlottie v0.0.0-20210807002906-98c1b2421989 // indirect
|
||||||
|
github.com/Jeffail/gabs v1.4.0 // indirect
|
||||||
|
github.com/apex/log v1.9.0 // indirect
|
||||||
|
github.com/av-elier/go-decimal-to-rational v0.0.0-20191127152832-89e6aad02ecf // indirect
|
||||||
|
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||||
|
github.com/dustin/go-humanize v1.0.0 // indirect
|
||||||
|
github.com/dyatlov/go-opengraph v0.0.0-20210112100619-dae8665a5b09 // indirect
|
||||||
|
github.com/francoispqt/gojay v1.2.13 // indirect
|
||||||
|
github.com/go-asn1-ber/asn1-ber v1.5.3 // indirect
|
||||||
|
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||||
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
|
github.com/google/uuid v1.2.0 // indirect
|
||||||
|
github.com/gopackage/ddp v0.0.3 // indirect
|
||||||
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
|
github.com/json-iterator/go v1.1.11 // indirect
|
||||||
|
github.com/kettek/apng v0.0.0-20191108220231-414630eed80f // indirect
|
||||||
|
github.com/klauspost/cpuid/v2 v2.0.6 // indirect
|
||||||
|
github.com/labstack/gommon v0.3.0 // indirect
|
||||||
|
github.com/magiconair/properties v1.8.5 // indirect
|
||||||
|
github.com/mattermost/go-i18n v1.11.0 // indirect
|
||||||
|
github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d // indirect
|
||||||
|
github.com/mattermost/logr v1.0.13 // indirect
|
||||||
|
github.com/mattermost/logr/v2 v2.0.10 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.8 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
|
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||||
|
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||||
|
github.com/minio/md5-simd v1.1.2 // indirect
|
||||||
|
github.com/minio/minio-go/v7 v7.0.11 // indirect
|
||||||
|
github.com/minio/sha256-simd v1.0.0 // indirect
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
|
github.com/mitchellh/mapstructure v1.4.2 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||||
|
github.com/monaco-io/request v1.0.5 // indirect
|
||||||
|
github.com/mreiferson/go-httpclient v0.0.0-20201222173833-5e475fde3a4d // indirect
|
||||||
|
github.com/mrexodia/wray v0.0.0-20160318003008-78a2c1f284ff // indirect
|
||||||
|
github.com/pborman/uuid v1.2.1 // indirect
|
||||||
|
github.com/pelletier/go-toml v1.9.4 // indirect
|
||||||
|
github.com/philhofer/fwd v1.1.1 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/rickb777/date v1.12.4 // indirect
|
||||||
|
github.com/rickb777/plural v1.2.0 // indirect
|
||||||
|
github.com/rivo/uniseg v0.2.0 // indirect
|
||||||
|
github.com/shazow/rateio v0.0.0-20200113175441-4461efc8bdc4 // indirect
|
||||||
|
github.com/sizeofint/webpanimation v0.0.0-20210809145948-1d2b32119882 // indirect
|
||||||
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
|
||||||
|
github.com/spf13/afero v1.6.0 // indirect
|
||||||
|
github.com/spf13/cast v1.4.1 // indirect
|
||||||
|
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||||
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
|
github.com/subosito/gotenv v1.2.0 // indirect
|
||||||
|
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
|
||||||
|
github.com/tinylib/msgp v1.1.6 // indirect
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
|
github.com/valyala/fasttemplate v1.2.1 // indirect
|
||||||
|
github.com/wiggin77/cfg v1.0.2 // indirect
|
||||||
|
github.com/wiggin77/merror v1.0.3 // indirect
|
||||||
|
github.com/wiggin77/srslog v1.0.1 // indirect
|
||||||
|
go.uber.org/atomic v1.8.0 // indirect
|
||||||
|
go.uber.org/multierr v1.7.0 // indirect
|
||||||
|
go.uber.org/zap v1.17.0 // indirect
|
||||||
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
|
||||||
|
golang.org/x/net v0.0.0-20210913180222-943fd674d43e // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0 // indirect
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
|
||||||
|
golang.org/x/text v0.3.7 // indirect
|
||||||
|
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 // indirect
|
||||||
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
|
google.golang.org/protobuf v1.27.1 // indirect
|
||||||
|
gopkg.in/ini.v1 v1.63.2 // indirect
|
||||||
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||||
|
)
|
||||||
|
|
||||||
|
go 1.17
|
||||||
|
@ -111,7 +111,7 @@ func (m *MMClient) GetFileLinks(filenames []string) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *MMClient) GetPosts(channelId string, limit int) *model.PostList { //nolint:golint
|
func (m *MMClient) GetPosts(channelId string, limit int) *model.PostList { //nolint:golint
|
||||||
res, resp := m.Client.GetPostsForChannel(channelId, 0, limit, "")
|
res, resp := m.Client.GetPostsForChannel(channelId, 0, limit, "", true)
|
||||||
if resp.Error != nil {
|
if resp.Error != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -119,7 +119,7 @@ func (m *MMClient) GetPosts(channelId string, limit int) *model.PostList { //nol
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *MMClient) GetPostsSince(channelId string, time int64) *model.PostList { //nolint:golint
|
func (m *MMClient) GetPostsSince(channelId string, time int64) *model.PostList { //nolint:golint
|
||||||
res, resp := m.Client.GetPostsSince(channelId, time)
|
res, resp := m.Client.GetPostsSince(channelId, time, true)
|
||||||
if resp.Error != nil {
|
if resp.Error != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
1
vendor/github.com/Benau/go_rlottie/go.mod
generated
vendored
1
vendor/github.com/Benau/go_rlottie/go.mod
generated
vendored
@ -1 +0,0 @@
|
|||||||
module github.com/Benau/go_rlottie
|
|
1
vendor/github.com/Jeffail/gabs/go.mod
generated
vendored
1
vendor/github.com/Jeffail/gabs/go.mod
generated
vendored
@ -1 +0,0 @@
|
|||||||
module github.com/Jeffail/gabs
|
|
8
vendor/github.com/Philipp15b/go-steam/go.mod
generated
vendored
8
vendor/github.com/Philipp15b/go-steam/go.mod
generated
vendored
@ -1,8 +0,0 @@
|
|||||||
module github.com/Philipp15b/go-steam
|
|
||||||
|
|
||||||
go 1.14
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/davecgh/go-spew v1.1.1
|
|
||||||
github.com/golang/protobuf v1.4.2
|
|
||||||
)
|
|
22
vendor/github.com/Philipp15b/go-steam/go.sum
generated
vendored
22
vendor/github.com/Philipp15b/go-steam/go.sum
generated
vendored
@ -1,22 +0,0 @@
|
|||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
|
||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
|
||||||
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
|
||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
|
||||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
|
||||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
|
||||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
|
||||||
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
|
||||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
11
vendor/github.com/Rhymen/go-whatsapp/go.mod
generated
vendored
11
vendor/github.com/Rhymen/go-whatsapp/go.mod
generated
vendored
@ -1,11 +0,0 @@
|
|||||||
module github.com/Rhymen/go-whatsapp
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/golang/protobuf v1.4.1
|
|
||||||
github.com/gorilla/websocket v1.4.1
|
|
||||||
github.com/pkg/errors v0.8.1
|
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
|
|
||||||
google.golang.org/protobuf v1.25.0
|
|
||||||
)
|
|
||||||
|
|
||||||
go 1.13
|
|
71
vendor/github.com/Rhymen/go-whatsapp/go.sum
generated
vendored
71
vendor/github.com/Rhymen/go-whatsapp/go.sum
generated
vendored
@ -1,71 +0,0 @@
|
|||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
|
||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
|
||||||
github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0=
|
|
||||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
|
|
||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
|
|
||||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
|
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
|
||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
|
||||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
|
||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
|
||||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
|
||||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
|
||||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
10
vendor/github.com/SevereCloud/vksdk/v2/go.mod
generated
vendored
10
vendor/github.com/SevereCloud/vksdk/v2/go.mod
generated
vendored
@ -1,10 +0,0 @@
|
|||||||
module github.com/SevereCloud/vksdk/v2
|
|
||||||
|
|
||||||
go 1.13
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/gorilla/schema v1.2.0
|
|
||||||
github.com/gorilla/websocket v1.4.2
|
|
||||||
github.com/stretchr/testify v1.7.0
|
|
||||||
golang.org/x/text v0.3.5
|
|
||||||
)
|
|
18
vendor/github.com/SevereCloud/vksdk/v2/go.sum
generated
vendored
18
vendor/github.com/SevereCloud/vksdk/v2/go.sum
generated
vendored
@ -1,18 +0,0 @@
|
|||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc=
|
|
||||||
github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
|
|
||||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
|
||||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
|
|
||||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
1
vendor/github.com/apex/log/.gitignore
generated
vendored
Normal file
1
vendor/github.com/apex/log/.gitignore
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
.envrc
|
75
vendor/github.com/apex/log/History.md
generated
vendored
Normal file
75
vendor/github.com/apex/log/History.md
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
|
||||||
|
v1.9.0 / 2020-08-18
|
||||||
|
===================
|
||||||
|
|
||||||
|
* add `WithDuration()` method to record a duration as milliseconds
|
||||||
|
* add: ignore nil errors in `WithError()`
|
||||||
|
* change trace duration to milliseconds (arguably a breaking change)
|
||||||
|
|
||||||
|
v1.8.0 / 2020-08-05
|
||||||
|
===================
|
||||||
|
|
||||||
|
* refactor apexlogs handler to not make the AddEvents() call if there are no events to flush
|
||||||
|
|
||||||
|
v1.7.1 / 2020-08-05
|
||||||
|
===================
|
||||||
|
|
||||||
|
* fix potential nil panic in apexlogs handler
|
||||||
|
|
||||||
|
v1.7.0 / 2020-08-03
|
||||||
|
===================
|
||||||
|
|
||||||
|
* add FlushSync() to apexlogs handler
|
||||||
|
|
||||||
|
v1.6.0 / 2020-07-13
|
||||||
|
===================
|
||||||
|
|
||||||
|
* update apex/logs dep to v1.0.0
|
||||||
|
* docs: mention that Flush() is non-blocking now, use Close()
|
||||||
|
|
||||||
|
v1.5.0 / 2020-07-11
|
||||||
|
===================
|
||||||
|
|
||||||
|
* add buffering to Apex Logs handler
|
||||||
|
|
||||||
|
v1.4.0 / 2020-06-16
|
||||||
|
===================
|
||||||
|
|
||||||
|
* add AuthToken to apexlogs handler
|
||||||
|
|
||||||
|
v1.3.0 / 2020-05-26
|
||||||
|
===================
|
||||||
|
|
||||||
|
* change FromContext() to always return a logger
|
||||||
|
|
||||||
|
v1.2.0 / 2020-05-26
|
||||||
|
===================
|
||||||
|
|
||||||
|
* add log.NewContext() and log.FromContext(). Closes #78
|
||||||
|
|
||||||
|
v1.1.4 / 2020-04-22
|
||||||
|
===================
|
||||||
|
|
||||||
|
* add apexlogs HTTPClient support
|
||||||
|
|
||||||
|
v1.1.3 / 2020-04-22
|
||||||
|
===================
|
||||||
|
|
||||||
|
* add events len check before flushing to apexlogs handler
|
||||||
|
|
||||||
|
v1.1.2 / 2020-01-29
|
||||||
|
===================
|
||||||
|
|
||||||
|
* refactor apexlogs handler to use github.com/apex/logs client
|
||||||
|
|
||||||
|
v1.1.1 / 2019-06-24
|
||||||
|
===================
|
||||||
|
|
||||||
|
* add go.mod
|
||||||
|
* add rough pass at apexlogs handler
|
||||||
|
|
||||||
|
v1.1.0 / 2018-10-11
|
||||||
|
===================
|
||||||
|
|
||||||
|
* fix: cli handler to show non-string fields appropriately
|
||||||
|
* fix: cli using fatih/color to better support windows
|
22
vendor/github.com/apex/log/LICENSE
generated
vendored
Normal file
22
vendor/github.com/apex/log/LICENSE
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
(The MIT License)
|
||||||
|
|
||||||
|
Copyright (c) 2015 TJ Holowaychuk tj@tjholowaychuk.com
|
||||||
|
|
||||||
|
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.
|
2
vendor/github.com/apex/log/Makefile
generated
vendored
Normal file
2
vendor/github.com/apex/log/Makefile
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
include github.com/tj/make/golang
|
61
vendor/github.com/apex/log/Readme.md
generated
vendored
Normal file
61
vendor/github.com/apex/log/Readme.md
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
|
||||||
|
![Structured logging for golang](assets/title.png)
|
||||||
|
|
||||||
|
Package log implements a simple structured logging API inspired by Logrus, designed with centralization in mind. Read more on [Medium](https://medium.com/@tjholowaychuk/apex-log-e8d9627f4a9a#.rav8yhkud).
|
||||||
|
|
||||||
|
## Handlers
|
||||||
|
|
||||||
|
- __apexlogs__ – handler for [Apex Logs](https://apex.sh/logs/)
|
||||||
|
- __cli__ – human-friendly CLI output
|
||||||
|
- __discard__ – discards all logs
|
||||||
|
- __es__ – Elasticsearch handler
|
||||||
|
- __graylog__ – Graylog handler
|
||||||
|
- __json__ – JSON output handler
|
||||||
|
- __kinesis__ – AWS Kinesis handler
|
||||||
|
- __level__ – level filter handler
|
||||||
|
- __logfmt__ – logfmt plain-text formatter
|
||||||
|
- __memory__ – in-memory handler for tests
|
||||||
|
- __multi__ – fan-out to multiple handlers
|
||||||
|
- __papertrail__ – Papertrail handler
|
||||||
|
- __text__ – human-friendly colored output
|
||||||
|
- __delta__ – outputs the delta between log calls and spinner
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
Example using the [Apex Logs](https://apex.sh/logs/) handler.
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/apex/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ctx := log.WithFields(log.Fields{
|
||||||
|
"file": "something.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"user": "tobi",
|
||||||
|
})
|
||||||
|
|
||||||
|
for range time.Tick(time.Millisecond * 200) {
|
||||||
|
ctx.Info("upload")
|
||||||
|
ctx.Info("upload complete")
|
||||||
|
ctx.Warn("upload retry")
|
||||||
|
ctx.WithError(errors.New("unauthorized")).Error("upload failed")
|
||||||
|
ctx.Errorf("failed to upload %s", "img.png")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[![Build Status](https://semaphoreci.com/api/v1/projects/d8a8b1c0-45b0-4b89-b066-99d788d0b94c/642077/badge.svg)](https://semaphoreci.com/tj/log)
|
||||||
|
[![GoDoc](https://godoc.org/github.com/apex/log?status.svg)](https://godoc.org/github.com/apex/log)
|
||||||
|
![](https://img.shields.io/badge/license-MIT-blue.svg)
|
||||||
|
![](https://img.shields.io/badge/status-stable-green.svg)
|
||||||
|
|
||||||
|
<a href="https://apex.sh"><img src="http://tjholowaychuk.com:6000/svg/sponsor"></a>
|
19
vendor/github.com/apex/log/context.go
generated
vendored
Normal file
19
vendor/github.com/apex/log/context.go
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
|
// logKey is a private context key.
|
||||||
|
type logKey struct{}
|
||||||
|
|
||||||
|
// NewContext returns a new context with logger.
|
||||||
|
func NewContext(ctx context.Context, v Interface) context.Context {
|
||||||
|
return context.WithValue(ctx, logKey{}, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromContext returns the logger from context, or log.Log.
|
||||||
|
func FromContext(ctx context.Context) Interface {
|
||||||
|
if v, ok := ctx.Value(logKey{}).(Interface); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return Log
|
||||||
|
}
|
45
vendor/github.com/apex/log/default.go
generated
vendored
Normal file
45
vendor/github.com/apex/log/default.go
generated
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
|
// field used for sorting.
|
||||||
|
type field struct {
|
||||||
|
Name string
|
||||||
|
Value interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// by sorts fields by name.
|
||||||
|
type byName []field
|
||||||
|
|
||||||
|
func (a byName) Len() int { return len(a) }
|
||||||
|
func (a byName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
|
func (a byName) Less(i, j int) bool { return a[i].Name < a[j].Name }
|
||||||
|
|
||||||
|
// handleStdLog outpouts to the stlib log.
|
||||||
|
func handleStdLog(e *Entry) error {
|
||||||
|
level := levelNames[e.Level]
|
||||||
|
|
||||||
|
var fields []field
|
||||||
|
|
||||||
|
for k, v := range e.Fields {
|
||||||
|
fields = append(fields, field{k, v})
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Sort(byName(fields))
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
fmt.Fprintf(&b, "%5s %-25s", level, e.Message)
|
||||||
|
|
||||||
|
for _, f := range fields {
|
||||||
|
fmt.Fprintf(&b, " %s=%v", f.Name, f.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println(b.String())
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
10
vendor/github.com/apex/log/doc.go
generated
vendored
Normal file
10
vendor/github.com/apex/log/doc.go
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
Package log implements a simple structured logging API designed with few assumptions. Designed for
|
||||||
|
centralized logging solutions such as Kinesis which require encoding and decoding before fanning-out
|
||||||
|
to handlers.
|
||||||
|
|
||||||
|
You may use this package with inline handlers, much like Logrus, however a centralized solution
|
||||||
|
is recommended so that apps do not need to be re-deployed to add or remove logging service
|
||||||
|
providers.
|
||||||
|
*/
|
||||||
|
package log
|
182
vendor/github.com/apex/log/entry.go
generated
vendored
Normal file
182
vendor/github.com/apex/log/entry.go
generated
vendored
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// assert interface compliance.
|
||||||
|
var _ Interface = (*Entry)(nil)
|
||||||
|
|
||||||
|
// Now returns the current time.
|
||||||
|
var Now = time.Now
|
||||||
|
|
||||||
|
// Entry represents a single log entry.
|
||||||
|
type Entry struct {
|
||||||
|
Logger *Logger `json:"-"`
|
||||||
|
Fields Fields `json:"fields"`
|
||||||
|
Level Level `json:"level"`
|
||||||
|
Timestamp time.Time `json:"timestamp"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
start time.Time
|
||||||
|
fields []Fields
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewEntry returns a new entry for `log`.
|
||||||
|
func NewEntry(log *Logger) *Entry {
|
||||||
|
return &Entry{
|
||||||
|
Logger: log,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithFields returns a new entry with `fields` set.
|
||||||
|
func (e *Entry) WithFields(fields Fielder) *Entry {
|
||||||
|
f := []Fields{}
|
||||||
|
f = append(f, e.fields...)
|
||||||
|
f = append(f, fields.Fields())
|
||||||
|
return &Entry{
|
||||||
|
Logger: e.Logger,
|
||||||
|
fields: f,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithField returns a new entry with the `key` and `value` set.
|
||||||
|
func (e *Entry) WithField(key string, value interface{}) *Entry {
|
||||||
|
return e.WithFields(Fields{key: value})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDuration returns a new entry with the "duration" field set
|
||||||
|
// to the given duration in milliseconds.
|
||||||
|
func (e *Entry) WithDuration(d time.Duration) *Entry {
|
||||||
|
return e.WithField("duration", d.Milliseconds())
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithError returns a new entry with the "error" set to `err`.
|
||||||
|
//
|
||||||
|
// The given error may implement .Fielder, if it does the method
|
||||||
|
// will add all its `.Fields()` into the returned entry.
|
||||||
|
func (e *Entry) WithError(err error) *Entry {
|
||||||
|
if err == nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := e.WithField("error", err.Error())
|
||||||
|
|
||||||
|
if s, ok := err.(stackTracer); ok {
|
||||||
|
frame := s.StackTrace()[0]
|
||||||
|
|
||||||
|
name := fmt.Sprintf("%n", frame)
|
||||||
|
file := fmt.Sprintf("%+s", frame)
|
||||||
|
line := fmt.Sprintf("%d", frame)
|
||||||
|
|
||||||
|
parts := strings.Split(file, "\n\t")
|
||||||
|
if len(parts) > 1 {
|
||||||
|
file = parts[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = ctx.WithField("source", fmt.Sprintf("%s: %s:%s", name, file, line))
|
||||||
|
}
|
||||||
|
|
||||||
|
if f, ok := err.(Fielder); ok {
|
||||||
|
ctx = ctx.WithFields(f.Fields())
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug level message.
|
||||||
|
func (e *Entry) Debug(msg string) {
|
||||||
|
e.Logger.log(DebugLevel, e, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info level message.
|
||||||
|
func (e *Entry) Info(msg string) {
|
||||||
|
e.Logger.log(InfoLevel, e, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warn level message.
|
||||||
|
func (e *Entry) Warn(msg string) {
|
||||||
|
e.Logger.log(WarnLevel, e, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error level message.
|
||||||
|
func (e *Entry) Error(msg string) {
|
||||||
|
e.Logger.log(ErrorLevel, e, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fatal level message, followed by an exit.
|
||||||
|
func (e *Entry) Fatal(msg string) {
|
||||||
|
e.Logger.log(FatalLevel, e, msg)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debugf level formatted message.
|
||||||
|
func (e *Entry) Debugf(msg string, v ...interface{}) {
|
||||||
|
e.Debug(fmt.Sprintf(msg, v...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infof level formatted message.
|
||||||
|
func (e *Entry) Infof(msg string, v ...interface{}) {
|
||||||
|
e.Info(fmt.Sprintf(msg, v...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warnf level formatted message.
|
||||||
|
func (e *Entry) Warnf(msg string, v ...interface{}) {
|
||||||
|
e.Warn(fmt.Sprintf(msg, v...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorf level formatted message.
|
||||||
|
func (e *Entry) Errorf(msg string, v ...interface{}) {
|
||||||
|
e.Error(fmt.Sprintf(msg, v...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fatalf level formatted message, followed by an exit.
|
||||||
|
func (e *Entry) Fatalf(msg string, v ...interface{}) {
|
||||||
|
e.Fatal(fmt.Sprintf(msg, v...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trace returns a new entry with a Stop method to fire off
|
||||||
|
// a corresponding completion log, useful with defer.
|
||||||
|
func (e *Entry) Trace(msg string) *Entry {
|
||||||
|
e.Info(msg)
|
||||||
|
v := e.WithFields(e.Fields)
|
||||||
|
v.Message = msg
|
||||||
|
v.start = time.Now()
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop should be used with Trace, to fire off the completion message. When
|
||||||
|
// an `err` is passed the "error" field is set, and the log level is error.
|
||||||
|
func (e *Entry) Stop(err *error) {
|
||||||
|
if err == nil || *err == nil {
|
||||||
|
e.WithDuration(time.Since(e.start)).Info(e.Message)
|
||||||
|
} else {
|
||||||
|
e.WithDuration(time.Since(e.start)).WithError(*err).Error(e.Message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// mergedFields returns the fields list collapsed into a single map.
|
||||||
|
func (e *Entry) mergedFields() Fields {
|
||||||
|
f := Fields{}
|
||||||
|
|
||||||
|
for _, fields := range e.fields {
|
||||||
|
for k, v := range fields {
|
||||||
|
f[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
// finalize returns a copy of the Entry with Fields merged.
|
||||||
|
func (e *Entry) finalize(level Level, msg string) *Entry {
|
||||||
|
return &Entry{
|
||||||
|
Logger: e.Logger,
|
||||||
|
Fields: e.mergedFields(),
|
||||||
|
Level: level,
|
||||||
|
Message: msg,
|
||||||
|
Timestamp: Now(),
|
||||||
|
}
|
||||||
|
}
|
22
vendor/github.com/apex/log/interface.go
generated
vendored
Normal file
22
vendor/github.com/apex/log/interface.go
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// Interface represents the API of both Logger and Entry.
|
||||||
|
type Interface interface {
|
||||||
|
WithFields(Fielder) *Entry
|
||||||
|
WithField(string, interface{}) *Entry
|
||||||
|
WithDuration(time.Duration) *Entry
|
||||||
|
WithError(error) *Entry
|
||||||
|
Debug(string)
|
||||||
|
Info(string)
|
||||||
|
Warn(string)
|
||||||
|
Error(string)
|
||||||
|
Fatal(string)
|
||||||
|
Debugf(string, ...interface{})
|
||||||
|
Infof(string, ...interface{})
|
||||||
|
Warnf(string, ...interface{})
|
||||||
|
Errorf(string, ...interface{})
|
||||||
|
Fatalf(string, ...interface{})
|
||||||
|
Trace(string) *Entry
|
||||||
|
}
|
81
vendor/github.com/apex/log/levels.go
generated
vendored
Normal file
81
vendor/github.com/apex/log/levels.go
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrInvalidLevel is returned if the severity level is invalid.
|
||||||
|
var ErrInvalidLevel = errors.New("invalid level")
|
||||||
|
|
||||||
|
// Level of severity.
|
||||||
|
type Level int
|
||||||
|
|
||||||
|
// Log levels.
|
||||||
|
const (
|
||||||
|
InvalidLevel Level = iota - 1
|
||||||
|
DebugLevel
|
||||||
|
InfoLevel
|
||||||
|
WarnLevel
|
||||||
|
ErrorLevel
|
||||||
|
FatalLevel
|
||||||
|
)
|
||||||
|
|
||||||
|
var levelNames = [...]string{
|
||||||
|
DebugLevel: "debug",
|
||||||
|
InfoLevel: "info",
|
||||||
|
WarnLevel: "warn",
|
||||||
|
ErrorLevel: "error",
|
||||||
|
FatalLevel: "fatal",
|
||||||
|
}
|
||||||
|
|
||||||
|
var levelStrings = map[string]Level{
|
||||||
|
"debug": DebugLevel,
|
||||||
|
"info": InfoLevel,
|
||||||
|
"warn": WarnLevel,
|
||||||
|
"warning": WarnLevel,
|
||||||
|
"error": ErrorLevel,
|
||||||
|
"fatal": FatalLevel,
|
||||||
|
}
|
||||||
|
|
||||||
|
// String implementation.
|
||||||
|
func (l Level) String() string {
|
||||||
|
return levelNames[l]
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implementation.
|
||||||
|
func (l Level) MarshalJSON() ([]byte, error) {
|
||||||
|
return []byte(`"` + l.String() + `"`), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implementation.
|
||||||
|
func (l *Level) UnmarshalJSON(b []byte) error {
|
||||||
|
v, err := ParseLevel(string(bytes.Trim(b, `"`)))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*l = v
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseLevel parses level string.
|
||||||
|
func ParseLevel(s string) (Level, error) {
|
||||||
|
l, ok := levelStrings[strings.ToLower(s)]
|
||||||
|
if !ok {
|
||||||
|
return InvalidLevel, ErrInvalidLevel
|
||||||
|
}
|
||||||
|
|
||||||
|
return l, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustParseLevel parses level string or panics.
|
||||||
|
func MustParseLevel(s string) Level {
|
||||||
|
l, err := ParseLevel(s)
|
||||||
|
if err != nil {
|
||||||
|
panic("invalid log level")
|
||||||
|
}
|
||||||
|
|
||||||
|
return l
|
||||||
|
}
|
156
vendor/github.com/apex/log/logger.go
generated
vendored
Normal file
156
vendor/github.com/apex/log/logger.go
generated
vendored
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
stdlog "log"
|
||||||
|
"sort"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// assert interface compliance.
|
||||||
|
var _ Interface = (*Logger)(nil)
|
||||||
|
|
||||||
|
// Fielder is an interface for providing fields to custom types.
|
||||||
|
type Fielder interface {
|
||||||
|
Fields() Fields
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fields represents a map of entry level data used for structured logging.
|
||||||
|
type Fields map[string]interface{}
|
||||||
|
|
||||||
|
// Fields implements Fielder.
|
||||||
|
func (f Fields) Fields() Fields {
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get field value by name.
|
||||||
|
func (f Fields) Get(name string) interface{} {
|
||||||
|
return f[name]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Names returns field names sorted.
|
||||||
|
func (f Fields) Names() (v []string) {
|
||||||
|
for k := range f {
|
||||||
|
v = append(v, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(v)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// The HandlerFunc type is an adapter to allow the use of ordinary functions as
|
||||||
|
// log handlers. If f is a function with the appropriate signature,
|
||||||
|
// HandlerFunc(f) is a Handler object that calls f.
|
||||||
|
type HandlerFunc func(*Entry) error
|
||||||
|
|
||||||
|
// HandleLog calls f(e).
|
||||||
|
func (f HandlerFunc) HandleLog(e *Entry) error {
|
||||||
|
return f(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handler is used to handle log events, outputting them to
|
||||||
|
// stdio or sending them to remote services. See the "handlers"
|
||||||
|
// directory for implementations.
|
||||||
|
//
|
||||||
|
// It is left up to Handlers to implement thread-safety.
|
||||||
|
type Handler interface {
|
||||||
|
HandleLog(*Entry) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Logger represents a logger with configurable Level and Handler.
|
||||||
|
type Logger struct {
|
||||||
|
Handler Handler
|
||||||
|
Level Level
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithFields returns a new entry with `fields` set.
|
||||||
|
func (l *Logger) WithFields(fields Fielder) *Entry {
|
||||||
|
return NewEntry(l).WithFields(fields.Fields())
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithField returns a new entry with the `key` and `value` set.
|
||||||
|
//
|
||||||
|
// Note that the `key` should not have spaces in it - use camel
|
||||||
|
// case or underscores
|
||||||
|
func (l *Logger) WithField(key string, value interface{}) *Entry {
|
||||||
|
return NewEntry(l).WithField(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDuration returns a new entry with the "duration" field set
|
||||||
|
// to the given duration in milliseconds.
|
||||||
|
func (l *Logger) WithDuration(d time.Duration) *Entry {
|
||||||
|
return NewEntry(l).WithDuration(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithError returns a new entry with the "error" set to `err`.
|
||||||
|
func (l *Logger) WithError(err error) *Entry {
|
||||||
|
return NewEntry(l).WithError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug level message.
|
||||||
|
func (l *Logger) Debug(msg string) {
|
||||||
|
NewEntry(l).Debug(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info level message.
|
||||||
|
func (l *Logger) Info(msg string) {
|
||||||
|
NewEntry(l).Info(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warn level message.
|
||||||
|
func (l *Logger) Warn(msg string) {
|
||||||
|
NewEntry(l).Warn(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error level message.
|
||||||
|
func (l *Logger) Error(msg string) {
|
||||||
|
NewEntry(l).Error(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fatal level message, followed by an exit.
|
||||||
|
func (l *Logger) Fatal(msg string) {
|
||||||
|
NewEntry(l).Fatal(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debugf level formatted message.
|
||||||
|
func (l *Logger) Debugf(msg string, v ...interface{}) {
|
||||||
|
NewEntry(l).Debugf(msg, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infof level formatted message.
|
||||||
|
func (l *Logger) Infof(msg string, v ...interface{}) {
|
||||||
|
NewEntry(l).Infof(msg, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warnf level formatted message.
|
||||||
|
func (l *Logger) Warnf(msg string, v ...interface{}) {
|
||||||
|
NewEntry(l).Warnf(msg, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorf level formatted message.
|
||||||
|
func (l *Logger) Errorf(msg string, v ...interface{}) {
|
||||||
|
NewEntry(l).Errorf(msg, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fatalf level formatted message, followed by an exit.
|
||||||
|
func (l *Logger) Fatalf(msg string, v ...interface{}) {
|
||||||
|
NewEntry(l).Fatalf(msg, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trace returns a new entry with a Stop method to fire off
|
||||||
|
// a corresponding completion log, useful with defer.
|
||||||
|
func (l *Logger) Trace(msg string) *Entry {
|
||||||
|
return NewEntry(l).Trace(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// log the message, invoking the handler. We clone the entry here
|
||||||
|
// to bypass the overhead in Entry methods when the level is not
|
||||||
|
// met.
|
||||||
|
func (l *Logger) log(level Level, e *Entry, msg string) {
|
||||||
|
if level < l.Level {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := l.Handler.HandleLog(e.finalize(level, msg)); err != nil {
|
||||||
|
stdlog.Printf("error logging: %s", err)
|
||||||
|
}
|
||||||
|
}
|
108
vendor/github.com/apex/log/pkg.go
generated
vendored
Normal file
108
vendor/github.com/apex/log/pkg.go
generated
vendored
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// singletons ftw?
|
||||||
|
var Log Interface = &Logger{
|
||||||
|
Handler: HandlerFunc(handleStdLog),
|
||||||
|
Level: InfoLevel,
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHandler sets the handler. This is not thread-safe.
|
||||||
|
// The default handler outputs to the stdlib log.
|
||||||
|
func SetHandler(h Handler) {
|
||||||
|
if logger, ok := Log.(*Logger); ok {
|
||||||
|
logger.Handler = h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLevel sets the log level. This is not thread-safe.
|
||||||
|
func SetLevel(l Level) {
|
||||||
|
if logger, ok := Log.(*Logger); ok {
|
||||||
|
logger.Level = l
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLevelFromString sets the log level from a string, panicing when invalid. This is not thread-safe.
|
||||||
|
func SetLevelFromString(s string) {
|
||||||
|
if logger, ok := Log.(*Logger); ok {
|
||||||
|
logger.Level = MustParseLevel(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithFields returns a new entry with `fields` set.
|
||||||
|
func WithFields(fields Fielder) *Entry {
|
||||||
|
return Log.WithFields(fields)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithField returns a new entry with the `key` and `value` set.
|
||||||
|
func WithField(key string, value interface{}) *Entry {
|
||||||
|
return Log.WithField(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDuration returns a new entry with the "duration" field set
|
||||||
|
// to the given duration in milliseconds.
|
||||||
|
func WithDuration(d time.Duration) *Entry {
|
||||||
|
return Log.WithDuration(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithError returns a new entry with the "error" set to `err`.
|
||||||
|
func WithError(err error) *Entry {
|
||||||
|
return Log.WithError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug level message.
|
||||||
|
func Debug(msg string) {
|
||||||
|
Log.Debug(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info level message.
|
||||||
|
func Info(msg string) {
|
||||||
|
Log.Info(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warn level message.
|
||||||
|
func Warn(msg string) {
|
||||||
|
Log.Warn(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error level message.
|
||||||
|
func Error(msg string) {
|
||||||
|
Log.Error(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fatal level message, followed by an exit.
|
||||||
|
func Fatal(msg string) {
|
||||||
|
Log.Fatal(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debugf level formatted message.
|
||||||
|
func Debugf(msg string, v ...interface{}) {
|
||||||
|
Log.Debugf(msg, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infof level formatted message.
|
||||||
|
func Infof(msg string, v ...interface{}) {
|
||||||
|
Log.Infof(msg, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warnf level formatted message.
|
||||||
|
func Warnf(msg string, v ...interface{}) {
|
||||||
|
Log.Warnf(msg, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorf level formatted message.
|
||||||
|
func Errorf(msg string, v ...interface{}) {
|
||||||
|
Log.Errorf(msg, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fatalf level formatted message, followed by an exit.
|
||||||
|
func Fatalf(msg string, v ...interface{}) {
|
||||||
|
Log.Fatalf(msg, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trace returns a new entry with a Stop method to fire off
|
||||||
|
// a corresponding completion log, useful with defer.
|
||||||
|
func Trace(msg string) *Entry {
|
||||||
|
return Log.Trace(msg)
|
||||||
|
}
|
8
vendor/github.com/apex/log/stack.go
generated
vendored
Normal file
8
vendor/github.com/apex/log/stack.go
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import "github.com/pkg/errors"
|
||||||
|
|
||||||
|
// stackTracer interface.
|
||||||
|
type stackTracer interface {
|
||||||
|
StackTrace() errors.StackTrace
|
||||||
|
}
|
3
vendor/github.com/d5/tengo/v2/go.mod
generated
vendored
3
vendor/github.com/d5/tengo/v2/go.mod
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
module github.com/d5/tengo/v2
|
|
||||||
|
|
||||||
go 1.13
|
|
0
vendor/github.com/d5/tengo/v2/go.sum
generated
vendored
0
vendor/github.com/d5/tengo/v2/go.sum
generated
vendored
13
vendor/github.com/dgrijalva/jwt-go/.travis.yml
generated
vendored
13
vendor/github.com/dgrijalva/jwt-go/.travis.yml
generated
vendored
@ -1,13 +0,0 @@
|
|||||||
language: go
|
|
||||||
|
|
||||||
script:
|
|
||||||
- go vet ./...
|
|
||||||
- go test -v ./...
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.3
|
|
||||||
- 1.4
|
|
||||||
- 1.5
|
|
||||||
- 1.6
|
|
||||||
- 1.7
|
|
||||||
- tip
|
|
97
vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md
generated
vendored
97
vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md
generated
vendored
@ -1,97 +0,0 @@
|
|||||||
## Migration Guide from v2 -> v3
|
|
||||||
|
|
||||||
Version 3 adds several new, frequently requested features. To do so, it introduces a few breaking changes. We've worked to keep these as minimal as possible. This guide explains the breaking changes and how you can quickly update your code.
|
|
||||||
|
|
||||||
### `Token.Claims` is now an interface type
|
|
||||||
|
|
||||||
The most requested feature from the 2.0 verison of this library was the ability to provide a custom type to the JSON parser for claims. This was implemented by introducing a new interface, `Claims`, to replace `map[string]interface{}`. We also included two concrete implementations of `Claims`: `MapClaims` and `StandardClaims`.
|
|
||||||
|
|
||||||
`MapClaims` is an alias for `map[string]interface{}` with built in validation behavior. It is the default claims type when using `Parse`. The usage is unchanged except you must type cast the claims property.
|
|
||||||
|
|
||||||
The old example for parsing a token looked like this..
|
|
||||||
|
|
||||||
```go
|
|
||||||
if token, err := jwt.Parse(tokenString, keyLookupFunc); err == nil {
|
|
||||||
fmt.Printf("Token for user %v expires %v", token.Claims["user"], token.Claims["exp"])
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
is now directly mapped to...
|
|
||||||
|
|
||||||
```go
|
|
||||||
if token, err := jwt.Parse(tokenString, keyLookupFunc); err == nil {
|
|
||||||
claims := token.Claims.(jwt.MapClaims)
|
|
||||||
fmt.Printf("Token for user %v expires %v", claims["user"], claims["exp"])
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
`StandardClaims` is designed to be embedded in your custom type. You can supply a custom claims type with the new `ParseWithClaims` function. Here's an example of using a custom claims type.
|
|
||||||
|
|
||||||
```go
|
|
||||||
type MyCustomClaims struct {
|
|
||||||
User string
|
|
||||||
*StandardClaims
|
|
||||||
}
|
|
||||||
|
|
||||||
if token, err := jwt.ParseWithClaims(tokenString, &MyCustomClaims{}, keyLookupFunc); err == nil {
|
|
||||||
claims := token.Claims.(*MyCustomClaims)
|
|
||||||
fmt.Printf("Token for user %v expires %v", claims.User, claims.StandardClaims.ExpiresAt)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `ParseFromRequest` has been moved
|
|
||||||
|
|
||||||
To keep this library focused on the tokens without becoming overburdened with complex request processing logic, `ParseFromRequest` and its new companion `ParseFromRequestWithClaims` have been moved to a subpackage, `request`. The method signatues have also been augmented to receive a new argument: `Extractor`.
|
|
||||||
|
|
||||||
`Extractors` do the work of picking the token string out of a request. The interface is simple and composable.
|
|
||||||
|
|
||||||
This simple parsing example:
|
|
||||||
|
|
||||||
```go
|
|
||||||
if token, err := jwt.ParseFromRequest(tokenString, req, keyLookupFunc); err == nil {
|
|
||||||
fmt.Printf("Token for user %v expires %v", token.Claims["user"], token.Claims["exp"])
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
is directly mapped to:
|
|
||||||
|
|
||||||
```go
|
|
||||||
if token, err := request.ParseFromRequest(req, request.OAuth2Extractor, keyLookupFunc); err == nil {
|
|
||||||
claims := token.Claims.(jwt.MapClaims)
|
|
||||||
fmt.Printf("Token for user %v expires %v", claims["user"], claims["exp"])
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
There are several concrete `Extractor` types provided for your convenience:
|
|
||||||
|
|
||||||
* `HeaderExtractor` will search a list of headers until one contains content.
|
|
||||||
* `ArgumentExtractor` will search a list of keys in request query and form arguments until one contains content.
|
|
||||||
* `MultiExtractor` will try a list of `Extractors` in order until one returns content.
|
|
||||||
* `AuthorizationHeaderExtractor` will look in the `Authorization` header for a `Bearer` token.
|
|
||||||
* `OAuth2Extractor` searches the places an OAuth2 token would be specified (per the spec): `Authorization` header and `access_token` argument
|
|
||||||
* `PostExtractionFilter` wraps an `Extractor`, allowing you to process the content before it's parsed. A simple example is stripping the `Bearer ` text from a header
|
|
||||||
|
|
||||||
|
|
||||||
### RSA signing methods no longer accept `[]byte` keys
|
|
||||||
|
|
||||||
Due to a [critical vulnerability](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/), we've decided the convenience of accepting `[]byte` instead of `rsa.PublicKey` or `rsa.PrivateKey` isn't worth the risk of misuse.
|
|
||||||
|
|
||||||
To replace this behavior, we've added two helper methods: `ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error)` and `ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error)`. These are just simple helpers for unpacking PEM encoded PKCS1 and PKCS8 keys. If your keys are encoded any other way, all you need to do is convert them to the `crypto/rsa` package's types.
|
|
||||||
|
|
||||||
```go
|
|
||||||
func keyLookupFunc(*Token) (interface{}, error) {
|
|
||||||
// Don't forget to validate the alg is what you expect:
|
|
||||||
if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
|
|
||||||
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look up key
|
|
||||||
key, err := lookupPublicKey(token.Header["kid"])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unpack key from PEM encoded PKCS8
|
|
||||||
return jwt.ParseRSAPublicKeyFromPEM(key)
|
|
||||||
}
|
|
||||||
```
|
|
12
vendor/github.com/disintegration/imaging/.travis.yml
generated
vendored
12
vendor/github.com/disintegration/imaging/.travis.yml
generated
vendored
@ -1,12 +0,0 @@
|
|||||||
language: go
|
|
||||||
go:
|
|
||||||
- "1.10.x"
|
|
||||||
- "1.11.x"
|
|
||||||
- "1.12.x"
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- go get github.com/mattn/goveralls
|
|
||||||
|
|
||||||
script:
|
|
||||||
- go test -v -race -cover
|
|
||||||
- $GOPATH/bin/goveralls -service=travis-ci
|
|
21
vendor/github.com/disintegration/imaging/LICENSE
generated
vendored
21
vendor/github.com/disintegration/imaging/LICENSE
generated
vendored
@ -1,21 +0,0 @@
|
|||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2012 Grigory Dryapak
|
|
||||||
|
|
||||||
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.
|
|
226
vendor/github.com/disintegration/imaging/README.md
generated
vendored
226
vendor/github.com/disintegration/imaging/README.md
generated
vendored
@ -1,226 +0,0 @@
|
|||||||
# Imaging
|
|
||||||
|
|
||||||
[![GoDoc](https://godoc.org/github.com/disintegration/imaging?status.svg)](https://godoc.org/github.com/disintegration/imaging)
|
|
||||||
[![Build Status](https://travis-ci.org/disintegration/imaging.svg?branch=master)](https://travis-ci.org/disintegration/imaging)
|
|
||||||
[![Coverage Status](https://coveralls.io/repos/github/disintegration/imaging/badge.svg?branch=master&service=github)](https://coveralls.io/github/disintegration/imaging?branch=master)
|
|
||||||
[![Go Report Card](https://goreportcard.com/badge/github.com/disintegration/imaging)](https://goreportcard.com/report/github.com/disintegration/imaging)
|
|
||||||
|
|
||||||
Package imaging provides basic image processing functions (resize, rotate, crop, brightness/contrast adjustments, etc.).
|
|
||||||
|
|
||||||
All the image processing functions provided by the package accept any image type that implements `image.Image` interface
|
|
||||||
as an input, and return a new image of `*image.NRGBA` type (32bit RGBA colors, non-premultiplied alpha).
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
go get -u github.com/disintegration/imaging
|
|
||||||
|
|
||||||
## Documentation
|
|
||||||
|
|
||||||
http://godoc.org/github.com/disintegration/imaging
|
|
||||||
|
|
||||||
## Usage examples
|
|
||||||
|
|
||||||
A few usage examples can be found below. See the documentation for the full list of supported functions.
|
|
||||||
|
|
||||||
### Image resizing
|
|
||||||
|
|
||||||
```go
|
|
||||||
// Resize srcImage to size = 128x128px using the Lanczos filter.
|
|
||||||
dstImage128 := imaging.Resize(srcImage, 128, 128, imaging.Lanczos)
|
|
||||||
|
|
||||||
// Resize srcImage to width = 800px preserving the aspect ratio.
|
|
||||||
dstImage800 := imaging.Resize(srcImage, 800, 0, imaging.Lanczos)
|
|
||||||
|
|
||||||
// Scale down srcImage to fit the 800x600px bounding box.
|
|
||||||
dstImageFit := imaging.Fit(srcImage, 800, 600, imaging.Lanczos)
|
|
||||||
|
|
||||||
// Resize and crop the srcImage to fill the 100x100px area.
|
|
||||||
dstImageFill := imaging.Fill(srcImage, 100, 100, imaging.Center, imaging.Lanczos)
|
|
||||||
```
|
|
||||||
|
|
||||||
Imaging supports image resizing using various resampling filters. The most notable ones:
|
|
||||||
- `Lanczos` - A high-quality resampling filter for photographic images yielding sharp results.
|
|
||||||
- `CatmullRom` - A sharp cubic filter that is faster than Lanczos filter while providing similar results.
|
|
||||||
- `MitchellNetravali` - A cubic filter that produces smoother results with less ringing artifacts than CatmullRom.
|
|
||||||
- `Linear` - Bilinear resampling filter, produces smooth output. Faster than cubic filters.
|
|
||||||
- `Box` - Simple and fast averaging filter appropriate for downscaling. When upscaling it's similar to NearestNeighbor.
|
|
||||||
- `NearestNeighbor` - Fastest resampling filter, no antialiasing.
|
|
||||||
|
|
||||||
The full list of supported filters: NearestNeighbor, Box, Linear, Hermite, MitchellNetravali, CatmullRom, BSpline, Gaussian, Lanczos, Hann, Hamming, Blackman, Bartlett, Welch, Cosine. Custom filters can be created using ResampleFilter struct.
|
|
||||||
|
|
||||||
**Resampling filters comparison**
|
|
||||||
|
|
||||||
Original image:
|
|
||||||
|
|
||||||
![srcImage](testdata/branches.png)
|
|
||||||
|
|
||||||
The same image resized from 600x400px to 150x100px using different resampling filters.
|
|
||||||
From faster (lower quality) to slower (higher quality):
|
|
||||||
|
|
||||||
Filter | Resize result
|
|
||||||
--------------------------|---------------------------------------------
|
|
||||||
`imaging.NearestNeighbor` | ![dstImage](testdata/out_resize_nearest.png)
|
|
||||||
`imaging.Linear` | ![dstImage](testdata/out_resize_linear.png)
|
|
||||||
`imaging.CatmullRom` | ![dstImage](testdata/out_resize_catrom.png)
|
|
||||||
`imaging.Lanczos` | ![dstImage](testdata/out_resize_lanczos.png)
|
|
||||||
|
|
||||||
|
|
||||||
### Gaussian Blur
|
|
||||||
|
|
||||||
```go
|
|
||||||
dstImage := imaging.Blur(srcImage, 0.5)
|
|
||||||
```
|
|
||||||
|
|
||||||
Sigma parameter allows to control the strength of the blurring effect.
|
|
||||||
|
|
||||||
Original image | Sigma = 0.5 | Sigma = 1.5
|
|
||||||
-----------------------------------|----------------------------------------|---------------------------------------
|
|
||||||
![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_blur_0.5.png) | ![dstImage](testdata/out_blur_1.5.png)
|
|
||||||
|
|
||||||
### Sharpening
|
|
||||||
|
|
||||||
```go
|
|
||||||
dstImage := imaging.Sharpen(srcImage, 0.5)
|
|
||||||
```
|
|
||||||
|
|
||||||
`Sharpen` uses gaussian function internally. Sigma parameter allows to control the strength of the sharpening effect.
|
|
||||||
|
|
||||||
Original image | Sigma = 0.5 | Sigma = 1.5
|
|
||||||
-----------------------------------|-------------------------------------------|------------------------------------------
|
|
||||||
![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_sharpen_0.5.png) | ![dstImage](testdata/out_sharpen_1.5.png)
|
|
||||||
|
|
||||||
### Gamma correction
|
|
||||||
|
|
||||||
```go
|
|
||||||
dstImage := imaging.AdjustGamma(srcImage, 0.75)
|
|
||||||
```
|
|
||||||
|
|
||||||
Original image | Gamma = 0.75 | Gamma = 1.25
|
|
||||||
-----------------------------------|------------------------------------------|-----------------------------------------
|
|
||||||
![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_gamma_0.75.png) | ![dstImage](testdata/out_gamma_1.25.png)
|
|
||||||
|
|
||||||
### Contrast adjustment
|
|
||||||
|
|
||||||
```go
|
|
||||||
dstImage := imaging.AdjustContrast(srcImage, 20)
|
|
||||||
```
|
|
||||||
|
|
||||||
Original image | Contrast = 15 | Contrast = -15
|
|
||||||
-----------------------------------|--------------------------------------------|-------------------------------------------
|
|
||||||
![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_contrast_p15.png) | ![dstImage](testdata/out_contrast_m15.png)
|
|
||||||
|
|
||||||
### Brightness adjustment
|
|
||||||
|
|
||||||
```go
|
|
||||||
dstImage := imaging.AdjustBrightness(srcImage, 20)
|
|
||||||
```
|
|
||||||
|
|
||||||
Original image | Brightness = 10 | Brightness = -10
|
|
||||||
-----------------------------------|----------------------------------------------|---------------------------------------------
|
|
||||||
![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_brightness_p10.png) | ![dstImage](testdata/out_brightness_m10.png)
|
|
||||||
|
|
||||||
### Saturation adjustment
|
|
||||||
|
|
||||||
```go
|
|
||||||
dstImage := imaging.AdjustSaturation(srcImage, 20)
|
|
||||||
```
|
|
||||||
|
|
||||||
Original image | Saturation = 30 | Saturation = -30
|
|
||||||
-----------------------------------|----------------------------------------------|---------------------------------------------
|
|
||||||
![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_saturation_p30.png) | ![dstImage](testdata/out_saturation_m30.png)
|
|
||||||
|
|
||||||
## FAQ
|
|
||||||
|
|
||||||
### Incorrect image orientation after processing (e.g. an image appears rotated after resizing)
|
|
||||||
|
|
||||||
Most probably, the given image contains the EXIF orientation tag.
|
|
||||||
The stadard `image/*` packages do not support loading and saving
|
|
||||||
this kind of information. To fix the issue, try opening images with
|
|
||||||
the `AutoOrientation` decode option. If this option is set to `true`,
|
|
||||||
the image orientation is changed after decoding, according to the
|
|
||||||
orientation tag (if present). Here's the example:
|
|
||||||
|
|
||||||
```go
|
|
||||||
img, err := imaging.Open("test.jpg", imaging.AutoOrientation(true))
|
|
||||||
```
|
|
||||||
|
|
||||||
### What's the difference between `imaging` and `gift` packages?
|
|
||||||
|
|
||||||
[imaging](https://github.com/disintegration/imaging)
|
|
||||||
is designed to be a lightweight and simple image manipulation package.
|
|
||||||
It provides basic image processing functions and a few helper functions
|
|
||||||
such as `Open` and `Save`. It consistently returns *image.NRGBA image
|
|
||||||
type (8 bits per channel, RGBA).
|
|
||||||
|
|
||||||
[gift](https://github.com/disintegration/gift)
|
|
||||||
supports more advanced image processing, for example, sRGB/Linear color
|
|
||||||
space conversions. It also supports different output image types
|
|
||||||
(e.g. 16 bits per channel) and provides easy-to-use API for chaining
|
|
||||||
multiple processing steps together.
|
|
||||||
|
|
||||||
## Example code
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"image"
|
|
||||||
"image/color"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/disintegration/imaging"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Open a test image.
|
|
||||||
src, err := imaging.Open("testdata/flowers.png")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("failed to open image: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Crop the original image to 300x300px size using the center anchor.
|
|
||||||
src = imaging.CropAnchor(src, 300, 300, imaging.Center)
|
|
||||||
|
|
||||||
// Resize the cropped image to width = 200px preserving the aspect ratio.
|
|
||||||
src = imaging.Resize(src, 200, 0, imaging.Lanczos)
|
|
||||||
|
|
||||||
// Create a blurred version of the image.
|
|
||||||
img1 := imaging.Blur(src, 5)
|
|
||||||
|
|
||||||
// Create a grayscale version of the image with higher contrast and sharpness.
|
|
||||||
img2 := imaging.Grayscale(src)
|
|
||||||
img2 = imaging.AdjustContrast(img2, 20)
|
|
||||||
img2 = imaging.Sharpen(img2, 2)
|
|
||||||
|
|
||||||
// Create an inverted version of the image.
|
|
||||||
img3 := imaging.Invert(src)
|
|
||||||
|
|
||||||
// Create an embossed version of the image using a convolution filter.
|
|
||||||
img4 := imaging.Convolve3x3(
|
|
||||||
src,
|
|
||||||
[9]float64{
|
|
||||||
-1, -1, 0,
|
|
||||||
-1, 1, 1,
|
|
||||||
0, 1, 1,
|
|
||||||
},
|
|
||||||
nil,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Create a new image and paste the four produced images into it.
|
|
||||||
dst := imaging.New(400, 400, color.NRGBA{0, 0, 0, 0})
|
|
||||||
dst = imaging.Paste(dst, img1, image.Pt(0, 0))
|
|
||||||
dst = imaging.Paste(dst, img2, image.Pt(0, 200))
|
|
||||||
dst = imaging.Paste(dst, img3, image.Pt(200, 0))
|
|
||||||
dst = imaging.Paste(dst, img4, image.Pt(200, 200))
|
|
||||||
|
|
||||||
// Save the resulting image as JPEG.
|
|
||||||
err = imaging.Save(dst, "testdata/out_example.jpg")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("failed to save image: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Output:
|
|
||||||
|
|
||||||
![dstImage](testdata/out_example.jpg)
|
|
253
vendor/github.com/disintegration/imaging/adjust.go
generated
vendored
253
vendor/github.com/disintegration/imaging/adjust.go
generated
vendored
@ -1,253 +0,0 @@
|
|||||||
package imaging
|
|
||||||
|
|
||||||
import (
|
|
||||||
"image"
|
|
||||||
"image/color"
|
|
||||||
"math"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Grayscale produces a grayscale version of the image.
|
|
||||||
func Grayscale(img image.Image) *image.NRGBA {
|
|
||||||
src := newScanner(img)
|
|
||||||
dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
|
|
||||||
parallel(0, src.h, func(ys <-chan int) {
|
|
||||||
for y := range ys {
|
|
||||||
i := y * dst.Stride
|
|
||||||
src.scan(0, y, src.w, y+1, dst.Pix[i:i+src.w*4])
|
|
||||||
for x := 0; x < src.w; x++ {
|
|
||||||
d := dst.Pix[i : i+3 : i+3]
|
|
||||||
r := d[0]
|
|
||||||
g := d[1]
|
|
||||||
b := d[2]
|
|
||||||
f := 0.299*float64(r) + 0.587*float64(g) + 0.114*float64(b)
|
|
||||||
y := uint8(f + 0.5)
|
|
||||||
d[0] = y
|
|
||||||
d[1] = y
|
|
||||||
d[2] = y
|
|
||||||
i += 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invert produces an inverted (negated) version of the image.
|
|
||||||
func Invert(img image.Image) *image.NRGBA {
|
|
||||||
src := newScanner(img)
|
|
||||||
dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
|
|
||||||
parallel(0, src.h, func(ys <-chan int) {
|
|
||||||
for y := range ys {
|
|
||||||
i := y * dst.Stride
|
|
||||||
src.scan(0, y, src.w, y+1, dst.Pix[i:i+src.w*4])
|
|
||||||
for x := 0; x < src.w; x++ {
|
|
||||||
d := dst.Pix[i : i+3 : i+3]
|
|
||||||
d[0] = 255 - d[0]
|
|
||||||
d[1] = 255 - d[1]
|
|
||||||
d[2] = 255 - d[2]
|
|
||||||
i += 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
// AdjustSaturation changes the saturation of the image using the percentage parameter and returns the adjusted image.
|
|
||||||
// The percentage must be in the range (-100, 100).
|
|
||||||
// The percentage = 0 gives the original image.
|
|
||||||
// The percentage = 100 gives the image with the saturation value doubled for each pixel.
|
|
||||||
// The percentage = -100 gives the image with the saturation value zeroed for each pixel (grayscale).
|
|
||||||
//
|
|
||||||
// Examples:
|
|
||||||
// dstImage = imaging.AdjustSaturation(srcImage, 25) // Increase image saturation by 25%.
|
|
||||||
// dstImage = imaging.AdjustSaturation(srcImage, -10) // Decrease image saturation by 10%.
|
|
||||||
//
|
|
||||||
func AdjustSaturation(img image.Image, percentage float64) *image.NRGBA {
|
|
||||||
percentage = math.Min(math.Max(percentage, -100), 100)
|
|
||||||
multiplier := 1 + percentage/100
|
|
||||||
|
|
||||||
return AdjustFunc(img, func(c color.NRGBA) color.NRGBA {
|
|
||||||
h, s, l := rgbToHSL(c.R, c.G, c.B)
|
|
||||||
s *= multiplier
|
|
||||||
if s > 1 {
|
|
||||||
s = 1
|
|
||||||
}
|
|
||||||
r, g, b := hslToRGB(h, s, l)
|
|
||||||
return color.NRGBA{r, g, b, c.A}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// AdjustContrast changes the contrast of the image using the percentage parameter and returns the adjusted image.
|
|
||||||
// The percentage must be in range (-100, 100). The percentage = 0 gives the original image.
|
|
||||||
// The percentage = -100 gives solid gray image.
|
|
||||||
//
|
|
||||||
// Examples:
|
|
||||||
//
|
|
||||||
// dstImage = imaging.AdjustContrast(srcImage, -10) // Decrease image contrast by 10%.
|
|
||||||
// dstImage = imaging.AdjustContrast(srcImage, 20) // Increase image contrast by 20%.
|
|
||||||
//
|
|
||||||
func AdjustContrast(img image.Image, percentage float64) *image.NRGBA {
|
|
||||||
percentage = math.Min(math.Max(percentage, -100.0), 100.0)
|
|
||||||
lut := make([]uint8, 256)
|
|
||||||
|
|
||||||
v := (100.0 + percentage) / 100.0
|
|
||||||
for i := 0; i < 256; i++ {
|
|
||||||
switch {
|
|
||||||
case 0 <= v && v <= 1:
|
|
||||||
lut[i] = clamp((0.5 + (float64(i)/255.0-0.5)*v) * 255.0)
|
|
||||||
case 1 < v && v < 2:
|
|
||||||
lut[i] = clamp((0.5 + (float64(i)/255.0-0.5)*(1/(2.0-v))) * 255.0)
|
|
||||||
default:
|
|
||||||
lut[i] = uint8(float64(i)/255.0+0.5) * 255
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return adjustLUT(img, lut)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AdjustBrightness changes the brightness of the image using the percentage parameter and returns the adjusted image.
|
|
||||||
// The percentage must be in range (-100, 100). The percentage = 0 gives the original image.
|
|
||||||
// The percentage = -100 gives solid black image. The percentage = 100 gives solid white image.
|
|
||||||
//
|
|
||||||
// Examples:
|
|
||||||
//
|
|
||||||
// dstImage = imaging.AdjustBrightness(srcImage, -15) // Decrease image brightness by 15%.
|
|
||||||
// dstImage = imaging.AdjustBrightness(srcImage, 10) // Increase image brightness by 10%.
|
|
||||||
//
|
|
||||||
func AdjustBrightness(img image.Image, percentage float64) *image.NRGBA {
|
|
||||||
percentage = math.Min(math.Max(percentage, -100.0), 100.0)
|
|
||||||
lut := make([]uint8, 256)
|
|
||||||
|
|
||||||
shift := 255.0 * percentage / 100.0
|
|
||||||
for i := 0; i < 256; i++ {
|
|
||||||
lut[i] = clamp(float64(i) + shift)
|
|
||||||
}
|
|
||||||
|
|
||||||
return adjustLUT(img, lut)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AdjustGamma performs a gamma correction on the image and returns the adjusted image.
|
|
||||||
// Gamma parameter must be positive. Gamma = 1.0 gives the original image.
|
|
||||||
// Gamma less than 1.0 darkens the image and gamma greater than 1.0 lightens it.
|
|
||||||
//
|
|
||||||
// Example:
|
|
||||||
//
|
|
||||||
// dstImage = imaging.AdjustGamma(srcImage, 0.7)
|
|
||||||
//
|
|
||||||
func AdjustGamma(img image.Image, gamma float64) *image.NRGBA {
|
|
||||||
e := 1.0 / math.Max(gamma, 0.0001)
|
|
||||||
lut := make([]uint8, 256)
|
|
||||||
|
|
||||||
for i := 0; i < 256; i++ {
|
|
||||||
lut[i] = clamp(math.Pow(float64(i)/255.0, e) * 255.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
return adjustLUT(img, lut)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AdjustSigmoid changes the contrast of the image using a sigmoidal function and returns the adjusted image.
|
|
||||||
// It's a non-linear contrast change useful for photo adjustments as it preserves highlight and shadow detail.
|
|
||||||
// The midpoint parameter is the midpoint of contrast that must be between 0 and 1, typically 0.5.
|
|
||||||
// The factor parameter indicates how much to increase or decrease the contrast, typically in range (-10, 10).
|
|
||||||
// If the factor parameter is positive the image contrast is increased otherwise the contrast is decreased.
|
|
||||||
//
|
|
||||||
// Examples:
|
|
||||||
//
|
|
||||||
// dstImage = imaging.AdjustSigmoid(srcImage, 0.5, 3.0) // Increase the contrast.
|
|
||||||
// dstImage = imaging.AdjustSigmoid(srcImage, 0.5, -3.0) // Decrease the contrast.
|
|
||||||
//
|
|
||||||
func AdjustSigmoid(img image.Image, midpoint, factor float64) *image.NRGBA {
|
|
||||||
if factor == 0 {
|
|
||||||
return Clone(img)
|
|
||||||
}
|
|
||||||
|
|
||||||
lut := make([]uint8, 256)
|
|
||||||
a := math.Min(math.Max(midpoint, 0.0), 1.0)
|
|
||||||
b := math.Abs(factor)
|
|
||||||
sig0 := sigmoid(a, b, 0)
|
|
||||||
sig1 := sigmoid(a, b, 1)
|
|
||||||
e := 1.0e-6
|
|
||||||
|
|
||||||
if factor > 0 {
|
|
||||||
for i := 0; i < 256; i++ {
|
|
||||||
x := float64(i) / 255.0
|
|
||||||
sigX := sigmoid(a, b, x)
|
|
||||||
f := (sigX - sig0) / (sig1 - sig0)
|
|
||||||
lut[i] = clamp(f * 255.0)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for i := 0; i < 256; i++ {
|
|
||||||
x := float64(i) / 255.0
|
|
||||||
arg := math.Min(math.Max((sig1-sig0)*x+sig0, e), 1.0-e)
|
|
||||||
f := a - math.Log(1.0/arg-1.0)/b
|
|
||||||
lut[i] = clamp(f * 255.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return adjustLUT(img, lut)
|
|
||||||
}
|
|
||||||
|
|
||||||
func sigmoid(a, b, x float64) float64 {
|
|
||||||
return 1 / (1 + math.Exp(b*(a-x)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// adjustLUT applies the given lookup table to the colors of the image.
|
|
||||||
func adjustLUT(img image.Image, lut []uint8) *image.NRGBA {
|
|
||||||
src := newScanner(img)
|
|
||||||
dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
|
|
||||||
lut = lut[0:256]
|
|
||||||
parallel(0, src.h, func(ys <-chan int) {
|
|
||||||
for y := range ys {
|
|
||||||
i := y * dst.Stride
|
|
||||||
src.scan(0, y, src.w, y+1, dst.Pix[i:i+src.w*4])
|
|
||||||
for x := 0; x < src.w; x++ {
|
|
||||||
d := dst.Pix[i : i+3 : i+3]
|
|
||||||
d[0] = lut[d[0]]
|
|
||||||
d[1] = lut[d[1]]
|
|
||||||
d[2] = lut[d[2]]
|
|
||||||
i += 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
// AdjustFunc applies the fn function to each pixel of the img image and returns the adjusted image.
|
|
||||||
//
|
|
||||||
// Example:
|
|
||||||
//
|
|
||||||
// dstImage = imaging.AdjustFunc(
|
|
||||||
// srcImage,
|
|
||||||
// func(c color.NRGBA) color.NRGBA {
|
|
||||||
// // Shift the red channel by 16.
|
|
||||||
// r := int(c.R) + 16
|
|
||||||
// if r > 255 {
|
|
||||||
// r = 255
|
|
||||||
// }
|
|
||||||
// return color.NRGBA{uint8(r), c.G, c.B, c.A}
|
|
||||||
// }
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
func AdjustFunc(img image.Image, fn func(c color.NRGBA) color.NRGBA) *image.NRGBA {
|
|
||||||
src := newScanner(img)
|
|
||||||
dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
|
|
||||||
parallel(0, src.h, func(ys <-chan int) {
|
|
||||||
for y := range ys {
|
|
||||||
i := y * dst.Stride
|
|
||||||
src.scan(0, y, src.w, y+1, dst.Pix[i:i+src.w*4])
|
|
||||||
for x := 0; x < src.w; x++ {
|
|
||||||
d := dst.Pix[i : i+4 : i+4]
|
|
||||||
r := d[0]
|
|
||||||
g := d[1]
|
|
||||||
b := d[2]
|
|
||||||
a := d[3]
|
|
||||||
c := fn(color.NRGBA{r, g, b, a})
|
|
||||||
d[0] = c.R
|
|
||||||
d[1] = c.G
|
|
||||||
d[2] = c.B
|
|
||||||
d[3] = c.A
|
|
||||||
i += 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return dst
|
|
||||||
}
|
|
148
vendor/github.com/disintegration/imaging/convolution.go
generated
vendored
148
vendor/github.com/disintegration/imaging/convolution.go
generated
vendored
@ -1,148 +0,0 @@
|
|||||||
package imaging
|
|
||||||
|
|
||||||
import (
|
|
||||||
"image"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ConvolveOptions are convolution parameters.
|
|
||||||
type ConvolveOptions struct {
|
|
||||||
// If Normalize is true the kernel is normalized before convolution.
|
|
||||||
Normalize bool
|
|
||||||
|
|
||||||
// If Abs is true the absolute value of each color channel is taken after convolution.
|
|
||||||
Abs bool
|
|
||||||
|
|
||||||
// Bias is added to each color channel value after convolution.
|
|
||||||
Bias int
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convolve3x3 convolves the image with the specified 3x3 convolution kernel.
|
|
||||||
// Default parameters are used if a nil *ConvolveOptions is passed.
|
|
||||||
func Convolve3x3(img image.Image, kernel [9]float64, options *ConvolveOptions) *image.NRGBA {
|
|
||||||
return convolve(img, kernel[:], options)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convolve5x5 convolves the image with the specified 5x5 convolution kernel.
|
|
||||||
// Default parameters are used if a nil *ConvolveOptions is passed.
|
|
||||||
func Convolve5x5(img image.Image, kernel [25]float64, options *ConvolveOptions) *image.NRGBA {
|
|
||||||
return convolve(img, kernel[:], options)
|
|
||||||
}
|
|
||||||
|
|
||||||
func convolve(img image.Image, kernel []float64, options *ConvolveOptions) *image.NRGBA {
|
|
||||||
src := toNRGBA(img)
|
|
||||||
w := src.Bounds().Max.X
|
|
||||||
h := src.Bounds().Max.Y
|
|
||||||
dst := image.NewNRGBA(image.Rect(0, 0, w, h))
|
|
||||||
|
|
||||||
if w < 1 || h < 1 {
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
if options == nil {
|
|
||||||
options = &ConvolveOptions{}
|
|
||||||
}
|
|
||||||
|
|
||||||
if options.Normalize {
|
|
||||||
normalizeKernel(kernel)
|
|
||||||
}
|
|
||||||
|
|
||||||
type coef struct {
|
|
||||||
x, y int
|
|
||||||
k float64
|
|
||||||
}
|
|
||||||
var coefs []coef
|
|
||||||
var m int
|
|
||||||
|
|
||||||
switch len(kernel) {
|
|
||||||
case 9:
|
|
||||||
m = 1
|
|
||||||
case 25:
|
|
||||||
m = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
i := 0
|
|
||||||
for y := -m; y <= m; y++ {
|
|
||||||
for x := -m; x <= m; x++ {
|
|
||||||
if kernel[i] != 0 {
|
|
||||||
coefs = append(coefs, coef{x: x, y: y, k: kernel[i]})
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
parallel(0, h, func(ys <-chan int) {
|
|
||||||
for y := range ys {
|
|
||||||
for x := 0; x < w; x++ {
|
|
||||||
var r, g, b float64
|
|
||||||
for _, c := range coefs {
|
|
||||||
ix := x + c.x
|
|
||||||
if ix < 0 {
|
|
||||||
ix = 0
|
|
||||||
} else if ix >= w {
|
|
||||||
ix = w - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
iy := y + c.y
|
|
||||||
if iy < 0 {
|
|
||||||
iy = 0
|
|
||||||
} else if iy >= h {
|
|
||||||
iy = h - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
off := iy*src.Stride + ix*4
|
|
||||||
s := src.Pix[off : off+3 : off+3]
|
|
||||||
r += float64(s[0]) * c.k
|
|
||||||
g += float64(s[1]) * c.k
|
|
||||||
b += float64(s[2]) * c.k
|
|
||||||
}
|
|
||||||
|
|
||||||
if options.Abs {
|
|
||||||
if r < 0 {
|
|
||||||
r = -r
|
|
||||||
}
|
|
||||||
if g < 0 {
|
|
||||||
g = -g
|
|
||||||
}
|
|
||||||
if b < 0 {
|
|
||||||
b = -b
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if options.Bias != 0 {
|
|
||||||
r += float64(options.Bias)
|
|
||||||
g += float64(options.Bias)
|
|
||||||
b += float64(options.Bias)
|
|
||||||
}
|
|
||||||
|
|
||||||
srcOff := y*src.Stride + x*4
|
|
||||||
dstOff := y*dst.Stride + x*4
|
|
||||||
d := dst.Pix[dstOff : dstOff+4 : dstOff+4]
|
|
||||||
d[0] = clamp(r)
|
|
||||||
d[1] = clamp(g)
|
|
||||||
d[2] = clamp(b)
|
|
||||||
d[3] = src.Pix[srcOff+3]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
func normalizeKernel(kernel []float64) {
|
|
||||||
var sum, sumpos float64
|
|
||||||
for i := range kernel {
|
|
||||||
sum += kernel[i]
|
|
||||||
if kernel[i] > 0 {
|
|
||||||
sumpos += kernel[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if sum != 0 {
|
|
||||||
for i := range kernel {
|
|
||||||
kernel[i] /= sum
|
|
||||||
}
|
|
||||||
} else if sumpos != 0 {
|
|
||||||
for i := range kernel {
|
|
||||||
kernel[i] /= sumpos
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
7
vendor/github.com/disintegration/imaging/doc.go
generated
vendored
7
vendor/github.com/disintegration/imaging/doc.go
generated
vendored
@ -1,7 +0,0 @@
|
|||||||
/*
|
|
||||||
Package imaging provides basic image processing functions (resize, rotate, crop, brightness/contrast adjustments, etc.).
|
|
||||||
|
|
||||||
All the image processing functions provided by the package accept any image type that implements image.Image interface
|
|
||||||
as an input, and return a new image of *image.NRGBA type (32bit RGBA colors, non-premultiplied alpha).
|
|
||||||
*/
|
|
||||||
package imaging
|
|
169
vendor/github.com/disintegration/imaging/effects.go
generated
vendored
169
vendor/github.com/disintegration/imaging/effects.go
generated
vendored
@ -1,169 +0,0 @@
|
|||||||
package imaging
|
|
||||||
|
|
||||||
import (
|
|
||||||
"image"
|
|
||||||
"math"
|
|
||||||
)
|
|
||||||
|
|
||||||
func gaussianBlurKernel(x, sigma float64) float64 {
|
|
||||||
return math.Exp(-(x*x)/(2*sigma*sigma)) / (sigma * math.Sqrt(2*math.Pi))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Blur produces a blurred version of the image using a Gaussian function.
|
|
||||||
// Sigma parameter must be positive and indicates how much the image will be blurred.
|
|
||||||
//
|
|
||||||
// Example:
|
|
||||||
//
|
|
||||||
// dstImage := imaging.Blur(srcImage, 3.5)
|
|
||||||
//
|
|
||||||
func Blur(img image.Image, sigma float64) *image.NRGBA {
|
|
||||||
if sigma <= 0 {
|
|
||||||
return Clone(img)
|
|
||||||
}
|
|
||||||
|
|
||||||
radius := int(math.Ceil(sigma * 3.0))
|
|
||||||
kernel := make([]float64, radius+1)
|
|
||||||
|
|
||||||
for i := 0; i <= radius; i++ {
|
|
||||||
kernel[i] = gaussianBlurKernel(float64(i), sigma)
|
|
||||||
}
|
|
||||||
|
|
||||||
return blurVertical(blurHorizontal(img, kernel), kernel)
|
|
||||||
}
|
|
||||||
|
|
||||||
func blurHorizontal(img image.Image, kernel []float64) *image.NRGBA {
|
|
||||||
src := newScanner(img)
|
|
||||||
dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
|
|
||||||
radius := len(kernel) - 1
|
|
||||||
|
|
||||||
parallel(0, src.h, func(ys <-chan int) {
|
|
||||||
scanLine := make([]uint8, src.w*4)
|
|
||||||
scanLineF := make([]float64, len(scanLine))
|
|
||||||
for y := range ys {
|
|
||||||
src.scan(0, y, src.w, y+1, scanLine)
|
|
||||||
for i, v := range scanLine {
|
|
||||||
scanLineF[i] = float64(v)
|
|
||||||
}
|
|
||||||
for x := 0; x < src.w; x++ {
|
|
||||||
min := x - radius
|
|
||||||
if min < 0 {
|
|
||||||
min = 0
|
|
||||||
}
|
|
||||||
max := x + radius
|
|
||||||
if max > src.w-1 {
|
|
||||||
max = src.w - 1
|
|
||||||
}
|
|
||||||
var r, g, b, a, wsum float64
|
|
||||||
for ix := min; ix <= max; ix++ {
|
|
||||||
i := ix * 4
|
|
||||||
weight := kernel[absint(x-ix)]
|
|
||||||
wsum += weight
|
|
||||||
s := scanLineF[i : i+4 : i+4]
|
|
||||||
wa := s[3] * weight
|
|
||||||
r += s[0] * wa
|
|
||||||
g += s[1] * wa
|
|
||||||
b += s[2] * wa
|
|
||||||
a += wa
|
|
||||||
}
|
|
||||||
if a != 0 {
|
|
||||||
aInv := 1 / a
|
|
||||||
j := y*dst.Stride + x*4
|
|
||||||
d := dst.Pix[j : j+4 : j+4]
|
|
||||||
d[0] = clamp(r * aInv)
|
|
||||||
d[1] = clamp(g * aInv)
|
|
||||||
d[2] = clamp(b * aInv)
|
|
||||||
d[3] = clamp(a / wsum)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
func blurVertical(img image.Image, kernel []float64) *image.NRGBA {
|
|
||||||
src := newScanner(img)
|
|
||||||
dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
|
|
||||||
radius := len(kernel) - 1
|
|
||||||
|
|
||||||
parallel(0, src.w, func(xs <-chan int) {
|
|
||||||
scanLine := make([]uint8, src.h*4)
|
|
||||||
scanLineF := make([]float64, len(scanLine))
|
|
||||||
for x := range xs {
|
|
||||||
src.scan(x, 0, x+1, src.h, scanLine)
|
|
||||||
for i, v := range scanLine {
|
|
||||||
scanLineF[i] = float64(v)
|
|
||||||
}
|
|
||||||
for y := 0; y < src.h; y++ {
|
|
||||||
min := y - radius
|
|
||||||
if min < 0 {
|
|
||||||
min = 0
|
|
||||||
}
|
|
||||||
max := y + radius
|
|
||||||
if max > src.h-1 {
|
|
||||||
max = src.h - 1
|
|
||||||
}
|
|
||||||
var r, g, b, a, wsum float64
|
|
||||||
for iy := min; iy <= max; iy++ {
|
|
||||||
i := iy * 4
|
|
||||||
weight := kernel[absint(y-iy)]
|
|
||||||
wsum += weight
|
|
||||||
s := scanLineF[i : i+4 : i+4]
|
|
||||||
wa := s[3] * weight
|
|
||||||
r += s[0] * wa
|
|
||||||
g += s[1] * wa
|
|
||||||
b += s[2] * wa
|
|
||||||
a += wa
|
|
||||||
}
|
|
||||||
if a != 0 {
|
|
||||||
aInv := 1 / a
|
|
||||||
j := y*dst.Stride + x*4
|
|
||||||
d := dst.Pix[j : j+4 : j+4]
|
|
||||||
d[0] = clamp(r * aInv)
|
|
||||||
d[1] = clamp(g * aInv)
|
|
||||||
d[2] = clamp(b * aInv)
|
|
||||||
d[3] = clamp(a / wsum)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sharpen produces a sharpened version of the image.
|
|
||||||
// Sigma parameter must be positive and indicates how much the image will be sharpened.
|
|
||||||
//
|
|
||||||
// Example:
|
|
||||||
//
|
|
||||||
// dstImage := imaging.Sharpen(srcImage, 3.5)
|
|
||||||
//
|
|
||||||
func Sharpen(img image.Image, sigma float64) *image.NRGBA {
|
|
||||||
if sigma <= 0 {
|
|
||||||
return Clone(img)
|
|
||||||
}
|
|
||||||
|
|
||||||
src := newScanner(img)
|
|
||||||
dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
|
|
||||||
blurred := Blur(img, sigma)
|
|
||||||
|
|
||||||
parallel(0, src.h, func(ys <-chan int) {
|
|
||||||
scanLine := make([]uint8, src.w*4)
|
|
||||||
for y := range ys {
|
|
||||||
src.scan(0, y, src.w, y+1, scanLine)
|
|
||||||
j := y * dst.Stride
|
|
||||||
for i := 0; i < src.w*4; i++ {
|
|
||||||
val := int(scanLine[i])<<1 - int(blurred.Pix[j])
|
|
||||||
if val < 0 {
|
|
||||||
val = 0
|
|
||||||
} else if val > 0xff {
|
|
||||||
val = 0xff
|
|
||||||
}
|
|
||||||
dst.Pix[j] = uint8(val)
|
|
||||||
j++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return dst
|
|
||||||
}
|
|
3
vendor/github.com/disintegration/imaging/go.mod
generated
vendored
3
vendor/github.com/disintegration/imaging/go.mod
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
module github.com/disintegration/imaging
|
|
||||||
|
|
||||||
require golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8
|
|
3
vendor/github.com/disintegration/imaging/go.sum
generated
vendored
3
vendor/github.com/disintegration/imaging/go.sum
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U=
|
|
||||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
52
vendor/github.com/disintegration/imaging/histogram.go
generated
vendored
52
vendor/github.com/disintegration/imaging/histogram.go
generated
vendored
@ -1,52 +0,0 @@
|
|||||||
package imaging
|
|
||||||
|
|
||||||
import (
|
|
||||||
"image"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Histogram returns a normalized histogram of an image.
|
|
||||||
//
|
|
||||||
// Resulting histogram is represented as an array of 256 floats, where
|
|
||||||
// histogram[i] is a probability of a pixel being of a particular luminance i.
|
|
||||||
func Histogram(img image.Image) [256]float64 {
|
|
||||||
var mu sync.Mutex
|
|
||||||
var histogram [256]float64
|
|
||||||
var total float64
|
|
||||||
|
|
||||||
src := newScanner(img)
|
|
||||||
if src.w == 0 || src.h == 0 {
|
|
||||||
return histogram
|
|
||||||
}
|
|
||||||
|
|
||||||
parallel(0, src.h, func(ys <-chan int) {
|
|
||||||
var tmpHistogram [256]float64
|
|
||||||
var tmpTotal float64
|
|
||||||
scanLine := make([]uint8, src.w*4)
|
|
||||||
for y := range ys {
|
|
||||||
src.scan(0, y, src.w, y+1, scanLine)
|
|
||||||
i := 0
|
|
||||||
for x := 0; x < src.w; x++ {
|
|
||||||
s := scanLine[i : i+3 : i+3]
|
|
||||||
r := s[0]
|
|
||||||
g := s[1]
|
|
||||||
b := s[2]
|
|
||||||
y := 0.299*float32(r) + 0.587*float32(g) + 0.114*float32(b)
|
|
||||||
tmpHistogram[int(y+0.5)]++
|
|
||||||
tmpTotal++
|
|
||||||
i += 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mu.Lock()
|
|
||||||
for i := 0; i < 256; i++ {
|
|
||||||
histogram[i] += tmpHistogram[i]
|
|
||||||
}
|
|
||||||
total += tmpTotal
|
|
||||||
mu.Unlock()
|
|
||||||
})
|
|
||||||
|
|
||||||
for i := 0; i < 256; i++ {
|
|
||||||
histogram[i] = histogram[i] / total
|
|
||||||
}
|
|
||||||
return histogram
|
|
||||||
}
|
|
444
vendor/github.com/disintegration/imaging/io.go
generated
vendored
444
vendor/github.com/disintegration/imaging/io.go
generated
vendored
@ -1,444 +0,0 @@
|
|||||||
package imaging
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"errors"
|
|
||||||
"image"
|
|
||||||
"image/draw"
|
|
||||||
"image/gif"
|
|
||||||
"image/jpeg"
|
|
||||||
"image/png"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"golang.org/x/image/bmp"
|
|
||||||
"golang.org/x/image/tiff"
|
|
||||||
)
|
|
||||||
|
|
||||||
type fileSystem interface {
|
|
||||||
Create(string) (io.WriteCloser, error)
|
|
||||||
Open(string) (io.ReadCloser, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type localFS struct{}
|
|
||||||
|
|
||||||
func (localFS) Create(name string) (io.WriteCloser, error) { return os.Create(name) }
|
|
||||||
func (localFS) Open(name string) (io.ReadCloser, error) { return os.Open(name) }
|
|
||||||
|
|
||||||
var fs fileSystem = localFS{}
|
|
||||||
|
|
||||||
type decodeConfig struct {
|
|
||||||
autoOrientation bool
|
|
||||||
}
|
|
||||||
|
|
||||||
var defaultDecodeConfig = decodeConfig{
|
|
||||||
autoOrientation: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeOption sets an optional parameter for the Decode and Open functions.
|
|
||||||
type DecodeOption func(*decodeConfig)
|
|
||||||
|
|
||||||
// AutoOrientation returns a DecodeOption that sets the auto-orientation mode.
|
|
||||||
// If auto-orientation is enabled, the image will be transformed after decoding
|
|
||||||
// according to the EXIF orientation tag (if present). By default it's disabled.
|
|
||||||
func AutoOrientation(enabled bool) DecodeOption {
|
|
||||||
return func(c *decodeConfig) {
|
|
||||||
c.autoOrientation = enabled
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode reads an image from r.
|
|
||||||
func Decode(r io.Reader, opts ...DecodeOption) (image.Image, error) {
|
|
||||||
cfg := defaultDecodeConfig
|
|
||||||
for _, option := range opts {
|
|
||||||
option(&cfg)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !cfg.autoOrientation {
|
|
||||||
img, _, err := image.Decode(r)
|
|
||||||
return img, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var orient orientation
|
|
||||||
pr, pw := io.Pipe()
|
|
||||||
r = io.TeeReader(r, pw)
|
|
||||||
done := make(chan struct{})
|
|
||||||
go func() {
|
|
||||||
defer close(done)
|
|
||||||
orient = readOrientation(pr)
|
|
||||||
io.Copy(ioutil.Discard, pr)
|
|
||||||
}()
|
|
||||||
|
|
||||||
img, _, err := image.Decode(r)
|
|
||||||
pw.Close()
|
|
||||||
<-done
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return fixOrientation(img, orient), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open loads an image from file.
|
|
||||||
//
|
|
||||||
// Examples:
|
|
||||||
//
|
|
||||||
// // Load an image from file.
|
|
||||||
// img, err := imaging.Open("test.jpg")
|
|
||||||
//
|
|
||||||
// // Load an image and transform it depending on the EXIF orientation tag (if present).
|
|
||||||
// img, err := imaging.Open("test.jpg", imaging.AutoOrientation(true))
|
|
||||||
//
|
|
||||||
func Open(filename string, opts ...DecodeOption) (image.Image, error) {
|
|
||||||
file, err := fs.Open(filename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
return Decode(file, opts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format is an image file format.
|
|
||||||
type Format int
|
|
||||||
|
|
||||||
// Image file formats.
|
|
||||||
const (
|
|
||||||
JPEG Format = iota
|
|
||||||
PNG
|
|
||||||
GIF
|
|
||||||
TIFF
|
|
||||||
BMP
|
|
||||||
)
|
|
||||||
|
|
||||||
var formatExts = map[string]Format{
|
|
||||||
"jpg": JPEG,
|
|
||||||
"jpeg": JPEG,
|
|
||||||
"png": PNG,
|
|
||||||
"gif": GIF,
|
|
||||||
"tif": TIFF,
|
|
||||||
"tiff": TIFF,
|
|
||||||
"bmp": BMP,
|
|
||||||
}
|
|
||||||
|
|
||||||
var formatNames = map[Format]string{
|
|
||||||
JPEG: "JPEG",
|
|
||||||
PNG: "PNG",
|
|
||||||
GIF: "GIF",
|
|
||||||
TIFF: "TIFF",
|
|
||||||
BMP: "BMP",
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f Format) String() string {
|
|
||||||
return formatNames[f]
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrUnsupportedFormat means the given image format is not supported.
|
|
||||||
var ErrUnsupportedFormat = errors.New("imaging: unsupported image format")
|
|
||||||
|
|
||||||
// FormatFromExtension parses image format from filename extension:
|
|
||||||
// "jpg" (or "jpeg"), "png", "gif", "tif" (or "tiff") and "bmp" are supported.
|
|
||||||
func FormatFromExtension(ext string) (Format, error) {
|
|
||||||
if f, ok := formatExts[strings.ToLower(strings.TrimPrefix(ext, "."))]; ok {
|
|
||||||
return f, nil
|
|
||||||
}
|
|
||||||
return -1, ErrUnsupportedFormat
|
|
||||||
}
|
|
||||||
|
|
||||||
// FormatFromFilename parses image format from filename:
|
|
||||||
// "jpg" (or "jpeg"), "png", "gif", "tif" (or "tiff") and "bmp" are supported.
|
|
||||||
func FormatFromFilename(filename string) (Format, error) {
|
|
||||||
ext := filepath.Ext(filename)
|
|
||||||
return FormatFromExtension(ext)
|
|
||||||
}
|
|
||||||
|
|
||||||
type encodeConfig struct {
|
|
||||||
jpegQuality int
|
|
||||||
gifNumColors int
|
|
||||||
gifQuantizer draw.Quantizer
|
|
||||||
gifDrawer draw.Drawer
|
|
||||||
pngCompressionLevel png.CompressionLevel
|
|
||||||
}
|
|
||||||
|
|
||||||
var defaultEncodeConfig = encodeConfig{
|
|
||||||
jpegQuality: 95,
|
|
||||||
gifNumColors: 256,
|
|
||||||
gifQuantizer: nil,
|
|
||||||
gifDrawer: nil,
|
|
||||||
pngCompressionLevel: png.DefaultCompression,
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeOption sets an optional parameter for the Encode and Save functions.
|
|
||||||
type EncodeOption func(*encodeConfig)
|
|
||||||
|
|
||||||
// JPEGQuality returns an EncodeOption that sets the output JPEG quality.
|
|
||||||
// Quality ranges from 1 to 100 inclusive, higher is better. Default is 95.
|
|
||||||
func JPEGQuality(quality int) EncodeOption {
|
|
||||||
return func(c *encodeConfig) {
|
|
||||||
c.jpegQuality = quality
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GIFNumColors returns an EncodeOption that sets the maximum number of colors
|
|
||||||
// used in the GIF-encoded image. It ranges from 1 to 256. Default is 256.
|
|
||||||
func GIFNumColors(numColors int) EncodeOption {
|
|
||||||
return func(c *encodeConfig) {
|
|
||||||
c.gifNumColors = numColors
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GIFQuantizer returns an EncodeOption that sets the quantizer that is used to produce
|
|
||||||
// a palette of the GIF-encoded image.
|
|
||||||
func GIFQuantizer(quantizer draw.Quantizer) EncodeOption {
|
|
||||||
return func(c *encodeConfig) {
|
|
||||||
c.gifQuantizer = quantizer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GIFDrawer returns an EncodeOption that sets the drawer that is used to convert
|
|
||||||
// the source image to the desired palette of the GIF-encoded image.
|
|
||||||
func GIFDrawer(drawer draw.Drawer) EncodeOption {
|
|
||||||
return func(c *encodeConfig) {
|
|
||||||
c.gifDrawer = drawer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PNGCompressionLevel returns an EncodeOption that sets the compression level
|
|
||||||
// of the PNG-encoded image. Default is png.DefaultCompression.
|
|
||||||
func PNGCompressionLevel(level png.CompressionLevel) EncodeOption {
|
|
||||||
return func(c *encodeConfig) {
|
|
||||||
c.pngCompressionLevel = level
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode writes the image img to w in the specified format (JPEG, PNG, GIF, TIFF or BMP).
|
|
||||||
func Encode(w io.Writer, img image.Image, format Format, opts ...EncodeOption) error {
|
|
||||||
cfg := defaultEncodeConfig
|
|
||||||
for _, option := range opts {
|
|
||||||
option(&cfg)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch format {
|
|
||||||
case JPEG:
|
|
||||||
if nrgba, ok := img.(*image.NRGBA); ok && nrgba.Opaque() {
|
|
||||||
rgba := &image.RGBA{
|
|
||||||
Pix: nrgba.Pix,
|
|
||||||
Stride: nrgba.Stride,
|
|
||||||
Rect: nrgba.Rect,
|
|
||||||
}
|
|
||||||
return jpeg.Encode(w, rgba, &jpeg.Options{Quality: cfg.jpegQuality})
|
|
||||||
}
|
|
||||||
return jpeg.Encode(w, img, &jpeg.Options{Quality: cfg.jpegQuality})
|
|
||||||
|
|
||||||
case PNG:
|
|
||||||
encoder := png.Encoder{CompressionLevel: cfg.pngCompressionLevel}
|
|
||||||
return encoder.Encode(w, img)
|
|
||||||
|
|
||||||
case GIF:
|
|
||||||
return gif.Encode(w, img, &gif.Options{
|
|
||||||
NumColors: cfg.gifNumColors,
|
|
||||||
Quantizer: cfg.gifQuantizer,
|
|
||||||
Drawer: cfg.gifDrawer,
|
|
||||||
})
|
|
||||||
|
|
||||||
case TIFF:
|
|
||||||
return tiff.Encode(w, img, &tiff.Options{Compression: tiff.Deflate, Predictor: true})
|
|
||||||
|
|
||||||
case BMP:
|
|
||||||
return bmp.Encode(w, img)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ErrUnsupportedFormat
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save saves the image to file with the specified filename.
|
|
||||||
// The format is determined from the filename extension:
|
|
||||||
// "jpg" (or "jpeg"), "png", "gif", "tif" (or "tiff") and "bmp" are supported.
|
|
||||||
//
|
|
||||||
// Examples:
|
|
||||||
//
|
|
||||||
// // Save the image as PNG.
|
|
||||||
// err := imaging.Save(img, "out.png")
|
|
||||||
//
|
|
||||||
// // Save the image as JPEG with optional quality parameter set to 80.
|
|
||||||
// err := imaging.Save(img, "out.jpg", imaging.JPEGQuality(80))
|
|
||||||
//
|
|
||||||
func Save(img image.Image, filename string, opts ...EncodeOption) (err error) {
|
|
||||||
f, err := FormatFromFilename(filename)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
file, err := fs.Create(filename)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = Encode(file, img, f, opts...)
|
|
||||||
errc := file.Close()
|
|
||||||
if err == nil {
|
|
||||||
err = errc
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// orientation is an EXIF flag that specifies the transformation
|
|
||||||
// that should be applied to image to display it correctly.
|
|
||||||
type orientation int
|
|
||||||
|
|
||||||
const (
|
|
||||||
orientationUnspecified = 0
|
|
||||||
orientationNormal = 1
|
|
||||||
orientationFlipH = 2
|
|
||||||
orientationRotate180 = 3
|
|
||||||
orientationFlipV = 4
|
|
||||||
orientationTranspose = 5
|
|
||||||
orientationRotate270 = 6
|
|
||||||
orientationTransverse = 7
|
|
||||||
orientationRotate90 = 8
|
|
||||||
)
|
|
||||||
|
|
||||||
// readOrientation tries to read the orientation EXIF flag from image data in r.
|
|
||||||
// If the EXIF data block is not found or the orientation flag is not found
|
|
||||||
// or any other error occures while reading the data, it returns the
|
|
||||||
// orientationUnspecified (0) value.
|
|
||||||
func readOrientation(r io.Reader) orientation {
|
|
||||||
const (
|
|
||||||
markerSOI = 0xffd8
|
|
||||||
markerAPP1 = 0xffe1
|
|
||||||
exifHeader = 0x45786966
|
|
||||||
byteOrderBE = 0x4d4d
|
|
||||||
byteOrderLE = 0x4949
|
|
||||||
orientationTag = 0x0112
|
|
||||||
)
|
|
||||||
|
|
||||||
// Check if JPEG SOI marker is present.
|
|
||||||
var soi uint16
|
|
||||||
if err := binary.Read(r, binary.BigEndian, &soi); err != nil {
|
|
||||||
return orientationUnspecified
|
|
||||||
}
|
|
||||||
if soi != markerSOI {
|
|
||||||
return orientationUnspecified // Missing JPEG SOI marker.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find JPEG APP1 marker.
|
|
||||||
for {
|
|
||||||
var marker, size uint16
|
|
||||||
if err := binary.Read(r, binary.BigEndian, &marker); err != nil {
|
|
||||||
return orientationUnspecified
|
|
||||||
}
|
|
||||||
if err := binary.Read(r, binary.BigEndian, &size); err != nil {
|
|
||||||
return orientationUnspecified
|
|
||||||
}
|
|
||||||
if marker>>8 != 0xff {
|
|
||||||
return orientationUnspecified // Invalid JPEG marker.
|
|
||||||
}
|
|
||||||
if marker == markerAPP1 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if size < 2 {
|
|
||||||
return orientationUnspecified // Invalid block size.
|
|
||||||
}
|
|
||||||
if _, err := io.CopyN(ioutil.Discard, r, int64(size-2)); err != nil {
|
|
||||||
return orientationUnspecified
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if EXIF header is present.
|
|
||||||
var header uint32
|
|
||||||
if err := binary.Read(r, binary.BigEndian, &header); err != nil {
|
|
||||||
return orientationUnspecified
|
|
||||||
}
|
|
||||||
if header != exifHeader {
|
|
||||||
return orientationUnspecified
|
|
||||||
}
|
|
||||||
if _, err := io.CopyN(ioutil.Discard, r, 2); err != nil {
|
|
||||||
return orientationUnspecified
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read byte order information.
|
|
||||||
var (
|
|
||||||
byteOrderTag uint16
|
|
||||||
byteOrder binary.ByteOrder
|
|
||||||
)
|
|
||||||
if err := binary.Read(r, binary.BigEndian, &byteOrderTag); err != nil {
|
|
||||||
return orientationUnspecified
|
|
||||||
}
|
|
||||||
switch byteOrderTag {
|
|
||||||
case byteOrderBE:
|
|
||||||
byteOrder = binary.BigEndian
|
|
||||||
case byteOrderLE:
|
|
||||||
byteOrder = binary.LittleEndian
|
|
||||||
default:
|
|
||||||
return orientationUnspecified // Invalid byte order flag.
|
|
||||||
}
|
|
||||||
if _, err := io.CopyN(ioutil.Discard, r, 2); err != nil {
|
|
||||||
return orientationUnspecified
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip the EXIF offset.
|
|
||||||
var offset uint32
|
|
||||||
if err := binary.Read(r, byteOrder, &offset); err != nil {
|
|
||||||
return orientationUnspecified
|
|
||||||
}
|
|
||||||
if offset < 8 {
|
|
||||||
return orientationUnspecified // Invalid offset value.
|
|
||||||
}
|
|
||||||
if _, err := io.CopyN(ioutil.Discard, r, int64(offset-8)); err != nil {
|
|
||||||
return orientationUnspecified
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the number of tags.
|
|
||||||
var numTags uint16
|
|
||||||
if err := binary.Read(r, byteOrder, &numTags); err != nil {
|
|
||||||
return orientationUnspecified
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the orientation tag.
|
|
||||||
for i := 0; i < int(numTags); i++ {
|
|
||||||
var tag uint16
|
|
||||||
if err := binary.Read(r, byteOrder, &tag); err != nil {
|
|
||||||
return orientationUnspecified
|
|
||||||
}
|
|
||||||
if tag != orientationTag {
|
|
||||||
if _, err := io.CopyN(ioutil.Discard, r, 10); err != nil {
|
|
||||||
return orientationUnspecified
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if _, err := io.CopyN(ioutil.Discard, r, 6); err != nil {
|
|
||||||
return orientationUnspecified
|
|
||||||
}
|
|
||||||
var val uint16
|
|
||||||
if err := binary.Read(r, byteOrder, &val); err != nil {
|
|
||||||
return orientationUnspecified
|
|
||||||
}
|
|
||||||
if val < 1 || val > 8 {
|
|
||||||
return orientationUnspecified // Invalid tag value.
|
|
||||||
}
|
|
||||||
return orientation(val)
|
|
||||||
}
|
|
||||||
return orientationUnspecified // Missing orientation tag.
|
|
||||||
}
|
|
||||||
|
|
||||||
// fixOrientation applies a transform to img corresponding to the given orientation flag.
|
|
||||||
func fixOrientation(img image.Image, o orientation) image.Image {
|
|
||||||
switch o {
|
|
||||||
case orientationNormal:
|
|
||||||
case orientationFlipH:
|
|
||||||
img = FlipH(img)
|
|
||||||
case orientationFlipV:
|
|
||||||
img = FlipV(img)
|
|
||||||
case orientationRotate90:
|
|
||||||
img = Rotate90(img)
|
|
||||||
case orientationRotate180:
|
|
||||||
img = Rotate180(img)
|
|
||||||
case orientationRotate270:
|
|
||||||
img = Rotate270(img)
|
|
||||||
case orientationTranspose:
|
|
||||||
img = Transpose(img)
|
|
||||||
case orientationTransverse:
|
|
||||||
img = Transverse(img)
|
|
||||||
}
|
|
||||||
return img
|
|
||||||
}
|
|
595
vendor/github.com/disintegration/imaging/resize.go
generated
vendored
595
vendor/github.com/disintegration/imaging/resize.go
generated
vendored
@ -1,595 +0,0 @@
|
|||||||
package imaging
|
|
||||||
|
|
||||||
import (
|
|
||||||
"image"
|
|
||||||
"math"
|
|
||||||
)
|
|
||||||
|
|
||||||
type indexWeight struct {
|
|
||||||
index int
|
|
||||||
weight float64
|
|
||||||
}
|
|
||||||
|
|
||||||
func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) [][]indexWeight {
|
|
||||||
du := float64(srcSize) / float64(dstSize)
|
|
||||||
scale := du
|
|
||||||
if scale < 1.0 {
|
|
||||||
scale = 1.0
|
|
||||||
}
|
|
||||||
ru := math.Ceil(scale * filter.Support)
|
|
||||||
|
|
||||||
out := make([][]indexWeight, dstSize)
|
|
||||||
tmp := make([]indexWeight, 0, dstSize*int(ru+2)*2)
|
|
||||||
|
|
||||||
for v := 0; v < dstSize; v++ {
|
|
||||||
fu := (float64(v)+0.5)*du - 0.5
|
|
||||||
|
|
||||||
begin := int(math.Ceil(fu - ru))
|
|
||||||
if begin < 0 {
|
|
||||||
begin = 0
|
|
||||||
}
|
|
||||||
end := int(math.Floor(fu + ru))
|
|
||||||
if end > srcSize-1 {
|
|
||||||
end = srcSize - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
var sum float64
|
|
||||||
for u := begin; u <= end; u++ {
|
|
||||||
w := filter.Kernel((float64(u) - fu) / scale)
|
|
||||||
if w != 0 {
|
|
||||||
sum += w
|
|
||||||
tmp = append(tmp, indexWeight{index: u, weight: w})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if sum != 0 {
|
|
||||||
for i := range tmp {
|
|
||||||
tmp[i].weight /= sum
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out[v] = tmp
|
|
||||||
tmp = tmp[len(tmp):]
|
|
||||||
}
|
|
||||||
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resize resizes the image to the specified width and height using the specified resampling
|
|
||||||
// filter and returns the transformed image. If one of width or height is 0, the image aspect
|
|
||||||
// ratio is preserved.
|
|
||||||
//
|
|
||||||
// Example:
|
|
||||||
//
|
|
||||||
// dstImage := imaging.Resize(srcImage, 800, 600, imaging.Lanczos)
|
|
||||||
//
|
|
||||||
func Resize(img image.Image, width, height int, filter ResampleFilter) *image.NRGBA {
|
|
||||||
dstW, dstH := width, height
|
|
||||||
if dstW < 0 || dstH < 0 {
|
|
||||||
return &image.NRGBA{}
|
|
||||||
}
|
|
||||||
if dstW == 0 && dstH == 0 {
|
|
||||||
return &image.NRGBA{}
|
|
||||||
}
|
|
||||||
|
|
||||||
srcW := img.Bounds().Dx()
|
|
||||||
srcH := img.Bounds().Dy()
|
|
||||||
if srcW <= 0 || srcH <= 0 {
|
|
||||||
return &image.NRGBA{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If new width or height is 0 then preserve aspect ratio, minimum 1px.
|
|
||||||
if dstW == 0 {
|
|
||||||
tmpW := float64(dstH) * float64(srcW) / float64(srcH)
|
|
||||||
dstW = int(math.Max(1.0, math.Floor(tmpW+0.5)))
|
|
||||||
}
|
|
||||||
if dstH == 0 {
|
|
||||||
tmpH := float64(dstW) * float64(srcH) / float64(srcW)
|
|
||||||
dstH = int(math.Max(1.0, math.Floor(tmpH+0.5)))
|
|
||||||
}
|
|
||||||
|
|
||||||
if filter.Support <= 0 {
|
|
||||||
// Nearest-neighbor special case.
|
|
||||||
return resizeNearest(img, dstW, dstH)
|
|
||||||
}
|
|
||||||
|
|
||||||
if srcW != dstW && srcH != dstH {
|
|
||||||
return resizeVertical(resizeHorizontal(img, dstW, filter), dstH, filter)
|
|
||||||
}
|
|
||||||
if srcW != dstW {
|
|
||||||
return resizeHorizontal(img, dstW, filter)
|
|
||||||
}
|
|
||||||
if srcH != dstH {
|
|
||||||
return resizeVertical(img, dstH, filter)
|
|
||||||
}
|
|
||||||
return Clone(img)
|
|
||||||
}
|
|
||||||
|
|
||||||
func resizeHorizontal(img image.Image, width int, filter ResampleFilter) *image.NRGBA {
|
|
||||||
src := newScanner(img)
|
|
||||||
dst := image.NewNRGBA(image.Rect(0, 0, width, src.h))
|
|
||||||
weights := precomputeWeights(width, src.w, filter)
|
|
||||||
parallel(0, src.h, func(ys <-chan int) {
|
|
||||||
scanLine := make([]uint8, src.w*4)
|
|
||||||
for y := range ys {
|
|
||||||
src.scan(0, y, src.w, y+1, scanLine)
|
|
||||||
j0 := y * dst.Stride
|
|
||||||
for x := range weights {
|
|
||||||
var r, g, b, a float64
|
|
||||||
for _, w := range weights[x] {
|
|
||||||
i := w.index * 4
|
|
||||||
s := scanLine[i : i+4 : i+4]
|
|
||||||
aw := float64(s[3]) * w.weight
|
|
||||||
r += float64(s[0]) * aw
|
|
||||||
g += float64(s[1]) * aw
|
|
||||||
b += float64(s[2]) * aw
|
|
||||||
a += aw
|
|
||||||
}
|
|
||||||
if a != 0 {
|
|
||||||
aInv := 1 / a
|
|
||||||
j := j0 + x*4
|
|
||||||
d := dst.Pix[j : j+4 : j+4]
|
|
||||||
d[0] = clamp(r * aInv)
|
|
||||||
d[1] = clamp(g * aInv)
|
|
||||||
d[2] = clamp(b * aInv)
|
|
||||||
d[3] = clamp(a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
func resizeVertical(img image.Image, height int, filter ResampleFilter) *image.NRGBA {
|
|
||||||
src := newScanner(img)
|
|
||||||
dst := image.NewNRGBA(image.Rect(0, 0, src.w, height))
|
|
||||||
weights := precomputeWeights(height, src.h, filter)
|
|
||||||
parallel(0, src.w, func(xs <-chan int) {
|
|
||||||
scanLine := make([]uint8, src.h*4)
|
|
||||||
for x := range xs {
|
|
||||||
src.scan(x, 0, x+1, src.h, scanLine)
|
|
||||||
for y := range weights {
|
|
||||||
var r, g, b, a float64
|
|
||||||
for _, w := range weights[y] {
|
|
||||||
i := w.index * 4
|
|
||||||
s := scanLine[i : i+4 : i+4]
|
|
||||||
aw := float64(s[3]) * w.weight
|
|
||||||
r += float64(s[0]) * aw
|
|
||||||
g += float64(s[1]) * aw
|
|
||||||
b += float64(s[2]) * aw
|
|
||||||
a += aw
|
|
||||||
}
|
|
||||||
if a != 0 {
|
|
||||||
aInv := 1 / a
|
|
||||||
j := y*dst.Stride + x*4
|
|
||||||
d := dst.Pix[j : j+4 : j+4]
|
|
||||||
d[0] = clamp(r * aInv)
|
|
||||||
d[1] = clamp(g * aInv)
|
|
||||||
d[2] = clamp(b * aInv)
|
|
||||||
d[3] = clamp(a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
// resizeNearest is a fast nearest-neighbor resize, no filtering.
|
|
||||||
func resizeNearest(img image.Image, width, height int) *image.NRGBA {
|
|
||||||
dst := image.NewNRGBA(image.Rect(0, 0, width, height))
|
|
||||||
dx := float64(img.Bounds().Dx()) / float64(width)
|
|
||||||
dy := float64(img.Bounds().Dy()) / float64(height)
|
|
||||||
|
|
||||||
if dx > 1 && dy > 1 {
|
|
||||||
src := newScanner(img)
|
|
||||||
parallel(0, height, func(ys <-chan int) {
|
|
||||||
for y := range ys {
|
|
||||||
srcY := int((float64(y) + 0.5) * dy)
|
|
||||||
dstOff := y * dst.Stride
|
|
||||||
for x := 0; x < width; x++ {
|
|
||||||
srcX := int((float64(x) + 0.5) * dx)
|
|
||||||
src.scan(srcX, srcY, srcX+1, srcY+1, dst.Pix[dstOff:dstOff+4])
|
|
||||||
dstOff += 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
src := toNRGBA(img)
|
|
||||||
parallel(0, height, func(ys <-chan int) {
|
|
||||||
for y := range ys {
|
|
||||||
srcY := int((float64(y) + 0.5) * dy)
|
|
||||||
srcOff0 := srcY * src.Stride
|
|
||||||
dstOff := y * dst.Stride
|
|
||||||
for x := 0; x < width; x++ {
|
|
||||||
srcX := int((float64(x) + 0.5) * dx)
|
|
||||||
srcOff := srcOff0 + srcX*4
|
|
||||||
copy(dst.Pix[dstOff:dstOff+4], src.Pix[srcOff:srcOff+4])
|
|
||||||
dstOff += 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fit scales down the image using the specified resample filter to fit the specified
|
|
||||||
// maximum width and height and returns the transformed image.
|
|
||||||
//
|
|
||||||
// Example:
|
|
||||||
//
|
|
||||||
// dstImage := imaging.Fit(srcImage, 800, 600, imaging.Lanczos)
|
|
||||||
//
|
|
||||||
func Fit(img image.Image, width, height int, filter ResampleFilter) *image.NRGBA {
|
|
||||||
maxW, maxH := width, height
|
|
||||||
|
|
||||||
if maxW <= 0 || maxH <= 0 {
|
|
||||||
return &image.NRGBA{}
|
|
||||||
}
|
|
||||||
|
|
||||||
srcBounds := img.Bounds()
|
|
||||||
srcW := srcBounds.Dx()
|
|
||||||
srcH := srcBounds.Dy()
|
|
||||||
|
|
||||||
if srcW <= 0 || srcH <= 0 {
|
|
||||||
return &image.NRGBA{}
|
|
||||||
}
|
|
||||||
|
|
||||||
if srcW <= maxW && srcH <= maxH {
|
|
||||||
return Clone(img)
|
|
||||||
}
|
|
||||||
|
|
||||||
srcAspectRatio := float64(srcW) / float64(srcH)
|
|
||||||
maxAspectRatio := float64(maxW) / float64(maxH)
|
|
||||||
|
|
||||||
var newW, newH int
|
|
||||||
if srcAspectRatio > maxAspectRatio {
|
|
||||||
newW = maxW
|
|
||||||
newH = int(float64(newW) / srcAspectRatio)
|
|
||||||
} else {
|
|
||||||
newH = maxH
|
|
||||||
newW = int(float64(newH) * srcAspectRatio)
|
|
||||||
}
|
|
||||||
|
|
||||||
return Resize(img, newW, newH, filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill creates an image with the specified dimensions and fills it with the scaled source image.
|
|
||||||
// To achieve the correct aspect ratio without stretching, the source image will be cropped.
|
|
||||||
//
|
|
||||||
// Example:
|
|
||||||
//
|
|
||||||
// dstImage := imaging.Fill(srcImage, 800, 600, imaging.Center, imaging.Lanczos)
|
|
||||||
//
|
|
||||||
func Fill(img image.Image, width, height int, anchor Anchor, filter ResampleFilter) *image.NRGBA {
|
|
||||||
dstW, dstH := width, height
|
|
||||||
|
|
||||||
if dstW <= 0 || dstH <= 0 {
|
|
||||||
return &image.NRGBA{}
|
|
||||||
}
|
|
||||||
|
|
||||||
srcBounds := img.Bounds()
|
|
||||||
srcW := srcBounds.Dx()
|
|
||||||
srcH := srcBounds.Dy()
|
|
||||||
|
|
||||||
if srcW <= 0 || srcH <= 0 {
|
|
||||||
return &image.NRGBA{}
|
|
||||||
}
|
|
||||||
|
|
||||||
if srcW == dstW && srcH == dstH {
|
|
||||||
return Clone(img)
|
|
||||||
}
|
|
||||||
|
|
||||||
if srcW >= 100 && srcH >= 100 {
|
|
||||||
return cropAndResize(img, dstW, dstH, anchor, filter)
|
|
||||||
}
|
|
||||||
return resizeAndCrop(img, dstW, dstH, anchor, filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
// cropAndResize crops the image to the smallest possible size that has the required aspect ratio using
|
|
||||||
// the given anchor point, then scales it to the specified dimensions and returns the transformed image.
|
|
||||||
//
|
|
||||||
// This is generally faster than resizing first, but may result in inaccuracies when used on small source images.
|
|
||||||
func cropAndResize(img image.Image, width, height int, anchor Anchor, filter ResampleFilter) *image.NRGBA {
|
|
||||||
dstW, dstH := width, height
|
|
||||||
|
|
||||||
srcBounds := img.Bounds()
|
|
||||||
srcW := srcBounds.Dx()
|
|
||||||
srcH := srcBounds.Dy()
|
|
||||||
srcAspectRatio := float64(srcW) / float64(srcH)
|
|
||||||
dstAspectRatio := float64(dstW) / float64(dstH)
|
|
||||||
|
|
||||||
var tmp *image.NRGBA
|
|
||||||
if srcAspectRatio < dstAspectRatio {
|
|
||||||
cropH := float64(srcW) * float64(dstH) / float64(dstW)
|
|
||||||
tmp = CropAnchor(img, srcW, int(math.Max(1, cropH)+0.5), anchor)
|
|
||||||
} else {
|
|
||||||
cropW := float64(srcH) * float64(dstW) / float64(dstH)
|
|
||||||
tmp = CropAnchor(img, int(math.Max(1, cropW)+0.5), srcH, anchor)
|
|
||||||
}
|
|
||||||
|
|
||||||
return Resize(tmp, dstW, dstH, filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
// resizeAndCrop resizes the image to the smallest possible size that will cover the specified dimensions,
|
|
||||||
// crops the resized image to the specified dimensions using the given anchor point and returns
|
|
||||||
// the transformed image.
|
|
||||||
func resizeAndCrop(img image.Image, width, height int, anchor Anchor, filter ResampleFilter) *image.NRGBA {
|
|
||||||
dstW, dstH := width, height
|
|
||||||
|
|
||||||
srcBounds := img.Bounds()
|
|
||||||
srcW := srcBounds.Dx()
|
|
||||||
srcH := srcBounds.Dy()
|
|
||||||
srcAspectRatio := float64(srcW) / float64(srcH)
|
|
||||||
dstAspectRatio := float64(dstW) / float64(dstH)
|
|
||||||
|
|
||||||
var tmp *image.NRGBA
|
|
||||||
if srcAspectRatio < dstAspectRatio {
|
|
||||||
tmp = Resize(img, dstW, 0, filter)
|
|
||||||
} else {
|
|
||||||
tmp = Resize(img, 0, dstH, filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
return CropAnchor(tmp, dstW, dstH, anchor)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Thumbnail scales the image up or down using the specified resample filter, crops it
|
|
||||||
// to the specified width and hight and returns the transformed image.
|
|
||||||
//
|
|
||||||
// Example:
|
|
||||||
//
|
|
||||||
// dstImage := imaging.Thumbnail(srcImage, 100, 100, imaging.Lanczos)
|
|
||||||
//
|
|
||||||
func Thumbnail(img image.Image, width, height int, filter ResampleFilter) *image.NRGBA {
|
|
||||||
return Fill(img, width, height, Center, filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResampleFilter specifies a resampling filter to be used for image resizing.
|
|
||||||
//
|
|
||||||
// General filter recommendations:
|
|
||||||
//
|
|
||||||
// - Lanczos
|
|
||||||
// A high-quality resampling filter for photographic images yielding sharp results.
|
|
||||||
//
|
|
||||||
// - CatmullRom
|
|
||||||
// A sharp cubic filter that is faster than Lanczos filter while providing similar results.
|
|
||||||
//
|
|
||||||
// - MitchellNetravali
|
|
||||||
// A cubic filter that produces smoother results with less ringing artifacts than CatmullRom.
|
|
||||||
//
|
|
||||||
// - Linear
|
|
||||||
// Bilinear resampling filter, produces a smooth output. Faster than cubic filters.
|
|
||||||
//
|
|
||||||
// - Box
|
|
||||||
// Simple and fast averaging filter appropriate for downscaling.
|
|
||||||
// When upscaling it's similar to NearestNeighbor.
|
|
||||||
//
|
|
||||||
// - NearestNeighbor
|
|
||||||
// Fastest resampling filter, no antialiasing.
|
|
||||||
//
|
|
||||||
type ResampleFilter struct {
|
|
||||||
Support float64
|
|
||||||
Kernel func(float64) float64
|
|
||||||
}
|
|
||||||
|
|
||||||
// NearestNeighbor is a nearest-neighbor filter (no anti-aliasing).
|
|
||||||
var NearestNeighbor ResampleFilter
|
|
||||||
|
|
||||||
// Box filter (averaging pixels).
|
|
||||||
var Box ResampleFilter
|
|
||||||
|
|
||||||
// Linear filter.
|
|
||||||
var Linear ResampleFilter
|
|
||||||
|
|
||||||
// Hermite cubic spline filter (BC-spline; B=0; C=0).
|
|
||||||
var Hermite ResampleFilter
|
|
||||||
|
|
||||||
// MitchellNetravali is Mitchell-Netravali cubic filter (BC-spline; B=1/3; C=1/3).
|
|
||||||
var MitchellNetravali ResampleFilter
|
|
||||||
|
|
||||||
// CatmullRom is a Catmull-Rom - sharp cubic filter (BC-spline; B=0; C=0.5).
|
|
||||||
var CatmullRom ResampleFilter
|
|
||||||
|
|
||||||
// BSpline is a smooth cubic filter (BC-spline; B=1; C=0).
|
|
||||||
var BSpline ResampleFilter
|
|
||||||
|
|
||||||
// Gaussian is a Gaussian blurring filter.
|
|
||||||
var Gaussian ResampleFilter
|
|
||||||
|
|
||||||
// Bartlett is a Bartlett-windowed sinc filter (3 lobes).
|
|
||||||
var Bartlett ResampleFilter
|
|
||||||
|
|
||||||
// Lanczos filter (3 lobes).
|
|
||||||
var Lanczos ResampleFilter
|
|
||||||
|
|
||||||
// Hann is a Hann-windowed sinc filter (3 lobes).
|
|
||||||
var Hann ResampleFilter
|
|
||||||
|
|
||||||
// Hamming is a Hamming-windowed sinc filter (3 lobes).
|
|
||||||
var Hamming ResampleFilter
|
|
||||||
|
|
||||||
// Blackman is a Blackman-windowed sinc filter (3 lobes).
|
|
||||||
var Blackman ResampleFilter
|
|
||||||
|
|
||||||
// Welch is a Welch-windowed sinc filter (parabolic window, 3 lobes).
|
|
||||||
var Welch ResampleFilter
|
|
||||||
|
|
||||||
// Cosine is a Cosine-windowed sinc filter (3 lobes).
|
|
||||||
var Cosine ResampleFilter
|
|
||||||
|
|
||||||
func bcspline(x, b, c float64) float64 {
|
|
||||||
var y float64
|
|
||||||
x = math.Abs(x)
|
|
||||||
if x < 1.0 {
|
|
||||||
y = ((12-9*b-6*c)*x*x*x + (-18+12*b+6*c)*x*x + (6 - 2*b)) / 6
|
|
||||||
} else if x < 2.0 {
|
|
||||||
y = ((-b-6*c)*x*x*x + (6*b+30*c)*x*x + (-12*b-48*c)*x + (8*b + 24*c)) / 6
|
|
||||||
}
|
|
||||||
return y
|
|
||||||
}
|
|
||||||
|
|
||||||
func sinc(x float64) float64 {
|
|
||||||
if x == 0 {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return math.Sin(math.Pi*x) / (math.Pi * x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
NearestNeighbor = ResampleFilter{
|
|
||||||
Support: 0.0, // special case - not applying the filter
|
|
||||||
}
|
|
||||||
|
|
||||||
Box = ResampleFilter{
|
|
||||||
Support: 0.5,
|
|
||||||
Kernel: func(x float64) float64 {
|
|
||||||
x = math.Abs(x)
|
|
||||||
if x <= 0.5 {
|
|
||||||
return 1.0
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
Linear = ResampleFilter{
|
|
||||||
Support: 1.0,
|
|
||||||
Kernel: func(x float64) float64 {
|
|
||||||
x = math.Abs(x)
|
|
||||||
if x < 1.0 {
|
|
||||||
return 1.0 - x
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
Hermite = ResampleFilter{
|
|
||||||
Support: 1.0,
|
|
||||||
Kernel: func(x float64) float64 {
|
|
||||||
x = math.Abs(x)
|
|
||||||
if x < 1.0 {
|
|
||||||
return bcspline(x, 0.0, 0.0)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
MitchellNetravali = ResampleFilter{
|
|
||||||
Support: 2.0,
|
|
||||||
Kernel: func(x float64) float64 {
|
|
||||||
x = math.Abs(x)
|
|
||||||
if x < 2.0 {
|
|
||||||
return bcspline(x, 1.0/3.0, 1.0/3.0)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
CatmullRom = ResampleFilter{
|
|
||||||
Support: 2.0,
|
|
||||||
Kernel: func(x float64) float64 {
|
|
||||||
x = math.Abs(x)
|
|
||||||
if x < 2.0 {
|
|
||||||
return bcspline(x, 0.0, 0.5)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
BSpline = ResampleFilter{
|
|
||||||
Support: 2.0,
|
|
||||||
Kernel: func(x float64) float64 {
|
|
||||||
x = math.Abs(x)
|
|
||||||
if x < 2.0 {
|
|
||||||
return bcspline(x, 1.0, 0.0)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
Gaussian = ResampleFilter{
|
|
||||||
Support: 2.0,
|
|
||||||
Kernel: func(x float64) float64 {
|
|
||||||
x = math.Abs(x)
|
|
||||||
if x < 2.0 {
|
|
||||||
return math.Exp(-2 * x * x)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
Bartlett = ResampleFilter{
|
|
||||||
Support: 3.0,
|
|
||||||
Kernel: func(x float64) float64 {
|
|
||||||
x = math.Abs(x)
|
|
||||||
if x < 3.0 {
|
|
||||||
return sinc(x) * (3.0 - x) / 3.0
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
Lanczos = ResampleFilter{
|
|
||||||
Support: 3.0,
|
|
||||||
Kernel: func(x float64) float64 {
|
|
||||||
x = math.Abs(x)
|
|
||||||
if x < 3.0 {
|
|
||||||
return sinc(x) * sinc(x/3.0)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
Hann = ResampleFilter{
|
|
||||||
Support: 3.0,
|
|
||||||
Kernel: func(x float64) float64 {
|
|
||||||
x = math.Abs(x)
|
|
||||||
if x < 3.0 {
|
|
||||||
return sinc(x) * (0.5 + 0.5*math.Cos(math.Pi*x/3.0))
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
Hamming = ResampleFilter{
|
|
||||||
Support: 3.0,
|
|
||||||
Kernel: func(x float64) float64 {
|
|
||||||
x = math.Abs(x)
|
|
||||||
if x < 3.0 {
|
|
||||||
return sinc(x) * (0.54 + 0.46*math.Cos(math.Pi*x/3.0))
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
Blackman = ResampleFilter{
|
|
||||||
Support: 3.0,
|
|
||||||
Kernel: func(x float64) float64 {
|
|
||||||
x = math.Abs(x)
|
|
||||||
if x < 3.0 {
|
|
||||||
return sinc(x) * (0.42 - 0.5*math.Cos(math.Pi*x/3.0+math.Pi) + 0.08*math.Cos(2.0*math.Pi*x/3.0))
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
Welch = ResampleFilter{
|
|
||||||
Support: 3.0,
|
|
||||||
Kernel: func(x float64) float64 {
|
|
||||||
x = math.Abs(x)
|
|
||||||
if x < 3.0 {
|
|
||||||
return sinc(x) * (1.0 - (x * x / 9.0))
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
Cosine = ResampleFilter{
|
|
||||||
Support: 3.0,
|
|
||||||
Kernel: func(x float64) float64 {
|
|
||||||
x = math.Abs(x)
|
|
||||||
if x < 3.0 {
|
|
||||||
return sinc(x) * math.Cos((math.Pi/2.0)*(x/3.0))
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
285
vendor/github.com/disintegration/imaging/scanner.go
generated
vendored
285
vendor/github.com/disintegration/imaging/scanner.go
generated
vendored
@ -1,285 +0,0 @@
|
|||||||
package imaging
|
|
||||||
|
|
||||||
import (
|
|
||||||
"image"
|
|
||||||
"image/color"
|
|
||||||
)
|
|
||||||
|
|
||||||
type scanner struct {
|
|
||||||
image image.Image
|
|
||||||
w, h int
|
|
||||||
palette []color.NRGBA
|
|
||||||
}
|
|
||||||
|
|
||||||
func newScanner(img image.Image) *scanner {
|
|
||||||
s := &scanner{
|
|
||||||
image: img,
|
|
||||||
w: img.Bounds().Dx(),
|
|
||||||
h: img.Bounds().Dy(),
|
|
||||||
}
|
|
||||||
if img, ok := img.(*image.Paletted); ok {
|
|
||||||
s.palette = make([]color.NRGBA, len(img.Palette))
|
|
||||||
for i := 0; i < len(img.Palette); i++ {
|
|
||||||
s.palette[i] = color.NRGBAModel.Convert(img.Palette[i]).(color.NRGBA)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// scan scans the given rectangular region of the image into dst.
|
|
||||||
func (s *scanner) scan(x1, y1, x2, y2 int, dst []uint8) {
|
|
||||||
switch img := s.image.(type) {
|
|
||||||
case *image.NRGBA:
|
|
||||||
size := (x2 - x1) * 4
|
|
||||||
j := 0
|
|
||||||
i := y1*img.Stride + x1*4
|
|
||||||
if size == 4 {
|
|
||||||
for y := y1; y < y2; y++ {
|
|
||||||
d := dst[j : j+4 : j+4]
|
|
||||||
s := img.Pix[i : i+4 : i+4]
|
|
||||||
d[0] = s[0]
|
|
||||||
d[1] = s[1]
|
|
||||||
d[2] = s[2]
|
|
||||||
d[3] = s[3]
|
|
||||||
j += size
|
|
||||||
i += img.Stride
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for y := y1; y < y2; y++ {
|
|
||||||
copy(dst[j:j+size], img.Pix[i:i+size])
|
|
||||||
j += size
|
|
||||||
i += img.Stride
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case *image.NRGBA64:
|
|
||||||
j := 0
|
|
||||||
for y := y1; y < y2; y++ {
|
|
||||||
i := y*img.Stride + x1*8
|
|
||||||
for x := x1; x < x2; x++ {
|
|
||||||
s := img.Pix[i : i+8 : i+8]
|
|
||||||
d := dst[j : j+4 : j+4]
|
|
||||||
d[0] = s[0]
|
|
||||||
d[1] = s[2]
|
|
||||||
d[2] = s[4]
|
|
||||||
d[3] = s[6]
|
|
||||||
j += 4
|
|
||||||
i += 8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case *image.RGBA:
|
|
||||||
j := 0
|
|
||||||
for y := y1; y < y2; y++ {
|
|
||||||
i := y*img.Stride + x1*4
|
|
||||||
for x := x1; x < x2; x++ {
|
|
||||||
d := dst[j : j+4 : j+4]
|
|
||||||
a := img.Pix[i+3]
|
|
||||||
switch a {
|
|
||||||
case 0:
|
|
||||||
d[0] = 0
|
|
||||||
d[1] = 0
|
|
||||||
d[2] = 0
|
|
||||||
d[3] = a
|
|
||||||
case 0xff:
|
|
||||||
s := img.Pix[i : i+4 : i+4]
|
|
||||||
d[0] = s[0]
|
|
||||||
d[1] = s[1]
|
|
||||||
d[2] = s[2]
|
|
||||||
d[3] = a
|
|
||||||
default:
|
|
||||||
s := img.Pix[i : i+4 : i+4]
|
|
||||||
r16 := uint16(s[0])
|
|
||||||
g16 := uint16(s[1])
|
|
||||||
b16 := uint16(s[2])
|
|
||||||
a16 := uint16(a)
|
|
||||||
d[0] = uint8(r16 * 0xff / a16)
|
|
||||||
d[1] = uint8(g16 * 0xff / a16)
|
|
||||||
d[2] = uint8(b16 * 0xff / a16)
|
|
||||||
d[3] = a
|
|
||||||
}
|
|
||||||
j += 4
|
|
||||||
i += 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case *image.RGBA64:
|
|
||||||
j := 0
|
|
||||||
for y := y1; y < y2; y++ {
|
|
||||||
i := y*img.Stride + x1*8
|
|
||||||
for x := x1; x < x2; x++ {
|
|
||||||
s := img.Pix[i : i+8 : i+8]
|
|
||||||
d := dst[j : j+4 : j+4]
|
|
||||||
a := s[6]
|
|
||||||
switch a {
|
|
||||||
case 0:
|
|
||||||
d[0] = 0
|
|
||||||
d[1] = 0
|
|
||||||
d[2] = 0
|
|
||||||
case 0xff:
|
|
||||||
d[0] = s[0]
|
|
||||||
d[1] = s[2]
|
|
||||||
d[2] = s[4]
|
|
||||||
default:
|
|
||||||
r32 := uint32(s[0])<<8 | uint32(s[1])
|
|
||||||
g32 := uint32(s[2])<<8 | uint32(s[3])
|
|
||||||
b32 := uint32(s[4])<<8 | uint32(s[5])
|
|
||||||
a32 := uint32(s[6])<<8 | uint32(s[7])
|
|
||||||
d[0] = uint8((r32 * 0xffff / a32) >> 8)
|
|
||||||
d[1] = uint8((g32 * 0xffff / a32) >> 8)
|
|
||||||
d[2] = uint8((b32 * 0xffff / a32) >> 8)
|
|
||||||
}
|
|
||||||
d[3] = a
|
|
||||||
j += 4
|
|
||||||
i += 8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case *image.Gray:
|
|
||||||
j := 0
|
|
||||||
for y := y1; y < y2; y++ {
|
|
||||||
i := y*img.Stride + x1
|
|
||||||
for x := x1; x < x2; x++ {
|
|
||||||
c := img.Pix[i]
|
|
||||||
d := dst[j : j+4 : j+4]
|
|
||||||
d[0] = c
|
|
||||||
d[1] = c
|
|
||||||
d[2] = c
|
|
||||||
d[3] = 0xff
|
|
||||||
j += 4
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case *image.Gray16:
|
|
||||||
j := 0
|
|
||||||
for y := y1; y < y2; y++ {
|
|
||||||
i := y*img.Stride + x1*2
|
|
||||||
for x := x1; x < x2; x++ {
|
|
||||||
c := img.Pix[i]
|
|
||||||
d := dst[j : j+4 : j+4]
|
|
||||||
d[0] = c
|
|
||||||
d[1] = c
|
|
||||||
d[2] = c
|
|
||||||
d[3] = 0xff
|
|
||||||
j += 4
|
|
||||||
i += 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case *image.YCbCr:
|
|
||||||
j := 0
|
|
||||||
x1 += img.Rect.Min.X
|
|
||||||
x2 += img.Rect.Min.X
|
|
||||||
y1 += img.Rect.Min.Y
|
|
||||||
y2 += img.Rect.Min.Y
|
|
||||||
|
|
||||||
hy := img.Rect.Min.Y / 2
|
|
||||||
hx := img.Rect.Min.X / 2
|
|
||||||
for y := y1; y < y2; y++ {
|
|
||||||
iy := (y-img.Rect.Min.Y)*img.YStride + (x1 - img.Rect.Min.X)
|
|
||||||
|
|
||||||
var yBase int
|
|
||||||
switch img.SubsampleRatio {
|
|
||||||
case image.YCbCrSubsampleRatio444, image.YCbCrSubsampleRatio422:
|
|
||||||
yBase = (y - img.Rect.Min.Y) * img.CStride
|
|
||||||
case image.YCbCrSubsampleRatio420, image.YCbCrSubsampleRatio440:
|
|
||||||
yBase = (y/2 - hy) * img.CStride
|
|
||||||
}
|
|
||||||
|
|
||||||
for x := x1; x < x2; x++ {
|
|
||||||
var ic int
|
|
||||||
switch img.SubsampleRatio {
|
|
||||||
case image.YCbCrSubsampleRatio444, image.YCbCrSubsampleRatio440:
|
|
||||||
ic = yBase + (x - img.Rect.Min.X)
|
|
||||||
case image.YCbCrSubsampleRatio422, image.YCbCrSubsampleRatio420:
|
|
||||||
ic = yBase + (x/2 - hx)
|
|
||||||
default:
|
|
||||||
ic = img.COffset(x, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
yy1 := int32(img.Y[iy]) * 0x10101
|
|
||||||
cb1 := int32(img.Cb[ic]) - 128
|
|
||||||
cr1 := int32(img.Cr[ic]) - 128
|
|
||||||
|
|
||||||
r := yy1 + 91881*cr1
|
|
||||||
if uint32(r)&0xff000000 == 0 {
|
|
||||||
r >>= 16
|
|
||||||
} else {
|
|
||||||
r = ^(r >> 31)
|
|
||||||
}
|
|
||||||
|
|
||||||
g := yy1 - 22554*cb1 - 46802*cr1
|
|
||||||
if uint32(g)&0xff000000 == 0 {
|
|
||||||
g >>= 16
|
|
||||||
} else {
|
|
||||||
g = ^(g >> 31)
|
|
||||||
}
|
|
||||||
|
|
||||||
b := yy1 + 116130*cb1
|
|
||||||
if uint32(b)&0xff000000 == 0 {
|
|
||||||
b >>= 16
|
|
||||||
} else {
|
|
||||||
b = ^(b >> 31)
|
|
||||||
}
|
|
||||||
|
|
||||||
d := dst[j : j+4 : j+4]
|
|
||||||
d[0] = uint8(r)
|
|
||||||
d[1] = uint8(g)
|
|
||||||
d[2] = uint8(b)
|
|
||||||
d[3] = 0xff
|
|
||||||
|
|
||||||
iy++
|
|
||||||
j += 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case *image.Paletted:
|
|
||||||
j := 0
|
|
||||||
for y := y1; y < y2; y++ {
|
|
||||||
i := y*img.Stride + x1
|
|
||||||
for x := x1; x < x2; x++ {
|
|
||||||
c := s.palette[img.Pix[i]]
|
|
||||||
d := dst[j : j+4 : j+4]
|
|
||||||
d[0] = c.R
|
|
||||||
d[1] = c.G
|
|
||||||
d[2] = c.B
|
|
||||||
d[3] = c.A
|
|
||||||
j += 4
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
j := 0
|
|
||||||
b := s.image.Bounds()
|
|
||||||
x1 += b.Min.X
|
|
||||||
x2 += b.Min.X
|
|
||||||
y1 += b.Min.Y
|
|
||||||
y2 += b.Min.Y
|
|
||||||
for y := y1; y < y2; y++ {
|
|
||||||
for x := x1; x < x2; x++ {
|
|
||||||
r16, g16, b16, a16 := s.image.At(x, y).RGBA()
|
|
||||||
d := dst[j : j+4 : j+4]
|
|
||||||
switch a16 {
|
|
||||||
case 0xffff:
|
|
||||||
d[0] = uint8(r16 >> 8)
|
|
||||||
d[1] = uint8(g16 >> 8)
|
|
||||||
d[2] = uint8(b16 >> 8)
|
|
||||||
d[3] = 0xff
|
|
||||||
case 0:
|
|
||||||
d[0] = 0
|
|
||||||
d[1] = 0
|
|
||||||
d[2] = 0
|
|
||||||
d[3] = 0
|
|
||||||
default:
|
|
||||||
d[0] = uint8(((r16 * 0xffff) / a16) >> 8)
|
|
||||||
d[1] = uint8(((g16 * 0xffff) / a16) >> 8)
|
|
||||||
d[2] = uint8(((b16 * 0xffff) / a16) >> 8)
|
|
||||||
d[3] = uint8(a16 >> 8)
|
|
||||||
}
|
|
||||||
j += 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
249
vendor/github.com/disintegration/imaging/tools.go
generated
vendored
249
vendor/github.com/disintegration/imaging/tools.go
generated
vendored
@ -1,249 +0,0 @@
|
|||||||
package imaging
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"image"
|
|
||||||
"image/color"
|
|
||||||
"math"
|
|
||||||
)
|
|
||||||
|
|
||||||
// New creates a new image with the specified width and height, and fills it with the specified color.
|
|
||||||
func New(width, height int, fillColor color.Color) *image.NRGBA {
|
|
||||||
if width <= 0 || height <= 0 {
|
|
||||||
return &image.NRGBA{}
|
|
||||||
}
|
|
||||||
|
|
||||||
c := color.NRGBAModel.Convert(fillColor).(color.NRGBA)
|
|
||||||
if (c == color.NRGBA{0, 0, 0, 0}) {
|
|
||||||
return image.NewNRGBA(image.Rect(0, 0, width, height))
|
|
||||||
}
|
|
||||||
|
|
||||||
return &image.NRGBA{
|
|
||||||
Pix: bytes.Repeat([]byte{c.R, c.G, c.B, c.A}, width*height),
|
|
||||||
Stride: 4 * width,
|
|
||||||
Rect: image.Rect(0, 0, width, height),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clone returns a copy of the given image.
|
|
||||||
func Clone(img image.Image) *image.NRGBA {
|
|
||||||
src := newScanner(img)
|
|
||||||
dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
|
|
||||||
size := src.w * 4
|
|
||||||
parallel(0, src.h, func(ys <-chan int) {
|
|
||||||
for y := range ys {
|
|
||||||
i := y * dst.Stride
|
|
||||||
src.scan(0, y, src.w, y+1, dst.Pix[i:i+size])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
// Anchor is the anchor point for image alignment.
|
|
||||||
type Anchor int
|
|
||||||
|
|
||||||
// Anchor point positions.
|
|
||||||
const (
|
|
||||||
Center Anchor = iota
|
|
||||||
TopLeft
|
|
||||||
Top
|
|
||||||
TopRight
|
|
||||||
Left
|
|
||||||
Right
|
|
||||||
BottomLeft
|
|
||||||
Bottom
|
|
||||||
BottomRight
|
|
||||||
)
|
|
||||||
|
|
||||||
func anchorPt(b image.Rectangle, w, h int, anchor Anchor) image.Point {
|
|
||||||
var x, y int
|
|
||||||
switch anchor {
|
|
||||||
case TopLeft:
|
|
||||||
x = b.Min.X
|
|
||||||
y = b.Min.Y
|
|
||||||
case Top:
|
|
||||||
x = b.Min.X + (b.Dx()-w)/2
|
|
||||||
y = b.Min.Y
|
|
||||||
case TopRight:
|
|
||||||
x = b.Max.X - w
|
|
||||||
y = b.Min.Y
|
|
||||||
case Left:
|
|
||||||
x = b.Min.X
|
|
||||||
y = b.Min.Y + (b.Dy()-h)/2
|
|
||||||
case Right:
|
|
||||||
x = b.Max.X - w
|
|
||||||
y = b.Min.Y + (b.Dy()-h)/2
|
|
||||||
case BottomLeft:
|
|
||||||
x = b.Min.X
|
|
||||||
y = b.Max.Y - h
|
|
||||||
case Bottom:
|
|
||||||
x = b.Min.X + (b.Dx()-w)/2
|
|
||||||
y = b.Max.Y - h
|
|
||||||
case BottomRight:
|
|
||||||
x = b.Max.X - w
|
|
||||||
y = b.Max.Y - h
|
|
||||||
default:
|
|
||||||
x = b.Min.X + (b.Dx()-w)/2
|
|
||||||
y = b.Min.Y + (b.Dy()-h)/2
|
|
||||||
}
|
|
||||||
return image.Pt(x, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Crop cuts out a rectangular region with the specified bounds
|
|
||||||
// from the image and returns the cropped image.
|
|
||||||
func Crop(img image.Image, rect image.Rectangle) *image.NRGBA {
|
|
||||||
r := rect.Intersect(img.Bounds()).Sub(img.Bounds().Min)
|
|
||||||
if r.Empty() {
|
|
||||||
return &image.NRGBA{}
|
|
||||||
}
|
|
||||||
src := newScanner(img)
|
|
||||||
dst := image.NewNRGBA(image.Rect(0, 0, r.Dx(), r.Dy()))
|
|
||||||
rowSize := r.Dx() * 4
|
|
||||||
parallel(r.Min.Y, r.Max.Y, func(ys <-chan int) {
|
|
||||||
for y := range ys {
|
|
||||||
i := (y - r.Min.Y) * dst.Stride
|
|
||||||
src.scan(r.Min.X, y, r.Max.X, y+1, dst.Pix[i:i+rowSize])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
// CropAnchor cuts out a rectangular region with the specified size
|
|
||||||
// from the image using the specified anchor point and returns the cropped image.
|
|
||||||
func CropAnchor(img image.Image, width, height int, anchor Anchor) *image.NRGBA {
|
|
||||||
srcBounds := img.Bounds()
|
|
||||||
pt := anchorPt(srcBounds, width, height, anchor)
|
|
||||||
r := image.Rect(0, 0, width, height).Add(pt)
|
|
||||||
b := srcBounds.Intersect(r)
|
|
||||||
return Crop(img, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CropCenter cuts out a rectangular region with the specified size
|
|
||||||
// from the center of the image and returns the cropped image.
|
|
||||||
func CropCenter(img image.Image, width, height int) *image.NRGBA {
|
|
||||||
return CropAnchor(img, width, height, Center)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Paste pastes the img image to the background image at the specified position and returns the combined image.
|
|
||||||
func Paste(background, img image.Image, pos image.Point) *image.NRGBA {
|
|
||||||
dst := Clone(background)
|
|
||||||
pos = pos.Sub(background.Bounds().Min)
|
|
||||||
pasteRect := image.Rectangle{Min: pos, Max: pos.Add(img.Bounds().Size())}
|
|
||||||
interRect := pasteRect.Intersect(dst.Bounds())
|
|
||||||
if interRect.Empty() {
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
src := newScanner(img)
|
|
||||||
parallel(interRect.Min.Y, interRect.Max.Y, func(ys <-chan int) {
|
|
||||||
for y := range ys {
|
|
||||||
x1 := interRect.Min.X - pasteRect.Min.X
|
|
||||||
x2 := interRect.Max.X - pasteRect.Min.X
|
|
||||||
y1 := y - pasteRect.Min.Y
|
|
||||||
y2 := y1 + 1
|
|
||||||
i1 := y*dst.Stride + interRect.Min.X*4
|
|
||||||
i2 := i1 + interRect.Dx()*4
|
|
||||||
src.scan(x1, y1, x2, y2, dst.Pix[i1:i2])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
// PasteCenter pastes the img image to the center of the background image and returns the combined image.
|
|
||||||
func PasteCenter(background, img image.Image) *image.NRGBA {
|
|
||||||
bgBounds := background.Bounds()
|
|
||||||
bgW := bgBounds.Dx()
|
|
||||||
bgH := bgBounds.Dy()
|
|
||||||
bgMinX := bgBounds.Min.X
|
|
||||||
bgMinY := bgBounds.Min.Y
|
|
||||||
|
|
||||||
centerX := bgMinX + bgW/2
|
|
||||||
centerY := bgMinY + bgH/2
|
|
||||||
|
|
||||||
x0 := centerX - img.Bounds().Dx()/2
|
|
||||||
y0 := centerY - img.Bounds().Dy()/2
|
|
||||||
|
|
||||||
return Paste(background, img, image.Pt(x0, y0))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overlay draws the img image over the background image at given position
|
|
||||||
// and returns the combined image. Opacity parameter is the opacity of the img
|
|
||||||
// image layer, used to compose the images, it must be from 0.0 to 1.0.
|
|
||||||
//
|
|
||||||
// Examples:
|
|
||||||
//
|
|
||||||
// // Draw spriteImage over backgroundImage at the given position (x=50, y=50).
|
|
||||||
// dstImage := imaging.Overlay(backgroundImage, spriteImage, image.Pt(50, 50), 1.0)
|
|
||||||
//
|
|
||||||
// // Blend two opaque images of the same size.
|
|
||||||
// dstImage := imaging.Overlay(imageOne, imageTwo, image.Pt(0, 0), 0.5)
|
|
||||||
//
|
|
||||||
func Overlay(background, img image.Image, pos image.Point, opacity float64) *image.NRGBA {
|
|
||||||
opacity = math.Min(math.Max(opacity, 0.0), 1.0) // Ensure 0.0 <= opacity <= 1.0.
|
|
||||||
dst := Clone(background)
|
|
||||||
pos = pos.Sub(background.Bounds().Min)
|
|
||||||
pasteRect := image.Rectangle{Min: pos, Max: pos.Add(img.Bounds().Size())}
|
|
||||||
interRect := pasteRect.Intersect(dst.Bounds())
|
|
||||||
if interRect.Empty() {
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
src := newScanner(img)
|
|
||||||
parallel(interRect.Min.Y, interRect.Max.Y, func(ys <-chan int) {
|
|
||||||
scanLine := make([]uint8, interRect.Dx()*4)
|
|
||||||
for y := range ys {
|
|
||||||
x1 := interRect.Min.X - pasteRect.Min.X
|
|
||||||
x2 := interRect.Max.X - pasteRect.Min.X
|
|
||||||
y1 := y - pasteRect.Min.Y
|
|
||||||
y2 := y1 + 1
|
|
||||||
src.scan(x1, y1, x2, y2, scanLine)
|
|
||||||
i := y*dst.Stride + interRect.Min.X*4
|
|
||||||
j := 0
|
|
||||||
for x := interRect.Min.X; x < interRect.Max.X; x++ {
|
|
||||||
d := dst.Pix[i : i+4 : i+4]
|
|
||||||
r1 := float64(d[0])
|
|
||||||
g1 := float64(d[1])
|
|
||||||
b1 := float64(d[2])
|
|
||||||
a1 := float64(d[3])
|
|
||||||
|
|
||||||
s := scanLine[j : j+4 : j+4]
|
|
||||||
r2 := float64(s[0])
|
|
||||||
g2 := float64(s[1])
|
|
||||||
b2 := float64(s[2])
|
|
||||||
a2 := float64(s[3])
|
|
||||||
|
|
||||||
coef2 := opacity * a2 / 255
|
|
||||||
coef1 := (1 - coef2) * a1 / 255
|
|
||||||
coefSum := coef1 + coef2
|
|
||||||
coef1 /= coefSum
|
|
||||||
coef2 /= coefSum
|
|
||||||
|
|
||||||
d[0] = uint8(r1*coef1 + r2*coef2)
|
|
||||||
d[1] = uint8(g1*coef1 + g2*coef2)
|
|
||||||
d[2] = uint8(b1*coef1 + b2*coef2)
|
|
||||||
d[3] = uint8(math.Min(a1+a2*opacity*(255-a1)/255, 255))
|
|
||||||
|
|
||||||
i += 4
|
|
||||||
j += 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
// OverlayCenter overlays the img image to the center of the background image and
|
|
||||||
// returns the combined image. Opacity parameter is the opacity of the img
|
|
||||||
// image layer, used to compose the images, it must be from 0.0 to 1.0.
|
|
||||||
func OverlayCenter(background, img image.Image, opacity float64) *image.NRGBA {
|
|
||||||
bgBounds := background.Bounds()
|
|
||||||
bgW := bgBounds.Dx()
|
|
||||||
bgH := bgBounds.Dy()
|
|
||||||
bgMinX := bgBounds.Min.X
|
|
||||||
bgMinY := bgBounds.Min.Y
|
|
||||||
|
|
||||||
centerX := bgMinX + bgW/2
|
|
||||||
centerY := bgMinY + bgH/2
|
|
||||||
|
|
||||||
x0 := centerX - img.Bounds().Dx()/2
|
|
||||||
y0 := centerY - img.Bounds().Dy()/2
|
|
||||||
|
|
||||||
return Overlay(background, img, image.Point{x0, y0}, opacity)
|
|
||||||
}
|
|
268
vendor/github.com/disintegration/imaging/transform.go
generated
vendored
268
vendor/github.com/disintegration/imaging/transform.go
generated
vendored
@ -1,268 +0,0 @@
|
|||||||
package imaging
|
|
||||||
|
|
||||||
import (
|
|
||||||
"image"
|
|
||||||
"image/color"
|
|
||||||
"math"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FlipH flips the image horizontally (from left to right) and returns the transformed image.
|
|
||||||
func FlipH(img image.Image) *image.NRGBA {
|
|
||||||
src := newScanner(img)
|
|
||||||
dstW := src.w
|
|
||||||
dstH := src.h
|
|
||||||
rowSize := dstW * 4
|
|
||||||
dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
|
|
||||||
parallel(0, dstH, func(ys <-chan int) {
|
|
||||||
for dstY := range ys {
|
|
||||||
i := dstY * dst.Stride
|
|
||||||
srcY := dstY
|
|
||||||
src.scan(0, srcY, src.w, srcY+1, dst.Pix[i:i+rowSize])
|
|
||||||
reverse(dst.Pix[i : i+rowSize])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
// FlipV flips the image vertically (from top to bottom) and returns the transformed image.
|
|
||||||
func FlipV(img image.Image) *image.NRGBA {
|
|
||||||
src := newScanner(img)
|
|
||||||
dstW := src.w
|
|
||||||
dstH := src.h
|
|
||||||
rowSize := dstW * 4
|
|
||||||
dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
|
|
||||||
parallel(0, dstH, func(ys <-chan int) {
|
|
||||||
for dstY := range ys {
|
|
||||||
i := dstY * dst.Stride
|
|
||||||
srcY := dstH - dstY - 1
|
|
||||||
src.scan(0, srcY, src.w, srcY+1, dst.Pix[i:i+rowSize])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transpose flips the image horizontally and rotates 90 degrees counter-clockwise.
|
|
||||||
func Transpose(img image.Image) *image.NRGBA {
|
|
||||||
src := newScanner(img)
|
|
||||||
dstW := src.h
|
|
||||||
dstH := src.w
|
|
||||||
rowSize := dstW * 4
|
|
||||||
dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
|
|
||||||
parallel(0, dstH, func(ys <-chan int) {
|
|
||||||
for dstY := range ys {
|
|
||||||
i := dstY * dst.Stride
|
|
||||||
srcX := dstY
|
|
||||||
src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transverse flips the image vertically and rotates 90 degrees counter-clockwise.
|
|
||||||
func Transverse(img image.Image) *image.NRGBA {
|
|
||||||
src := newScanner(img)
|
|
||||||
dstW := src.h
|
|
||||||
dstH := src.w
|
|
||||||
rowSize := dstW * 4
|
|
||||||
dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
|
|
||||||
parallel(0, dstH, func(ys <-chan int) {
|
|
||||||
for dstY := range ys {
|
|
||||||
i := dstY * dst.Stride
|
|
||||||
srcX := dstH - dstY - 1
|
|
||||||
src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize])
|
|
||||||
reverse(dst.Pix[i : i+rowSize])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rotate90 rotates the image 90 degrees counter-clockwise and returns the transformed image.
|
|
||||||
func Rotate90(img image.Image) *image.NRGBA {
|
|
||||||
src := newScanner(img)
|
|
||||||
dstW := src.h
|
|
||||||
dstH := src.w
|
|
||||||
rowSize := dstW * 4
|
|
||||||
dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
|
|
||||||
parallel(0, dstH, func(ys <-chan int) {
|
|
||||||
for dstY := range ys {
|
|
||||||
i := dstY * dst.Stride
|
|
||||||
srcX := dstH - dstY - 1
|
|
||||||
src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rotate180 rotates the image 180 degrees counter-clockwise and returns the transformed image.
|
|
||||||
func Rotate180(img image.Image) *image.NRGBA {
|
|
||||||
src := newScanner(img)
|
|
||||||
dstW := src.w
|
|
||||||
dstH := src.h
|
|
||||||
rowSize := dstW * 4
|
|
||||||
dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
|
|
||||||
parallel(0, dstH, func(ys <-chan int) {
|
|
||||||
for dstY := range ys {
|
|
||||||
i := dstY * dst.Stride
|
|
||||||
srcY := dstH - dstY - 1
|
|
||||||
src.scan(0, srcY, src.w, srcY+1, dst.Pix[i:i+rowSize])
|
|
||||||
reverse(dst.Pix[i : i+rowSize])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rotate270 rotates the image 270 degrees counter-clockwise and returns the transformed image.
|
|
||||||
func Rotate270(img image.Image) *image.NRGBA {
|
|
||||||
src := newScanner(img)
|
|
||||||
dstW := src.h
|
|
||||||
dstH := src.w
|
|
||||||
rowSize := dstW * 4
|
|
||||||
dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
|
|
||||||
parallel(0, dstH, func(ys <-chan int) {
|
|
||||||
for dstY := range ys {
|
|
||||||
i := dstY * dst.Stride
|
|
||||||
srcX := dstY
|
|
||||||
src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize])
|
|
||||||
reverse(dst.Pix[i : i+rowSize])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rotate rotates an image by the given angle counter-clockwise .
|
|
||||||
// The angle parameter is the rotation angle in degrees.
|
|
||||||
// The bgColor parameter specifies the color of the uncovered zone after the rotation.
|
|
||||||
func Rotate(img image.Image, angle float64, bgColor color.Color) *image.NRGBA {
|
|
||||||
angle = angle - math.Floor(angle/360)*360
|
|
||||||
|
|
||||||
switch angle {
|
|
||||||
case 0:
|
|
||||||
return Clone(img)
|
|
||||||
case 90:
|
|
||||||
return Rotate90(img)
|
|
||||||
case 180:
|
|
||||||
return Rotate180(img)
|
|
||||||
case 270:
|
|
||||||
return Rotate270(img)
|
|
||||||
}
|
|
||||||
|
|
||||||
src := toNRGBA(img)
|
|
||||||
srcW := src.Bounds().Max.X
|
|
||||||
srcH := src.Bounds().Max.Y
|
|
||||||
dstW, dstH := rotatedSize(srcW, srcH, angle)
|
|
||||||
dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
|
|
||||||
|
|
||||||
if dstW <= 0 || dstH <= 0 {
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
srcXOff := float64(srcW)/2 - 0.5
|
|
||||||
srcYOff := float64(srcH)/2 - 0.5
|
|
||||||
dstXOff := float64(dstW)/2 - 0.5
|
|
||||||
dstYOff := float64(dstH)/2 - 0.5
|
|
||||||
|
|
||||||
bgColorNRGBA := color.NRGBAModel.Convert(bgColor).(color.NRGBA)
|
|
||||||
sin, cos := math.Sincos(math.Pi * angle / 180)
|
|
||||||
|
|
||||||
parallel(0, dstH, func(ys <-chan int) {
|
|
||||||
for dstY := range ys {
|
|
||||||
for dstX := 0; dstX < dstW; dstX++ {
|
|
||||||
xf, yf := rotatePoint(float64(dstX)-dstXOff, float64(dstY)-dstYOff, sin, cos)
|
|
||||||
xf, yf = xf+srcXOff, yf+srcYOff
|
|
||||||
interpolatePoint(dst, dstX, dstY, src, xf, yf, bgColorNRGBA)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
func rotatePoint(x, y, sin, cos float64) (float64, float64) {
|
|
||||||
return x*cos - y*sin, x*sin + y*cos
|
|
||||||
}
|
|
||||||
|
|
||||||
func rotatedSize(w, h int, angle float64) (int, int) {
|
|
||||||
if w <= 0 || h <= 0 {
|
|
||||||
return 0, 0
|
|
||||||
}
|
|
||||||
|
|
||||||
sin, cos := math.Sincos(math.Pi * angle / 180)
|
|
||||||
x1, y1 := rotatePoint(float64(w-1), 0, sin, cos)
|
|
||||||
x2, y2 := rotatePoint(float64(w-1), float64(h-1), sin, cos)
|
|
||||||
x3, y3 := rotatePoint(0, float64(h-1), sin, cos)
|
|
||||||
|
|
||||||
minx := math.Min(x1, math.Min(x2, math.Min(x3, 0)))
|
|
||||||
maxx := math.Max(x1, math.Max(x2, math.Max(x3, 0)))
|
|
||||||
miny := math.Min(y1, math.Min(y2, math.Min(y3, 0)))
|
|
||||||
maxy := math.Max(y1, math.Max(y2, math.Max(y3, 0)))
|
|
||||||
|
|
||||||
neww := maxx - minx + 1
|
|
||||||
if neww-math.Floor(neww) > 0.1 {
|
|
||||||
neww++
|
|
||||||
}
|
|
||||||
newh := maxy - miny + 1
|
|
||||||
if newh-math.Floor(newh) > 0.1 {
|
|
||||||
newh++
|
|
||||||
}
|
|
||||||
|
|
||||||
return int(neww), int(newh)
|
|
||||||
}
|
|
||||||
|
|
||||||
func interpolatePoint(dst *image.NRGBA, dstX, dstY int, src *image.NRGBA, xf, yf float64, bgColor color.NRGBA) {
|
|
||||||
j := dstY*dst.Stride + dstX*4
|
|
||||||
d := dst.Pix[j : j+4 : j+4]
|
|
||||||
|
|
||||||
x0 := int(math.Floor(xf))
|
|
||||||
y0 := int(math.Floor(yf))
|
|
||||||
bounds := src.Bounds()
|
|
||||||
if !image.Pt(x0, y0).In(image.Rect(bounds.Min.X-1, bounds.Min.Y-1, bounds.Max.X, bounds.Max.Y)) {
|
|
||||||
d[0] = bgColor.R
|
|
||||||
d[1] = bgColor.G
|
|
||||||
d[2] = bgColor.B
|
|
||||||
d[3] = bgColor.A
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
xq := xf - float64(x0)
|
|
||||||
yq := yf - float64(y0)
|
|
||||||
points := [4]image.Point{
|
|
||||||
{x0, y0},
|
|
||||||
{x0 + 1, y0},
|
|
||||||
{x0, y0 + 1},
|
|
||||||
{x0 + 1, y0 + 1},
|
|
||||||
}
|
|
||||||
weights := [4]float64{
|
|
||||||
(1 - xq) * (1 - yq),
|
|
||||||
xq * (1 - yq),
|
|
||||||
(1 - xq) * yq,
|
|
||||||
xq * yq,
|
|
||||||
}
|
|
||||||
|
|
||||||
var r, g, b, a float64
|
|
||||||
for i := 0; i < 4; i++ {
|
|
||||||
p := points[i]
|
|
||||||
w := weights[i]
|
|
||||||
if p.In(bounds) {
|
|
||||||
i := p.Y*src.Stride + p.X*4
|
|
||||||
s := src.Pix[i : i+4 : i+4]
|
|
||||||
wa := float64(s[3]) * w
|
|
||||||
r += float64(s[0]) * wa
|
|
||||||
g += float64(s[1]) * wa
|
|
||||||
b += float64(s[2]) * wa
|
|
||||||
a += wa
|
|
||||||
} else {
|
|
||||||
wa := float64(bgColor.A) * w
|
|
||||||
r += float64(bgColor.R) * wa
|
|
||||||
g += float64(bgColor.G) * wa
|
|
||||||
b += float64(bgColor.B) * wa
|
|
||||||
a += wa
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if a != 0 {
|
|
||||||
aInv := 1 / a
|
|
||||||
d[0] = clamp(r * aInv)
|
|
||||||
d[1] = clamp(g * aInv)
|
|
||||||
d[2] = clamp(b * aInv)
|
|
||||||
d[3] = clamp(a)
|
|
||||||
}
|
|
||||||
}
|
|
167
vendor/github.com/disintegration/imaging/utils.go
generated
vendored
167
vendor/github.com/disintegration/imaging/utils.go
generated
vendored
@ -1,167 +0,0 @@
|
|||||||
package imaging
|
|
||||||
|
|
||||||
import (
|
|
||||||
"image"
|
|
||||||
"math"
|
|
||||||
"runtime"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// parallel processes the data in separate goroutines.
|
|
||||||
func parallel(start, stop int, fn func(<-chan int)) {
|
|
||||||
count := stop - start
|
|
||||||
if count < 1 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
procs := runtime.GOMAXPROCS(0)
|
|
||||||
if procs > count {
|
|
||||||
procs = count
|
|
||||||
}
|
|
||||||
|
|
||||||
c := make(chan int, count)
|
|
||||||
for i := start; i < stop; i++ {
|
|
||||||
c <- i
|
|
||||||
}
|
|
||||||
close(c)
|
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
for i := 0; i < procs; i++ {
|
|
||||||
wg.Add(1)
|
|
||||||
go func() {
|
|
||||||
defer wg.Done()
|
|
||||||
fn(c)
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
wg.Wait()
|
|
||||||
}
|
|
||||||
|
|
||||||
// absint returns the absolute value of i.
|
|
||||||
func absint(i int) int {
|
|
||||||
if i < 0 {
|
|
||||||
return -i
|
|
||||||
}
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
|
|
||||||
// clamp rounds and clamps float64 value to fit into uint8.
|
|
||||||
func clamp(x float64) uint8 {
|
|
||||||
v := int64(x + 0.5)
|
|
||||||
if v > 255 {
|
|
||||||
return 255
|
|
||||||
}
|
|
||||||
if v > 0 {
|
|
||||||
return uint8(v)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func reverse(pix []uint8) {
|
|
||||||
if len(pix) <= 4 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
i := 0
|
|
||||||
j := len(pix) - 4
|
|
||||||
for i < j {
|
|
||||||
pi := pix[i : i+4 : i+4]
|
|
||||||
pj := pix[j : j+4 : j+4]
|
|
||||||
pi[0], pj[0] = pj[0], pi[0]
|
|
||||||
pi[1], pj[1] = pj[1], pi[1]
|
|
||||||
pi[2], pj[2] = pj[2], pi[2]
|
|
||||||
pi[3], pj[3] = pj[3], pi[3]
|
|
||||||
i += 4
|
|
||||||
j -= 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func toNRGBA(img image.Image) *image.NRGBA {
|
|
||||||
if img, ok := img.(*image.NRGBA); ok {
|
|
||||||
return &image.NRGBA{
|
|
||||||
Pix: img.Pix,
|
|
||||||
Stride: img.Stride,
|
|
||||||
Rect: img.Rect.Sub(img.Rect.Min),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Clone(img)
|
|
||||||
}
|
|
||||||
|
|
||||||
// rgbToHSL converts a color from RGB to HSL.
|
|
||||||
func rgbToHSL(r, g, b uint8) (float64, float64, float64) {
|
|
||||||
rr := float64(r) / 255
|
|
||||||
gg := float64(g) / 255
|
|
||||||
bb := float64(b) / 255
|
|
||||||
|
|
||||||
max := math.Max(rr, math.Max(gg, bb))
|
|
||||||
min := math.Min(rr, math.Min(gg, bb))
|
|
||||||
|
|
||||||
l := (max + min) / 2
|
|
||||||
|
|
||||||
if max == min {
|
|
||||||
return 0, 0, l
|
|
||||||
}
|
|
||||||
|
|
||||||
var h, s float64
|
|
||||||
d := max - min
|
|
||||||
if l > 0.5 {
|
|
||||||
s = d / (2 - max - min)
|
|
||||||
} else {
|
|
||||||
s = d / (max + min)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch max {
|
|
||||||
case rr:
|
|
||||||
h = (gg - bb) / d
|
|
||||||
if g < b {
|
|
||||||
h += 6
|
|
||||||
}
|
|
||||||
case gg:
|
|
||||||
h = (bb-rr)/d + 2
|
|
||||||
case bb:
|
|
||||||
h = (rr-gg)/d + 4
|
|
||||||
}
|
|
||||||
h /= 6
|
|
||||||
|
|
||||||
return h, s, l
|
|
||||||
}
|
|
||||||
|
|
||||||
// hslToRGB converts a color from HSL to RGB.
|
|
||||||
func hslToRGB(h, s, l float64) (uint8, uint8, uint8) {
|
|
||||||
var r, g, b float64
|
|
||||||
if s == 0 {
|
|
||||||
v := clamp(l * 255)
|
|
||||||
return v, v, v
|
|
||||||
}
|
|
||||||
|
|
||||||
var q float64
|
|
||||||
if l < 0.5 {
|
|
||||||
q = l * (1 + s)
|
|
||||||
} else {
|
|
||||||
q = l + s - l*s
|
|
||||||
}
|
|
||||||
p := 2*l - q
|
|
||||||
|
|
||||||
r = hueToRGB(p, q, h+1/3.0)
|
|
||||||
g = hueToRGB(p, q, h)
|
|
||||||
b = hueToRGB(p, q, h-1/3.0)
|
|
||||||
|
|
||||||
return clamp(r * 255), clamp(g * 255), clamp(b * 255)
|
|
||||||
}
|
|
||||||
|
|
||||||
func hueToRGB(p, q, t float64) float64 {
|
|
||||||
if t < 0 {
|
|
||||||
t++
|
|
||||||
}
|
|
||||||
if t > 1 {
|
|
||||||
t--
|
|
||||||
}
|
|
||||||
if t < 1/6.0 {
|
|
||||||
return p + (q-p)*6*t
|
|
||||||
}
|
|
||||||
if t < 1/2.0 {
|
|
||||||
return q
|
|
||||||
}
|
|
||||||
if t < 2/3.0 {
|
|
||||||
return p + (q-p)*(2/3.0-t)*6
|
|
||||||
}
|
|
||||||
return p
|
|
||||||
}
|
|
24
vendor/github.com/francoispqt/gojay/go.mod
generated
vendored
24
vendor/github.com/francoispqt/gojay/go.mod
generated
vendored
@ -1,24 +0,0 @@
|
|||||||
module github.com/francoispqt/gojay
|
|
||||||
|
|
||||||
go 1.12
|
|
||||||
|
|
||||||
require (
|
|
||||||
cloud.google.com/go v0.37.0 // indirect
|
|
||||||
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23
|
|
||||||
github.com/go-errors/errors v1.0.1
|
|
||||||
github.com/golang/protobuf v1.3.1 // indirect
|
|
||||||
github.com/json-iterator/go v1.1.6
|
|
||||||
github.com/lunixbochs/vtclean v1.0.0 // indirect
|
|
||||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
|
||||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
|
||||||
github.com/pkg/errors v0.8.1 // indirect
|
|
||||||
github.com/stretchr/testify v1.2.2
|
|
||||||
github.com/viant/assertly v0.4.8
|
|
||||||
github.com/viant/toolbox v0.24.0
|
|
||||||
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a // indirect
|
|
||||||
golang.org/x/net v0.0.0-20190313220215-9f648a60d977
|
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421 // indirect
|
|
||||||
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f // indirect
|
|
||||||
gopkg.in/yaml.v2 v2.2.2 // indirect
|
|
||||||
)
|
|
182
vendor/github.com/francoispqt/gojay/go.sum
generated
vendored
182
vendor/github.com/francoispqt/gojay/go.sum
generated
vendored
@ -1,182 +0,0 @@
|
|||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
|
||||||
cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
|
||||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
|
||||||
cloud.google.com/go v0.37.0 h1:69FNAINiZfsEuwH3fKq8QrAAnHz+2m4XL4kVYi5BX0Q=
|
|
||||||
cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo=
|
|
||||||
dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
|
|
||||||
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
|
|
||||||
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
|
|
||||||
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
|
|
||||||
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
|
||||||
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
|
|
||||||
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23 h1:D21IyuvjDCshj1/qq+pCNd3VZOAEI9jy6Bi131YlXgI=
|
|
||||||
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
|
||||||
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
|
||||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
|
||||||
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
|
||||||
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
|
|
||||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
|
||||||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
|
||||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
|
||||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
|
||||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
|
||||||
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
|
||||||
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
|
||||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
|
||||||
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
|
|
||||||
github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs=
|
|
||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|
||||||
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|
||||||
github.com/lunixbochs/vtclean v1.0.0 h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+LVb8=
|
|
||||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
|
||||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe h1:W/GaMY0y69G4cFlmsC6B9sbuo2fP8OFP1ABjt4kPz+w=
|
|
||||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
|
||||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
|
||||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
|
||||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
|
||||||
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
|
||||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
|
||||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
|
||||||
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
|
||||||
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
|
||||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
|
||||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
|
||||||
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
|
|
||||||
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
|
|
||||||
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
|
|
||||||
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
|
|
||||||
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
|
|
||||||
github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw=
|
|
||||||
github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI=
|
|
||||||
github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU=
|
|
||||||
github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag=
|
|
||||||
github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg=
|
|
||||||
github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw=
|
|
||||||
github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y=
|
|
||||||
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
|
||||||
github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q=
|
|
||||||
github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ=
|
|
||||||
github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I=
|
|
||||||
github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0=
|
|
||||||
github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
|
|
||||||
github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk=
|
|
||||||
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
|
||||||
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
|
|
||||||
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
|
|
||||||
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
|
|
||||||
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
|
|
||||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
|
||||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
|
||||||
github.com/viant/assertly v0.4.8 h1:5x1GzBaRteIwTr5RAGFVG14uNeRFxVNbXPWrK2qAgpc=
|
|
||||||
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
|
||||||
github.com/viant/toolbox v0.24.0 h1:6TteTDQ68CjgcCe8wH3D3ZhUQQOJXMTbj/D9rkk2a1k=
|
|
||||||
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
|
|
||||||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
|
||||||
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
|
||||||
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
|
|
||||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
|
||||||
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a h1:YX8ljsm6wXlHZO+aRz9Exqr0evNhKRNe5K/gi+zKh4U=
|
|
||||||
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
|
||||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190313220215-9f648a60d977 h1:actzWV6iWn3GLqN8dZjzsB+CLt+gaV2+wsxroxiQI8I=
|
|
||||||
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421 h1:Wo7BWFiOk0QRFMLYMqJGFMd9CgUAcGx7V+qEg/h5IBI=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
|
||||||
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
|
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f h1:yCrMx/EeIue0+Qca57bWZS7VX6ymEoypmhWyPhz0NHM=
|
|
||||||
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
|
||||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
|
||||||
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
|
||||||
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
|
||||||
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
|
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
|
||||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
|
||||||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
|
||||||
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
|
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
|
||||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
|
||||||
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
|
||||||
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
|
|
||||||
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
|
||||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
|
||||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
|
||||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
|
||||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
|
|
||||||
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
|
|
2
vendor/github.com/fsnotify/fsnotify/.mailmap
generated
vendored
Normal file
2
vendor/github.com/fsnotify/fsnotify/.mailmap
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Chris Howey <howeyc@gmail.com> <chris@howey.me>
|
||||||
|
Nathan Youngman <git@nathany.com> <4566+nathany@users.noreply.github.com>
|
36
vendor/github.com/fsnotify/fsnotify/.travis.yml
generated
vendored
36
vendor/github.com/fsnotify/fsnotify/.travis.yml
generated
vendored
@ -1,36 +0,0 @@
|
|||||||
sudo: false
|
|
||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- "stable"
|
|
||||||
- "1.11.x"
|
|
||||||
- "1.10.x"
|
|
||||||
- "1.9.x"
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- go: "stable"
|
|
||||||
env: GOLINT=true
|
|
||||||
allow_failures:
|
|
||||||
- go: tip
|
|
||||||
fast_finish: true
|
|
||||||
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- if [ ! -z "${GOLINT}" ]; then go get -u golang.org/x/lint/golint; fi
|
|
||||||
|
|
||||||
script:
|
|
||||||
- go test --race ./...
|
|
||||||
|
|
||||||
after_script:
|
|
||||||
- test -z "$(gofmt -s -l -w . | tee /dev/stderr)"
|
|
||||||
- if [ ! -z "${GOLINT}" ]; then echo running golint; golint --set_exit_status ./...; else echo skipping golint; fi
|
|
||||||
- go vet ./...
|
|
||||||
|
|
||||||
os:
|
|
||||||
- linux
|
|
||||||
- osx
|
|
||||||
- windows
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
email: false
|
|
16
vendor/github.com/fsnotify/fsnotify/AUTHORS
generated
vendored
16
vendor/github.com/fsnotify/fsnotify/AUTHORS
generated
vendored
@ -4,35 +4,44 @@
|
|||||||
|
|
||||||
# You can update this list using the following command:
|
# You can update this list using the following command:
|
||||||
#
|
#
|
||||||
# $ git shortlog -se | awk '{print $2 " " $3 " " $4}'
|
# $ (head -n10 AUTHORS && git shortlog -se | sed -E 's/^\s+[0-9]+\t//') | tee AUTHORS
|
||||||
|
|
||||||
# Please keep the list sorted.
|
# Please keep the list sorted.
|
||||||
|
|
||||||
Aaron L <aaron@bettercoder.net>
|
Aaron L <aaron@bettercoder.net>
|
||||||
Adrien Bustany <adrien@bustany.org>
|
Adrien Bustany <adrien@bustany.org>
|
||||||
|
Alexey Kazakov <alkazako@redhat.com>
|
||||||
Amit Krishnan <amit.krishnan@oracle.com>
|
Amit Krishnan <amit.krishnan@oracle.com>
|
||||||
Anmol Sethi <me@anmol.io>
|
Anmol Sethi <me@anmol.io>
|
||||||
Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
|
Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
|
||||||
|
Brian Goff <cpuguy83@gmail.com>
|
||||||
Bruno Bigras <bigras.bruno@gmail.com>
|
Bruno Bigras <bigras.bruno@gmail.com>
|
||||||
Caleb Spare <cespare@gmail.com>
|
Caleb Spare <cespare@gmail.com>
|
||||||
Case Nelson <case@teammating.com>
|
Case Nelson <case@teammating.com>
|
||||||
Chris Howey <chris@howey.me> <howeyc@gmail.com>
|
Chris Howey <howeyc@gmail.com>
|
||||||
Christoffer Buchholz <christoffer.buchholz@gmail.com>
|
Christoffer Buchholz <christoffer.buchholz@gmail.com>
|
||||||
Daniel Wagner-Hall <dawagner@gmail.com>
|
Daniel Wagner-Hall <dawagner@gmail.com>
|
||||||
Dave Cheney <dave@cheney.net>
|
Dave Cheney <dave@cheney.net>
|
||||||
|
Eric Lin <linxiulei@gmail.com>
|
||||||
Evan Phoenix <evan@fallingsnow.net>
|
Evan Phoenix <evan@fallingsnow.net>
|
||||||
Francisco Souza <f@souza.cc>
|
Francisco Souza <f@souza.cc>
|
||||||
|
Gautam Dey <gautam.dey77@gmail.com>
|
||||||
Hari haran <hariharan.uno@gmail.com>
|
Hari haran <hariharan.uno@gmail.com>
|
||||||
John C Barstow
|
Ichinose Shogo <shogo82148@gmail.com>
|
||||||
|
Johannes Ebke <johannes@ebke.org>
|
||||||
|
John C Barstow <jbowtie@amathaine.com>
|
||||||
Kelvin Fo <vmirage@gmail.com>
|
Kelvin Fo <vmirage@gmail.com>
|
||||||
Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp>
|
Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp>
|
||||||
Matt Layher <mdlayher@gmail.com>
|
Matt Layher <mdlayher@gmail.com>
|
||||||
|
Matthias Stone <matthias@bellstone.ca>
|
||||||
Nathan Youngman <git@nathany.com>
|
Nathan Youngman <git@nathany.com>
|
||||||
Nickolai Zeldovich <nickolai@csail.mit.edu>
|
Nickolai Zeldovich <nickolai@csail.mit.edu>
|
||||||
|
Oliver Bristow <evilumbrella+github@gmail.com>
|
||||||
Patrick <patrick@dropbox.com>
|
Patrick <patrick@dropbox.com>
|
||||||
Paul Hammond <paul@paulhammond.org>
|
Paul Hammond <paul@paulhammond.org>
|
||||||
Pawel Knap <pawelknap88@gmail.com>
|
Pawel Knap <pawelknap88@gmail.com>
|
||||||
Pieter Droogendijk <pieter@binky.org.uk>
|
Pieter Droogendijk <pieter@binky.org.uk>
|
||||||
|
Pratik Shinde <pratikshinde320@gmail.com>
|
||||||
Pursuit92 <JoshChase@techpursuit.net>
|
Pursuit92 <JoshChase@techpursuit.net>
|
||||||
Riku Voipio <riku.voipio@linaro.org>
|
Riku Voipio <riku.voipio@linaro.org>
|
||||||
Rob Figueiredo <robfig@gmail.com>
|
Rob Figueiredo <robfig@gmail.com>
|
||||||
@ -41,6 +50,7 @@ Slawek Ligus <root@ooz.ie>
|
|||||||
Soge Zhang <zhssoge@gmail.com>
|
Soge Zhang <zhssoge@gmail.com>
|
||||||
Tiffany Jernigan <tiffany.jernigan@intel.com>
|
Tiffany Jernigan <tiffany.jernigan@intel.com>
|
||||||
Tilak Sharma <tilaks@google.com>
|
Tilak Sharma <tilaks@google.com>
|
||||||
|
Tobias Klauser <tobias.klauser@gmail.com>
|
||||||
Tom Payne <twpayne@gmail.com>
|
Tom Payne <twpayne@gmail.com>
|
||||||
Travis Cline <travis.cline@gmail.com>
|
Travis Cline <travis.cline@gmail.com>
|
||||||
Tudor Golubenco <tudor.g@gmail.com>
|
Tudor Golubenco <tudor.g@gmail.com>
|
||||||
|
116
vendor/github.com/fsnotify/fsnotify/CHANGELOG.md
generated
vendored
116
vendor/github.com/fsnotify/fsnotify/CHANGELOG.md
generated
vendored
@ -1,6 +1,28 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## v1.4.7 / 2018-01-09
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [1.5.1] - 2021-08-24
|
||||||
|
|
||||||
|
* Revert Add AddRaw to not follow symlinks
|
||||||
|
|
||||||
|
## [1.5.0] - 2021-08-20
|
||||||
|
|
||||||
|
* Go: Increase minimum required version to Go 1.12 [#381](https://github.com/fsnotify/fsnotify/pull/381)
|
||||||
|
* Feature: Add AddRaw method which does not follow symlinks when adding a watch [#289](https://github.com/fsnotify/fsnotify/pull/298)
|
||||||
|
* Windows: Follow symlinks by default like on all other systems [#289](https://github.com/fsnotify/fsnotify/pull/289)
|
||||||
|
* CI: Use GitHub Actions for CI and cover go 1.12-1.17
|
||||||
|
[#378](https://github.com/fsnotify/fsnotify/pull/378)
|
||||||
|
[#381](https://github.com/fsnotify/fsnotify/pull/381)
|
||||||
|
[#385](https://github.com/fsnotify/fsnotify/pull/385)
|
||||||
|
* Go 1.14+: Fix unsafe pointer conversion [#325](https://github.com/fsnotify/fsnotify/pull/325)
|
||||||
|
|
||||||
|
## [1.4.7] - 2018-01-09
|
||||||
|
|
||||||
* BSD/macOS: Fix possible deadlock on closing the watcher on kqueue (thanks @nhooyr and @glycerine)
|
* BSD/macOS: Fix possible deadlock on closing the watcher on kqueue (thanks @nhooyr and @glycerine)
|
||||||
* Tests: Fix missing verb on format string (thanks @rchiossi)
|
* Tests: Fix missing verb on format string (thanks @rchiossi)
|
||||||
@ -10,62 +32,62 @@
|
|||||||
* Linux: Properly handle inotify's IN_Q_OVERFLOW event (thanks @zeldovich)
|
* Linux: Properly handle inotify's IN_Q_OVERFLOW event (thanks @zeldovich)
|
||||||
* Docs: replace references to OS X with macOS
|
* Docs: replace references to OS X with macOS
|
||||||
|
|
||||||
## v1.4.2 / 2016-10-10
|
## [1.4.2] - 2016-10-10
|
||||||
|
|
||||||
* Linux: use InotifyInit1 with IN_CLOEXEC to stop leaking a file descriptor to a child process when using fork/exec [#178](https://github.com/fsnotify/fsnotify/pull/178) (thanks @pattyshack)
|
* Linux: use InotifyInit1 with IN_CLOEXEC to stop leaking a file descriptor to a child process when using fork/exec [#178](https://github.com/fsnotify/fsnotify/pull/178) (thanks @pattyshack)
|
||||||
|
|
||||||
## v1.4.1 / 2016-10-04
|
## [1.4.1] - 2016-10-04
|
||||||
|
|
||||||
* Fix flaky inotify stress test on Linux [#177](https://github.com/fsnotify/fsnotify/pull/177) (thanks @pattyshack)
|
* Fix flaky inotify stress test on Linux [#177](https://github.com/fsnotify/fsnotify/pull/177) (thanks @pattyshack)
|
||||||
|
|
||||||
## v1.4.0 / 2016-10-01
|
## [1.4.0] - 2016-10-01
|
||||||
|
|
||||||
* add a String() method to Event.Op [#165](https://github.com/fsnotify/fsnotify/pull/165) (thanks @oozie)
|
* add a String() method to Event.Op [#165](https://github.com/fsnotify/fsnotify/pull/165) (thanks @oozie)
|
||||||
|
|
||||||
## v1.3.1 / 2016-06-28
|
## [1.3.1] - 2016-06-28
|
||||||
|
|
||||||
* Windows: fix for double backslash when watching the root of a drive [#151](https://github.com/fsnotify/fsnotify/issues/151) (thanks @brunoqc)
|
* Windows: fix for double backslash when watching the root of a drive [#151](https://github.com/fsnotify/fsnotify/issues/151) (thanks @brunoqc)
|
||||||
|
|
||||||
## v1.3.0 / 2016-04-19
|
## [1.3.0] - 2016-04-19
|
||||||
|
|
||||||
* Support linux/arm64 by [patching](https://go-review.googlesource.com/#/c/21971/) x/sys/unix and switching to to it from syscall (thanks @suihkulokki) [#135](https://github.com/fsnotify/fsnotify/pull/135)
|
* Support linux/arm64 by [patching](https://go-review.googlesource.com/#/c/21971/) x/sys/unix and switching to to it from syscall (thanks @suihkulokki) [#135](https://github.com/fsnotify/fsnotify/pull/135)
|
||||||
|
|
||||||
## v1.2.10 / 2016-03-02
|
## [1.2.10] - 2016-03-02
|
||||||
|
|
||||||
* Fix golint errors in windows.go [#121](https://github.com/fsnotify/fsnotify/pull/121) (thanks @tiffanyfj)
|
* Fix golint errors in windows.go [#121](https://github.com/fsnotify/fsnotify/pull/121) (thanks @tiffanyfj)
|
||||||
|
|
||||||
## v1.2.9 / 2016-01-13
|
## [1.2.9] - 2016-01-13
|
||||||
|
|
||||||
kqueue: Fix logic for CREATE after REMOVE [#111](https://github.com/fsnotify/fsnotify/pull/111) (thanks @bep)
|
kqueue: Fix logic for CREATE after REMOVE [#111](https://github.com/fsnotify/fsnotify/pull/111) (thanks @bep)
|
||||||
|
|
||||||
## v1.2.8 / 2015-12-17
|
## [1.2.8] - 2015-12-17
|
||||||
|
|
||||||
* kqueue: fix race condition in Close [#105](https://github.com/fsnotify/fsnotify/pull/105) (thanks @djui for reporting the issue and @ppknap for writing a failing test)
|
* kqueue: fix race condition in Close [#105](https://github.com/fsnotify/fsnotify/pull/105) (thanks @djui for reporting the issue and @ppknap for writing a failing test)
|
||||||
* inotify: fix race in test
|
* inotify: fix race in test
|
||||||
* enable race detection for continuous integration (Linux, Mac, Windows)
|
* enable race detection for continuous integration (Linux, Mac, Windows)
|
||||||
|
|
||||||
## v1.2.5 / 2015-10-17
|
## [1.2.5] - 2015-10-17
|
||||||
|
|
||||||
* inotify: use epoll_create1 for arm64 support (requires Linux 2.6.27 or later) [#100](https://github.com/fsnotify/fsnotify/pull/100) (thanks @suihkulokki)
|
* inotify: use epoll_create1 for arm64 support (requires Linux 2.6.27 or later) [#100](https://github.com/fsnotify/fsnotify/pull/100) (thanks @suihkulokki)
|
||||||
* inotify: fix path leaks [#73](https://github.com/fsnotify/fsnotify/pull/73) (thanks @chamaken)
|
* inotify: fix path leaks [#73](https://github.com/fsnotify/fsnotify/pull/73) (thanks @chamaken)
|
||||||
* kqueue: watch for rename events on subdirectories [#83](https://github.com/fsnotify/fsnotify/pull/83) (thanks @guotie)
|
* kqueue: watch for rename events on subdirectories [#83](https://github.com/fsnotify/fsnotify/pull/83) (thanks @guotie)
|
||||||
* kqueue: avoid infinite loops from symlinks cycles [#101](https://github.com/fsnotify/fsnotify/pull/101) (thanks @illicitonion)
|
* kqueue: avoid infinite loops from symlinks cycles [#101](https://github.com/fsnotify/fsnotify/pull/101) (thanks @illicitonion)
|
||||||
|
|
||||||
## v1.2.1 / 2015-10-14
|
## [1.2.1] - 2015-10-14
|
||||||
|
|
||||||
* kqueue: don't watch named pipes [#98](https://github.com/fsnotify/fsnotify/pull/98) (thanks @evanphx)
|
* kqueue: don't watch named pipes [#98](https://github.com/fsnotify/fsnotify/pull/98) (thanks @evanphx)
|
||||||
|
|
||||||
## v1.2.0 / 2015-02-08
|
## [1.2.0] - 2015-02-08
|
||||||
|
|
||||||
* inotify: use epoll to wake up readEvents [#66](https://github.com/fsnotify/fsnotify/pull/66) (thanks @PieterD)
|
* inotify: use epoll to wake up readEvents [#66](https://github.com/fsnotify/fsnotify/pull/66) (thanks @PieterD)
|
||||||
* inotify: closing watcher should now always shut down goroutine [#63](https://github.com/fsnotify/fsnotify/pull/63) (thanks @PieterD)
|
* inotify: closing watcher should now always shut down goroutine [#63](https://github.com/fsnotify/fsnotify/pull/63) (thanks @PieterD)
|
||||||
* kqueue: close kqueue after removing watches, fixes [#59](https://github.com/fsnotify/fsnotify/issues/59)
|
* kqueue: close kqueue after removing watches, fixes [#59](https://github.com/fsnotify/fsnotify/issues/59)
|
||||||
|
|
||||||
## v1.1.1 / 2015-02-05
|
## [1.1.1] - 2015-02-05
|
||||||
|
|
||||||
* inotify: Retry read on EINTR [#61](https://github.com/fsnotify/fsnotify/issues/61) (thanks @PieterD)
|
* inotify: Retry read on EINTR [#61](https://github.com/fsnotify/fsnotify/issues/61) (thanks @PieterD)
|
||||||
|
|
||||||
## v1.1.0 / 2014-12-12
|
## [1.1.0] - 2014-12-12
|
||||||
|
|
||||||
* kqueue: rework internals [#43](https://github.com/fsnotify/fsnotify/pull/43)
|
* kqueue: rework internals [#43](https://github.com/fsnotify/fsnotify/pull/43)
|
||||||
* add low-level functions
|
* add low-level functions
|
||||||
@ -77,22 +99,22 @@ kqueue: Fix logic for CREATE after REMOVE [#111](https://github.com/fsnotify/fsn
|
|||||||
* kqueue: fix regression in rework causing subdirectories to be watched [#48](https://github.com/fsnotify/fsnotify/issues/48)
|
* kqueue: fix regression in rework causing subdirectories to be watched [#48](https://github.com/fsnotify/fsnotify/issues/48)
|
||||||
* kqueue: cleanup internal watch before sending remove event [#51](https://github.com/fsnotify/fsnotify/issues/51)
|
* kqueue: cleanup internal watch before sending remove event [#51](https://github.com/fsnotify/fsnotify/issues/51)
|
||||||
|
|
||||||
## v1.0.4 / 2014-09-07
|
## [1.0.4] - 2014-09-07
|
||||||
|
|
||||||
* kqueue: add dragonfly to the build tags.
|
* kqueue: add dragonfly to the build tags.
|
||||||
* Rename source code files, rearrange code so exported APIs are at the top.
|
* Rename source code files, rearrange code so exported APIs are at the top.
|
||||||
* Add done channel to example code. [#37](https://github.com/fsnotify/fsnotify/pull/37) (thanks @chenyukang)
|
* Add done channel to example code. [#37](https://github.com/fsnotify/fsnotify/pull/37) (thanks @chenyukang)
|
||||||
|
|
||||||
## v1.0.3 / 2014-08-19
|
## [1.0.3] - 2014-08-19
|
||||||
|
|
||||||
* [Fix] Windows MOVED_TO now translates to Create like on BSD and Linux. [#36](https://github.com/fsnotify/fsnotify/issues/36)
|
* [Fix] Windows MOVED_TO now translates to Create like on BSD and Linux. [#36](https://github.com/fsnotify/fsnotify/issues/36)
|
||||||
|
|
||||||
## v1.0.2 / 2014-08-17
|
## [1.0.2] - 2014-08-17
|
||||||
|
|
||||||
* [Fix] Missing create events on macOS. [#14](https://github.com/fsnotify/fsnotify/issues/14) (thanks @zhsso)
|
* [Fix] Missing create events on macOS. [#14](https://github.com/fsnotify/fsnotify/issues/14) (thanks @zhsso)
|
||||||
* [Fix] Make ./path and path equivalent. (thanks @zhsso)
|
* [Fix] Make ./path and path equivalent. (thanks @zhsso)
|
||||||
|
|
||||||
## v1.0.0 / 2014-08-15
|
## [1.0.0] - 2014-08-15
|
||||||
|
|
||||||
* [API] Remove AddWatch on Windows, use Add.
|
* [API] Remove AddWatch on Windows, use Add.
|
||||||
* Improve documentation for exported identifiers. [#30](https://github.com/fsnotify/fsnotify/issues/30)
|
* Improve documentation for exported identifiers. [#30](https://github.com/fsnotify/fsnotify/issues/30)
|
||||||
@ -146,51 +168,51 @@ kqueue: Fix logic for CREATE after REMOVE [#111](https://github.com/fsnotify/fsn
|
|||||||
* no tests for the current implementation
|
* no tests for the current implementation
|
||||||
* not fully implemented on Windows [#93](https://github.com/howeyc/fsnotify/issues/93#issuecomment-39285195)
|
* not fully implemented on Windows [#93](https://github.com/howeyc/fsnotify/issues/93#issuecomment-39285195)
|
||||||
|
|
||||||
## v0.9.3 / 2014-12-31
|
## [0.9.3] - 2014-12-31
|
||||||
|
|
||||||
* kqueue: cleanup internal watch before sending remove event [#51](https://github.com/fsnotify/fsnotify/issues/51)
|
* kqueue: cleanup internal watch before sending remove event [#51](https://github.com/fsnotify/fsnotify/issues/51)
|
||||||
|
|
||||||
## v0.9.2 / 2014-08-17
|
## [0.9.2] - 2014-08-17
|
||||||
|
|
||||||
* [Backport] Fix missing create events on macOS. [#14](https://github.com/fsnotify/fsnotify/issues/14) (thanks @zhsso)
|
* [Backport] Fix missing create events on macOS. [#14](https://github.com/fsnotify/fsnotify/issues/14) (thanks @zhsso)
|
||||||
|
|
||||||
## v0.9.1 / 2014-06-12
|
## [0.9.1] - 2014-06-12
|
||||||
|
|
||||||
* Fix data race on kevent buffer (thanks @tilaks) [#98](https://github.com/howeyc/fsnotify/pull/98)
|
* Fix data race on kevent buffer (thanks @tilaks) [#98](https://github.com/howeyc/fsnotify/pull/98)
|
||||||
|
|
||||||
## v0.9.0 / 2014-01-17
|
## [0.9.0] - 2014-01-17
|
||||||
|
|
||||||
* IsAttrib() for events that only concern a file's metadata [#79][] (thanks @abustany)
|
* IsAttrib() for events that only concern a file's metadata [#79][] (thanks @abustany)
|
||||||
* [Fix] kqueue: fix deadlock [#77][] (thanks @cespare)
|
* [Fix] kqueue: fix deadlock [#77][] (thanks @cespare)
|
||||||
* [NOTICE] Development has moved to `code.google.com/p/go.exp/fsnotify` in preparation for inclusion in the Go standard library.
|
* [NOTICE] Development has moved to `code.google.com/p/go.exp/fsnotify` in preparation for inclusion in the Go standard library.
|
||||||
|
|
||||||
## v0.8.12 / 2013-11-13
|
## [0.8.12] - 2013-11-13
|
||||||
|
|
||||||
* [API] Remove FD_SET and friends from Linux adapter
|
* [API] Remove FD_SET and friends from Linux adapter
|
||||||
|
|
||||||
## v0.8.11 / 2013-11-02
|
## [0.8.11] - 2013-11-02
|
||||||
|
|
||||||
* [Doc] Add Changelog [#72][] (thanks @nathany)
|
* [Doc] Add Changelog [#72][] (thanks @nathany)
|
||||||
* [Doc] Spotlight and double modify events on macOS [#62][] (reported by @paulhammond)
|
* [Doc] Spotlight and double modify events on macOS [#62][] (reported by @paulhammond)
|
||||||
|
|
||||||
## v0.8.10 / 2013-10-19
|
## [0.8.10] - 2013-10-19
|
||||||
|
|
||||||
* [Fix] kqueue: remove file watches when parent directory is removed [#71][] (reported by @mdwhatcott)
|
* [Fix] kqueue: remove file watches when parent directory is removed [#71][] (reported by @mdwhatcott)
|
||||||
* [Fix] kqueue: race between Close and readEvents [#70][] (reported by @bernerdschaefer)
|
* [Fix] kqueue: race between Close and readEvents [#70][] (reported by @bernerdschaefer)
|
||||||
* [Doc] specify OS-specific limits in README (thanks @debrando)
|
* [Doc] specify OS-specific limits in README (thanks @debrando)
|
||||||
|
|
||||||
## v0.8.9 / 2013-09-08
|
## [0.8.9] - 2013-09-08
|
||||||
|
|
||||||
* [Doc] Contributing (thanks @nathany)
|
* [Doc] Contributing (thanks @nathany)
|
||||||
* [Doc] update package path in example code [#63][] (thanks @paulhammond)
|
* [Doc] update package path in example code [#63][] (thanks @paulhammond)
|
||||||
* [Doc] GoCI badge in README (Linux only) [#60][]
|
* [Doc] GoCI badge in README (Linux only) [#60][]
|
||||||
* [Doc] Cross-platform testing with Vagrant [#59][] (thanks @nathany)
|
* [Doc] Cross-platform testing with Vagrant [#59][] (thanks @nathany)
|
||||||
|
|
||||||
## v0.8.8 / 2013-06-17
|
## [0.8.8] - 2013-06-17
|
||||||
|
|
||||||
* [Fix] Windows: handle `ERROR_MORE_DATA` on Windows [#49][] (thanks @jbowtie)
|
* [Fix] Windows: handle `ERROR_MORE_DATA` on Windows [#49][] (thanks @jbowtie)
|
||||||
|
|
||||||
## v0.8.7 / 2013-06-03
|
## [0.8.7] - 2013-06-03
|
||||||
|
|
||||||
* [API] Make syscall flags internal
|
* [API] Make syscall flags internal
|
||||||
* [Fix] inotify: ignore event changes
|
* [Fix] inotify: ignore event changes
|
||||||
@ -198,74 +220,74 @@ kqueue: Fix logic for CREATE after REMOVE [#111](https://github.com/fsnotify/fsn
|
|||||||
* [Fix] tests on Windows
|
* [Fix] tests on Windows
|
||||||
* lower case error messages
|
* lower case error messages
|
||||||
|
|
||||||
## v0.8.6 / 2013-05-23
|
## [0.8.6] - 2013-05-23
|
||||||
|
|
||||||
* kqueue: Use EVT_ONLY flag on Darwin
|
* kqueue: Use EVT_ONLY flag on Darwin
|
||||||
* [Doc] Update README with full example
|
* [Doc] Update README with full example
|
||||||
|
|
||||||
## v0.8.5 / 2013-05-09
|
## [0.8.5] - 2013-05-09
|
||||||
|
|
||||||
* [Fix] inotify: allow monitoring of "broken" symlinks (thanks @tsg)
|
* [Fix] inotify: allow monitoring of "broken" symlinks (thanks @tsg)
|
||||||
|
|
||||||
## v0.8.4 / 2013-04-07
|
## [0.8.4] - 2013-04-07
|
||||||
|
|
||||||
* [Fix] kqueue: watch all file events [#40][] (thanks @ChrisBuchholz)
|
* [Fix] kqueue: watch all file events [#40][] (thanks @ChrisBuchholz)
|
||||||
|
|
||||||
## v0.8.3 / 2013-03-13
|
## [0.8.3] - 2013-03-13
|
||||||
|
|
||||||
* [Fix] inoitfy/kqueue memory leak [#36][] (reported by @nbkolchin)
|
* [Fix] inoitfy/kqueue memory leak [#36][] (reported by @nbkolchin)
|
||||||
* [Fix] kqueue: use fsnFlags for watching a directory [#33][] (reported by @nbkolchin)
|
* [Fix] kqueue: use fsnFlags for watching a directory [#33][] (reported by @nbkolchin)
|
||||||
|
|
||||||
## v0.8.2 / 2013-02-07
|
## [0.8.2] - 2013-02-07
|
||||||
|
|
||||||
* [Doc] add Authors
|
* [Doc] add Authors
|
||||||
* [Fix] fix data races for map access [#29][] (thanks @fsouza)
|
* [Fix] fix data races for map access [#29][] (thanks @fsouza)
|
||||||
|
|
||||||
## v0.8.1 / 2013-01-09
|
## [0.8.1] - 2013-01-09
|
||||||
|
|
||||||
* [Fix] Windows path separators
|
* [Fix] Windows path separators
|
||||||
* [Doc] BSD License
|
* [Doc] BSD License
|
||||||
|
|
||||||
## v0.8.0 / 2012-11-09
|
## [0.8.0] - 2012-11-09
|
||||||
|
|
||||||
* kqueue: directory watching improvements (thanks @vmirage)
|
* kqueue: directory watching improvements (thanks @vmirage)
|
||||||
* inotify: add `IN_MOVED_TO` [#25][] (requested by @cpisto)
|
* inotify: add `IN_MOVED_TO` [#25][] (requested by @cpisto)
|
||||||
* [Fix] kqueue: deleting watched directory [#24][] (reported by @jakerr)
|
* [Fix] kqueue: deleting watched directory [#24][] (reported by @jakerr)
|
||||||
|
|
||||||
## v0.7.4 / 2012-10-09
|
## [0.7.4] - 2012-10-09
|
||||||
|
|
||||||
* [Fix] inotify: fixes from https://codereview.appspot.com/5418045/ (ugorji)
|
* [Fix] inotify: fixes from https://codereview.appspot.com/5418045/ (ugorji)
|
||||||
* [Fix] kqueue: preserve watch flags when watching for delete [#21][] (reported by @robfig)
|
* [Fix] kqueue: preserve watch flags when watching for delete [#21][] (reported by @robfig)
|
||||||
* [Fix] kqueue: watch the directory even if it isn't a new watch (thanks @robfig)
|
* [Fix] kqueue: watch the directory even if it isn't a new watch (thanks @robfig)
|
||||||
* [Fix] kqueue: modify after recreation of file
|
* [Fix] kqueue: modify after recreation of file
|
||||||
|
|
||||||
## v0.7.3 / 2012-09-27
|
## [0.7.3] - 2012-09-27
|
||||||
|
|
||||||
* [Fix] kqueue: watch with an existing folder inside the watched folder (thanks @vmirage)
|
* [Fix] kqueue: watch with an existing folder inside the watched folder (thanks @vmirage)
|
||||||
* [Fix] kqueue: no longer get duplicate CREATE events
|
* [Fix] kqueue: no longer get duplicate CREATE events
|
||||||
|
|
||||||
## v0.7.2 / 2012-09-01
|
## [0.7.2] - 2012-09-01
|
||||||
|
|
||||||
* kqueue: events for created directories
|
* kqueue: events for created directories
|
||||||
|
|
||||||
## v0.7.1 / 2012-07-14
|
## [0.7.1] - 2012-07-14
|
||||||
|
|
||||||
* [Fix] for renaming files
|
* [Fix] for renaming files
|
||||||
|
|
||||||
## v0.7.0 / 2012-07-02
|
## [0.7.0] - 2012-07-02
|
||||||
|
|
||||||
* [Feature] FSNotify flags
|
* [Feature] FSNotify flags
|
||||||
* [Fix] inotify: Added file name back to event path
|
* [Fix] inotify: Added file name back to event path
|
||||||
|
|
||||||
## v0.6.0 / 2012-06-06
|
## [0.6.0] - 2012-06-06
|
||||||
|
|
||||||
* kqueue: watch files after directory created (thanks @tmc)
|
* kqueue: watch files after directory created (thanks @tmc)
|
||||||
|
|
||||||
## v0.5.1 / 2012-05-22
|
## [0.5.1] - 2012-05-22
|
||||||
|
|
||||||
* [Fix] inotify: remove all watches before Close()
|
* [Fix] inotify: remove all watches before Close()
|
||||||
|
|
||||||
## v0.5.0 / 2012-05-03
|
## [0.5.0] - 2012-05-03
|
||||||
|
|
||||||
* [API] kqueue: return errors during watch instead of sending over channel
|
* [API] kqueue: return errors during watch instead of sending over channel
|
||||||
* kqueue: match symlink behavior on Linux
|
* kqueue: match symlink behavior on Linux
|
||||||
@ -273,22 +295,22 @@ kqueue: Fix logic for CREATE after REMOVE [#111](https://github.com/fsnotify/fsn
|
|||||||
* [Fix] kqueue: handle EINTR (reported by @robfig)
|
* [Fix] kqueue: handle EINTR (reported by @robfig)
|
||||||
* [Doc] Godoc example [#1][] (thanks @davecheney)
|
* [Doc] Godoc example [#1][] (thanks @davecheney)
|
||||||
|
|
||||||
## v0.4.0 / 2012-03-30
|
## [0.4.0] - 2012-03-30
|
||||||
|
|
||||||
* Go 1 released: build with go tool
|
* Go 1 released: build with go tool
|
||||||
* [Feature] Windows support using winfsnotify
|
* [Feature] Windows support using winfsnotify
|
||||||
* Windows does not have attribute change notifications
|
* Windows does not have attribute change notifications
|
||||||
* Roll attribute notifications into IsModify
|
* Roll attribute notifications into IsModify
|
||||||
|
|
||||||
## v0.3.0 / 2012-02-19
|
## [0.3.0] - 2012-02-19
|
||||||
|
|
||||||
* kqueue: add files when watch directory
|
* kqueue: add files when watch directory
|
||||||
|
|
||||||
## v0.2.0 / 2011-12-30
|
## [0.2.0] - 2011-12-30
|
||||||
|
|
||||||
* update to latest Go weekly code
|
* update to latest Go weekly code
|
||||||
|
|
||||||
## v0.1.0 / 2011-10-19
|
## [0.1.0] - 2011-10-19
|
||||||
|
|
||||||
* kqueue: add watch on file creation to match inotify
|
* kqueue: add watch on file creation to match inotify
|
||||||
* kqueue: create file event
|
* kqueue: create file event
|
||||||
|
6
vendor/github.com/fsnotify/fsnotify/README.md
generated
vendored
6
vendor/github.com/fsnotify/fsnotify/README.md
generated
vendored
@ -12,9 +12,9 @@ Cross platform: Windows, Linux, BSD and macOS.
|
|||||||
|
|
||||||
| Adapter | OS | Status |
|
| Adapter | OS | Status |
|
||||||
| --------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
|
| --------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| inotify | Linux 2.6.27 or later, Android\* | Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify) |
|
| inotify | Linux 2.6.27 or later, Android\* | Supported |
|
||||||
| kqueue | BSD, macOS, iOS\* | Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify) |
|
| kqueue | BSD, macOS, iOS\* | Supported |
|
||||||
| ReadDirectoryChangesW | Windows | Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify) |
|
| ReadDirectoryChangesW | Windows | Supported |
|
||||||
| FSEvents | macOS | [Planned](https://github.com/fsnotify/fsnotify/issues/11) |
|
| FSEvents | macOS | [Planned](https://github.com/fsnotify/fsnotify/issues/11) |
|
||||||
| FEN | Solaris 11 | [In Progress](https://github.com/fsnotify/fsnotify/issues/12) |
|
| FEN | Solaris 11 | [In Progress](https://github.com/fsnotify/fsnotify/issues/12) |
|
||||||
| fanotify | Linux 2.6.37+ | [Planned](https://github.com/fsnotify/fsnotify/issues/114) |
|
| fanotify | Linux 2.6.37+ | [Planned](https://github.com/fsnotify/fsnotify/issues/114) |
|
||||||
|
1
vendor/github.com/fsnotify/fsnotify/fen.go
generated
vendored
1
vendor/github.com/fsnotify/fsnotify/fen.go
generated
vendored
@ -2,6 +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.
|
||||||
|
|
||||||
|
//go:build solaris
|
||||||
// +build solaris
|
// +build solaris
|
||||||
|
|
||||||
package fsnotify
|
package fsnotify
|
||||||
|
1
vendor/github.com/fsnotify/fsnotify/fsnotify.go
generated
vendored
1
vendor/github.com/fsnotify/fsnotify/fsnotify.go
generated
vendored
@ -2,6 +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.
|
||||||
|
|
||||||
|
//go:build !plan9
|
||||||
// +build !plan9
|
// +build !plan9
|
||||||
|
|
||||||
// Package fsnotify provides a platform-independent interface for file system notifications.
|
// Package fsnotify provides a platform-independent interface for file system notifications.
|
||||||
|
5
vendor/github.com/fsnotify/fsnotify/go.mod
generated
vendored
5
vendor/github.com/fsnotify/fsnotify/go.mod
generated
vendored
@ -1,5 +0,0 @@
|
|||||||
module github.com/fsnotify/fsnotify
|
|
||||||
|
|
||||||
go 1.13
|
|
||||||
|
|
||||||
require golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9
|
|
2
vendor/github.com/fsnotify/fsnotify/go.sum
generated
vendored
2
vendor/github.com/fsnotify/fsnotify/go.sum
generated
vendored
@ -1,2 +0,0 @@
|
|||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9 h1:L2auWcuQIvxz9xSEqzESnV/QN/gNRXNApHi3fYwl2w0=
|
|
||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
3
vendor/github.com/fsnotify/fsnotify/inotify.go
generated
vendored
3
vendor/github.com/fsnotify/fsnotify/inotify.go
generated
vendored
@ -2,6 +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.
|
||||||
|
|
||||||
|
//go:build linux
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
package fsnotify
|
package fsnotify
|
||||||
@ -272,7 +273,7 @@ func (w *Watcher) readEvents() {
|
|||||||
|
|
||||||
if nameLen > 0 {
|
if nameLen > 0 {
|
||||||
// Point "bytes" at the first byte of the filename
|
// Point "bytes" at the first byte of the filename
|
||||||
bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))
|
bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen]
|
||||||
// The filename is padded with NULL bytes. TrimRight() gets rid of those.
|
// The filename is padded with NULL bytes. TrimRight() gets rid of those.
|
||||||
name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000")
|
name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000")
|
||||||
}
|
}
|
||||||
|
1
vendor/github.com/fsnotify/fsnotify/inotify_poller.go
generated
vendored
1
vendor/github.com/fsnotify/fsnotify/inotify_poller.go
generated
vendored
@ -2,6 +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.
|
||||||
|
|
||||||
|
//go:build linux
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
package fsnotify
|
package fsnotify
|
||||||
|
1
vendor/github.com/fsnotify/fsnotify/kqueue.go
generated
vendored
1
vendor/github.com/fsnotify/fsnotify/kqueue.go
generated
vendored
@ -2,6 +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.
|
||||||
|
|
||||||
|
//go:build freebsd || openbsd || netbsd || dragonfly || darwin
|
||||||
// +build freebsd openbsd netbsd dragonfly darwin
|
// +build freebsd openbsd netbsd dragonfly darwin
|
||||||
|
|
||||||
package fsnotify
|
package fsnotify
|
||||||
|
1
vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go
generated
vendored
1
vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go
generated
vendored
@ -2,6 +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.
|
||||||
|
|
||||||
|
//go:build freebsd || openbsd || netbsd || dragonfly
|
||||||
// +build freebsd openbsd netbsd dragonfly
|
// +build freebsd openbsd netbsd dragonfly
|
||||||
|
|
||||||
package fsnotify
|
package fsnotify
|
||||||
|
1
vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go
generated
vendored
1
vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go
generated
vendored
@ -2,6 +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.
|
||||||
|
|
||||||
|
//go:build darwin
|
||||||
// +build darwin
|
// +build darwin
|
||||||
|
|
||||||
package fsnotify
|
package fsnotify
|
||||||
|
1
vendor/github.com/fsnotify/fsnotify/windows.go
generated
vendored
1
vendor/github.com/fsnotify/fsnotify/windows.go
generated
vendored
@ -2,6 +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.
|
||||||
|
|
||||||
|
//go:build windows
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
package fsnotify
|
package fsnotify
|
||||||
|
3
vendor/github.com/go-asn1-ber/asn1-ber/go.mod
generated
vendored
3
vendor/github.com/go-asn1-ber/asn1-ber/go.mod
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
module github.com/go-asn1-ber/asn1-ber
|
|
||||||
|
|
||||||
go 1.13
|
|
5
vendor/github.com/go-telegram-bot-api/telegram-bot-api/go.mod
generated
vendored
5
vendor/github.com/go-telegram-bot-api/telegram-bot-api/go.mod
generated
vendored
@ -1,5 +0,0 @@
|
|||||||
module github.com/go-telegram-bot-api/telegram-bot-api
|
|
||||||
|
|
||||||
go 1.12
|
|
||||||
|
|
||||||
require github.com/technoweenie/multipartstreamer v1.0.1
|
|
2
vendor/github.com/go-telegram-bot-api/telegram-bot-api/go.sum
generated
vendored
2
vendor/github.com/go-telegram-bot-api/telegram-bot-api/go.sum
generated
vendored
@ -1,2 +0,0 @@
|
|||||||
github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
|
|
||||||
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
|
|
@ -1,4 +1,4 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
bin
|
bin
|
||||||
|
.idea/
|
||||||
|
|
@ -1,4 +1,5 @@
|
|||||||
Copyright (c) 2012 Dave Grijalva
|
Copyright (c) 2012 Dave Grijalva
|
||||||
|
Copyright (c) 2021 golang-jwt maintainers
|
||||||
|
|
||||||
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:
|
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:
|
||||||
|
|
22
vendor/github.com/golang-jwt/jwt/MIGRATION_GUIDE.md
generated
vendored
Normal file
22
vendor/github.com/golang-jwt/jwt/MIGRATION_GUIDE.md
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
## Migration Guide (v3.2.1)
|
||||||
|
|
||||||
|
Starting from [v3.2.1](https://github.com/golang-jwt/jwt/releases/tag/v3.2.1]), the import path has changed from `github.com/dgrijalva/jwt-go` to `github.com/golang-jwt/jwt`. Future releases will be using the `github.com/golang-jwt/jwt` import path and continue the existing versioning scheme of `v3.x.x+incompatible`. Backwards-compatible patches and fixes will be done on the `v3` release branch, where as new build-breaking features will be developed in a `v4` release, possibly including a SIV-style import path.
|
||||||
|
|
||||||
|
### go.mod replacement
|
||||||
|
|
||||||
|
In a first step, the easiest way is to use `go mod edit` to issue a replacement.
|
||||||
|
|
||||||
|
```
|
||||||
|
go mod edit -replace github.com/dgrijalva/jwt-go=github.com/golang-jwt/jwt@v3.2.1+incompatible
|
||||||
|
go mod tidy
|
||||||
|
```
|
||||||
|
|
||||||
|
This will still keep the old import path in your code but replace it with the new package and also introduce a new indirect dependency to `github.com/golang-jwt/jwt`. Try to compile your project; it should still work.
|
||||||
|
|
||||||
|
### Cleanup
|
||||||
|
|
||||||
|
If your code still consistently builds, you can replace all occurences of `github.com/dgrijalva/jwt-go` with `github.com/golang-jwt/jwt`, either manually or by using tools such as `sed`. Finally, the `replace` directive in the `go.mod` file can be removed.
|
||||||
|
|
||||||
|
## Older releases (before v3.2.0)
|
||||||
|
|
||||||
|
The original migration guide for older releases can be found at https://github.com/dgrijalva/jwt-go/blob/master/MIGRATION_GUIDE.md.
|
@ -1,25 +1,34 @@
|
|||||||
# jwt-go
|
# jwt-go
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/dgrijalva/jwt-go.svg?branch=master)](https://travis-ci.org/dgrijalva/jwt-go)
|
[![build](https://github.com/golang-jwt/jwt/actions/workflows/build.yml/badge.svg)](https://github.com/golang-jwt/jwt/actions/workflows/build.yml)
|
||||||
[![GoDoc](https://godoc.org/github.com/dgrijalva/jwt-go?status.svg)](https://godoc.org/github.com/dgrijalva/jwt-go)
|
[![Go Reference](https://pkg.go.dev/badge/github.com/golang-jwt/jwt.svg)](https://pkg.go.dev/github.com/golang-jwt/jwt)
|
||||||
|
|
||||||
A [go](http://www.golang.org) (or 'golang' for search engine friendliness) implementation of [JSON Web Tokens](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html)
|
A [go](http://www.golang.org) (or 'golang' for search engine friendliness) implementation of [JSON Web Tokens](https://datatracker.ietf.org/doc/html/rfc7519).
|
||||||
|
|
||||||
**NEW VERSION COMING:** There have been a lot of improvements suggested since the version 3.0.0 released in 2016. I'm working now on cutting two different releases: 3.2.0 will contain any non-breaking changes or enhancements. 4.0.0 will follow shortly which will include breaking changes. See the 4.0.0 milestone to get an idea of what's coming. If you have other ideas, or would like to participate in 4.0.0, now's the time. If you depend on this library and don't want to be interrupted, I recommend you use your dependency mangement tool to pin to version 3.
|
**IMPORT PATH CHANGE:** Starting from [v3.2.1](https://github.com/golang-jwt/jwt/releases/tag/v3.2.1), the import path has changed from `github.com/dgrijalva/jwt-go` to `github.com/golang-jwt/jwt`. After the original author of the library suggested migrating the maintenance of `jwt-go`, a dedicated team of open source maintainers decided to clone the existing library into this repository. See [dgrijalva/jwt-go#462](https://github.com/dgrijalva/jwt-go/issues/462) for a detailed discussion on this topic.
|
||||||
|
|
||||||
**SECURITY NOTICE:** Some older versions of Go have a security issue in the cryotp/elliptic. Recommendation is to upgrade to at least 1.8.3. See issue #216 for more detail.
|
Future releases will be using the `github.com/golang-jwt/jwt` import path and continue the existing versioning scheme of `v3.x.x+incompatible`. Backwards-compatible patches and fixes will be done on the `v3` release branch, where as new build-breaking features will be developed in a `v4` release, possibly including a SIV-style import path.
|
||||||
|
|
||||||
**SECURITY NOTICE:** It's important that you [validate the `alg` presented is what you expect](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/). This library attempts to make it easy to do the right thing by requiring key types match the expected alg, but you should take the extra step to verify it in your usage. See the examples provided.
|
**SECURITY NOTICE:** Some older versions of Go have a security issue in the crypto/elliptic. Recommendation is to upgrade to at least 1.15 See issue [dgrijalva/jwt-go#216](https://github.com/dgrijalva/jwt-go/issues/216) for more detail.
|
||||||
|
|
||||||
|
**SECURITY NOTICE:** It's important that you [validate the `alg` presented is what you expect](https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/). This library attempts to make it easy to do the right thing by requiring key types match the expected alg, but you should take the extra step to verify it in your usage. See the examples provided.
|
||||||
|
|
||||||
|
### Supported Go versions
|
||||||
|
|
||||||
|
Our support of Go versions is aligned with Go's [version release policy](https://golang.org/doc/devel/release#policy).
|
||||||
|
So we will support a major version of Go until there are two newer major releases.
|
||||||
|
We no longer support building jwt-go with unsupported Go versions, as these contain security vulnerabilities
|
||||||
|
which will not be fixed.
|
||||||
|
|
||||||
## What the heck is a JWT?
|
## What the heck is a JWT?
|
||||||
|
|
||||||
JWT.io has [a great introduction](https://jwt.io/introduction) to JSON Web Tokens.
|
JWT.io has [a great introduction](https://jwt.io/introduction) to JSON Web Tokens.
|
||||||
|
|
||||||
In short, it's a signed JSON object that does something useful (for example, authentication). It's commonly used for `Bearer` tokens in Oauth 2. A token is made of three parts, separated by `.`'s. The first two parts are JSON objects, that have been [base64url](http://tools.ietf.org/html/rfc4648) encoded. The last part is the signature, encoded the same way.
|
In short, it's a signed JSON object that does something useful (for example, authentication). It's commonly used for `Bearer` tokens in Oauth 2. A token is made of three parts, separated by `.`'s. The first two parts are JSON objects, that have been [base64url](https://datatracker.ietf.org/doc/html/rfc4648) encoded. The last part is the signature, encoded the same way.
|
||||||
|
|
||||||
The first part is called the header. It contains the necessary information for verifying the last part, the signature. For example, which encryption method was used for signing and what key was used.
|
The first part is called the header. It contains the necessary information for verifying the last part, the signature. For example, which encryption method was used for signing and what key was used.
|
||||||
|
|
||||||
The part in the middle is the interesting bit. It's called the Claims and contains the actual stuff you care about. Refer to [the RFC](http://self-issued.info/docs/draft-jones-json-web-token.html) for information about reserved keys and the proper way to add your own.
|
The part in the middle is the interesting bit. It's called the Claims and contains the actual stuff you care about. Refer to [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519) for information about reserved keys and the proper way to add your own.
|
||||||
|
|
||||||
## What's in the box?
|
## What's in the box?
|
||||||
|
|
||||||
@ -27,31 +36,31 @@ This library supports the parsing and verification as well as the generation and
|
|||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
See [the project documentation](https://godoc.org/github.com/dgrijalva/jwt-go) for examples of usage:
|
See [the project documentation](https://pkg.go.dev/github.com/golang-jwt/jwt) for examples of usage:
|
||||||
|
|
||||||
* [Simple example of parsing and validating a token](https://godoc.org/github.com/dgrijalva/jwt-go#example-Parse--Hmac)
|
* [Simple example of parsing and validating a token](https://pkg.go.dev/github.com/golang-jwt/jwt#example-Parse-Hmac)
|
||||||
* [Simple example of building and signing a token](https://godoc.org/github.com/dgrijalva/jwt-go#example-New--Hmac)
|
* [Simple example of building and signing a token](https://pkg.go.dev/github.com/golang-jwt/jwt#example-New-Hmac)
|
||||||
* [Directory of Examples](https://godoc.org/github.com/dgrijalva/jwt-go#pkg-examples)
|
* [Directory of Examples](https://pkg.go.dev/github.com/golang-jwt/jwt#pkg-examples)
|
||||||
|
|
||||||
## Extensions
|
## Extensions
|
||||||
|
|
||||||
This library publishes all the necessary components for adding your own signing methods. Simply implement the `SigningMethod` interface and register a factory method using `RegisterSigningMethod`.
|
This library publishes all the necessary components for adding your own signing methods. Simply implement the `SigningMethod` interface and register a factory method using `RegisterSigningMethod`.
|
||||||
|
|
||||||
Here's an example of an extension that integrates with the Google App Engine signing tools: https://github.com/someone1/gcp-jwt-go
|
Here's an example of an extension that integrates with multiple Google Cloud Platform signing tools (AppEngine, IAM API, Cloud KMS): https://github.com/someone1/gcp-jwt-go
|
||||||
|
|
||||||
## Compliance
|
## Compliance
|
||||||
|
|
||||||
This library was last reviewed to comply with [RTF 7519](http://www.rfc-editor.org/info/rfc7519) dated May 2015 with a few notable differences:
|
This library was last reviewed to comply with [RTF 7519](https://datatracker.ietf.org/doc/html/rfc7519) dated May 2015 with a few notable differences:
|
||||||
|
|
||||||
* In order to protect against accidental use of [Unsecured JWTs](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#UnsecuredJWT), tokens using `alg=none` will only be accepted if the constant `jwt.UnsafeAllowNoneSignatureType` is provided as the key.
|
* In order to protect against accidental use of [Unsecured JWTs](https://datatracker.ietf.org/doc/html/rfc7519#section-6), tokens using `alg=none` will only be accepted if the constant `jwt.UnsafeAllowNoneSignatureType` is provided as the key.
|
||||||
|
|
||||||
## Project Status & Versioning
|
## Project Status & Versioning
|
||||||
|
|
||||||
This library is considered production ready. Feedback and feature requests are appreciated. The API should be considered stable. There should be very few backwards-incompatible changes outside of major version updates (and only with good reason).
|
This library is considered production ready. Feedback and feature requests are appreciated. The API should be considered stable. There should be very few backwards-incompatible changes outside of major version updates (and only with good reason).
|
||||||
|
|
||||||
This project uses [Semantic Versioning 2.0.0](http://semver.org). Accepted pull requests will land on `master`. Periodically, versions will be tagged from `master`. You can find all the releases on [the project releases page](https://github.com/dgrijalva/jwt-go/releases).
|
This project uses [Semantic Versioning 2.0.0](http://semver.org). Accepted pull requests will land on `main`. Periodically, versions will be tagged from `main`. You can find all the releases on [the project releases page](https://github.com/golang-jwt/jwt/releases).
|
||||||
|
|
||||||
While we try to make it obvious when we make breaking changes, there isn't a great mechanism for pushing announcements out to users. You may want to use this alternative package include: `gopkg.in/dgrijalva/jwt-go.v3`. It will do the right thing WRT semantic versioning.
|
While we try to make it obvious when we make breaking changes, there isn't a great mechanism for pushing announcements out to users. You may want to use this alternative package include: `gopkg.in/golang-jwt/jwt.v3`. It will do the right thing WRT semantic versioning.
|
||||||
|
|
||||||
**BREAKING CHANGES:***
|
**BREAKING CHANGES:***
|
||||||
* Version 3.0.0 includes _a lot_ of changes from the 2.x line, including a few that break the API. We've tried to break as few things as possible, so there should just be a few type signature changes. A full list of breaking changes is available in `VERSION_HISTORY.md`. See `MIGRATION_GUIDE.md` for more information on updating your code.
|
* Version 3.0.0 includes _a lot_ of changes from the 2.x line, including a few that break the API. We've tried to break as few things as possible, so there should just be a few type signature changes. A full list of breaking changes is available in `VERSION_HISTORY.md`. See `MIGRATION_GUIDE.md` for more information on updating your code.
|
||||||
@ -79,9 +88,9 @@ Asymmetric signing methods, such as RSA, use different keys for signing and veri
|
|||||||
|
|
||||||
Each signing method expects a different object type for its signing keys. See the package documentation for details. Here are the most common ones:
|
Each signing method expects a different object type for its signing keys. See the package documentation for details. Here are the most common ones:
|
||||||
|
|
||||||
* The [HMAC signing method](https://godoc.org/github.com/dgrijalva/jwt-go#SigningMethodHMAC) (`HS256`,`HS384`,`HS512`) expect `[]byte` values for signing and validation
|
* The [HMAC signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodHMAC) (`HS256`,`HS384`,`HS512`) expect `[]byte` values for signing and validation
|
||||||
* The [RSA signing method](https://godoc.org/github.com/dgrijalva/jwt-go#SigningMethodRSA) (`RS256`,`RS384`,`RS512`) expect `*rsa.PrivateKey` for signing and `*rsa.PublicKey` for validation
|
* The [RSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodRSA) (`RS256`,`RS384`,`RS512`) expect `*rsa.PrivateKey` for signing and `*rsa.PublicKey` for validation
|
||||||
* The [ECDSA signing method](https://godoc.org/github.com/dgrijalva/jwt-go#SigningMethodECDSA) (`ES256`,`ES384`,`ES512`) expect `*ecdsa.PrivateKey` for signing and `*ecdsa.PublicKey` for validation
|
* The [ECDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodECDSA) (`ES256`,`ES384`,`ES512`) expect `*ecdsa.PrivateKey` for signing and `*ecdsa.PublicKey` for validation
|
||||||
|
|
||||||
### JWT and OAuth
|
### JWT and OAuth
|
||||||
|
|
||||||
@ -93,8 +102,12 @@ Without going too far down the rabbit hole, here's a description of the interact
|
|||||||
* OAuth defines several options for passing around authentication data. One popular method is called a "bearer token". A bearer token is simply a string that _should_ only be held by an authenticated user. Thus, simply presenting this token proves your identity. You can probably derive from here why a JWT might make a good bearer token.
|
* OAuth defines several options for passing around authentication data. One popular method is called a "bearer token". A bearer token is simply a string that _should_ only be held by an authenticated user. Thus, simply presenting this token proves your identity. You can probably derive from here why a JWT might make a good bearer token.
|
||||||
* Because bearer tokens are used for authentication, it's important they're kept secret. This is why transactions that use bearer tokens typically happen over SSL.
|
* Because bearer tokens are used for authentication, it's important they're kept secret. This is why transactions that use bearer tokens typically happen over SSL.
|
||||||
|
|
||||||
|
### Troubleshooting
|
||||||
|
|
||||||
|
This library uses descriptive error messages whenever possible. If you are not getting the expected result, have a look at the errors. The most common place people get stuck is providing the correct type of key to the parser. See the above section on signing methods and key types.
|
||||||
|
|
||||||
## More
|
## More
|
||||||
|
|
||||||
Documentation can be found [on godoc.org](http://godoc.org/github.com/dgrijalva/jwt-go).
|
Documentation can be found [on pkg.go.dev](https://pkg.go.dev/github.com/golang-jwt/jwt).
|
||||||
|
|
||||||
The command line utility included in this project (cmd/jwt) provides a straightforward example of token creation and parsing as well as a useful tool for debugging your own integration. You'll also find several implementation examples in the documentation.
|
The command line utility included in this project (cmd/jwt) provides a straightforward example of token creation and parsing as well as a useful tool for debugging your own integration. You'll also find several implementation examples in the documentation.
|
@ -1,5 +1,18 @@
|
|||||||
## `jwt-go` Version History
|
## `jwt-go` Version History
|
||||||
|
|
||||||
|
#### 3.2.2
|
||||||
|
|
||||||
|
* Starting from this release, we are adopting the policy to support the most 2 recent versions of Go currently available. By the time of this release, this is Go 1.15 and 1.16 ([#28](https://github.com/golang-jwt/jwt/pull/28)).
|
||||||
|
* Fixed a potential issue that could occur when the verification of `exp`, `iat` or `nbf` was not required and contained invalid contents, i.e. non-numeric/date. Thanks for @thaJeztah for making us aware of that and @giorgos-f3 for originally reporting it to the formtech fork ([#40](https://github.com/golang-jwt/jwt/pull/40)).
|
||||||
|
* Added support for EdDSA / ED25519 ([#36](https://github.com/golang-jwt/jwt/pull/36)).
|
||||||
|
* Optimized allocations ([#33](https://github.com/golang-jwt/jwt/pull/33)).
|
||||||
|
|
||||||
|
#### 3.2.1
|
||||||
|
|
||||||
|
* **Import Path Change**: See MIGRATION_GUIDE.md for tips on updating your code
|
||||||
|
* Changed the import path from `github.com/dgrijalva/jwt-go` to `github.com/golang-jwt/jwt`
|
||||||
|
* Fixed type confusing issue between `string` and `[]string` in `VerifyAudience` ([#12](https://github.com/golang-jwt/jwt/pull/12)). This fixes CVE-2020-26160
|
||||||
|
|
||||||
#### 3.2.0
|
#### 3.2.0
|
||||||
|
|
||||||
* Added method `ParseUnverified` to allow users to split up the tasks of parsing and validation
|
* Added method `ParseUnverified` to allow users to split up the tasks of parsing and validation
|
@ -35,18 +35,18 @@ func (c StandardClaims) Valid() error {
|
|||||||
|
|
||||||
// The claims below are optional, by default, so if they are set to the
|
// The claims below are optional, by default, so if they are set to the
|
||||||
// default value in Go, let's not fail the verification for them.
|
// default value in Go, let's not fail the verification for them.
|
||||||
if c.VerifyExpiresAt(now, false) == false {
|
if !c.VerifyExpiresAt(now, false) {
|
||||||
delta := time.Unix(now, 0).Sub(time.Unix(c.ExpiresAt, 0))
|
delta := time.Unix(now, 0).Sub(time.Unix(c.ExpiresAt, 0))
|
||||||
vErr.Inner = fmt.Errorf("token is expired by %v", delta)
|
vErr.Inner = fmt.Errorf("token is expired by %v", delta)
|
||||||
vErr.Errors |= ValidationErrorExpired
|
vErr.Errors |= ValidationErrorExpired
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.VerifyIssuedAt(now, false) == false {
|
if !c.VerifyIssuedAt(now, false) {
|
||||||
vErr.Inner = fmt.Errorf("Token used before issued")
|
vErr.Inner = fmt.Errorf("Token used before issued")
|
||||||
vErr.Errors |= ValidationErrorIssuedAt
|
vErr.Errors |= ValidationErrorIssuedAt
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.VerifyNotBefore(now, false) == false {
|
if !c.VerifyNotBefore(now, false) {
|
||||||
vErr.Inner = fmt.Errorf("token is not valid yet")
|
vErr.Inner = fmt.Errorf("token is not valid yet")
|
||||||
vErr.Errors |= ValidationErrorNotValidYet
|
vErr.Errors |= ValidationErrorNotValidYet
|
||||||
}
|
}
|
||||||
@ -61,7 +61,7 @@ func (c StandardClaims) Valid() error {
|
|||||||
// Compares the aud claim against cmp.
|
// Compares the aud claim against cmp.
|
||||||
// If required is false, this method will return true if the value matches or is unset
|
// If required is false, this method will return true if the value matches or is unset
|
||||||
func (c *StandardClaims) VerifyAudience(cmp string, req bool) bool {
|
func (c *StandardClaims) VerifyAudience(cmp string, req bool) bool {
|
||||||
return verifyAud(c.Audience, cmp, req)
|
return verifyAud([]string{c.Audience}, cmp, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compares the exp claim against cmp.
|
// Compares the exp claim against cmp.
|
||||||
@ -90,15 +90,27 @@ func (c *StandardClaims) VerifyNotBefore(cmp int64, req bool) bool {
|
|||||||
|
|
||||||
// ----- helpers
|
// ----- helpers
|
||||||
|
|
||||||
func verifyAud(aud string, cmp string, required bool) bool {
|
func verifyAud(aud []string, cmp string, required bool) bool {
|
||||||
if aud == "" {
|
if len(aud) == 0 {
|
||||||
return !required
|
return !required
|
||||||
}
|
}
|
||||||
if subtle.ConstantTimeCompare([]byte(aud), []byte(cmp)) != 0 {
|
// use a var here to keep constant time compare when looping over a number of claims
|
||||||
return true
|
result := false
|
||||||
} else {
|
|
||||||
return false
|
var stringClaims string
|
||||||
|
for _, a := range aud {
|
||||||
|
if subtle.ConstantTimeCompare([]byte(a), []byte(cmp)) != 0 {
|
||||||
|
result = true
|
||||||
}
|
}
|
||||||
|
stringClaims = stringClaims + a
|
||||||
|
}
|
||||||
|
|
||||||
|
// case where "" is sent in one or many aud claims
|
||||||
|
if len(stringClaims) == 0 {
|
||||||
|
return !required
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func verifyExp(exp int64, now int64, required bool) bool {
|
func verifyExp(exp int64, now int64, required bool) bool {
|
0
vendor/github.com/dgrijalva/jwt-go/doc.go → vendor/github.com/golang-jwt/jwt/doc.go
generated
vendored
0
vendor/github.com/dgrijalva/jwt-go/doc.go → vendor/github.com/golang-jwt/jwt/doc.go
generated
vendored
24
vendor/github.com/dgrijalva/jwt-go/ecdsa.go → vendor/github.com/golang-jwt/jwt/ecdsa.go
generated
vendored
24
vendor/github.com/dgrijalva/jwt-go/ecdsa.go → vendor/github.com/golang-jwt/jwt/ecdsa.go
generated
vendored
@ -88,11 +88,11 @@ func (m *SigningMethodECDSA) Verify(signingString, signature string, key interfa
|
|||||||
hasher.Write([]byte(signingString))
|
hasher.Write([]byte(signingString))
|
||||||
|
|
||||||
// Verify the signature
|
// Verify the signature
|
||||||
if verifystatus := ecdsa.Verify(ecdsaKey, hasher.Sum(nil), r, s); verifystatus == true {
|
if verifystatus := ecdsa.Verify(ecdsaKey, hasher.Sum(nil), r, s); verifystatus {
|
||||||
return nil
|
return nil
|
||||||
} else {
|
|
||||||
return ErrECDSAVerification
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ErrECDSAVerification
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the Sign method from SigningMethod
|
// Implements the Sign method from SigningMethod
|
||||||
@ -128,18 +128,12 @@ func (m *SigningMethodECDSA) Sign(signingString string, key interface{}) (string
|
|||||||
keyBytes += 1
|
keyBytes += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// We serialize the outpus (r and s) into big-endian byte arrays and pad
|
// We serialize the outputs (r and s) into big-endian byte arrays
|
||||||
// them with zeros on the left to make sure the sizes work out. Both arrays
|
// padded with zeros on the left to make sure the sizes work out.
|
||||||
// must be keyBytes long, and the output must be 2*keyBytes long.
|
// Output must be 2*keyBytes long.
|
||||||
rBytes := r.Bytes()
|
out := make([]byte, 2*keyBytes)
|
||||||
rBytesPadded := make([]byte, keyBytes)
|
r.FillBytes(out[0:keyBytes]) // r is assigned to the first half of output.
|
||||||
copy(rBytesPadded[keyBytes-len(rBytes):], rBytes)
|
s.FillBytes(out[keyBytes:]) // s is assigned to the second half of output.
|
||||||
|
|
||||||
sBytes := s.Bytes()
|
|
||||||
sBytesPadded := make([]byte, keyBytes)
|
|
||||||
copy(sBytesPadded[keyBytes-len(sBytes):], sBytes)
|
|
||||||
|
|
||||||
out := append(rBytesPadded, sBytesPadded...)
|
|
||||||
|
|
||||||
return EncodeSegment(out), nil
|
return EncodeSegment(out), nil
|
||||||
} else {
|
} else {
|
@ -25,8 +25,10 @@ func ParseECPrivateKeyFromPEM(key []byte) (*ecdsa.PrivateKey, error) {
|
|||||||
// Parse the key
|
// Parse the key
|
||||||
var parsedKey interface{}
|
var parsedKey interface{}
|
||||||
if parsedKey, err = x509.ParseECPrivateKey(block.Bytes); err != nil {
|
if parsedKey, err = x509.ParseECPrivateKey(block.Bytes); err != nil {
|
||||||
|
if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var pkey *ecdsa.PrivateKey
|
var pkey *ecdsa.PrivateKey
|
||||||
var ok bool
|
var ok bool
|
81
vendor/github.com/golang-jwt/jwt/ed25519.go
generated
vendored
Normal file
81
vendor/github.com/golang-jwt/jwt/ed25519.go
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package jwt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"crypto/ed25519"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrEd25519Verification = errors.New("ed25519: verification error")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Implements the EdDSA family
|
||||||
|
// Expects ed25519.PrivateKey for signing and ed25519.PublicKey for verification
|
||||||
|
type SigningMethodEd25519 struct{}
|
||||||
|
|
||||||
|
// Specific instance for EdDSA
|
||||||
|
var (
|
||||||
|
SigningMethodEdDSA *SigningMethodEd25519
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SigningMethodEdDSA = &SigningMethodEd25519{}
|
||||||
|
RegisterSigningMethod(SigningMethodEdDSA.Alg(), func() SigningMethod {
|
||||||
|
return SigningMethodEdDSA
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SigningMethodEd25519) Alg() string {
|
||||||
|
return "EdDSA"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements the Verify method from SigningMethod
|
||||||
|
// For this verify method, key must be an ed25519.PublicKey
|
||||||
|
func (m *SigningMethodEd25519) Verify(signingString, signature string, key interface{}) error {
|
||||||
|
var err error
|
||||||
|
var ed25519Key ed25519.PublicKey
|
||||||
|
var ok bool
|
||||||
|
|
||||||
|
if ed25519Key, ok = key.(ed25519.PublicKey); !ok {
|
||||||
|
return ErrInvalidKeyType
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ed25519Key) != ed25519.PublicKeySize {
|
||||||
|
return ErrInvalidKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode the signature
|
||||||
|
var sig []byte
|
||||||
|
if sig, err = DecodeSegment(signature); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the signature
|
||||||
|
if !ed25519.Verify(ed25519Key, []byte(signingString), sig) {
|
||||||
|
return ErrEd25519Verification
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements the Sign method from SigningMethod
|
||||||
|
// For this signing method, key must be an ed25519.PrivateKey
|
||||||
|
func (m *SigningMethodEd25519) Sign(signingString string, key interface{}) (string, error) {
|
||||||
|
var ed25519Key ed25519.PrivateKey
|
||||||
|
var ok bool
|
||||||
|
|
||||||
|
if ed25519Key, ok = key.(ed25519.PrivateKey); !ok {
|
||||||
|
return "", ErrInvalidKeyType
|
||||||
|
}
|
||||||
|
|
||||||
|
// ed25519.Sign panics if private key not equal to ed25519.PrivateKeySize
|
||||||
|
// this allows to avoid recover usage
|
||||||
|
if len(ed25519Key) != ed25519.PrivateKeySize {
|
||||||
|
return "", ErrInvalidKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign the string and return the encoded result
|
||||||
|
sig := ed25519.Sign(ed25519Key, []byte(signingString))
|
||||||
|
return EncodeSegment(sig), nil
|
||||||
|
}
|
64
vendor/github.com/golang-jwt/jwt/ed25519_utils.go
generated
vendored
Normal file
64
vendor/github.com/golang-jwt/jwt/ed25519_utils.go
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package jwt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto"
|
||||||
|
"crypto/ed25519"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/pem"
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrNotEdPrivateKey = errors.New("Key is not a valid Ed25519 private key")
|
||||||
|
ErrNotEdPublicKey = errors.New("Key is not a valid Ed25519 public key")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Parse PEM-encoded Edwards curve private key
|
||||||
|
func ParseEdPrivateKeyFromPEM(key []byte) (crypto.PrivateKey, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// Parse PEM block
|
||||||
|
var block *pem.Block
|
||||||
|
if block, _ = pem.Decode(key); block == nil {
|
||||||
|
return nil, ErrKeyMustBePEMEncoded
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the key
|
||||||
|
var parsedKey interface{}
|
||||||
|
if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var pkey ed25519.PrivateKey
|
||||||
|
var ok bool
|
||||||
|
if pkey, ok = parsedKey.(ed25519.PrivateKey); !ok {
|
||||||
|
return nil, ErrNotEdPrivateKey
|
||||||
|
}
|
||||||
|
|
||||||
|
return pkey, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse PEM-encoded Edwards curve public key
|
||||||
|
func ParseEdPublicKeyFromPEM(key []byte) (crypto.PublicKey, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// Parse PEM block
|
||||||
|
var block *pem.Block
|
||||||
|
if block, _ = pem.Decode(key); block == nil {
|
||||||
|
return nil, ErrKeyMustBePEMEncoded
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the key
|
||||||
|
var parsedKey interface{}
|
||||||
|
if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var pkey ed25519.PublicKey
|
||||||
|
var ok bool
|
||||||
|
if pkey, ok = parsedKey.(ed25519.PublicKey); !ok {
|
||||||
|
return nil, ErrNotEdPublicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
return pkey, nil
|
||||||
|
}
|
@ -10,37 +10,59 @@ import (
|
|||||||
// This is the default claims type if you don't supply one
|
// This is the default claims type if you don't supply one
|
||||||
type MapClaims map[string]interface{}
|
type MapClaims map[string]interface{}
|
||||||
|
|
||||||
// Compares the aud claim against cmp.
|
// VerifyAudience Compares the aud claim against cmp.
|
||||||
// If required is false, this method will return true if the value matches or is unset
|
// If required is false, this method will return true if the value matches or is unset
|
||||||
func (m MapClaims) VerifyAudience(cmp string, req bool) bool {
|
func (m MapClaims) VerifyAudience(cmp string, req bool) bool {
|
||||||
aud, _ := m["aud"].(string)
|
var aud []string
|
||||||
|
switch v := m["aud"].(type) {
|
||||||
|
case string:
|
||||||
|
aud = append(aud, v)
|
||||||
|
case []string:
|
||||||
|
aud = v
|
||||||
|
case []interface{}:
|
||||||
|
for _, a := range v {
|
||||||
|
vs, ok := a.(string)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
aud = append(aud, vs)
|
||||||
|
}
|
||||||
|
}
|
||||||
return verifyAud(aud, cmp, req)
|
return verifyAud(aud, cmp, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compares the exp claim against cmp.
|
// Compares the exp claim against cmp.
|
||||||
// If required is false, this method will return true if the value matches or is unset
|
// If required is false, this method will return true if the value matches or is unset
|
||||||
func (m MapClaims) VerifyExpiresAt(cmp int64, req bool) bool {
|
func (m MapClaims) VerifyExpiresAt(cmp int64, req bool) bool {
|
||||||
switch exp := m["exp"].(type) {
|
exp, ok := m["exp"]
|
||||||
|
if !ok {
|
||||||
|
return !req
|
||||||
|
}
|
||||||
|
switch expType := exp.(type) {
|
||||||
case float64:
|
case float64:
|
||||||
return verifyExp(int64(exp), cmp, req)
|
return verifyExp(int64(expType), cmp, req)
|
||||||
case json.Number:
|
case json.Number:
|
||||||
v, _ := exp.Int64()
|
v, _ := expType.Int64()
|
||||||
return verifyExp(v, cmp, req)
|
return verifyExp(v, cmp, req)
|
||||||
}
|
}
|
||||||
return req == false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compares the iat claim against cmp.
|
// Compares the iat claim against cmp.
|
||||||
// If required is false, this method will return true if the value matches or is unset
|
// If required is false, this method will return true if the value matches or is unset
|
||||||
func (m MapClaims) VerifyIssuedAt(cmp int64, req bool) bool {
|
func (m MapClaims) VerifyIssuedAt(cmp int64, req bool) bool {
|
||||||
switch iat := m["iat"].(type) {
|
iat, ok := m["iat"]
|
||||||
|
if !ok {
|
||||||
|
return !req
|
||||||
|
}
|
||||||
|
switch iatType := iat.(type) {
|
||||||
case float64:
|
case float64:
|
||||||
return verifyIat(int64(iat), cmp, req)
|
return verifyIat(int64(iatType), cmp, req)
|
||||||
case json.Number:
|
case json.Number:
|
||||||
v, _ := iat.Int64()
|
v, _ := iatType.Int64()
|
||||||
return verifyIat(v, cmp, req)
|
return verifyIat(v, cmp, req)
|
||||||
}
|
}
|
||||||
return req == false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compares the iss claim against cmp.
|
// Compares the iss claim against cmp.
|
||||||
@ -53,14 +75,18 @@ func (m MapClaims) VerifyIssuer(cmp string, req bool) bool {
|
|||||||
// Compares the nbf claim against cmp.
|
// Compares the nbf claim against cmp.
|
||||||
// If required is false, this method will return true if the value matches or is unset
|
// If required is false, this method will return true if the value matches or is unset
|
||||||
func (m MapClaims) VerifyNotBefore(cmp int64, req bool) bool {
|
func (m MapClaims) VerifyNotBefore(cmp int64, req bool) bool {
|
||||||
switch nbf := m["nbf"].(type) {
|
nbf, ok := m["nbf"]
|
||||||
|
if !ok {
|
||||||
|
return !req
|
||||||
|
}
|
||||||
|
switch nbfType := nbf.(type) {
|
||||||
case float64:
|
case float64:
|
||||||
return verifyNbf(int64(nbf), cmp, req)
|
return verifyNbf(int64(nbfType), cmp, req)
|
||||||
case json.Number:
|
case json.Number:
|
||||||
v, _ := nbf.Int64()
|
v, _ := nbfType.Int64()
|
||||||
return verifyNbf(v, cmp, req)
|
return verifyNbf(v, cmp, req)
|
||||||
}
|
}
|
||||||
return req == false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validates time based claims "exp, iat, nbf".
|
// Validates time based claims "exp, iat, nbf".
|
||||||
@ -71,17 +97,17 @@ func (m MapClaims) Valid() error {
|
|||||||
vErr := new(ValidationError)
|
vErr := new(ValidationError)
|
||||||
now := TimeFunc().Unix()
|
now := TimeFunc().Unix()
|
||||||
|
|
||||||
if m.VerifyExpiresAt(now, false) == false {
|
if !m.VerifyExpiresAt(now, false) {
|
||||||
vErr.Inner = errors.New("Token is expired")
|
vErr.Inner = errors.New("Token is expired")
|
||||||
vErr.Errors |= ValidationErrorExpired
|
vErr.Errors |= ValidationErrorExpired
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.VerifyIssuedAt(now, false) == false {
|
if !m.VerifyIssuedAt(now, false) {
|
||||||
vErr.Inner = errors.New("Token used before issued")
|
vErr.Inner = errors.New("Token used before issued")
|
||||||
vErr.Errors |= ValidationErrorIssuedAt
|
vErr.Errors |= ValidationErrorIssuedAt
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.VerifyNotBefore(now, false) == false {
|
if !m.VerifyNotBefore(now, false) {
|
||||||
vErr.Inner = errors.New("Token is not valid yet")
|
vErr.Inner = errors.New("Token is not valid yet")
|
||||||
vErr.Errors |= ValidationErrorNotValidYet
|
vErr.Errors |= ValidationErrorNotValidYet
|
||||||
}
|
}
|
0
vendor/github.com/dgrijalva/jwt-go/rsa.go → vendor/github.com/golang-jwt/jwt/rsa.go
generated
vendored
0
vendor/github.com/dgrijalva/jwt-go/rsa.go → vendor/github.com/golang-jwt/jwt/rsa.go
generated
vendored
@ -12,9 +12,14 @@ import (
|
|||||||
type SigningMethodRSAPSS struct {
|
type SigningMethodRSAPSS struct {
|
||||||
*SigningMethodRSA
|
*SigningMethodRSA
|
||||||
Options *rsa.PSSOptions
|
Options *rsa.PSSOptions
|
||||||
|
// VerifyOptions is optional. If set overrides Options for rsa.VerifyPPS.
|
||||||
|
// Used to accept tokens signed with rsa.PSSSaltLengthAuto, what doesn't follow
|
||||||
|
// https://tools.ietf.org/html/rfc7518#section-3.5 but was used previously.
|
||||||
|
// See https://github.com/dgrijalva/jwt-go/issues/285#issuecomment-437451244 for details.
|
||||||
|
VerifyOptions *rsa.PSSOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
// Specific instances for RS/PS and company
|
// Specific instances for RS/PS and company.
|
||||||
var (
|
var (
|
||||||
SigningMethodPS256 *SigningMethodRSAPSS
|
SigningMethodPS256 *SigningMethodRSAPSS
|
||||||
SigningMethodPS384 *SigningMethodRSAPSS
|
SigningMethodPS384 *SigningMethodRSAPSS
|
||||||
@ -24,13 +29,15 @@ var (
|
|||||||
func init() {
|
func init() {
|
||||||
// PS256
|
// PS256
|
||||||
SigningMethodPS256 = &SigningMethodRSAPSS{
|
SigningMethodPS256 = &SigningMethodRSAPSS{
|
||||||
&SigningMethodRSA{
|
SigningMethodRSA: &SigningMethodRSA{
|
||||||
Name: "PS256",
|
Name: "PS256",
|
||||||
Hash: crypto.SHA256,
|
Hash: crypto.SHA256,
|
||||||
},
|
},
|
||||||
&rsa.PSSOptions{
|
Options: &rsa.PSSOptions{
|
||||||
|
SaltLength: rsa.PSSSaltLengthEqualsHash,
|
||||||
|
},
|
||||||
|
VerifyOptions: &rsa.PSSOptions{
|
||||||
SaltLength: rsa.PSSSaltLengthAuto,
|
SaltLength: rsa.PSSSaltLengthAuto,
|
||||||
Hash: crypto.SHA256,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
RegisterSigningMethod(SigningMethodPS256.Alg(), func() SigningMethod {
|
RegisterSigningMethod(SigningMethodPS256.Alg(), func() SigningMethod {
|
||||||
@ -39,13 +46,15 @@ func init() {
|
|||||||
|
|
||||||
// PS384
|
// PS384
|
||||||
SigningMethodPS384 = &SigningMethodRSAPSS{
|
SigningMethodPS384 = &SigningMethodRSAPSS{
|
||||||
&SigningMethodRSA{
|
SigningMethodRSA: &SigningMethodRSA{
|
||||||
Name: "PS384",
|
Name: "PS384",
|
||||||
Hash: crypto.SHA384,
|
Hash: crypto.SHA384,
|
||||||
},
|
},
|
||||||
&rsa.PSSOptions{
|
Options: &rsa.PSSOptions{
|
||||||
|
SaltLength: rsa.PSSSaltLengthEqualsHash,
|
||||||
|
},
|
||||||
|
VerifyOptions: &rsa.PSSOptions{
|
||||||
SaltLength: rsa.PSSSaltLengthAuto,
|
SaltLength: rsa.PSSSaltLengthAuto,
|
||||||
Hash: crypto.SHA384,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
RegisterSigningMethod(SigningMethodPS384.Alg(), func() SigningMethod {
|
RegisterSigningMethod(SigningMethodPS384.Alg(), func() SigningMethod {
|
||||||
@ -54,13 +63,15 @@ func init() {
|
|||||||
|
|
||||||
// PS512
|
// PS512
|
||||||
SigningMethodPS512 = &SigningMethodRSAPSS{
|
SigningMethodPS512 = &SigningMethodRSAPSS{
|
||||||
&SigningMethodRSA{
|
SigningMethodRSA: &SigningMethodRSA{
|
||||||
Name: "PS512",
|
Name: "PS512",
|
||||||
Hash: crypto.SHA512,
|
Hash: crypto.SHA512,
|
||||||
},
|
},
|
||||||
&rsa.PSSOptions{
|
Options: &rsa.PSSOptions{
|
||||||
|
SaltLength: rsa.PSSSaltLengthEqualsHash,
|
||||||
|
},
|
||||||
|
VerifyOptions: &rsa.PSSOptions{
|
||||||
SaltLength: rsa.PSSSaltLengthAuto,
|
SaltLength: rsa.PSSSaltLengthAuto,
|
||||||
Hash: crypto.SHA512,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
RegisterSigningMethod(SigningMethodPS512.Alg(), func() SigningMethod {
|
RegisterSigningMethod(SigningMethodPS512.Alg(), func() SigningMethod {
|
||||||
@ -94,7 +105,12 @@ func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interf
|
|||||||
hasher := m.Hash.New()
|
hasher := m.Hash.New()
|
||||||
hasher.Write([]byte(signingString))
|
hasher.Write([]byte(signingString))
|
||||||
|
|
||||||
return rsa.VerifyPSS(rsaKey, m.Hash, hasher.Sum(nil), sig, m.Options)
|
opts := m.Options
|
||||||
|
if m.VerifyOptions != nil {
|
||||||
|
opts = m.VerifyOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
return rsa.VerifyPSS(rsaKey, m.Hash, hasher.Sum(nil), sig, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the Sign method from SigningMethod
|
// Implements the Sign method from SigningMethod
|
@ -8,7 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrKeyMustBePEMEncoded = errors.New("Invalid Key: Key must be PEM encoded PKCS1 or PKCS8 private key")
|
ErrKeyMustBePEMEncoded = errors.New("Invalid Key: Key must be a PEM encoded PKCS1 or PKCS8 key")
|
||||||
ErrNotRSAPrivateKey = errors.New("Key is not a valid RSA private key")
|
ErrNotRSAPrivateKey = errors.New("Key is not a valid RSA private key")
|
||||||
ErrNotRSAPublicKey = errors.New("Key is not a valid RSA public key")
|
ErrNotRSAPublicKey = errors.New("Key is not a valid RSA public key")
|
||||||
)
|
)
|
10
vendor/github.com/dgrijalva/jwt-go/token.go → vendor/github.com/golang-jwt/jwt/token.go
generated
vendored
10
vendor/github.com/dgrijalva/jwt-go/token.go → vendor/github.com/golang-jwt/jwt/token.go
generated
vendored
@ -65,7 +65,7 @@ func (t *Token) SignedString(key interface{}) (string, error) {
|
|||||||
func (t *Token) SigningString() (string, error) {
|
func (t *Token) SigningString() (string, error) {
|
||||||
var err error
|
var err error
|
||||||
parts := make([]string, 2)
|
parts := make([]string, 2)
|
||||||
for i, _ := range parts {
|
for i := range parts {
|
||||||
var jsonValue []byte
|
var jsonValue []byte
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
if jsonValue, err = json.Marshal(t.Header); err != nil {
|
if jsonValue, err = json.Marshal(t.Header); err != nil {
|
||||||
@ -95,14 +95,10 @@ func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token
|
|||||||
|
|
||||||
// Encode JWT specific base64url encoding with padding stripped
|
// Encode JWT specific base64url encoding with padding stripped
|
||||||
func EncodeSegment(seg []byte) string {
|
func EncodeSegment(seg []byte) string {
|
||||||
return strings.TrimRight(base64.URLEncoding.EncodeToString(seg), "=")
|
return base64.RawURLEncoding.EncodeToString(seg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode JWT specific base64url encoding with padding stripped
|
// Decode JWT specific base64url encoding with padding stripped
|
||||||
func DecodeSegment(seg string) ([]byte, error) {
|
func DecodeSegment(seg string) ([]byte, error) {
|
||||||
if l := len(seg) % 4; l > 0 {
|
return base64.RawURLEncoding.DecodeString(seg)
|
||||||
seg += strings.Repeat("=", 4-l)
|
|
||||||
}
|
|
||||||
|
|
||||||
return base64.URLEncoding.DecodeString(seg)
|
|
||||||
}
|
}
|
7
vendor/github.com/gomarkdown/markdown/.gitpod
generated
vendored
7
vendor/github.com/gomarkdown/markdown/.gitpod
generated
vendored
@ -1,7 +0,0 @@
|
|||||||
checkoutLocation: "src/github.com/gomarkdown/markdown"
|
|
||||||
workspaceLocation: "."
|
|
||||||
tasks:
|
|
||||||
- command: >
|
|
||||||
cd /workspace/src/github.com/gomarkdown/markdown &&
|
|
||||||
go get -v ./... &&
|
|
||||||
go test -c
|
|
23
vendor/github.com/gomarkdown/markdown/README.md
generated
vendored
23
vendor/github.com/gomarkdown/markdown/README.md
generated
vendored
@ -25,6 +25,7 @@ Some tools using this package:
|
|||||||
- https://github.com/romanyx/mdopen : view markdown files in the default browser
|
- https://github.com/romanyx/mdopen : view markdown files in the default browser
|
||||||
- https://github.com/ystyle/sqlmanager : a library for manager sql with markdown like beetsql
|
- https://github.com/ystyle/sqlmanager : a library for manager sql with markdown like beetsql
|
||||||
- https://gitlab.com/kendellfab/fazer : library for making templates
|
- https://gitlab.com/kendellfab/fazer : library for making templates
|
||||||
|
- https://github.com/blmayer/tasker : a simple task list web app
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
@ -130,6 +131,12 @@ maybeUnsafeHTML := markdown.ToHTML(md, nil, nil)
|
|||||||
html := bluemonday.UGCPolicy().SanitizeBytes(maybeUnsafeHTML)
|
html := bluemonday.UGCPolicy().SanitizeBytes(maybeUnsafeHTML)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Windows / Mac newlines
|
||||||
|
|
||||||
|
The library only supports Unix newlines. If you have markdown text with possibly
|
||||||
|
Windows / Mac newlines, normalize newlines before caling this librar using
|
||||||
|
`d = markdown.NormalizeNewlines(d)`
|
||||||
|
|
||||||
## mdtohtml command-line tool
|
## mdtohtml command-line tool
|
||||||
|
|
||||||
https://github.com/gomarkdown/mdtohtml is a command-line markdown to html
|
https://github.com/gomarkdown/mdtohtml is a command-line markdown to html
|
||||||
@ -259,10 +266,10 @@ implements the following extensions:
|
|||||||
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 newlines in the input
|
||||||
translate into line breaks in the output. This extension is off by default.
|
translates into line breaks in the output. This extension is off by default.
|
||||||
|
|
||||||
- **Non blocking space**. With this extension enabled spaces preceeded by an backslash n the input
|
- **Non blocking space**. With this extension enabled spaces preceeded by a backslash
|
||||||
translate non-blocking spaces in the output. This extension is off by default.
|
in the input translates non-blocking spaces in the output. This extension is off by default.
|
||||||
|
|
||||||
- **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
|
||||||
@ -281,9 +288,9 @@ implements the following extensions:
|
|||||||
<sup>4</sup>⁄<sub>5</sub>.
|
<sup>4</sup>⁄<sub>5</sub>.
|
||||||
|
|
||||||
- **MathJaX Support** is an additional feature which is supported by
|
- **MathJaX Support** is an additional feature which is supported by
|
||||||
many markdown editor. It translate inline math equation quoted by `$`
|
many markdown editor. It translates inline math equations quoted by `$`
|
||||||
and display math block quoted by `$$` into MathJax compatible format.
|
and displays math blocks quoted by `$$` into MathJax compatible format.
|
||||||
hyphen `_` won't break LaTeX render within a math element any more.
|
Hyphens (`_`) won't break LaTeX render within a math element any more.
|
||||||
|
|
||||||
```
|
```
|
||||||
$$
|
$$
|
||||||
@ -299,13 +306,13 @@ implements the following extensions:
|
|||||||
$$
|
$$
|
||||||
```
|
```
|
||||||
|
|
||||||
- **Ordered list start number**. With this extension enabled an ordered list will start with the
|
- **Ordered list start number**. With this extension enabled an ordered list will start with
|
||||||
the number that was used to start it.
|
the number that was used to start it.
|
||||||
|
|
||||||
- **Super and subscript**. With this extension enabled sequences between ^ will indicate
|
- **Super and subscript**. With this extension enabled sequences between ^ will indicate
|
||||||
superscript and ~ will become a subscript. For example: H~2~O is a liquid, 2^10^ is 1024.
|
superscript and ~ will become a subscript. For example: H~2~O is a liquid, 2^10^ is 1024.
|
||||||
|
|
||||||
- **Block level attributes**, allow setting attributes (ID, classes and key/value pairs) on block
|
- **Block level attributes** allow setting attributes (ID, classes and key/value pairs) on block
|
||||||
level elements. The attribute must be enclosed with braces and be put on a line before the
|
level elements. The attribute must be enclosed with braces and be put on a line before the
|
||||||
element.
|
element.
|
||||||
|
|
||||||
|
10
vendor/github.com/gomarkdown/markdown/ast/attribute.go
generated
vendored
10
vendor/github.com/gomarkdown/markdown/ast/attribute.go
generated
vendored
@ -1,10 +0,0 @@
|
|||||||
package ast
|
|
||||||
|
|
||||||
// An attribute can be attached to block elements. They are specified as
|
|
||||||
// {#id .classs key="value"} where quotes for values are mandatory, multiple
|
|
||||||
// key/value pairs are separated by whitespace.
|
|
||||||
type Attribute struct {
|
|
||||||
ID []byte
|
|
||||||
Classes [][]byte
|
|
||||||
Attrs map[string][]byte
|
|
||||||
}
|
|
9
vendor/github.com/gomarkdown/markdown/ast/node.go
generated
vendored
9
vendor/github.com/gomarkdown/markdown/ast/node.go
generated
vendored
@ -1,5 +1,14 @@
|
|||||||
package ast
|
package ast
|
||||||
|
|
||||||
|
// An attribute can be attached to block elements. They are specified as
|
||||||
|
// {#id .classs key="value"} where quotes for values are mandatory, multiple
|
||||||
|
// key/value pairs are separated by whitespace.
|
||||||
|
type Attribute struct {
|
||||||
|
ID []byte
|
||||||
|
Classes [][]byte
|
||||||
|
Attrs map[string][]byte
|
||||||
|
}
|
||||||
|
|
||||||
// ListType contains bitwise or'ed flags for list and list item objects.
|
// ListType contains bitwise or'ed flags for list and list item objects.
|
||||||
type ListType int
|
type ListType int
|
||||||
|
|
||||||
|
5
vendor/github.com/gomarkdown/markdown/go.mod
generated
vendored
5
vendor/github.com/gomarkdown/markdown/go.mod
generated
vendored
@ -1,5 +0,0 @@
|
|||||||
module github.com/gomarkdown/markdown
|
|
||||||
|
|
||||||
go 1.12
|
|
||||||
|
|
||||||
require golang.org/dl v0.0.0-20190829154251-82a15e2f2ead // indirect
|
|
1
vendor/github.com/gomarkdown/markdown/go.sum
generated
vendored
1
vendor/github.com/gomarkdown/markdown/go.sum
generated
vendored
@ -1 +0,0 @@
|
|||||||
golang.org/dl v0.0.0-20190829154251-82a15e2f2ead/go.mod h1:IUMfjQLJQd4UTqG1Z90tenwKoCX93Gn3MAQJMOSBsDQ=
|
|
41
vendor/github.com/gomarkdown/markdown/html/renderer.go
generated
vendored
41
vendor/github.com/gomarkdown/markdown/html/renderer.go
generated
vendored
@ -304,25 +304,6 @@ func isRelativeLink(link []byte) (yes bool) {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Renderer) ensureUniqueHeadingID(id string) string {
|
|
||||||
for count, found := r.headingIDs[id]; found; count, found = r.headingIDs[id] {
|
|
||||||
tmp := fmt.Sprintf("%s-%d", id, count+1)
|
|
||||||
|
|
||||||
if _, tmpFound := r.headingIDs[tmp]; !tmpFound {
|
|
||||||
r.headingIDs[id] = count + 1
|
|
||||||
id = tmp
|
|
||||||
} else {
|
|
||||||
id = id + "-1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, found := r.headingIDs[id]; !found {
|
|
||||||
r.headingIDs[id] = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return id
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Renderer) addAbsPrefix(link []byte) []byte {
|
func (r *Renderer) addAbsPrefix(link []byte) []byte {
|
||||||
if r.opts.AbsolutePrefix != "" && isRelativeLink(link) && link[0] != '.' {
|
if r.opts.AbsolutePrefix != "" && isRelativeLink(link) && link[0] != '.' {
|
||||||
newDest := r.opts.AbsolutePrefix
|
newDest := r.opts.AbsolutePrefix
|
||||||
@ -701,8 +682,28 @@ func (r *Renderer) headingEnter(w io.Writer, nodeData *ast.Heading) {
|
|||||||
if class != "" {
|
if class != "" {
|
||||||
attrs = []string{`class="` + class + `"`}
|
attrs = []string{`class="` + class + `"`}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ensureUniqueHeadingID := func(id string) string {
|
||||||
|
for count, found := r.headingIDs[id]; found; count, found = r.headingIDs[id] {
|
||||||
|
tmp := fmt.Sprintf("%s-%d", id, count+1)
|
||||||
|
|
||||||
|
if _, tmpFound := r.headingIDs[tmp]; !tmpFound {
|
||||||
|
r.headingIDs[id] = count + 1
|
||||||
|
id = tmp
|
||||||
|
} else {
|
||||||
|
id = id + "-1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, found := r.headingIDs[id]; !found {
|
||||||
|
r.headingIDs[id] = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
if nodeData.HeadingID != "" {
|
if nodeData.HeadingID != "" {
|
||||||
id := r.ensureUniqueHeadingID(nodeData.HeadingID)
|
id := ensureUniqueHeadingID(nodeData.HeadingID)
|
||||||
if r.opts.HeadingIDPrefix != "" {
|
if r.opts.HeadingIDPrefix != "" {
|
||||||
id = r.opts.HeadingIDPrefix + id
|
id = r.opts.HeadingIDPrefix + id
|
||||||
}
|
}
|
||||||
|
26
vendor/github.com/gomarkdown/markdown/markdown.go
generated
vendored
26
vendor/github.com/gomarkdown/markdown/markdown.go
generated
vendored
@ -83,3 +83,29 @@ func ToHTML(markdown []byte, p *parser.Parser, renderer Renderer) []byte {
|
|||||||
}
|
}
|
||||||
return Render(doc, renderer)
|
return Render(doc, renderer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NormalizeNewlines converts Windows and Mac newlines to Unix newlines
|
||||||
|
// The parser only supports Unix newlines. If your mardown content
|
||||||
|
// might contain Windows or Mac newlines, use this function to convert to Unix newlines
|
||||||
|
func NormalizeNewlines(d []byte) []byte {
|
||||||
|
wi := 0
|
||||||
|
n := len(d)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
c := d[i]
|
||||||
|
// 13 is CR
|
||||||
|
if c != 13 {
|
||||||
|
d[wi] = c
|
||||||
|
wi++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// replace CR (mac / win) with LF (unix)
|
||||||
|
d[wi] = 10
|
||||||
|
wi++
|
||||||
|
if i < n-1 && d[i+1] == 10 {
|
||||||
|
// this was CRLF, so skip the LF
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return d[:wi]
|
||||||
|
}
|
||||||
|
332
vendor/github.com/gomarkdown/markdown/parser/block.go
generated
vendored
332
vendor/github.com/gomarkdown/markdown/parser/block.go
generated
vendored
@ -74,9 +74,9 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// sanitizeAnchorName returns a sanitized anchor name for the given text.
|
// sanitizeHeadingID returns a sanitized anchor name for the given text.
|
||||||
// Taken from https://github.com/shurcooL/sanitized_anchor_name/blob/master/main.go#L14:1
|
// Taken from https://github.com/shurcooL/sanitized_anchor_name/blob/master/main.go#L14:1
|
||||||
func sanitizeAnchorName(text string) string {
|
func sanitizeHeadingID(text string) string {
|
||||||
var anchorName []rune
|
var anchorName []rune
|
||||||
var futureDash = false
|
var futureDash = false
|
||||||
for _, r := range text {
|
for _, r := range text {
|
||||||
@ -91,6 +91,9 @@ func sanitizeAnchorName(text string) string {
|
|||||||
futureDash = true
|
futureDash = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(anchorName) == 0 {
|
||||||
|
return "empty"
|
||||||
|
}
|
||||||
return string(anchorName)
|
return string(anchorName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,12 +281,6 @@ func (p *Parser) block(data []byte) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// table:
|
|
||||||
//
|
|
||||||
// Name | Age | Phone
|
|
||||||
// ------|-----|---------
|
|
||||||
// Bob | 31 | 555-1234
|
|
||||||
// Alice | 27 | 555-4321
|
|
||||||
if p.extensions&Tables != 0 {
|
if p.extensions&Tables != 0 {
|
||||||
if i := p.table(data); i > 0 {
|
if i := p.table(data); i > 0 {
|
||||||
data = data[i:]
|
data = data[i:]
|
||||||
@ -422,13 +419,14 @@ func (p *Parser) prefixHeading(data []byte) int {
|
|||||||
end--
|
end--
|
||||||
}
|
}
|
||||||
if end > i {
|
if end > i {
|
||||||
if id == "" && p.extensions&AutoHeadingIDs != 0 {
|
|
||||||
id = sanitizeAnchorName(string(data[i:end]))
|
|
||||||
}
|
|
||||||
block := &ast.Heading{
|
block := &ast.Heading{
|
||||||
HeadingID: id,
|
HeadingID: id,
|
||||||
Level: level,
|
Level: level,
|
||||||
}
|
}
|
||||||
|
if id == "" && p.extensions&AutoHeadingIDs != 0 {
|
||||||
|
block.HeadingID = sanitizeHeadingID(string(data[i:end]))
|
||||||
|
p.allHeadingsWithAutoID = append(p.allHeadingsWithAutoID, block)
|
||||||
|
}
|
||||||
block.Content = data[i:end]
|
block.Content = data[i:end]
|
||||||
p.addBlock(block)
|
p.addBlock(block)
|
||||||
}
|
}
|
||||||
@ -492,14 +490,15 @@ func (p *Parser) prefixSpecialHeading(data []byte) int {
|
|||||||
end--
|
end--
|
||||||
}
|
}
|
||||||
if end > i {
|
if end > i {
|
||||||
if id == "" && p.extensions&AutoHeadingIDs != 0 {
|
|
||||||
id = sanitizeAnchorName(string(data[i:end]))
|
|
||||||
}
|
|
||||||
block := &ast.Heading{
|
block := &ast.Heading{
|
||||||
HeadingID: id,
|
HeadingID: id,
|
||||||
IsSpecial: true,
|
IsSpecial: true,
|
||||||
Level: 1, // always level 1.
|
Level: 1, // always level 1.
|
||||||
}
|
}
|
||||||
|
if id == "" && p.extensions&AutoHeadingIDs != 0 {
|
||||||
|
block.HeadingID = sanitizeHeadingID(string(data[i:end]))
|
||||||
|
p.allHeadingsWithAutoID = append(p.allHeadingsWithAutoID, block)
|
||||||
|
}
|
||||||
block.Literal = data[i:end]
|
block.Literal = data[i:end]
|
||||||
block.Content = data[i:end]
|
block.Content = data[i:end]
|
||||||
p.addBlock(block)
|
p.addBlock(block)
|
||||||
@ -647,7 +646,7 @@ func (p *Parser) html(data []byte, doRender bool) int {
|
|||||||
if doRender {
|
if doRender {
|
||||||
// trim newlines
|
// trim newlines
|
||||||
end := backChar(data, i, '\n')
|
end := backChar(data, i, '\n')
|
||||||
htmlBLock := &ast.HTMLBlock{ast.Leaf{Content: data[:end]}}
|
htmlBLock := &ast.HTMLBlock{Leaf: ast.Leaf{Content: data[:end]}}
|
||||||
p.addBlock(htmlBLock)
|
p.addBlock(htmlBLock)
|
||||||
finalizeHTMLBlock(htmlBLock)
|
finalizeHTMLBlock(htmlBLock)
|
||||||
}
|
}
|
||||||
@ -669,7 +668,7 @@ func (p *Parser) htmlComment(data []byte, doRender bool) int {
|
|||||||
if doRender {
|
if doRender {
|
||||||
// trim trailing newlines
|
// trim trailing newlines
|
||||||
end := backChar(data, size, '\n')
|
end := backChar(data, size, '\n')
|
||||||
htmlBLock := &ast.HTMLBlock{ast.Leaf{Content: data[:end]}}
|
htmlBLock := &ast.HTMLBlock{Leaf: ast.Leaf{Content: data[:end]}}
|
||||||
p.addBlock(htmlBLock)
|
p.addBlock(htmlBLock)
|
||||||
finalizeHTMLBlock(htmlBLock)
|
finalizeHTMLBlock(htmlBLock)
|
||||||
}
|
}
|
||||||
@ -701,7 +700,7 @@ func (p *Parser) htmlHr(data []byte, doRender bool) int {
|
|||||||
if doRender {
|
if doRender {
|
||||||
// trim newlines
|
// trim newlines
|
||||||
end := backChar(data, size, '\n')
|
end := backChar(data, size, '\n')
|
||||||
htmlBlock := &ast.HTMLBlock{ast.Leaf{Content: data[:end]}}
|
htmlBlock := &ast.HTMLBlock{Leaf: ast.Leaf{Content: data[:end]}}
|
||||||
p.addBlock(htmlBlock)
|
p.addBlock(htmlBlock)
|
||||||
finalizeHTMLBlock(htmlBlock)
|
finalizeHTMLBlock(htmlBlock)
|
||||||
}
|
}
|
||||||
@ -1005,294 +1004,6 @@ func finalizeCodeBlock(code *ast.CodeBlock) {
|
|||||||
code.Content = nil
|
code.Content = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) table(data []byte) int {
|
|
||||||
i, columns, table := p.tableHeader(data)
|
|
||||||
if i == 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
p.addBlock(&ast.TableBody{})
|
|
||||||
|
|
||||||
for i < len(data) {
|
|
||||||
pipes, rowStart := 0, i
|
|
||||||
for ; i < len(data) && data[i] != '\n'; i++ {
|
|
||||||
if data[i] == '|' {
|
|
||||||
pipes++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if pipes == 0 {
|
|
||||||
i = rowStart
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// include the newline in data sent to tableRow
|
|
||||||
i = skipCharN(data, i, '\n', 1)
|
|
||||||
|
|
||||||
if p.tableFooter(data[rowStart:i]) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
p.tableRow(data[rowStart:i], columns, false)
|
|
||||||
}
|
|
||||||
if captionContent, id, consumed := p.caption(data[i:], []byte("Table: ")); consumed > 0 {
|
|
||||||
caption := &ast.Caption{}
|
|
||||||
p.Inline(caption, captionContent)
|
|
||||||
|
|
||||||
// Some switcheroo to re-insert the parsed table as a child of the captionfigure.
|
|
||||||
figure := &ast.CaptionFigure{}
|
|
||||||
figure.HeadingID = id
|
|
||||||
table2 := &ast.Table{}
|
|
||||||
// Retain any block level attributes.
|
|
||||||
table2.AsContainer().Attribute = table.AsContainer().Attribute
|
|
||||||
children := table.GetChildren()
|
|
||||||
ast.RemoveFromTree(table)
|
|
||||||
|
|
||||||
table2.SetChildren(children)
|
|
||||||
ast.AppendChild(figure, table2)
|
|
||||||
ast.AppendChild(figure, caption)
|
|
||||||
|
|
||||||
p.addChild(figure)
|
|
||||||
p.finalize(figure)
|
|
||||||
|
|
||||||
i += consumed
|
|
||||||
}
|
|
||||||
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if the specified position is preceded by an odd number of backslashes
|
|
||||||
func isBackslashEscaped(data []byte, i int) bool {
|
|
||||||
backslashes := 0
|
|
||||||
for i-backslashes-1 >= 0 && data[i-backslashes-1] == '\\' {
|
|
||||||
backslashes++
|
|
||||||
}
|
|
||||||
return backslashes&1 == 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// tableHeaders parses the header. If recognized it will also add a table.
|
|
||||||
func (p *Parser) tableHeader(data []byte) (size int, columns []ast.CellAlignFlags, table ast.Node) {
|
|
||||||
i := 0
|
|
||||||
colCount := 1
|
|
||||||
headerIsUnderline := true
|
|
||||||
for i = 0; i < len(data) && data[i] != '\n'; i++ {
|
|
||||||
if data[i] == '|' && !isBackslashEscaped(data, i) {
|
|
||||||
colCount++
|
|
||||||
}
|
|
||||||
if data[i] != '-' && data[i] != ' ' && data[i] != ':' && data[i] != '|' {
|
|
||||||
headerIsUnderline = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// doesn't look like a table header
|
|
||||||
if colCount == 1 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// include the newline in the data sent to tableRow
|
|
||||||
j := skipCharN(data, i, '\n', 1)
|
|
||||||
header := data[:j]
|
|
||||||
|
|
||||||
// column count ignores pipes at beginning or end of line
|
|
||||||
if data[0] == '|' {
|
|
||||||
colCount--
|
|
||||||
}
|
|
||||||
if i > 2 && data[i-1] == '|' && !isBackslashEscaped(data, i-1) {
|
|
||||||
colCount--
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the header looks like a underline, then we omit the header
|
|
||||||
// and parse the first line again as underline
|
|
||||||
if headerIsUnderline {
|
|
||||||
header = nil
|
|
||||||
i = 0
|
|
||||||
} else {
|
|
||||||
i++ // move past newline
|
|
||||||
}
|
|
||||||
|
|
||||||
columns = make([]ast.CellAlignFlags, colCount)
|
|
||||||
|
|
||||||
// move on to the header underline
|
|
||||||
if i >= len(data) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if data[i] == '|' && !isBackslashEscaped(data, i) {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
i = skipChar(data, i, ' ')
|
|
||||||
|
|
||||||
// each column header is of form: / *:?-+:? *|/ with # dashes + # colons >= 3
|
|
||||||
// and trailing | optional on last column
|
|
||||||
col := 0
|
|
||||||
n := len(data)
|
|
||||||
for i < n && data[i] != '\n' {
|
|
||||||
dashes := 0
|
|
||||||
|
|
||||||
if data[i] == ':' {
|
|
||||||
i++
|
|
||||||
columns[col] |= ast.TableAlignmentLeft
|
|
||||||
dashes++
|
|
||||||
}
|
|
||||||
for i < n && data[i] == '-' {
|
|
||||||
i++
|
|
||||||
dashes++
|
|
||||||
}
|
|
||||||
if i < n && data[i] == ':' {
|
|
||||||
i++
|
|
||||||
columns[col] |= ast.TableAlignmentRight
|
|
||||||
dashes++
|
|
||||||
}
|
|
||||||
for i < n && data[i] == ' ' {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
if i == n {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// end of column test is messy
|
|
||||||
switch {
|
|
||||||
case dashes < 3:
|
|
||||||
// not a valid column
|
|
||||||
return
|
|
||||||
|
|
||||||
case data[i] == '|' && !isBackslashEscaped(data, i):
|
|
||||||
// marker found, now skip past trailing whitespace
|
|
||||||
col++
|
|
||||||
i++
|
|
||||||
for i < n && data[i] == ' ' {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
// trailing junk found after last column
|
|
||||||
if col >= colCount && i < len(data) && data[i] != '\n' {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
case (data[i] != '|' || isBackslashEscaped(data, i)) && col+1 < colCount:
|
|
||||||
// something else found where marker was required
|
|
||||||
return
|
|
||||||
|
|
||||||
case data[i] == '\n':
|
|
||||||
// marker is optional for the last column
|
|
||||||
col++
|
|
||||||
|
|
||||||
default:
|
|
||||||
// trailing junk found after last column
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if col != colCount {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
table = &ast.Table{}
|
|
||||||
p.addBlock(table)
|
|
||||||
if header != nil {
|
|
||||||
p.addBlock(&ast.TableHeader{})
|
|
||||||
p.tableRow(header, columns, true)
|
|
||||||
}
|
|
||||||
size = skipCharN(data, i, '\n', 1)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Parser) tableRow(data []byte, columns []ast.CellAlignFlags, header bool) {
|
|
||||||
p.addBlock(&ast.TableRow{})
|
|
||||||
i, col := 0, 0
|
|
||||||
|
|
||||||
if data[i] == '|' && !isBackslashEscaped(data, i) {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
n := len(data)
|
|
||||||
colspans := 0 // keep track of total colspan in this row.
|
|
||||||
for col = 0; col < len(columns) && i < n; col++ {
|
|
||||||
colspan := 0
|
|
||||||
for i < n && data[i] == ' ' {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
cellStart := i
|
|
||||||
|
|
||||||
for i < n && (data[i] != '|' || isBackslashEscaped(data, i)) && data[i] != '\n' {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
cellEnd := i
|
|
||||||
|
|
||||||
// skip the end-of-cell marker, possibly taking us past end of buffer
|
|
||||||
// each _extra_ | means a colspan
|
|
||||||
for i < len(data) && data[i] == '|' && !isBackslashEscaped(data, i) {
|
|
||||||
i++
|
|
||||||
colspan++
|
|
||||||
}
|
|
||||||
// only colspan > 1 make sense.
|
|
||||||
if colspan < 2 {
|
|
||||||
colspan = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
for cellEnd > cellStart && cellEnd-1 < n && data[cellEnd-1] == ' ' {
|
|
||||||
cellEnd--
|
|
||||||
}
|
|
||||||
|
|
||||||
block := &ast.TableCell{
|
|
||||||
IsHeader: header,
|
|
||||||
Align: columns[col],
|
|
||||||
ColSpan: colspan,
|
|
||||||
}
|
|
||||||
block.Content = data[cellStart:cellEnd]
|
|
||||||
if cellStart == cellEnd && colspans > 0 {
|
|
||||||
// an empty cell that we should ignore, it exists because of colspan
|
|
||||||
colspans--
|
|
||||||
} else {
|
|
||||||
p.addBlock(block)
|
|
||||||
}
|
|
||||||
|
|
||||||
if colspan > 0 {
|
|
||||||
colspans += colspan - 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// pad it out with empty columns to get the right number
|
|
||||||
for ; col < len(columns); col++ {
|
|
||||||
block := &ast.TableCell{
|
|
||||||
IsHeader: header,
|
|
||||||
Align: columns[col],
|
|
||||||
}
|
|
||||||
p.addBlock(block)
|
|
||||||
}
|
|
||||||
|
|
||||||
// silently ignore rows with too many cells
|
|
||||||
}
|
|
||||||
|
|
||||||
// tableFooter parses the (optional) table footer.
|
|
||||||
func (p *Parser) tableFooter(data []byte) bool {
|
|
||||||
colCount := 1
|
|
||||||
i := 0
|
|
||||||
n := len(data)
|
|
||||||
for i < 3 && i < n && data[i] == ' ' { // ignore up to 3 spaces
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
for ; i < n && data[i] != '\n'; i++ {
|
|
||||||
if data[i] == '|' && !isBackslashEscaped(data, i) {
|
|
||||||
colCount++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// remaining data must be the = character
|
|
||||||
if data[i] != '=' {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// doesn't look like a table footer
|
|
||||||
if colCount == 1 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
p.addBlock(&ast.TableFooter{})
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns blockquote prefix length
|
// returns blockquote prefix length
|
||||||
func (p *Parser) quotePrefix(data []byte) int {
|
func (p *Parser) quotePrefix(data []byte) int {
|
||||||
i := 0
|
i := 0
|
||||||
@ -1887,15 +1598,14 @@ func (p *Parser) paragraph(data []byte) int {
|
|||||||
eol--
|
eol--
|
||||||
}
|
}
|
||||||
|
|
||||||
id := ""
|
|
||||||
if p.extensions&AutoHeadingIDs != 0 {
|
|
||||||
id = sanitizeAnchorName(string(data[prev:eol]))
|
|
||||||
}
|
|
||||||
|
|
||||||
block := &ast.Heading{
|
block := &ast.Heading{
|
||||||
Level: level,
|
Level: level,
|
||||||
HeadingID: id,
|
|
||||||
}
|
}
|
||||||
|
if p.extensions&AutoHeadingIDs != 0 {
|
||||||
|
block.HeadingID = sanitizeHeadingID(string(data[prev:eol]))
|
||||||
|
p.allHeadingsWithAutoID = append(p.allHeadingsWithAutoID, block)
|
||||||
|
}
|
||||||
|
|
||||||
block.Content = data[prev:eol]
|
block.Content = data[prev:eol]
|
||||||
p.addBlock(block)
|
p.addBlock(block)
|
||||||
|
|
||||||
|
311
vendor/github.com/gomarkdown/markdown/parser/block_table.go
generated
vendored
Normal file
311
vendor/github.com/gomarkdown/markdown/parser/block_table.go
generated
vendored
Normal file
@ -0,0 +1,311 @@
|
|||||||
|
package parser
|
||||||
|
|
||||||
|
import "github.com/gomarkdown/markdown/ast"
|
||||||
|
|
||||||
|
// check if the specified position is preceded by an odd number of backslashes
|
||||||
|
func isBackslashEscaped(data []byte, i int) bool {
|
||||||
|
backslashes := 0
|
||||||
|
for i-backslashes-1 >= 0 && data[i-backslashes-1] == '\\' {
|
||||||
|
backslashes++
|
||||||
|
}
|
||||||
|
return backslashes&1 == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Parser) tableRow(data []byte, columns []ast.CellAlignFlags, header bool) {
|
||||||
|
p.addBlock(&ast.TableRow{})
|
||||||
|
col := 0
|
||||||
|
|
||||||
|
i := skipChar(data, 0, '|')
|
||||||
|
|
||||||
|
n := len(data)
|
||||||
|
colspans := 0 // keep track of total colspan in this row.
|
||||||
|
for col = 0; col < len(columns) && i < n; col++ {
|
||||||
|
colspan := 0
|
||||||
|
i = skipChar(data, i, ' ')
|
||||||
|
|
||||||
|
cellStart := i
|
||||||
|
|
||||||
|
for i < n && (data[i] != '|' || isBackslashEscaped(data, i)) && data[i] != '\n' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
cellEnd := i
|
||||||
|
|
||||||
|
// skip the end-of-cell marker, possibly taking us past end of buffer
|
||||||
|
// each _extra_ | means a colspan
|
||||||
|
for i < len(data) && data[i] == '|' && !isBackslashEscaped(data, i) {
|
||||||
|
i++
|
||||||
|
colspan++
|
||||||
|
}
|
||||||
|
// only colspan > 1 make sense.
|
||||||
|
if colspan < 2 {
|
||||||
|
colspan = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
for cellEnd > cellStart && cellEnd-1 < n && data[cellEnd-1] == ' ' {
|
||||||
|
cellEnd--
|
||||||
|
}
|
||||||
|
|
||||||
|
block := &ast.TableCell{
|
||||||
|
IsHeader: header,
|
||||||
|
Align: columns[col],
|
||||||
|
ColSpan: colspan,
|
||||||
|
}
|
||||||
|
block.Content = data[cellStart:cellEnd]
|
||||||
|
if cellStart == cellEnd && colspans > 0 {
|
||||||
|
// an empty cell that we should ignore, it exists because of colspan
|
||||||
|
colspans--
|
||||||
|
} else {
|
||||||
|
p.addBlock(block)
|
||||||
|
}
|
||||||
|
|
||||||
|
if colspan > 0 {
|
||||||
|
colspans += colspan - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pad it out with empty columns to get the right number
|
||||||
|
for ; col < len(columns); col++ {
|
||||||
|
block := &ast.TableCell{
|
||||||
|
IsHeader: header,
|
||||||
|
Align: columns[col],
|
||||||
|
}
|
||||||
|
p.addBlock(block)
|
||||||
|
}
|
||||||
|
|
||||||
|
// silently ignore rows with too many cells
|
||||||
|
}
|
||||||
|
|
||||||
|
// tableFooter parses the (optional) table footer.
|
||||||
|
func (p *Parser) tableFooter(data []byte) bool {
|
||||||
|
colCount := 1
|
||||||
|
|
||||||
|
// ignore up to 3 spaces
|
||||||
|
n := len(data)
|
||||||
|
i := skipCharN(data, 0, ' ', 3)
|
||||||
|
for ; i < n && data[i] != '\n'; i++ {
|
||||||
|
if data[i] == '|' && !isBackslashEscaped(data, i) {
|
||||||
|
colCount++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// remaining data must be the = character
|
||||||
|
if data[i] != '=' {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// doesn't look like a table footer
|
||||||
|
if colCount == 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
p.addBlock(&ast.TableFooter{})
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// tableHeaders parses the header. If recognized it will also add a table.
|
||||||
|
func (p *Parser) tableHeader(data []byte) (size int, columns []ast.CellAlignFlags, table ast.Node) {
|
||||||
|
i := 0
|
||||||
|
colCount := 1
|
||||||
|
headerIsUnderline := true
|
||||||
|
headerIsWithEmptyFields := true
|
||||||
|
for i = 0; i < len(data) && data[i] != '\n'; i++ {
|
||||||
|
if data[i] == '|' && !isBackslashEscaped(data, i) {
|
||||||
|
colCount++
|
||||||
|
}
|
||||||
|
if data[i] != '-' && data[i] != ' ' && data[i] != ':' && data[i] != '|' {
|
||||||
|
headerIsUnderline = false
|
||||||
|
}
|
||||||
|
if data[i] != ' ' && data[i] != '|' {
|
||||||
|
headerIsWithEmptyFields = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// doesn't look like a table header
|
||||||
|
if colCount == 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// include the newline in the data sent to tableRow
|
||||||
|
j := skipCharN(data, i, '\n', 1)
|
||||||
|
header := data[:j]
|
||||||
|
|
||||||
|
// column count ignores pipes at beginning or end of line
|
||||||
|
if data[0] == '|' {
|
||||||
|
colCount--
|
||||||
|
}
|
||||||
|
{
|
||||||
|
tmp := header
|
||||||
|
// remove whitespace from the end
|
||||||
|
for len(tmp) > 0 {
|
||||||
|
lastIdx := len(tmp) - 1
|
||||||
|
if tmp[lastIdx] == '\n' || tmp[lastIdx] == ' ' {
|
||||||
|
tmp = tmp[:lastIdx]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n := len(tmp)
|
||||||
|
if n > 2 && tmp[n-1] == '|' && !isBackslashEscaped(tmp, n-1) {
|
||||||
|
colCount--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the header looks like a underline, then we omit the header
|
||||||
|
// and parse the first line again as underline
|
||||||
|
if headerIsUnderline && !headerIsWithEmptyFields {
|
||||||
|
header = nil
|
||||||
|
i = 0
|
||||||
|
} else {
|
||||||
|
i++ // move past newline
|
||||||
|
}
|
||||||
|
|
||||||
|
columns = make([]ast.CellAlignFlags, colCount)
|
||||||
|
|
||||||
|
// move on to the header underline
|
||||||
|
if i >= len(data) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if data[i] == '|' && !isBackslashEscaped(data, i) {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
i = skipChar(data, i, ' ')
|
||||||
|
|
||||||
|
// each column header is of form: / *:?-+:? *|/ with # dashes + # colons >= 3
|
||||||
|
// and trailing | optional on last column
|
||||||
|
col := 0
|
||||||
|
n := len(data)
|
||||||
|
for i < n && data[i] != '\n' {
|
||||||
|
dashes := 0
|
||||||
|
|
||||||
|
if data[i] == ':' {
|
||||||
|
i++
|
||||||
|
columns[col] |= ast.TableAlignmentLeft
|
||||||
|
dashes++
|
||||||
|
}
|
||||||
|
for i < n && data[i] == '-' {
|
||||||
|
i++
|
||||||
|
dashes++
|
||||||
|
}
|
||||||
|
if i < n && data[i] == ':' {
|
||||||
|
i++
|
||||||
|
columns[col] |= ast.TableAlignmentRight
|
||||||
|
dashes++
|
||||||
|
}
|
||||||
|
for i < n && data[i] == ' ' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if i == n {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// end of column test is messy
|
||||||
|
switch {
|
||||||
|
case dashes < 3:
|
||||||
|
// not a valid column
|
||||||
|
return
|
||||||
|
|
||||||
|
case data[i] == '|' && !isBackslashEscaped(data, i):
|
||||||
|
// marker found, now skip past trailing whitespace
|
||||||
|
col++
|
||||||
|
i++
|
||||||
|
for i < n && data[i] == ' ' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
// trailing junk found after last column
|
||||||
|
if col >= colCount && i < len(data) && data[i] != '\n' {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
case (data[i] != '|' || isBackslashEscaped(data, i)) && col+1 < colCount:
|
||||||
|
// something else found where marker was required
|
||||||
|
return
|
||||||
|
|
||||||
|
case data[i] == '\n':
|
||||||
|
// marker is optional for the last column
|
||||||
|
col++
|
||||||
|
|
||||||
|
default:
|
||||||
|
// trailing junk found after last column
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if col != colCount {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
table = &ast.Table{}
|
||||||
|
p.addBlock(table)
|
||||||
|
if header != nil {
|
||||||
|
p.addBlock(&ast.TableHeader{})
|
||||||
|
p.tableRow(header, columns, true)
|
||||||
|
}
|
||||||
|
size = skipCharN(data, i, '\n', 1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Table:
|
||||||
|
|
||||||
|
Name | Age | Phone
|
||||||
|
------|-----|---------
|
||||||
|
Bob | 31 | 555-1234
|
||||||
|
Alice | 27 | 555-4321
|
||||||
|
*/
|
||||||
|
func (p *Parser) table(data []byte) int {
|
||||||
|
i, columns, table := p.tableHeader(data)
|
||||||
|
if i == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
p.addBlock(&ast.TableBody{})
|
||||||
|
|
||||||
|
for i < len(data) {
|
||||||
|
pipes, rowStart := 0, i
|
||||||
|
for ; i < len(data) && data[i] != '\n'; i++ {
|
||||||
|
if data[i] == '|' {
|
||||||
|
pipes++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if pipes == 0 {
|
||||||
|
i = rowStart
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// include the newline in data sent to tableRow
|
||||||
|
i = skipCharN(data, i, '\n', 1)
|
||||||
|
|
||||||
|
if p.tableFooter(data[rowStart:i]) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
p.tableRow(data[rowStart:i], columns, false)
|
||||||
|
}
|
||||||
|
if captionContent, id, consumed := p.caption(data[i:], []byte("Table: ")); consumed > 0 {
|
||||||
|
caption := &ast.Caption{}
|
||||||
|
p.Inline(caption, captionContent)
|
||||||
|
|
||||||
|
// Some switcheroo to re-insert the parsed table as a child of the captionfigure.
|
||||||
|
figure := &ast.CaptionFigure{}
|
||||||
|
figure.HeadingID = id
|
||||||
|
table2 := &ast.Table{}
|
||||||
|
// Retain any block level attributes.
|
||||||
|
table2.AsContainer().Attribute = table.AsContainer().Attribute
|
||||||
|
children := table.GetChildren()
|
||||||
|
ast.RemoveFromTree(table)
|
||||||
|
|
||||||
|
table2.SetChildren(children)
|
||||||
|
ast.AppendChild(figure, table2)
|
||||||
|
ast.AppendChild(figure, caption)
|
||||||
|
|
||||||
|
p.addChild(figure)
|
||||||
|
p.finalize(figure)
|
||||||
|
|
||||||
|
i += consumed
|
||||||
|
}
|
||||||
|
|
||||||
|
return i
|
||||||
|
}
|
2
vendor/github.com/gomarkdown/markdown/parser/inline.go
generated
vendored
2
vendor/github.com/gomarkdown/markdown/parser/inline.go
generated
vendored
@ -1293,7 +1293,7 @@ func math(p *Parser, data []byte, offset int) (int, ast.Node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newTextNode(d []byte) *ast.Text {
|
func newTextNode(d []byte) *ast.Text {
|
||||||
return &ast.Text{ast.Leaf{Literal: d}}
|
return &ast.Text{Leaf: ast.Leaf{Literal: d}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func normalizeURI(s []byte) []byte {
|
func normalizeURI(s []byte) []byte {
|
||||||
|
24
vendor/github.com/gomarkdown/markdown/parser/parser.go
generated
vendored
24
vendor/github.com/gomarkdown/markdown/parser/parser.go
generated
vendored
@ -6,6 +6,7 @@ package parser
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
@ -113,6 +114,10 @@ type Parser struct {
|
|||||||
attr *ast.Attribute
|
attr *ast.Attribute
|
||||||
|
|
||||||
includeStack *incStack
|
includeStack *incStack
|
||||||
|
|
||||||
|
// collect headings where we auto-generated id so that we can
|
||||||
|
// ensure they are unique at the end
|
||||||
|
allHeadingsWithAutoID []*ast.Heading
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a markdown parser with CommonExtensions.
|
// New creates a markdown parser with CommonExtensions.
|
||||||
@ -282,6 +287,25 @@ func (p *Parser) Parse(input []byte) ast.Node {
|
|||||||
if p.Opts.Flags&SkipFootnoteList == 0 {
|
if p.Opts.Flags&SkipFootnoteList == 0 {
|
||||||
p.parseRefsToAST()
|
p.parseRefsToAST()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ensure HeadingIDs generated with AutoHeadingIDs are unique
|
||||||
|
// this is delayed here (as opposed to done when we create the id)
|
||||||
|
// so that we can preserve more original ids when there are conflicts
|
||||||
|
taken := map[string]bool{}
|
||||||
|
for _, h := range p.allHeadingsWithAutoID {
|
||||||
|
id := h.HeadingID
|
||||||
|
if id == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
n := 0
|
||||||
|
for taken[id] {
|
||||||
|
n++
|
||||||
|
id = h.HeadingID + "-" + strconv.Itoa(n)
|
||||||
|
}
|
||||||
|
h.HeadingID = id
|
||||||
|
taken[id] = true
|
||||||
|
}
|
||||||
|
|
||||||
return p.Doc
|
return p.Doc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
189
vendor/github.com/gomarkdown/markdown/tracking-perf.md
generated
vendored
189
vendor/github.com/gomarkdown/markdown/tracking-perf.md
generated
vendored
@ -1,189 +0,0 @@
|
|||||||
## Tracking perf changes
|
|
||||||
|
|
||||||
Initial performance:
|
|
||||||
```
|
|
||||||
goos: darwin
|
|
||||||
goarch: amd64
|
|
||||||
pkg: github.com/gomarkdown/markdown
|
|
||||||
BenchmarkEscapeHTML-8 2000000 823 ns/op 0 B/op 0 allocs/op
|
|
||||||
BenchmarkSmartDoubleQuotes-8 300000 5033 ns/op 9872 B/op 56 allocs/op
|
|
||||||
BenchmarkReferenceAmps-8 100000 19538 ns/op 26776 B/op 150 allocs/op
|
|
||||||
BenchmarkReferenceAutoLinks-8 100000 17574 ns/op 24544 B/op 132 allocs/op
|
|
||||||
BenchmarkReferenceBackslashEscapes-8 30000 50977 ns/op 76752 B/op 243 allocs/op
|
|
||||||
BenchmarkReferenceBlockquotesWithCodeBlocks-8 200000 8546 ns/op 12864 B/op 65 allocs/op
|
|
||||||
BenchmarkReferenceCodeBlocks-8 200000 9000 ns/op 14912 B/op 70 allocs/op
|
|
||||||
BenchmarkReferenceCodeSpans-8 200000 8856 ns/op 14992 B/op 69 allocs/op
|
|
||||||
BenchmarkReferenceHardWrappedPara-8 200000 6599 ns/op 11312 B/op 57 allocs/op
|
|
||||||
BenchmarkReferenceHorizontalRules-8 100000 15483 ns/op 23536 B/op 98 allocs/op
|
|
||||||
BenchmarkReferenceInlineHTMLAdvances-8 200000 6839 ns/op 12150 B/op 62 allocs/op
|
|
||||||
BenchmarkReferenceInlineHTMLSimple-8 100000 19940 ns/op 28488 B/op 117 allocs/op
|
|
||||||
BenchmarkReferenceInlineHTMLComments-8 200000 7455 ns/op 13440 B/op 64 allocs/op
|
|
||||||
BenchmarkReferenceLinksInline-8 100000 16425 ns/op 23664 B/op 147 allocs/op
|
|
||||||
BenchmarkReferenceLinksReference-8 30000 54895 ns/op 66464 B/op 416 allocs/op
|
|
||||||
BenchmarkReferenceLinksShortcut-8 100000 17647 ns/op 23776 B/op 158 allocs/op
|
|
||||||
BenchmarkReferenceLiterQuotesInTitles-8 200000 9367 ns/op 14832 B/op 95 allocs/op
|
|
||||||
BenchmarkReferenceMarkdownBasics-8 10000 129772 ns/op 130848 B/op 378 allocs/op
|
|
||||||
BenchmarkReferenceMarkdownSyntax-8 3000 502365 ns/op 461411 B/op 1411 allocs/op
|
|
||||||
BenchmarkReferenceNestedBlockquotes-8 200000 7028 ns/op 12688 B/op 64 allocs/op
|
|
||||||
BenchmarkReferenceOrderedAndUnorderedLists-8 20000 79686 ns/op 107520 B/op 374 allocs/op
|
|
||||||
BenchmarkReferenceStrongAndEm-8 200000 10020 ns/op 17792 B/op 78 allocs/op
|
|
||||||
BenchmarkReferenceTabs-8 200000 12025 ns/op 18224 B/op 81 allocs/op
|
|
||||||
BenchmarkReferenceTidyness-8 200000 8985 ns/op 14432 B/op 71 allocs/op
|
|
||||||
PASS
|
|
||||||
ok github.com/gomarkdown/markdown 45.375s
|
|
||||||
```
|
|
||||||
|
|
||||||
After switching to using interface{} for Node.Data:
|
|
||||||
```
|
|
||||||
BenchmarkEscapeHTML-8 2000000 929 ns/op 0 B/op 0 allocs/op
|
|
||||||
BenchmarkSmartDoubleQuotes-8 300000 5126 ns/op 9248 B/op 56 allocs/op
|
|
||||||
BenchmarkReferenceAmps-8 100000 19927 ns/op 17880 B/op 154 allocs/op
|
|
||||||
BenchmarkReferenceAutoLinks-8 100000 20732 ns/op 17360 B/op 141 allocs/op
|
|
||||||
BenchmarkReferenceBackslashEscapes-8 30000 50267 ns/op 38128 B/op 244 allocs/op
|
|
||||||
BenchmarkReferenceBlockquotesWithCodeBlocks-8 200000 8988 ns/op 10912 B/op 67 allocs/op
|
|
||||||
BenchmarkReferenceCodeBlocks-8 200000 8611 ns/op 12256 B/op 74 allocs/op
|
|
||||||
BenchmarkReferenceCodeSpans-8 200000 8256 ns/op 11248 B/op 69 allocs/op
|
|
||||||
BenchmarkReferenceHardWrappedPara-8 200000 6739 ns/op 9856 B/op 57 allocs/op
|
|
||||||
BenchmarkReferenceHorizontalRules-8 100000 15503 ns/op 15600 B/op 104 allocs/op
|
|
||||||
BenchmarkReferenceInlineHTMLAdvances-8 200000 6874 ns/op 10278 B/op 62 allocs/op
|
|
||||||
BenchmarkReferenceInlineHTMLSimple-8 100000 22271 ns/op 18552 B/op 121 allocs/op
|
|
||||||
BenchmarkReferenceInlineHTMLComments-8 200000 8315 ns/op 10736 B/op 64 allocs/op
|
|
||||||
BenchmarkReferenceLinksInline-8 100000 16155 ns/op 16912 B/op 152 allocs/op
|
|
||||||
BenchmarkReferenceLinksReference-8 30000 52387 ns/op 38192 B/op 445 allocs/op
|
|
||||||
BenchmarkReferenceLinksShortcut-8 100000 17111 ns/op 16592 B/op 167 allocs/op
|
|
||||||
BenchmarkReferenceLiterQuotesInTitles-8 200000 9164 ns/op 12048 B/op 97 allocs/op
|
|
||||||
BenchmarkReferenceMarkdownBasics-8 10000 129262 ns/op 87264 B/op 416 allocs/op
|
|
||||||
BenchmarkReferenceMarkdownSyntax-8 3000 496873 ns/op 293906 B/op 1559 allocs/op
|
|
||||||
BenchmarkReferenceNestedBlockquotes-8 200000 6854 ns/op 10192 B/op 64 allocs/op
|
|
||||||
BenchmarkReferenceOrderedAndUnorderedLists-8 20000 79633 ns/op 55024 B/op 447 allocs/op
|
|
||||||
BenchmarkReferenceStrongAndEm-8 200000 9637 ns/op 12176 B/op 78 allocs/op
|
|
||||||
BenchmarkReferenceTabs-8 100000 12164 ns/op 13776 B/op 87 allocs/op
|
|
||||||
BenchmarkReferenceTidyness-8 200000 8677 ns/op 11296 B/op 75 allocs/op
|
|
||||||
```
|
|
||||||
|
|
||||||
Not necessarily faster, but uses less bytes per op (but sometimes more allocs).
|
|
||||||
|
|
||||||
After tweaking the API:
|
|
||||||
```
|
|
||||||
$ ./s/run-bench.sh
|
|
||||||
|
|
||||||
go test -bench=. -test.benchmem
|
|
||||||
goos: darwin
|
|
||||||
goarch: amd64
|
|
||||||
pkg: github.com/gomarkdown/markdown
|
|
||||||
BenchmarkEscapeHTML-8 2000000 834 ns/op 0 B/op 0 allocs/op
|
|
||||||
BenchmarkSmartDoubleQuotes-8 300000 3486 ns/op 6160 B/op 27 allocs/op
|
|
||||||
BenchmarkReferenceAmps-8 100000 18158 ns/op 14792 B/op 125 allocs/op
|
|
||||||
BenchmarkReferenceAutoLinks-8 100000 16824 ns/op 14272 B/op 112 allocs/op
|
|
||||||
BenchmarkReferenceBackslashEscapes-8 30000 44066 ns/op 35040 B/op 215 allocs/op
|
|
||||||
BenchmarkReferenceBlockquotesWithCodeBlocks-8 200000 6868 ns/op 7824 B/op 38 allocs/op
|
|
||||||
BenchmarkReferenceCodeBlocks-8 200000 7157 ns/op 9168 B/op 45 allocs/op
|
|
||||||
BenchmarkReferenceCodeSpans-8 200000 6663 ns/op 8160 B/op 40 allocs/op
|
|
||||||
BenchmarkReferenceHardWrappedPara-8 300000 4821 ns/op 6768 B/op 28 allocs/op
|
|
||||||
BenchmarkReferenceHorizontalRules-8 100000 13033 ns/op 12512 B/op 75 allocs/op
|
|
||||||
BenchmarkReferenceInlineHTMLAdvances-8 300000 4998 ns/op 7190 B/op 33 allocs/op
|
|
||||||
BenchmarkReferenceInlineHTMLSimple-8 100000 17696 ns/op 15464 B/op 92 allocs/op
|
|
||||||
BenchmarkReferenceInlineHTMLComments-8 300000 5506 ns/op 7648 B/op 35 allocs/op
|
|
||||||
BenchmarkReferenceLinksInline-8 100000 14450 ns/op 13824 B/op 123 allocs/op
|
|
||||||
BenchmarkReferenceLinksReference-8 30000 52561 ns/op 35104 B/op 416 allocs/op
|
|
||||||
BenchmarkReferenceLinksShortcut-8 100000 15616 ns/op 13504 B/op 138 allocs/op
|
|
||||||
BenchmarkReferenceLiterQuotesInTitles-8 200000 7772 ns/op 8960 B/op 68 allocs/op
|
|
||||||
BenchmarkReferenceMarkdownBasics-8 10000 121436 ns/op 84176 B/op 387 allocs/op
|
|
||||||
BenchmarkReferenceMarkdownSyntax-8 3000 487404 ns/op 290818 B/op 1530 allocs/op
|
|
||||||
BenchmarkReferenceNestedBlockquotes-8 300000 5098 ns/op 7104 B/op 35 allocs/op
|
|
||||||
BenchmarkReferenceOrderedAndUnorderedLists-8 20000 74422 ns/op 51936 B/op 418 allocs/op
|
|
||||||
BenchmarkReferenceStrongAndEm-8 200000 7888 ns/op 9088 B/op 49 allocs/op
|
|
||||||
BenchmarkReferenceTabs-8 200000 10061 ns/op 10688 B/op 58 allocs/op
|
|
||||||
BenchmarkReferenceTidyness-8 200000 7152 ns/op 8208 B/op 46 allocs/op
|
|
||||||
ok github.com/gomarkdown/markdown 40.809s
|
|
||||||
```
|
|
||||||
|
|
||||||
After refactoring Renderer:
|
|
||||||
```
|
|
||||||
BenchmarkEscapeHTML-8 2000000 883 ns/op 0 B/op 0 allocs/op
|
|
||||||
BenchmarkSmartDoubleQuotes-8 300000 3717 ns/op 6208 B/op 29 allocs/op
|
|
||||||
BenchmarkReferenceAmps-8 100000 19135 ns/op 14680 B/op 123 allocs/op
|
|
||||||
BenchmarkReferenceAutoLinks-8 100000 17142 ns/op 14176 B/op 110 allocs/op
|
|
||||||
BenchmarkReferenceBackslashEscapes-8 30000 54616 ns/op 35088 B/op 217 allocs/op
|
|
||||||
BenchmarkReferenceBlockquotesWithCodeBlocks-8 200000 7993 ns/op 7872 B/op 40 allocs/op
|
|
||||||
BenchmarkReferenceCodeBlocks-8 200000 8285 ns/op 9216 B/op 47 allocs/op
|
|
||||||
BenchmarkReferenceCodeSpans-8 200000 7684 ns/op 8208 B/op 42 allocs/op
|
|
||||||
BenchmarkReferenceHardWrappedPara-8 200000 5595 ns/op 6816 B/op 30 allocs/op
|
|
||||||
BenchmarkReferenceHorizontalRules-8 100000 16444 ns/op 12560 B/op 77 allocs/op
|
|
||||||
BenchmarkReferenceInlineHTMLAdvances-8 200000 5415 ns/op 7238 B/op 35 allocs/op
|
|
||||||
BenchmarkReferenceInlineHTMLSimple-8 100000 19867 ns/op 15512 B/op 94 allocs/op
|
|
||||||
BenchmarkReferenceInlineHTMLComments-8 200000 6026 ns/op 7696 B/op 37 allocs/op
|
|
||||||
BenchmarkReferenceLinksInline-8 100000 14864 ns/op 13664 B/op 120 allocs/op
|
|
||||||
BenchmarkReferenceLinksReference-8 30000 52479 ns/op 34816 B/op 401 allocs/op
|
|
||||||
BenchmarkReferenceLinksShortcut-8 100000 15812 ns/op 13472 B/op 135 allocs/op
|
|
||||||
BenchmarkReferenceLiterQuotesInTitles-8 200000 7767 ns/op 8880 B/op 68 allocs/op
|
|
||||||
BenchmarkReferenceMarkdownBasics-8 10000 131065 ns/op 84048 B/op 386 allocs/op
|
|
||||||
BenchmarkReferenceMarkdownSyntax-8 2000 515604 ns/op 289953 B/op 1501 allocs/op
|
|
||||||
BenchmarkReferenceNestedBlockquotes-8 200000 5655 ns/op 7152 B/op 37 allocs/op
|
|
||||||
BenchmarkReferenceOrderedAndUnorderedLists-8 20000 84188 ns/op 51984 B/op 420 allocs/op
|
|
||||||
BenchmarkReferenceStrongAndEm-8 200000 8664 ns/op 9136 B/op 51 allocs/op
|
|
||||||
BenchmarkReferenceTabs-8 100000 11110 ns/op 10736 B/op 60 allocs/op
|
|
||||||
BenchmarkReferenceTidyness-8 200000 7628 ns/op 8256 B/op 48 allocs/op
|
|
||||||
ok github.com/gomarkdown/markdown 40.841s
|
|
||||||
```
|
|
||||||
|
|
||||||
After Node refactor to have Children array:
|
|
||||||
```
|
|
||||||
BenchmarkEscapeHTML-8 2000000 901 ns/op 0 B/op 0 allocs/op
|
|
||||||
BenchmarkSmartDoubleQuotes-8 300000 3905 ns/op 6224 B/op 31 allocs/op
|
|
||||||
BenchmarkReferenceAmps-8 100000 22216 ns/op 15560 B/op 157 allocs/op
|
|
||||||
BenchmarkReferenceAutoLinks-8 100000 20335 ns/op 14824 B/op 146 allocs/op
|
|
||||||
BenchmarkReferenceBackslashEscapes-8 20000 69174 ns/op 37392 B/op 316 allocs/op
|
|
||||||
BenchmarkReferenceBlockquotesWithCodeBlocks-8 200000 8443 ns/op 7968 B/op 48 allocs/op
|
|
||||||
BenchmarkReferenceCodeBlocks-8 200000 9250 ns/op 9392 B/op 58 allocs/op
|
|
||||||
BenchmarkReferenceCodeSpans-8 200000 8515 ns/op 8432 B/op 54 allocs/op
|
|
||||||
BenchmarkReferenceHardWrappedPara-8 200000 5738 ns/op 6856 B/op 34 allocs/op
|
|
||||||
BenchmarkReferenceHorizontalRules-8 100000 20864 ns/op 13648 B/op 93 allocs/op
|
|
||||||
BenchmarkReferenceInlineHTMLAdvances-8 200000 6187 ns/op 7310 B/op 40 allocs/op
|
|
||||||
BenchmarkReferenceInlineHTMLSimple-8 50000 23793 ns/op 16128 B/op 114 allocs/op
|
|
||||||
BenchmarkReferenceInlineHTMLComments-8 200000 7060 ns/op 7840 B/op 44 allocs/op
|
|
||||||
BenchmarkReferenceLinksInline-8 100000 18432 ns/op 14496 B/op 153 allocs/op
|
|
||||||
BenchmarkReferenceLinksReference-8 20000 67666 ns/op 37136 B/op 502 allocs/op
|
|
||||||
BenchmarkReferenceLinksShortcut-8 100000 19324 ns/op 13984 B/op 162 allocs/op
|
|
||||||
BenchmarkReferenceLiterQuotesInTitles-8 200000 8998 ns/op 9320 B/op 83 allocs/op
|
|
||||||
BenchmarkReferenceMarkdownBasics-8 10000 160908 ns/op 88152 B/op 518 allocs/op
|
|
||||||
BenchmarkReferenceMarkdownSyntax-8 2000 707160 ns/op 303801 B/op 2044 allocs/op
|
|
||||||
BenchmarkReferenceNestedBlockquotes-8 200000 6740 ns/op 7248 B/op 45 allocs/op
|
|
||||||
BenchmarkReferenceOrderedAndUnorderedLists-8 10000 115808 ns/op 55052 B/op 626 allocs/op
|
|
||||||
BenchmarkReferenceStrongAndEm-8 100000 10540 ns/op 9416 B/op 72 allocs/op
|
|
||||||
BenchmarkReferenceTabs-8 100000 13171 ns/op 10968 B/op 77 allocs/op
|
|
||||||
BenchmarkReferenceTidyness-8 200000 8903 ns/op 8404 B/op 62 allocs/op
|
|
||||||
PASS
|
|
||||||
ok github.com/gomarkdown/markdown 43.477s
|
|
||||||
```
|
|
||||||
It's slower (but opens up possibilities for further improvements).
|
|
||||||
|
|
||||||
After refactoring to make ast.Node a top-level thing.
|
|
||||||
```
|
|
||||||
BenchmarkEscapeHTML-8 2000000 829 ns/op 0 B/op 0 allocs/op
|
|
||||||
BenchmarkSmartDoubleQuotes-8 300000 3998 ns/op 6192 B/op 31 allocs/op
|
|
||||||
BenchmarkReferenceAmps-8 50000 27389 ns/op 15480 B/op 153 allocs/op
|
|
||||||
BenchmarkReferenceAutoLinks-8 50000 23106 ns/op 14656 B/op 137 allocs/op
|
|
||||||
BenchmarkReferenceBackslashEscapes-8 10000 112435 ns/op 36696 B/op 315 allocs/op
|
|
||||||
BenchmarkReferenceBlockquotesWithCodeBlocks-8 200000 9227 ns/op 7856 B/op 46 allocs/op
|
|
||||||
BenchmarkReferenceCodeBlocks-8 200000 10469 ns/op 9248 B/op 54 allocs/op
|
|
||||||
BenchmarkReferenceCodeSpans-8 200000 10522 ns/op 8368 B/op 54 allocs/op
|
|
||||||
BenchmarkReferenceHardWrappedPara-8 200000 6354 ns/op 6784 B/op 34 allocs/op
|
|
||||||
BenchmarkReferenceHorizontalRules-8 50000 32393 ns/op 13952 B/op 87 allocs/op
|
|
||||||
BenchmarkReferenceInlineHTMLAdvances-8 200000 6894 ns/op 7238 B/op 40 allocs/op
|
|
||||||
BenchmarkReferenceInlineHTMLSimple-8 50000 32942 ns/op 15864 B/op 110 allocs/op
|
|
||||||
BenchmarkReferenceInlineHTMLComments-8 200000 8181 ns/op 7776 B/op 44 allocs/op
|
|
||||||
BenchmarkReferenceLinksInline-8 100000 21679 ns/op 14400 B/op 148 allocs/op
|
|
||||||
BenchmarkReferenceLinksReference-8 20000 83928 ns/op 36688 B/op 473 allocs/op
|
|
||||||
BenchmarkReferenceLinksShortcut-8 100000 22053 ns/op 13872 B/op 153 allocs/op
|
|
||||||
BenchmarkReferenceLiterQuotesInTitles-8 100000 10784 ns/op 9296 B/op 81 allocs/op
|
|
||||||
BenchmarkReferenceMarkdownBasics-8 5000 237097 ns/op 87760 B/op 480 allocs/op
|
|
||||||
BenchmarkReferenceMarkdownSyntax-8 1000 1465402 ns/op 300769 B/op 1896 allocs/op
|
|
||||||
BenchmarkReferenceNestedBlockquotes-8 200000 7461 ns/op 7152 B/op 45 allocs/op
|
|
||||||
BenchmarkReferenceOrderedAndUnorderedLists-8 5000 212256 ns/op 53724 B/op 553 allocs/op
|
|
||||||
BenchmarkReferenceStrongAndEm-8 100000 13018 ns/op 9264 B/op 72 allocs/op
|
|
||||||
BenchmarkReferenceTabs-8 100000 15005 ns/op 10752 B/op 71 allocs/op
|
|
||||||
BenchmarkReferenceTidyness-8 200000 10308 ns/op 8292 B/op 58 allocs/op
|
|
||||||
PASS
|
|
||||||
ok github.com/gomarkdown/markdown 42.176s
|
|
||||||
```
|
|
1
vendor/github.com/google/gops/agent/sockopt_unix.go
generated
vendored
1
vendor/github.com/google/gops/agent/sockopt_unix.go
generated
vendored
@ -2,6 +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.
|
||||||
|
|
||||||
|
//go:build !js && !plan9 && !windows
|
||||||
// +build !js,!plan9,!windows
|
// +build !js,!plan9,!windows
|
||||||
|
|
||||||
package agent
|
package agent
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user