github.com/evanw/esbuild@v0.21.4/internal/helpers/glob.go (about) 1 package helpers 2 3 import "strings" 4 5 type GlobWildcard uint8 6 7 const ( 8 GlobNone GlobWildcard = iota 9 GlobAllExceptSlash 10 GlobAllIncludingSlash 11 ) 12 13 type GlobPart struct { 14 Prefix string 15 Wildcard GlobWildcard 16 } 17 18 // The returned array will always be at least one element. If there are no 19 // wildcards then it will be exactly one element, and if there are wildcards 20 // then it will be more than one element. 21 func ParseGlobPattern(text string) (pattern []GlobPart) { 22 for { 23 star := strings.IndexByte(text, '*') 24 if star < 0 { 25 pattern = append(pattern, GlobPart{Prefix: text}) 26 break 27 } 28 count := 1 29 for star+count < len(text) && text[star+count] == '*' { 30 count++ 31 } 32 wildcard := GlobAllExceptSlash 33 34 // Allow both "/" and "\" as slashes 35 if count > 1 && (star == 0 || text[star-1] == '/' || text[star-1] == '\\') && 36 (star+count == len(text) || text[star+count] == '/' || text[star+count] == '\\') { 37 wildcard = GlobAllIncludingSlash // A "globstar" path segment 38 } 39 40 pattern = append(pattern, GlobPart{Prefix: text[:star], Wildcard: wildcard}) 41 text = text[star+count:] 42 } 43 return 44 } 45 46 func GlobPatternToString(pattern []GlobPart) string { 47 sb := strings.Builder{} 48 for _, part := range pattern { 49 sb.WriteString(part.Prefix) 50 switch part.Wildcard { 51 case GlobAllExceptSlash: 52 sb.WriteByte('*') 53 case GlobAllIncludingSlash: 54 sb.WriteString("**") 55 } 56 } 57 return sb.String() 58 }