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  }