summaryrefslogtreecommitdiff
path: root/vendor/github.com/playwright-community/playwright-go/glob.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/playwright-community/playwright-go/glob.go')
-rw-r--r--vendor/github.com/playwright-community/playwright-go/glob.go170
1 files changed, 170 insertions, 0 deletions
diff --git a/vendor/github.com/playwright-community/playwright-go/glob.go b/vendor/github.com/playwright-community/playwright-go/glob.go
new file mode 100644
index 0000000..77deba3
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/glob.go
@@ -0,0 +1,170 @@
+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
+}