playwright-go/glob.go
Can Stand 64e0326e36
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
chore: roll to Playwright v1.52.0 (#540)
2025-05-05 21:22:21 +08:00

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
}