Skip to content

Commit

Permalink
chore: do the final cleanup of the migration
Browse files Browse the repository at this point in the history
  • Loading branch information
42atomys committed May 9, 2024
1 parent 8b921aa commit 1676e31
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 706 deletions.
1 change: 1 addition & 0 deletions .github/codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ github_checks:
ignore:
- benchmark/**
- docs/**
- sprig_functions_not_included_in_sprout.go
comment:
behavior: new
require_changes: true
72 changes: 29 additions & 43 deletions migrated_functions.go → sprig_functions_not_included_in_sprout.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
/**
* This file lists the functions originally part of the Sprig library that are
* intentionally excluded from the Sprout library. The exclusions are based on\
* community decisions and technical evaluations aimed at enhancing security,
* relevance, and performance in the context of Go templates.
* Each exclusion is supported by rational and further community discussions
* can be found on our GitHub issues page.
*
* Exclusion Criteria:
* 1. Crypto functions: Deemed inappropriate for Go templates due to inherent security risks.
* 2. Irrelevant functions: Omitted because they do not provide utility in the context of Go templates.
* 3. Deprecated/Insecure: Functions using outdated or insecure standards are excluded.
* 4. Temporary exclusions: Certain functions are temporarily excluded to prevent breaking changes,
* pending the implementation of the new loader feature.
* 5. Community decision: Choices made by the community are documented and can be discussed at
* https://github.com/42atomys/sprout/issues/1.
*
* The Sprout library is an open-source project and welcomes contributions from the community.
* To discuss existing exclusions or propose new ones, please contribute to the discussions on
* our GitHub repository.
*/
package sprout

