mirror of
https://github.com/wader/fq.git
synced 2024-12-18 19:01:34 +03:00
e3ae1440c9
Feels less cluttered, easier to read and more consistent. Still keep tovalue, tobytes etc that are more basic functions this only renamed format related functions. Also there is an exceptin for to/fromjson as it comes from jq. Also fixes lots of spelling errors while reading thru.
154 lines
3.2 KiB
Go
154 lines
3.2 KiB
Go
package text
|
|
|
|
import (
|
|
"net/url"
|
|
|
|
"github.com/wader/fq/internal/gojqex"
|
|
"github.com/wader/fq/pkg/interp"
|
|
)
|
|
|
|
func init() {
|
|
interp.RegisterFunc0("from_urlencode", func(_ *interp.Interp, c string) any {
|
|
u, err := url.QueryUnescape(c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return u
|
|
})
|
|
interp.RegisterFunc0("to_urlencode", func(_ *interp.Interp, c string) any {
|
|
return url.QueryEscape(c)
|
|
})
|
|
|
|
interp.RegisterFunc0("from_urlpath", func(_ *interp.Interp, c string) any {
|
|
u, err := url.PathUnescape(c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return u
|
|
})
|
|
interp.RegisterFunc0("to_urlpath", func(_ *interp.Interp, c string) any {
|
|
return url.PathEscape(c)
|
|
})
|
|
|
|
fromURLValues := func(q url.Values) any {
|
|
qm := map[string]any{}
|
|
for k, v := range q {
|
|
if len(v) > 1 {
|
|
vm := []any{}
|
|
for _, v := range v {
|
|
vm = append(vm, v)
|
|
}
|
|
qm[k] = vm
|
|
} else {
|
|
qm[k] = v[0]
|
|
}
|
|
}
|
|
|
|
return qm
|
|
}
|
|
interp.RegisterFunc0("from_urlquery", func(_ *interp.Interp, c string) any {
|
|
q, err := url.ParseQuery(c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return fromURLValues(q)
|
|
})
|
|
toURLValues := func(c map[string]any) url.Values {
|
|
qv := url.Values{}
|
|
for k, v := range c {
|
|
if va, ok := gojqex.Cast[[]any](v); ok {
|
|
var ss []string
|
|
for _, s := range va {
|
|
if s, ok := gojqex.Cast[string](s); ok {
|
|
ss = append(ss, s)
|
|
}
|
|
}
|
|
qv[k] = ss
|
|
} else if vs, ok := gojqex.Cast[string](v); ok {
|
|
qv[k] = []string{vs}
|
|
}
|
|
}
|
|
return qv
|
|
}
|
|
interp.RegisterFunc0("to_urlquery", func(_ *interp.Interp, c map[string]any) any {
|
|
// TODO: nicer
|
|
c, ok := gojqex.NormalizeToStrings(c).(map[string]any)
|
|
if !ok {
|
|
panic("not map")
|
|
}
|
|
return toURLValues(c).Encode()
|
|
})
|
|
|
|
interp.RegisterFunc0("from_url", func(_ *interp.Interp, c string) any {
|
|
u, err := url.Parse(c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
m := map[string]any{}
|
|
if u.Scheme != "" {
|
|
m["scheme"] = u.Scheme
|
|
}
|
|
if u.User != nil {
|
|
um := map[string]any{
|
|
"username": u.User.Username(),
|
|
}
|
|
if p, ok := u.User.Password(); ok {
|
|
um["password"] = p
|
|
}
|
|
m["user"] = um
|
|
}
|
|
if u.Host != "" {
|
|
m["host"] = u.Host
|
|
}
|
|
if u.Path != "" {
|
|
m["path"] = u.Path
|
|
}
|
|
if u.RawPath != "" {
|
|
m["rawpath"] = u.RawPath
|
|
}
|
|
if u.RawQuery != "" {
|
|
m["rawquery"] = u.RawQuery
|
|
m["query"] = fromURLValues(u.Query())
|
|
}
|
|
if u.Fragment != "" {
|
|
m["fragment"] = u.Fragment
|
|
}
|
|
return m
|
|
})
|
|
interp.RegisterFunc0("to_url", func(_ *interp.Interp, c map[string]any) any {
|
|
// TODO: nicer
|
|
c, ok := gojqex.NormalizeToStrings(c).(map[string]any)
|
|
if !ok {
|
|
panic("not map")
|
|
}
|
|
|
|
str := func(v any) string { s, _ := gojqex.Cast[string](v); return s }
|
|
u := url.URL{
|
|
Scheme: str(c["scheme"]),
|
|
Host: str(c["host"]),
|
|
Path: str(c["path"]),
|
|
Fragment: str(c["fragment"]),
|
|
}
|
|
|
|
if um, ok := gojqex.Cast[map[string]any](c["user"]); ok {
|
|
username, password := str(um["username"]), str(um["password"])
|
|
if username != "" {
|
|
if password == "" {
|
|
u.User = url.User(username)
|
|
} else {
|
|
u.User = url.UserPassword(username, password)
|
|
}
|
|
}
|
|
}
|
|
if s, ok := gojqex.Cast[string](c["rawquery"]); ok {
|
|
u.RawQuery = s
|
|
}
|
|
if qm, ok := gojqex.Cast[map[string]any](c["query"]); ok {
|
|
u.RawQuery = toURLValues(qm).Encode()
|
|
}
|
|
|
|
return u.String()
|
|
})
|
|
}
|