From d08b90c0ce651e66c55abdb805b76bdef125c187 Mon Sep 17 00:00:00 2001 From: Chris Clark Date: Wed, 18 Aug 2021 16:30:56 -0500 Subject: [PATCH] PIP-1383: Add ifMatchesRegexStr helper (#8) * add ifMatchesRegexStr helper * add logging --- go.mod | 5 +++- go.sum | 7 +++++ helper.go | 33 +++++++++++++++----- helper_test.go | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++ raymond.go | 14 +++++++++ 5 files changed, 132 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 98a910f..d05b6ab 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,7 @@ module github.com/mailgun/raymond/v2 go 1.16 -require gopkg.in/yaml.v2 v2.4.0 +require ( + github.com/sirupsen/logrus v1.8.1 // indirect + gopkg.in/yaml.v2 v2.4.0 +) diff --git a/go.sum b/go.sum index dd0bc19..714ea36 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,10 @@ +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= diff --git a/helper.go b/helper.go index de8b3df..dec1b87 100644 --- a/helper.go +++ b/helper.go @@ -3,8 +3,8 @@ package raymond import ( "errors" "fmt" - "log" "reflect" + "regexp" "strconv" "sync" ) @@ -37,6 +37,7 @@ func init() { RegisterHelper("ifGt", ifGtHelper) RegisterHelper("ifLt", ifLtHelper) RegisterHelper("ifEq", ifEqHelper) + RegisterHelper("ifMatchesRegexStr", ifMatchesRegexStr) } // RegisterHelper registers a global helper. That helper will be available to all templates. @@ -312,11 +313,11 @@ func ifGtHelper(a, b interface{}, options *Options) interface{} { var err error if aFloat, err = floatValue(a); err != nil { - // TODO: Log conversion failure. + log.WithError(err).Errorf("failed to convert value to float '%v'", a) return options.Inverse() } if bFloat, err = floatValue(b); err != nil { - // TODO: Log conversion failure + log.WithError(err).Errorf("failed to convert value to float '%v'", b) return options.Inverse() } @@ -332,11 +333,11 @@ func ifLtHelper(a, b interface{}, options *Options) interface{} { var err error if aFloat, err = floatValue(a); err != nil { - // TODO: Log conversion failure. + log.WithError(err).Errorf("failed to convert value to float '%v'", a) return options.Inverse() } if bFloat, err = floatValue(b); err != nil { - // TODO: Log conversion failure + log.WithError(err).Errorf("failed to convert value to float '%v'", b) return options.Inverse() } @@ -352,11 +353,11 @@ func ifEqHelper(a, b interface{}, options *Options) interface{} { var err error if aFloat, err = floatValue(a); err != nil { - // TODO: Log conversion failure. + log.WithError(err).Errorf("failed to convert value to float '%v'", a) return options.Inverse() } if bFloat, err = floatValue(b); err != nil { - // TODO: Log conversion failure + log.WithError(err).Errorf("failed to convert value to float '%v'", b) return options.Inverse() } @@ -367,6 +368,24 @@ func ifEqHelper(a, b interface{}, options *Options) interface{} { return options.Inverse() } +// ifMatchesRegexStr is helper function which does a regex match, where a is the expression to compile and +// b is the string to match against. +func ifMatchesRegexStr(a, b interface{}, options *Options) interface{} { + exp := Str(a) + match := Str(b) + + re, err := regexp.Compile(exp) + if err != nil { + log.WithError(err).Errorf("failed to compile regex '%v'", a) + return options.Inverse() + } + + if re.MatchString(match) { + return options.Fn() + } + return options.Inverse() +} + // #unless block helper func unlessHelper(conditional interface{}, options *Options) interface{} { if options.isIncludableZero() || IsTrue(conditional) { diff --git a/helper_test.go b/helper_test.go index 3b6fa60..8f16d59 100644 --- a/helper_test.go +++ b/helper_test.go @@ -362,6 +362,87 @@ var helperTests = []Test{ nil, nil, nil, `foo or bar are not numbers`, }, + { + "#ifMatchesRegexStr helper simple string match", + `{{#ifMatchesRegexStr "foo" bar}}The expression matches{{/ifMatchesRegexStr}}`, + map[string]interface{}{"bar": "foo"}, + nil, nil, nil, + `The expression matches`, + }, + { + "#ifMatchesRegexStr regex match", + `{{#ifMatchesRegexStr regex phone}}The expression matches{{/ifMatchesRegexStr}}`, + map[string]interface{}{ + "regex": "^(\\+\\d{1,2}\\s)?\\(?\\d{3}\\)?[\\s.-]\\d{3}[\\s.-]\\d{4}$", + "phone": "555-333-4545", + }, + nil, nil, nil, + `The expression matches`, + }, + { + "#ifMatchesRegexStr regex match with string conversion", + `{{#ifMatchesRegexStr regex phone}}The expression matches{{/ifMatchesRegexStr}}`, + map[string]interface{}{ + "regex": "^(\\+\\d{1,2}\\s)?\\(?\\d{3}\\)?\\d{3}\\d{4}$", + "phone": 5553334545, + }, + nil, nil, nil, + `The expression matches`, + }, + { + "#ifMatchesRegexStr helper simple string does not match", + `{{#ifMatchesRegexStr "foo" bar}}The expression matches{{/ifMatchesRegexStr}}`, + map[string]interface{}{"bar": "bar"}, + nil, nil, nil, + ``, + }, + { + "#ifMatchesRegexStr regex does not match", + `{{#ifMatchesRegexStr regex phone}}The expression matches{{/ifMatchesRegexStr}}`, + map[string]interface{}{ + "regex": "^(\\+\\d{1,2}\\s)?\\(?\\d{3}\\)?[\\s.-]\\d{3}[\\s.-]\\d{4}$", + "phone": "5553334545", + }, + nil, nil, nil, + ``, + }, + { + "#ifMatchesRegexStr regex does not match with string conversion", + `{{#ifMatchesRegexStr regex phone}}The expression matches{{/ifMatchesRegexStr}}`, + map[string]interface{}{ + "regex": "^(\\+\\d{1,2}\\s)?\\(?\\d{3}\\)?\\d{3}\\d{4}$", + "phone": 1, + }, + nil, nil, nil, + ``, + }, + { + "#ifMatchesRegexStr helper simple string trigger else", + `{{#ifMatchesRegexStr "foo" bar}}The expression matches{{else}}The expression does not match{{/ifMatchesRegexStr}}`, + map[string]interface{}{"bar": "bar"}, + nil, nil, nil, + `The expression does not match`, + }, + { + "#ifMatchesRegexStr regex trigger else", + `{{#ifMatchesRegexStr regex phone}}The expression matches{{else}}The expression does not match{{/ifMatchesRegexStr}}`, + map[string]interface{}{ + "regex": "^(\\+\\d{1,2}\\s)?\\(?\\d{3}\\)?[\\s.-]\\d{3}[\\s.-]\\d{4}$", + "phone": "5553334545", + }, + nil, nil, nil, + `The expression does not match`, + }, + { + "#ifMatchesRegexStr regex trigger else with string conversion", + `{{#ifMatchesRegexStr regex phone}}The expression matches{{else}}The expression does not match{{/ifMatchesRegexStr}}`, + map[string]interface{}{ + "regex": "^(\\+\\d{1,2}\\s)?\\(?\\d{3}\\)?\\d{3}\\d{4}$", + "phone": 1, + }, + nil, nil, nil, + `The expression does not match`, + }, { "#equal helper inside HTML tag", ``, diff --git a/raymond.go b/raymond.go index c6df6b3..86f1936 100644 --- a/raymond.go +++ b/raymond.go @@ -1,6 +1,20 @@ // Package raymond provides handlebars evaluation package raymond +import "github.com/sirupsen/logrus" + +var log *logrus.Entry + +func init() { + log = logrus.NewEntry(logrus.StandardLogger()) +} + +// SetLogger allows the user to set a customer logger adding the ability to add custom fields to +// the log entries. +func SetLogger(entry *logrus.Entry) { + log = entry +} + // Render parses a template and evaluates it with given context // // Note that this function call is not optimal as your template is parsed everytime you call it. You should use Parse() function instead.