mirror of
https://github.com/playwright-community/playwright-go.git
synced 2026-06-06 21:08:17 +08:00
Some checks failed
Go / Lint (push) Has been cancelled
Go / ${{ matrix.browser }} on ${{ matrix.os }}, go ${{ matrix.go }} (chromium, oldstable, macos-latest) (push) Has been cancelled
Go / ${{ matrix.browser }} on ${{ matrix.os }}, go ${{ matrix.go }} (chromium, oldstable, ubuntu-latest) (push) Has been cancelled
Go / ${{ matrix.browser }} on ${{ matrix.os }}, go ${{ matrix.go }} (chromium, oldstable, windows-latest) (push) Has been cancelled
Go / ${{ matrix.browser }} on ${{ matrix.os }}, go ${{ matrix.go }} (chromium, stable, macos-latest) (push) Has been cancelled
Go / ${{ matrix.browser }} on ${{ matrix.os }}, go ${{ matrix.go }} (chromium, stable, ubuntu-latest) (push) Has been cancelled
Go / ${{ matrix.browser }} on ${{ matrix.os }}, go ${{ matrix.go }} (chromium, stable, windows-latest) (push) Has been cancelled
Go / ${{ matrix.browser }} on ${{ matrix.os }}, go ${{ matrix.go }} (firefox, oldstable, macos-latest) (push) Has been cancelled
Go / ${{ matrix.browser }} on ${{ matrix.os }}, go ${{ matrix.go }} (firefox, oldstable, ubuntu-latest) (push) Has been cancelled
Go / ${{ matrix.browser }} on ${{ matrix.os }}, go ${{ matrix.go }} (firefox, oldstable, windows-latest) (push) Has been cancelled
Go / ${{ matrix.browser }} on ${{ matrix.os }}, go ${{ matrix.go }} (firefox, stable, macos-latest) (push) Has been cancelled
Go / ${{ matrix.browser }} on ${{ matrix.os }}, go ${{ matrix.go }} (firefox, stable, ubuntu-latest) (push) Has been cancelled
Go / ${{ matrix.browser }} on ${{ matrix.os }}, go ${{ matrix.go }} (firefox, stable, windows-latest) (push) Has been cancelled
Go / ${{ matrix.browser }} on ${{ matrix.os }}, go ${{ matrix.go }} (webkit, oldstable, macos-latest) (push) Has been cancelled
Go / ${{ matrix.browser }} on ${{ matrix.os }}, go ${{ matrix.go }} (webkit, oldstable, ubuntu-latest) (push) Has been cancelled
Go / ${{ matrix.browser }} on ${{ matrix.os }}, go ${{ matrix.go }} (webkit, oldstable, windows-latest) (push) Has been cancelled
Go / ${{ matrix.browser }} on ${{ matrix.os }}, go ${{ matrix.go }} (webkit, stable, macos-latest) (push) Has been cancelled
Go / ${{ matrix.browser }} on ${{ matrix.os }}, go ${{ matrix.go }} (webkit, stable, ubuntu-latest) (push) Has been cancelled
Go / ${{ matrix.browser }} on ${{ matrix.os }}, go ${{ matrix.go }} (webkit, stable, windows-latest) (push) Has been cancelled
Go / test-examples (push) Has been cancelled
Docs / Deploy docs (push) Has been cancelled
Verify Types / verify (push) Has been cancelled
Go / finish (push) Has been cancelled
171 lines
4.0 KiB
Go
171 lines
4.0 KiB
Go
package playwright
|
|
|
|
import (
|
|
"net/url"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
var escapedChars = map[rune]bool{
|
|
'$': true,
|
|
'^': true,
|
|
'+': true,
|
|
'.': true,
|
|
'*': true,
|
|
'(': true,
|
|
')': true,
|
|
'|': true,
|
|
'\\': true,
|
|
'?': true,
|
|
'{': true,
|
|
'}': true,
|
|
'[': true,
|
|
']': true,
|
|
}
|
|
|
|
func globMustToRegex(glob string) *regexp.Regexp {
|
|
tokens := []string{"^"}
|
|
inGroup := false
|
|
|
|
for i := 0; i < len(glob); i++ {
|
|
c := rune(glob[i])
|
|
if c == '\\' && i+1 < len(glob) {
|
|
char := rune(glob[i+1])
|
|
if _, ok := escapedChars[char]; ok {
|
|
tokens = append(tokens, "\\"+string(char))
|
|
} else {
|
|
tokens = append(tokens, string(char))
|
|
}
|
|
i++
|
|
} else if c == '*' {
|
|
beforeDeep := rune(0)
|
|
if i > 0 {
|
|
beforeDeep = rune(glob[i-1])
|
|
}
|
|
starCount := 1
|
|
for i+1 < len(glob) && glob[i+1] == '*' {
|
|
starCount++
|
|
i++
|
|
}
|
|
afterDeep := rune(0)
|
|
if i+1 < len(glob) {
|
|
afterDeep = rune(glob[i+1])
|
|
}
|
|
isDeep := starCount > 1 && (beforeDeep == '/' || beforeDeep == 0) && (afterDeep == '/' || afterDeep == 0)
|
|
if isDeep {
|
|
tokens = append(tokens, "((?:[^/]*(?:/|$))*)")
|
|
i++
|
|
} else {
|
|
tokens = append(tokens, "([^/]*)")
|
|
}
|
|
} else {
|
|
switch c {
|
|
case '{':
|
|
inGroup = true
|
|
tokens = append(tokens, "(")
|
|
case '}':
|
|
inGroup = false
|
|
tokens = append(tokens, ")")
|
|
case ',':
|
|
if inGroup {
|
|
tokens = append(tokens, "|")
|
|
} else {
|
|
tokens = append(tokens, "\\"+string(c))
|
|
}
|
|
default:
|
|
if _, ok := escapedChars[c]; ok {
|
|
tokens = append(tokens, "\\"+string(c))
|
|
} else {
|
|
tokens = append(tokens, string(c))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
tokens = append(tokens, "$")
|
|
return regexp.MustCompile(strings.Join(tokens, ""))
|
|
}
|
|
|
|
func resolveGlobToRegex(baseURL *string, glob string, isWebSocketUrl bool) *regexp.Regexp {
|
|
if isWebSocketUrl {
|
|
baseURL = toWebSocketBaseURL(baseURL)
|
|
}
|
|
glob = resolveGlobBase(baseURL, glob)
|
|
return globMustToRegex(glob)
|
|
}
|
|
|
|
func resolveGlobBase(baseURL *string, match string) string {
|
|
if strings.HasPrefix(match, "*") {
|
|
return match
|
|
}
|
|
|
|
tokenMap := make(map[string]string)
|
|
mapToken := func(original string, replacement string) string {
|
|
if len(original) == 0 {
|
|
return ""
|
|
}
|
|
tokenMap[replacement] = original
|
|
return replacement
|
|
}
|
|
// Escaped `\\?` behaves the same as `?` in our glob patterns.
|
|
match = strings.ReplaceAll(match, `\\?`, "?")
|
|
// Glob symbols may be escaped in the URL and some of them such as ? affect resolution,
|
|
// so we replace them with safe components first.
|
|
relativePath := strings.Split(match, "/")
|
|
for i, token := range relativePath {
|
|
if token == "." || token == ".." || token == "" {
|
|
continue
|
|
}
|
|
// Handle special case of http*://, note that the new schema has to be
|
|
// a web schema so that slashes are properly inserted after domain.
|
|
if i == 0 && strings.HasSuffix(token, ":") {
|
|
relativePath[i] = mapToken(token, "http:")
|
|
} else {
|
|
questionIndex := strings.Index(token, "?")
|
|
if questionIndex == -1 {
|
|
relativePath[i] = mapToken(token, "$_"+strconv.Itoa(i)+"_$")
|
|
} else {
|
|
newPrefix := mapToken(token[:questionIndex], "$_"+strconv.Itoa(i)+"_$")
|
|
newSuffix := mapToken(token[questionIndex:], "?$"+strconv.Itoa(i)+"_$")
|
|
relativePath[i] = newPrefix + newSuffix
|
|
}
|
|
}
|
|
}
|
|
resolved := constructURLBasedOnBaseURL(baseURL, strings.Join(relativePath, "/"))
|
|
for token, original := range tokenMap {
|
|
resolved = strings.ReplaceAll(resolved, token, original)
|
|
}
|
|
return resolved
|
|
}
|
|
|
|
func constructURLBasedOnBaseURL(baseURL *string, givenURL string) string {
|
|
u, err := url.Parse(givenURL)
|
|
if err != nil {
|
|
return givenURL
|
|
}
|
|
if baseURL != nil {
|
|
base, err := url.Parse(*baseURL)
|
|
if err != nil {
|
|
return givenURL
|
|
}
|
|
u = base.ResolveReference(u)
|
|
}
|
|
if u.Path == "" { // In Node.js, new URL('http://localhost') returns 'http://localhost/'.
|
|
u.Path = "/"
|
|
}
|
|
return u.String()
|
|
}
|
|
|
|
func toWebSocketBaseURL(baseURL *string) *string {
|
|
if baseURL == nil {
|
|
return nil
|
|
}
|
|
|
|
// Allow http(s) baseURL to match ws(s) urls.
|
|
re := regexp.MustCompile(`(?m)^http(s?://)`)
|
|
wsBaseURL := re.ReplaceAllString(*baseURL, "ws$1")
|
|
|
|
return &wsBaseURL
|
|
}
|