mirror of
https://github.com/playwright-community/playwright-go.git
synced 2026-06-03 21:02:27 +08:00
chore: Initial commit (#1)
This commit is contained in:
parent
d276d12a14
commit
24ae369ec8
28
.github/workflows/build.yml
vendored
Normal file
28
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
name: Go
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ^1.13
|
||||
id: go
|
||||
- uses: actions/checkout@v2
|
||||
- name: Download driver
|
||||
run: curl -o driver -sf https://storage.googleapis.com/mxschmitt-public-files/playwright-driver-1596843106133-linux
|
||||
- name: Install browsers
|
||||
run: |
|
||||
chmod +x driver
|
||||
./driver install
|
||||
- name: Get dependencies
|
||||
run: |
|
||||
go get -v -t -d ./...
|
||||
- name: Test
|
||||
run: go test -v .
|
||||
26
.gitignore
vendored
Normal file
26
.gitignore
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/go
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=go
|
||||
|
||||
### Go ###
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
||||
### Go Patch ###
|
||||
/vendor/
|
||||
/Godeps/
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/go
|
||||
driver*
|
||||
35
browser.go
Normal file
35
browser.go
Normal file
@ -0,0 +1,35 @@
|
||||
package playwright
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Browser struct {
|
||||
ChannelOwner
|
||||
IsConnected bool
|
||||
Contexts []*BrowserContext
|
||||
}
|
||||
|
||||
func (b *Browser) NewContext() (*BrowserContext, error) {
|
||||
channelOwner, err := b.channel.Send("newContext", nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not send message: %v", err)
|
||||
}
|
||||
context := channelOwner.(*Channel).object.(*BrowserContext)
|
||||
b.Contexts = append(b.Contexts, context)
|
||||
return context, nil
|
||||
}
|
||||
|
||||
func (b *Browser) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Browser) Version() string {
|
||||
return b.initializer.(map[string]interface{})["version"].(string)
|
||||
}
|
||||
|
||||
func newBrowser(parent *ChannelOwner, objectType string, guid string, initializer interface{}) *Browser {
|
||||
bt := &Browser{
|
||||
IsConnected: true,
|
||||
}
|
||||
bt.createChannelOwner(bt, parent, objectType, guid, initializer)
|
||||
return bt
|
||||
}
|
||||
22
browserContext.go
Normal file
22
browserContext.go
Normal file
@ -0,0 +1,22 @@
|
||||
package playwright
|
||||
|
||||
import "fmt"
|
||||
|
||||
type BrowserContext struct {
|
||||
ChannelOwner
|
||||
Pages []Page
|
||||
}
|
||||
|
||||
func (b *BrowserContext) NewPage() (*Page, error) {
|
||||
channelOwner, err := b.channel.Send("newPage", nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not send message: %v", err)
|
||||
}
|
||||
return channelOwner.(*Channel).object.(*Page), nil
|
||||
}
|
||||
|
||||
func newBrowserContext(parent *ChannelOwner, objectType string, guid string, initializer interface{}) *BrowserContext {
|
||||
bt := &BrowserContext{}
|
||||
bt.createChannelOwner(bt, parent, objectType, guid, initializer)
|
||||
return bt
|
||||
}
|
||||
21
browserContext_test.go
Normal file
21
browserContext_test.go
Normal file
@ -0,0 +1,21 @@
|
||||
package playwright
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestNewPage(t *testing.T) {
|
||||
pw, err := Run()
|
||||
if err != nil {
|
||||
t.Fatalf("could not launch playwright: %v", err)
|
||||
}
|
||||
browser, err := pw.Chromium.Launch()
|
||||
require.NoError(t, err)
|
||||
context, err := browser.NewContext()
|
||||
require.NoError(t, err)
|
||||
page, err := context.NewPage()
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, page)
|
||||
}
|
||||
31
browserType.go
Normal file
31
browserType.go
Normal file
@ -0,0 +1,31 @@
|
||||
package playwright
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type BrowserType struct {
|
||||
ChannelOwner
|
||||
}
|
||||
|
||||
func (b *BrowserType) Name() string {
|
||||
return b.initializer.(map[string]interface{})["name"].(string)
|
||||
}
|
||||
|
||||
func (b *BrowserType) ExecutablePath() string {
|
||||
return b.initializer.(map[string]interface{})["executablePath"].(string)
|
||||
}
|
||||
|
||||
func (b *BrowserType) Launch() (*Browser, error) {
|
||||
channelOwner, err := b.channel.Send("launch", nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not send message: %v", err)
|
||||
}
|
||||
return channelOwner.(*Channel).object.(*Browser), nil
|
||||
}
|
||||
|
||||
func newBrowserType(parent *ChannelOwner, objectType string, guid string, initializer interface{}) *BrowserType {
|
||||
bt := &BrowserType{}
|
||||
bt.createChannelOwner(bt, parent, objectType, guid, initializer)
|
||||
return bt
|
||||
}
|
||||
25
browserType_test.go
Normal file
25
browserType_test.go
Normal file
@ -0,0 +1,25 @@
|
||||
package playwright
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestBrowserName(t *testing.T) {
|
||||
pw, err := Run()
|
||||
if err != nil {
|
||||
t.Fatalf("could not launch playwright: %v", err)
|
||||
}
|
||||
require.Equal(t, pw.Chromium.Name(), "chromium")
|
||||
require.Equal(t, pw.Firefox.Name(), "firefox")
|
||||
require.Equal(t, pw.WebKit.Name(), "webkit")
|
||||
}
|
||||
|
||||
func TestExecutablePath(t *testing.T) {
|
||||
pw, err := Run()
|
||||
if err != nil {
|
||||
t.Fatalf("could not launch playwright: %v", err)
|
||||
}
|
||||
require.Greater(t, len(pw.Chromium.ExecutablePath()), 0)
|
||||
}
|
||||
39
browser_test.go
Normal file
39
browser_test.go
Normal file
@ -0,0 +1,39 @@
|
||||
package playwright
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestIsConnected(t *testing.T) {
|
||||
pw, err := Run()
|
||||
if err != nil {
|
||||
t.Fatalf("could not launch playwright: %v", err)
|
||||
}
|
||||
browser, err := pw.Chromium.Launch()
|
||||
require.NoError(t, err)
|
||||
require.True(t, browser.IsConnected)
|
||||
}
|
||||
|
||||
func TestVersion(t *testing.T) {
|
||||
pw, err := Run()
|
||||
if err != nil {
|
||||
t.Fatalf("could not launch playwright: %v", err)
|
||||
}
|
||||
browser, err := pw.Chromium.Launch()
|
||||
require.NoError(t, err)
|
||||
require.Greater(t, len(browser.Version()), 2)
|
||||
}
|
||||
|
||||
func TestNewContext(t *testing.T) {
|
||||
pw, err := Run()
|
||||
if err != nil {
|
||||
t.Fatalf("could not launch playwright: %v", err)
|
||||
}
|
||||
browser, err := pw.Chromium.Launch()
|
||||
require.NoError(t, err)
|
||||
context, err := browser.NewContext()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(context.Pages), 0)
|
||||
}
|
||||
20
browsers.json
Normal file
20
browsers.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"comment": "Do not edit this file, use utils/roll_browser.js",
|
||||
"browsers": [
|
||||
{
|
||||
"name": "chromium",
|
||||
"revision": "792639",
|
||||
"download": true
|
||||
},
|
||||
{
|
||||
"name": "firefox",
|
||||
"revision": "1154",
|
||||
"download": true
|
||||
},
|
||||
{
|
||||
"name": "webkit",
|
||||
"revision": "1322",
|
||||
"download": true
|
||||
}
|
||||
]
|
||||
}
|
||||
35
channel.go
Normal file
35
channel.go
Normal file
@ -0,0 +1,35 @@
|
||||
package playwright
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type Channel struct {
|
||||
guid string
|
||||
connection *Connection
|
||||
object interface{}
|
||||
}
|
||||
|
||||
func (c *Channel) Send(method string, params interface{}) (interface{}, error) {
|
||||
if params == nil {
|
||||
params = make(map[string]interface{})
|
||||
}
|
||||
result, err := c.connection.SendMessageToServer(c.guid, method, params)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not send message to server: %v", err)
|
||||
}
|
||||
if reflect.TypeOf(result).Kind() == reflect.Map {
|
||||
for key := range result.(map[string]interface{}) {
|
||||
return result.(map[string]interface{})[key], nil
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func newChannel(connection *Connection, guid string) *Channel {
|
||||
return &Channel{
|
||||
connection: connection,
|
||||
guid: guid,
|
||||
}
|
||||
}
|
||||
41
channelOwner.go
Normal file
41
channelOwner.go
Normal file
@ -0,0 +1,41 @@
|
||||
package playwright
|
||||
|
||||
type ChannelOwner struct {
|
||||
objectType string
|
||||
guid string
|
||||
channel *Channel
|
||||
objects map[string]*ChannelOwner
|
||||
connection *Connection
|
||||
initializer interface{}
|
||||
parent *ChannelOwner
|
||||
}
|
||||
|
||||
func (c *ChannelOwner) Dispose() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ChannelOwner) createChannelOwner(self interface{}, parent *ChannelOwner, objectType string, guid string, initializer interface{}) {
|
||||
c.objectType = objectType
|
||||
c.guid = guid
|
||||
c.parent = parent
|
||||
c.objects = make(map[string]*ChannelOwner)
|
||||
c.connection = parent.connection
|
||||
c.channel = newChannel(c.connection, guid)
|
||||
c.channel.object = self
|
||||
c.initializer = initializer
|
||||
c.connection.objects[guid] = c
|
||||
c.parent.objects[guid] = c
|
||||
}
|
||||
|
||||
func newRootChannelOwner(connection *Connection) *ChannelOwner {
|
||||
c := &ChannelOwner{
|
||||
objectType: "",
|
||||
guid: "",
|
||||
connection: connection,
|
||||
objects: make(map[string]*ChannelOwner),
|
||||
channel: newChannel(connection, ""),
|
||||
}
|
||||
c.channel.object = c
|
||||
c.connection.objects[""] = c
|
||||
return c
|
||||
}
|
||||
38
cmd/example.go
Normal file
38
cmd/example.go
Normal file
@ -0,0 +1,38 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/mxschmitt/playwright-golang"
|
||||
)
|
||||
|
||||
func main() {
|
||||
playwright, err := playwright.Run()
|
||||
if err != nil {
|
||||
log.Fatalf("could not launch playwright: %v", err)
|
||||
}
|
||||
browser, err := playwright.Chromium.Launch()
|
||||
if err != nil {
|
||||
log.Fatalf("could not launch Chromium: %v", err)
|
||||
}
|
||||
context, err := browser.NewContext()
|
||||
if err != nil {
|
||||
log.Fatalf("could not create context: %v", err)
|
||||
}
|
||||
page, err := context.NewPage()
|
||||
if err != nil {
|
||||
log.Fatalf("could not create page: %v", err)
|
||||
}
|
||||
if err = page.Goto("http://whatsmyuseragent.org/"); err != nil {
|
||||
log.Fatalf("could not goto: %v", err)
|
||||
}
|
||||
if err = page.Screenshot("example.png"); err != nil {
|
||||
log.Fatalf("could not create screenshot: %v", err)
|
||||
}
|
||||
if err = browser.Close(); err != nil {
|
||||
log.Fatalf("could not close browser: %v", err)
|
||||
}
|
||||
if err = playwright.Stop(); err != nil {
|
||||
log.Fatalf("could not stop Playwright: %v", err)
|
||||
}
|
||||
}
|
||||
151
connection.go
Normal file
151
connection.go
Normal file
@ -0,0 +1,151 @@
|
||||
package playwright
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type Connection struct {
|
||||
transport *Transport
|
||||
waitingForRemoteObjects map[string]chan interface{}
|
||||
objects map[string]*ChannelOwner
|
||||
lastID int
|
||||
rootObject *ChannelOwner
|
||||
callbacks map[int]chan interface{}
|
||||
}
|
||||
|
||||
func (c *Connection) Start() error {
|
||||
c.transport.SetDispatch(c.Dispatch)
|
||||
return c.transport.Start()
|
||||
}
|
||||
|
||||
func (c *Connection) Stop() error {
|
||||
return c.transport.Stop()
|
||||
}
|
||||
|
||||
func (c *Connection) CallOnObjectWithKnownName(name string) (interface{}, error) {
|
||||
if _, ok := c.waitingForRemoteObjects[name]; !ok {
|
||||
c.waitingForRemoteObjects[name] = make(chan interface{})
|
||||
}
|
||||
return <-c.waitingForRemoteObjects[name], nil
|
||||
}
|
||||
|
||||
func (c *Connection) Dispatch(msg *Message) error {
|
||||
method := msg.Method
|
||||
if msg.ID != 0 {
|
||||
c.callbacks[msg.ID] <- c.replaceGuidsWithChannels(msg.Result)
|
||||
// TODO: Error handling
|
||||
return nil
|
||||
}
|
||||
object := c.objects[msg.GUID]
|
||||
if method == "__create__" {
|
||||
c.createRemoteObject(
|
||||
object, msg.Params.Type, msg.Params.GUID, msg.Params.Initializer,
|
||||
)
|
||||
return nil
|
||||
}
|
||||
if method == "__dispose__" {
|
||||
object.Dispose()
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Connection) createRemoteObject(parent *ChannelOwner, objectType string, guid string, initializer interface{}) interface{} {
|
||||
initializer = c.replaceGuidsWithChannels(initializer)
|
||||
result := createObjectFactory(parent, objectType, guid, initializer)
|
||||
if _, ok := c.waitingForRemoteObjects[guid]; ok {
|
||||
c.waitingForRemoteObjects[guid] <- result
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (c *Connection) replaceChannelsWithGuids(payload interface{}) interface{} {
|
||||
if payload == nil {
|
||||
return nil
|
||||
}
|
||||
if valA, isChannel := payload.(Channel); isChannel {
|
||||
return map[string]string{
|
||||
"guid": valA.guid,
|
||||
}
|
||||
}
|
||||
v := reflect.ValueOf(payload)
|
||||
if v.Kind() == reflect.Slice {
|
||||
listV := payload.([]interface{})
|
||||
for i := 0; i < len(listV); i++ {
|
||||
listV[i] = c.replaceChannelsWithGuids(listV[i])
|
||||
}
|
||||
return listV
|
||||
}
|
||||
if v.Kind() == reflect.Map {
|
||||
mapV := payload.(map[string]interface{})
|
||||
if guid, hasGUID := mapV["guid"]; hasGUID {
|
||||
if channelOwner, ok := c.objects[guid.(string)]; ok {
|
||||
return channelOwner.channel
|
||||
}
|
||||
}
|
||||
for key := range mapV {
|
||||
mapV[key] = c.replaceChannelsWithGuids(mapV[key])
|
||||
}
|
||||
return mapV
|
||||
}
|
||||
return payload
|
||||
}
|
||||
|
||||
func (c *Connection) replaceGuidsWithChannels(payload interface{}) interface{} {
|
||||
if payload == nil {
|
||||
return nil
|
||||
}
|
||||
v := reflect.ValueOf(payload)
|
||||
if v.Kind() == reflect.Slice {
|
||||
listV := payload.([]interface{})
|
||||
for i := 0; i < len(listV); i++ {
|
||||
listV[i] = c.replaceGuidsWithChannels(listV[i])
|
||||
}
|
||||
return listV
|
||||
}
|
||||
if v.Kind() == reflect.Map {
|
||||
mapV := payload.(map[string]interface{})
|
||||
if guid, hasGUID := mapV["guid"]; hasGUID {
|
||||
if channelOwner, ok := c.objects[guid.(string)]; ok {
|
||||
return channelOwner.channel
|
||||
}
|
||||
}
|
||||
for key := range mapV {
|
||||
mapV[key] = c.replaceGuidsWithChannels(mapV[key])
|
||||
}
|
||||
return mapV
|
||||
}
|
||||
return payload
|
||||
}
|
||||
|
||||
func (c *Connection) SendMessageToServer(guid string, method string, params interface{}) (interface{}, error) {
|
||||
c.lastID++
|
||||
id := c.lastID
|
||||
message := map[string]interface{}{
|
||||
"id": id,
|
||||
"guid": guid,
|
||||
"method": method,
|
||||
"params": c.replaceGuidsWithChannels(params),
|
||||
}
|
||||
if _, ok := c.callbacks[id]; !ok {
|
||||
c.callbacks[id] = make(chan interface{})
|
||||
}
|
||||
if err := c.transport.Send(message); err != nil {
|
||||
return nil, fmt.Errorf("could not send message: %v", err)
|
||||
}
|
||||
return <-c.callbacks[id], nil
|
||||
}
|
||||
|
||||
func newConnection(stdin io.WriteCloser, stdout io.ReadCloser) *Connection {
|
||||
connection := &Connection{
|
||||
waitingForRemoteObjects: make(map[string]chan interface{}),
|
||||
transport: newTransport(stdin, stdout),
|
||||
objects: make(map[string]*ChannelOwner),
|
||||
callbacks: make(map[int]chan interface{}),
|
||||
}
|
||||
connection.rootObject = newRootChannelOwner(connection)
|
||||
return connection
|
||||
}
|
||||
19
frame.go
Normal file
19
frame.go
Normal file
@ -0,0 +1,19 @@
|
||||
package playwright
|
||||
|
||||
type Frame struct {
|
||||
ChannelOwner
|
||||
page Page
|
||||
url string
|
||||
}
|
||||
|
||||
func (b *Frame) URL() string {
|
||||
return b.url
|
||||
}
|
||||
|
||||
func newFrame(parent *ChannelOwner, objectType string, guid string, initializer interface{}) *Frame {
|
||||
bt := &Frame{
|
||||
url: initializer.(map[string]interface{})["url"].(string),
|
||||
}
|
||||
bt.createChannelOwner(bt, parent, objectType, guid, initializer)
|
||||
return bt
|
||||
}
|
||||
10
go.mod
Normal file
10
go.mod
Normal file
@ -0,0 +1,10 @@
|
||||
module github.com/mxschmitt/playwright-golang
|
||||
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/lucas-clemente/quic-go v0.17.3
|
||||
github.com/stretchr/testify v1.6.1
|
||||
gopkg.in/square/go-jose.v2 v2.5.1
|
||||
)
|
||||
222
go.sum
Normal file
222
go.sum
Normal file
@ -0,0 +1,222 @@
|
||||
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/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/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
|
||||
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
|
||||
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.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
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/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
|
||||
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
|
||||
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/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/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/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 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
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-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-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/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
|
||||
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/lucas-clemente/quic-go v0.17.3 h1:jMX/MmDNCljfisgMmPGUcBJ+zUh9w3d3ia4YJjYS3TM=
|
||||
github.com/lucas-clemente/quic-go v0.17.3/go.mod h1:I0+fcNTdb9eS1ZcjQZbDVPGchJ86chcIxPALn9lEJqE=
|
||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI=
|
||||
github.com/marten-seemann/qtls v0.9.1 h1:O0YKQxNVPaiFgMng0suWEOY2Sb4LT2sRn9Qimq3Z1IQ=
|
||||
github.com/marten-seemann/qtls v0.9.1/go.mod h1:T1MmAdDPyISzxlK6kjRr0pcZFBVd1OZbBb/j3cvzHhk=
|
||||
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/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mxschmitt/playwright v0.11.1 h1:gQnL++ixCQ0KvrL6taPoQP5I1UZLGo38Mm6EcpmG790=
|
||||
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/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
|
||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||
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/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
||||
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/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5 h1:Q7tZBpemrlsc2I7IyODzhtallWRSm4Q0d09pL6XbQtU=
|
||||
golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
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-20190228165749-92fc7df08ae7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/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/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/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-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/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
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=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
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/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=
|
||||
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=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
|
||||
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
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=
|
||||
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=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
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=
|
||||
24
objectFactory.go
Normal file
24
objectFactory.go
Normal file
@ -0,0 +1,24 @@
|
||||
package playwright
|
||||
|
||||
func createObjectFactory(parent *ChannelOwner, objectType string, guid string, initializer interface{}) interface{} {
|
||||
switch objectType {
|
||||
case "Playwright":
|
||||
return newPlaywright(parent, objectType, guid, initializer)
|
||||
case "BrowserType":
|
||||
return newBrowserType(parent, objectType, guid, initializer)
|
||||
case "Browser":
|
||||
return newBrowser(parent, objectType, guid, initializer)
|
||||
case "BrowserContext":
|
||||
return newBrowserContext(parent, objectType, guid, initializer)
|
||||
case "Frame":
|
||||
return newFrame(parent, objectType, guid, initializer)
|
||||
case "Page":
|
||||
return newPage(parent, objectType, guid, initializer)
|
||||
case "Selectors":
|
||||
return nil
|
||||
case "Electron":
|
||||
return nil
|
||||
default:
|
||||
panic(objectType)
|
||||
}
|
||||
}
|
||||
29
page.go
Normal file
29
page.go
Normal file
@ -0,0 +1,29 @@
|
||||
package playwright
|
||||
|
||||
type Page struct {
|
||||
ChannelOwner
|
||||
frames []*Frame
|
||||
mainFrame *Frame
|
||||
}
|
||||
|
||||
func (b *Page) Goto(url string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Page) Screenshot(path string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Page) URL() string {
|
||||
return b.mainFrame.URL()
|
||||
}
|
||||
|
||||
func newPage(parent *ChannelOwner, objectType string, guid string, initializer interface{}) *Page {
|
||||
channelOwner := (initializer.(map[string]interface{})["mainFrame"]).(*Channel).object
|
||||
bt := &Page{
|
||||
mainFrame: channelOwner.(*Frame),
|
||||
}
|
||||
bt.frames = []*Frame{bt.mainFrame}
|
||||
bt.createChannelOwner(bt, parent, objectType, guid, initializer)
|
||||
return bt
|
||||
}
|
||||
21
page_test.go
Normal file
21
page_test.go
Normal file
@ -0,0 +1,21 @@
|
||||
package playwright
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestPageURL(t *testing.T) {
|
||||
pw, err := Run()
|
||||
if err != nil {
|
||||
t.Fatalf("could not launch playwright: %v", err)
|
||||
}
|
||||
browser, err := pw.Chromium.Launch()
|
||||
require.NoError(t, err)
|
||||
context, err := browser.NewContext()
|
||||
require.NoError(t, err)
|
||||
page, err := context.NewPage()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, page.URL(), "about:blank")
|
||||
}
|
||||
21
playwright.go
Normal file
21
playwright.go
Normal file
@ -0,0 +1,21 @@
|
||||
package playwright
|
||||
|
||||
type Playwright struct {
|
||||
channelOwner ChannelOwner
|
||||
Chromium *BrowserType
|
||||
Firefox *BrowserType
|
||||
WebKit *BrowserType
|
||||
}
|
||||
|
||||
func (p *Playwright) Stop() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func newPlaywright(parent *ChannelOwner, objectType string, guid string, initializer interface{}) *Playwright {
|
||||
// TODO: add devices and selectors
|
||||
return &Playwright{
|
||||
Chromium: (initializer.(map[string]interface{})["chromium"]).(*Channel).object.(*BrowserType),
|
||||
Firefox: (initializer.(map[string]interface{})["firefox"]).(*Channel).object.(*BrowserType),
|
||||
WebKit: (initializer.(map[string]interface{})["webkit"]).(*Channel).object.(*BrowserType),
|
||||
}
|
||||
}
|
||||
28
run.go
Normal file
28
run.go
Normal file
@ -0,0 +1,28 @@
|
||||
package playwright
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
func Run() (*Playwright, error) {
|
||||
cmd := exec.Command("./driver")
|
||||
stdin, err := cmd.StdinPipe()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get stdin pipe: %v", err)
|
||||
}
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get stdout pipe: %v", err)
|
||||
}
|
||||
if err := cmd.Start(); err != nil {
|
||||
return nil, fmt.Errorf("could not start driver: %v", err)
|
||||
}
|
||||
connection := newConnection(stdin, stdout)
|
||||
go connection.Start()
|
||||
obj, err := connection.CallOnObjectWithKnownName("Playwright")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not call object: %v", err)
|
||||
}
|
||||
return obj.(*Playwright), nil
|
||||
}
|
||||
85
transport.go
Normal file
85
transport.go
Normal file
@ -0,0 +1,85 @@
|
||||
package playwright
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"gopkg.in/square/go-jose.v2/json"
|
||||
)
|
||||
|
||||
type Transport struct {
|
||||
stdin io.WriteCloser
|
||||
stdout io.ReadCloser
|
||||
dispatch func(msg *Message) error
|
||||
}
|
||||
|
||||
func (t *Transport) SetDispatch(dispatch func(msg *Message) error) {
|
||||
t.dispatch = dispatch
|
||||
}
|
||||
|
||||
func (t *Transport) Start() error {
|
||||
reader := bufio.NewReader(t.stdout)
|
||||
for {
|
||||
lengthContent := make([]byte, 4)
|
||||
_, err := io.ReadFull(reader, lengthContent)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not read padding: %v", err)
|
||||
}
|
||||
length := binary.LittleEndian.Uint32(lengthContent)
|
||||
|
||||
msg := &Message{}
|
||||
if err := json.NewDecoder(io.LimitReader(reader, int64(length))).Decode(&msg); err != nil {
|
||||
return fmt.Errorf("could not parse json: %v", err)
|
||||
}
|
||||
if os.Getenv("DEBUGP") != "" {
|
||||
spew.Dump("RECV>", msg)
|
||||
}
|
||||
t.dispatch(msg)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Transport) Stop() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
ID int `json:"id"`
|
||||
GUID string `json:"guid"`
|
||||
Method string `json:"method"`
|
||||
Params struct {
|
||||
Type string `json:"type"`
|
||||
GUID string `json:"guid"`
|
||||
Initializer interface{} `json:"initializer"`
|
||||
} `json:"params"`
|
||||
Result interface{} `json:"result"`
|
||||
Error struct {
|
||||
Message string `json:"message"`
|
||||
Stack string `json:"stack"`
|
||||
} `json:"error"`
|
||||
}
|
||||
|
||||
func (t *Transport) Send(message map[string]interface{}) error {
|
||||
msg, err := json.Marshal(message)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not marshal json: %v", err)
|
||||
}
|
||||
if os.Getenv("DEBUGP") != "" {
|
||||
spew.Dump("SEND>", message)
|
||||
}
|
||||
b := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(b, uint32(len(msg)))
|
||||
t.stdin.Write(b)
|
||||
t.stdin.Write(msg)
|
||||
return nil
|
||||
}
|
||||
|
||||
func newTransport(stdin io.WriteCloser, stdout io.ReadCloser) *Transport {
|
||||
return &Transport{
|
||||
stdout: stdout,
|
||||
stdin: stdin,
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user