import (
Expand Down Expand Up @@ -34,31 +55,10 @@ import (
"time"

sv2 "github.com/Masterminds/semver/v3"
"github.com/shopspring/decimal"
bcrypt_lib "golang.org/x/crypto/bcrypt"
"golang.org/x/crypto/scrypt"
)

func (fh *FunctionHandler) FillMapWithParts(parts []string) map[string]string {
res := make(map[string]string, len(parts))
for i, v := range parts {
res[fmt.Sprintf("_%d", i)] = v
}
return res
}

func (fh *FunctionHandler) DictGetOrEmpty(dict map[string]any, key string) string {
value, ok := dict[key]
if !ok {
return ""
}
tp := reflect.TypeOf(value).Kind()
if tp != reflect.String {
panic(fmt.Sprintf("unable to parse %s key, must be of type string, but %s found", key, tp.String()))
}
return reflect.ValueOf(value).String()
}

func (fh *FunctionHandler) UrlParse(v string) map[string]any {
dict := map[string]any{}
parsedURL, err := url.Parse(v)
Expand All @@ -83,14 +83,14 @@ func (fh *FunctionHandler) UrlParse(v string) map[string]any {

func (fh *FunctionHandler) UrlJoin(d map[string]any) string {
resURL := url.URL{
Scheme: fh.DictGetOrEmpty(d, "scheme"),
Host: fh.DictGetOrEmpty(d, "host"),
Path: fh.DictGetOrEmpty(d, "path"),
RawQuery: fh.DictGetOrEmpty(d, "query"),
Opaque: fh.DictGetOrEmpty(d, "opaque"),
Fragment: fh.DictGetOrEmpty(d, "fragment"),
}
userinfo := fh.DictGetOrEmpty(d, "userinfo")
Scheme: fh.Get(d, "scheme").(string),
Host: fh.Get(d, "host").(string),
Path: fh.Get(d, "path").(string),
RawQuery: fh.Get(d, "query").(string),
Opaque: fh.Get(d, "opaque").(string),
Fragment: fh.Get(d, "fragment").(string),
}
userinfo := fh.Get(d, "userinfo").(string)
var user *url.Userinfo
if userinfo != "" {
tempURL, err := url.Parse(fmt.Sprintf("proto://%s@host", userinfo))
Expand All @@ -104,20 +104,6 @@ func (fh *FunctionHandler) UrlJoin(d map[string]any) string {
return resURL.String()
}

func (fh *FunctionHandler) IntArrayToString(slice []int, delimeter string) string {
return strings.Trim(strings.Join(strings.Fields(fmt.Sprint(slice)), delimeter), "[]")
}

func (fh *FunctionHandler) ExecDecimalOp(a any, b []any, f func(d1, d2 decimal.Decimal) decimal.Decimal) float64 {
prt := decimal.NewFromFloat(fh.ToFloat64(a))
for _, x := range b {
dx := decimal.NewFromFloat(fh.ToFloat64(x))
prt = f(prt, dx)
}
rslt, _ := prt.Float64()
return rslt
}

func (fh *FunctionHandler) GetHostByName(name string) string {
addrs, _ := net.LookupHost(name)
//TODO: add error handing when release v3 comes out
Expand Down
6 changes: 0 additions & 6 deletions sprout.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,6 @@ func WithFunctionHandler(new *FunctionHandler) FunctionHandlerOption {
func FuncMap(opts ...FunctionHandlerOption) template.FuncMap {
fnHandler := NewFunctionHandler(opts...)

// BACKWARD COMPATIBILITY
// Fallback to FuncMap() to get the unmigrated functions
for k, v := range TxtFuncMap() {
fnHandler.funcMap[k] = v
}

// Added migrated functions
fnHandler.funcMap["hello"] = fnHandler.Hello

Expand Down
21 changes: 0 additions & 21 deletions sprout_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,24 +85,3 @@ func TestFuncMap_IncludesHello(t *testing.T) {

assert.Equal(t, "Hello!", helloFunc())
}

// This test ensures backward compatibility by checking if FuncMap (the function mentioned in the comment) exists or needs to be implemented for the test.
func TestFuncMap_BackwardCompatibility(t *testing.T) {
// Assuming FuncMap() is implemented and returns a template.FuncMap
// Replace the implementation details as per actual FuncMap function.
genericMap["TestFuncMap_BackwardCompatibility"] = func() string {
return "example"
}

funcMap := FuncMap()
exampleFunc, exists := funcMap["TestFuncMap_BackwardCompatibility"]
assert.True(t, exists)

result, ok := exampleFunc.(func() string)
assert.True(t, ok)
assert.Equal(t, "example", result())

helloFunc, ok := funcMap["hello"].(func() string)
assert.True(t, ok)
assert.Equal(t, "Hello!", helloFunc())
}
55 changes: 50 additions & 5 deletions strings_functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -955,7 +955,7 @@ func (fh *FunctionHandler) SwapCase(str string) string {
// {{ "apple,banana,cherry" | split "," }} // Output: { "_0":"apple", "_1":"banana", "_2":"cherry" }
func (fh *FunctionHandler) Split(sep, orig string) map[string]string {
parts := strings.Split(orig, sep)
return fh.FillMapWithParts(parts)
return fh.populateMapWithParts(parts)
}

// Splitn divides 'orig' into a map of string parts using 'sep' as the separator
Expand All @@ -976,7 +976,31 @@ func (fh *FunctionHandler) Split(sep, orig string) map[string]string {
// {{ "apple,banana,cherry" | split "," 2 }} // Output: { "_0":"apple", "_1":"banana,cherry" }
func (fh *FunctionHandler) Splitn(sep string, n int, orig string) map[string]string {
parts := strings.SplitN(orig, sep, n)
return fh.FillMapWithParts(parts)
return fh.populateMapWithParts(parts)
}

// populateMapWithParts converts an array of strings into a map with keys based
// on the index of each string.
//
// Parameters:
//
// parts []string - the array of strings to be converted into a map.
//
// Returns:
//
// map[string]string - a map where each key corresponds to an index (with an underscore prefix) of the string in the input array.
//
// Example:
//
// parts := []string{"apple", "banana", "cherry"}
// result := fh.populateMapWithParts(parts)
// fmt.Println(result) // Output: {"_0": "apple", "_1": "banana", "_2": "cherry"}
func (fh *FunctionHandler) populateMapWithParts(parts []string) map[string]string {
res := make(map[string]string, len(parts))
for i, v := range parts {
res[fmt.Sprintf("_%d", i)] = v
}
return res
}

// Substring extracts a substring from 's' starting at 'start' and ending at 'end'.
Expand Down Expand Up @@ -1088,7 +1112,7 @@ func (fh *FunctionHandler) Seq(params ...int) string {
if end < start {
increment = -1
}
return fh.IntArrayToString(fh.UntilStep(start, end+increment, increment), " ")
return fh.convertIntArrayToString(fh.UntilStep(start, end+increment, increment), " ")
case 3:
start := params[0]
end := params[2]
Expand All @@ -1099,16 +1123,37 @@ func (fh *FunctionHandler) Seq(params ...int) string {
return ""
}
}
return fh.IntArrayToString(fh.UntilStep(start, end+increment, step), " ")
return fh.convertIntArrayToString(fh.UntilStep(start, end+increment, step), " ")
case 2:
start := params[0]
end := params[1]
step := 1
if end < start {
step = -1
}
return fh.IntArrayToString(fh.UntilStep(start, end+step, step), " ")
return fh.convertIntArrayToString(fh.UntilStep(start, end+step, step), " ")
default:
return ""
}
}

// convertIntArrayToString converts an array of integers into a single string
// with elements separated by a given delimiter.
//
// Parameters:
//
// slice []int - the array of integers to convert.
// delimiter string - the string to use as a delimiter between the integers in the output string.
//
// Returns:
//
// string - the resulting string that concatenates all the integers in the array separated by the specified delimiter.
//
// Example:
//
// slice := []int{1, 2, 3, 4, 5}
// result := fh.convertIntArrayToString(slice, ", ")
// fmt.Println(result) // Output: "1, 2, 3, 4, 5"
func (fh *FunctionHandler) convertIntArrayToString(slice []int, delimeter string) string {
return strings.Trim(strings.Join(strings.Fields(fmt.Sprint(slice)), delimeter), "[]")
}
74 changes: 0 additions & 74 deletions to_migrate.go

This file was deleted.

Loading

0 comments on commit 1676e31

Please sign in to comment.