github.com/dop251/goja_nodejs@v0.0.0-20240418154818-2aae10d4cbcf/url/nodeurl.go (about)

     1  package url
     2  
     3  import (
     4  	"net/url"
     5  	"strings"
     6  )
     7  
     8  type searchParam struct {
     9  	name  string
    10  	value string
    11  }
    12  
    13  func (sp *searchParam) Encode() string {
    14  	return sp.string(true)
    15  }
    16  
    17  func escapeSearchParam(s string) string {
    18  	return escape(s, &tblEscapeURLQueryParam, true)
    19  }
    20  
    21  func (sp *searchParam) string(encode bool) string {
    22  	if encode {
    23  		return escapeSearchParam(sp.name) + "=" + escapeSearchParam(sp.value)
    24  	} else {
    25  		return sp.name + "=" + sp.value
    26  	}
    27  }
    28  
    29  type searchParams []searchParam
    30  
    31  func (s searchParams) Len() int {
    32  	return len(s)
    33  }
    34  
    35  func (s searchParams) Swap(i, j int) {
    36  	s[i], s[j] = s[j], s[i]
    37  }
    38  
    39  func (s searchParams) Less(i, j int) bool {
    40  	return strings.Compare(s[i].name, s[j].name) < 0
    41  }
    42  
    43  func (s searchParams) Encode() string {
    44  	var sb strings.Builder
    45  	for i, v := range s {
    46  		if i > 0 {
    47  			sb.WriteByte('&')
    48  		}
    49  		sb.WriteString(v.Encode())
    50  	}
    51  	return sb.String()
    52  }
    53  
    54  func (s searchParams) String() string {
    55  	var sb strings.Builder
    56  	for i, v := range s {
    57  		if i > 0 {
    58  			sb.WriteByte('&')
    59  		}
    60  		sb.WriteString(v.string(false))
    61  	}
    62  	return sb.String()
    63  }
    64  
    65  type nodeURL struct {
    66  	url          *url.URL
    67  	searchParams searchParams
    68  }
    69  
    70  type urlSearchParams nodeURL
    71  
    72  // This methods ensures that the url.URL has the proper RawQuery based on the searchParam
    73  // structs. If a change is made to the searchParams we need to keep them in sync.
    74  func (nu *nodeURL) syncSearchParams() {
    75  	if nu.rawQueryUpdateNeeded() {
    76  		nu.url.RawQuery = nu.searchParams.Encode()
    77  	}
    78  }
    79  
    80  func (nu *nodeURL) rawQueryUpdateNeeded() bool {
    81  	return len(nu.searchParams) > 0 && nu.url.RawQuery == ""
    82  }
    83  
    84  func (nu *nodeURL) String() string {
    85  	return nu.url.String()
    86  }
    87  
    88  func (sp *urlSearchParams) hasName(name string) bool {
    89  	for _, v := range sp.searchParams {
    90  		if v.name == name {
    91  			return true
    92  		}
    93  	}
    94  	return false
    95  }
    96  
    97  func (sp *urlSearchParams) hasValue(name, value string) bool {
    98  	for _, v := range sp.searchParams {
    99  		if v.name == name && v.value == value {
   100  			return true
   101  		}
   102  	}
   103  	return false
   104  }
   105  
   106  func (sp *urlSearchParams) getValues(name string) []string {
   107  	vals := make([]string, 0, len(sp.searchParams))
   108  	for _, v := range sp.searchParams {
   109  		if v.name == name {
   110  			vals = append(vals, v.value)
   111  		}
   112  	}
   113  
   114  	return vals
   115  }
   116  
   117  func (sp *urlSearchParams) getFirstValue(name string) (string, bool) {
   118  	for _, v := range sp.searchParams {
   119  		if v.name == name {
   120  			return v.value, true
   121  		}
   122  	}
   123  
   124  	return "", false
   125  }
   126  
   127  func parseSearchQuery(query string) (ret searchParams) {
   128  	if query == "" {
   129  		return
   130  	}
   131  
   132  	query = strings.TrimPrefix(query, "?")
   133  
   134  	for _, v := range strings.Split(query, "&") {
   135  		if v == "" {
   136  			continue
   137  		}
   138  		pair := strings.SplitN(v, "=", 2)
   139  		l := len(pair)
   140  		if l == 1 {
   141  			ret = append(ret, searchParam{name: unescapeSearchParam(pair[0]), value: ""})
   142  		} else if l == 2 {
   143  			ret = append(ret, searchParam{name: unescapeSearchParam(pair[0]), value: unescapeSearchParam(pair[1])})
   144  		}
   145  	}
   146  
   147  	return
   148  }