From 9d3ed69ffab722f961ccaea3170f9e9d611ed42f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=A1=EF=B8=8FNefe=E2=9A=A1=EF=B8=8F?= Date: Sun, 25 Feb 2024 23:47:48 +0100 Subject: [PATCH 1/3] feat: updated filters to use sync.Map instead of regular maps --- .semaphore/semaphore.yml | 36 ++++++++++++++++++------------------ filters.go | 19 ++++++++++++------- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/.semaphore/semaphore.yml b/.semaphore/semaphore.yml index 4a6cf64..1cb906b 100644 --- a/.semaphore/semaphore.yml +++ b/.semaphore/semaphore.yml @@ -1,18 +1,18 @@ -version: v1.0 -name: Go -agent: - machine: - type: e1-standard-2 - os_image: ubuntu2004 -blocks: - - name: Test - task: - jobs: - - name: go test - commands: - - sem-version go 1.18 - - export GOPATH=~/go - - 'export PATH=/home/semaphore/go/bin:$PATH' - - checkout - - go get ./... - - go test ./... +version: v1.0 +name: Go +agent: + machine: + type: e1-standard-2 + os_image: ubuntu2004 +blocks: + - name: Test + task: + jobs: + - name: go test + commands: + - sem-version go 1.18 + - export GOPATH=~/go + - 'export PATH=/home/semaphore/go/bin:$PATH' + - checkout + - go get ./... + - go test ./... diff --git a/filters.go b/filters.go index 7fa7a75..28fcc02 100644 --- a/filters.go +++ b/filters.go @@ -2,20 +2,22 @@ package pongo2 import ( "fmt" + "sync" ) // FilterFunction is the type filter functions must fulfil type FilterFunction func(in *Value, param *Value) (out *Value, err *Error) -var filters map[string]FilterFunction +// var filters map[string]FilterFunction +var filters *sync.Map func init() { - filters = make(map[string]FilterFunction) + filters = new(sync.Map) } // FilterExists returns true if the given filter is already registered func FilterExists(name string) bool { - _, existing := filters[name] + _, existing := filters.Load(name) return existing } @@ -27,7 +29,8 @@ func RegisterFilter(name string, fn FilterFunction) error { if FilterExists(name) { return fmt.Errorf("filter with name '%s' is already registered", name) } - filters[name] = fn + + filters.Store(name, fn) return nil } @@ -37,7 +40,7 @@ func ReplaceFilter(name string, fn FilterFunction) error { if !FilterExists(name) { return fmt.Errorf("filter with name '%s' does not exist (therefore cannot be overridden)", name) } - filters[name] = fn + filters.Store(name, fn) return nil } @@ -53,7 +56,7 @@ func MustApplyFilter(name string, value *Value, param *Value) *Value { // ApplyFilter applies a filter to a given value using the given parameters. // Returns a *pongo2.Value or an error. func ApplyFilter(name string, value *Value, param *Value) (*Value, *Error) { - fn, existing := filters[name] + storedValue, existing := filters.Load(name) if !existing { return nil, &Error{ Sender: "applyfilter", @@ -66,6 +69,7 @@ func ApplyFilter(name string, value *Value, param *Value) (*Value, *Error) { param = AsValue(nil) } + fn, _ := storedValue.(FilterFunction) return fn(value, param) } @@ -113,10 +117,11 @@ func (p *Parser) parseFilter() (*filterCall, *Error) { } // Get the appropriate filter function and bind it - filterFn, exists := filters[identToken.Val] + storedFunc, exists := filters.Load(identToken.Val) if !exists { return nil, p.Error(fmt.Sprintf("Filter '%s' does not exist.", identToken.Val), identToken) } + filterFn, _ := storedFunc.(FilterFunction) filter.filterFunc = filterFn From 75e48812673039caaeb05e37249cec55b149195c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=A1=EF=B8=8FNefe=E2=9A=A1=EF=B8=8F?= Date: Mon, 26 Feb 2024 00:02:04 +0100 Subject: [PATCH 2/3] updated escape filter reader --- template_sets.go | 2 +- variable.go | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/template_sets.go b/template_sets.go index 9a73eac..05ed69f 100644 --- a/template_sets.go +++ b/template_sets.go @@ -115,7 +115,7 @@ func (set *TemplateSet) BanTag(name string) error { // BanFilter bans a specific filter for this template set. See more in the documentation for TemplateSet. func (set *TemplateSet) BanFilter(name string) error { - _, has := filters[name] + _, has := filters.Load(name) if !has { return fmt.Errorf("filter '%s' not found", name) } diff --git a/variable.go b/variable.go index 96e047e..51c30f5 100644 --- a/variable.go +++ b/variable.go @@ -214,7 +214,13 @@ func (nv *nodeVariable) Execute(ctx *ExecutionContext, writer TemplateWriter) *E if !nv.expr.FilterApplied("safe") && !value.safe && value.IsString() && ctx.Autoescape { // apply escape filter - value, err = filters["escape"](value, nil) + storedValue, ok := filters.Load("escape") + if !ok { + return ctx.Error("filter 'escape' not found", nv.locationToken) + } + + fn, _ := storedValue.(FilterFunction) + value, err = fn(value, nil) if err != nil { return err } From d66709593f36584ecf9eb88d1e2a91cd5a732488 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=A1=EF=B8=8FNefe=E2=9A=A1=EF=B8=8F?= Date: Mon, 26 Feb 2024 10:45:14 +0100 Subject: [PATCH 3/3] feat: updated pongo2 filters to ensure it can take a variable from the general bind. --- filters.go | 28 ++++++++----- filters_builtin.go | 102 ++++++++++++++++++++++----------------------- tags_filter.go | 2 +- tags_firstof.go | 2 +- variable.go | 2 +- 5 files changed, 71 insertions(+), 65 deletions(-) diff --git a/filters.go b/filters.go index 28fcc02..beb872a 100644 --- a/filters.go +++ b/filters.go @@ -6,7 +6,7 @@ import ( ) // FilterFunction is the type filter functions must fulfil -type FilterFunction func(in *Value, param *Value) (out *Value, err *Error) +type FilterFunction func(in *Value, param *Value, bind map[string]any) (out *Value, err *Error) // var filters map[string]FilterFunction var filters *sync.Map @@ -40,22 +40,28 @@ func ReplaceFilter(name string, fn FilterFunction) error { if !FilterExists(name) { return fmt.Errorf("filter with name '%s' does not exist (therefore cannot be overridden)", name) } + filters.Swap(name, fn) + return nil +} + +func OverrideFilter(name string, fn FilterFunction) error { + filters.Delete(name) filters.Store(name, fn) return nil } // MustApplyFilter behaves like ApplyFilter, but panics on an error. -func MustApplyFilter(name string, value *Value, param *Value) *Value { - val, err := ApplyFilter(name, value, param) - if err != nil { - panic(err) - } - return val -} +//func MustApplyFilter(name string, value *Value, param *Value) *Value { +// val, err := ApplyFilter(name, value, param) +// if err != nil { +// panic(err) +// } +// return val +//} // ApplyFilter applies a filter to a given value using the given parameters. // Returns a *pongo2.Value or an error. -func ApplyFilter(name string, value *Value, param *Value) (*Value, *Error) { +func ApplyFilter(name string, value *Value, param *Value, bind map[string]any) (*Value, *Error) { storedValue, existing := filters.Load(name) if !existing { return nil, &Error{ @@ -70,7 +76,7 @@ func ApplyFilter(name string, value *Value, param *Value) (*Value, *Error) { } fn, _ := storedValue.(FilterFunction) - return fn(value, param) + return fn(value, param, bind) } type filterCall struct { @@ -95,7 +101,7 @@ func (fc *filterCall) Execute(v *Value, ctx *ExecutionContext) (*Value, *Error) param = AsValue(nil) } - filteredValue, err := fc.filterFunc(v, param) + filteredValue, err := fc.filterFunc(v, param, ctx.Public) if err != nil { return nil, err.updateFromTokenIfNeeded(ctx.template, fc.token) } diff --git a/filters_builtin.go b/filters_builtin.go index 2b436c2..c5ddf75 100644 --- a/filters_builtin.go +++ b/filters_builtin.go @@ -218,13 +218,13 @@ func filterTruncateHTMLHelper(value string, newOutput *bytes.Buffer, cond func() } } -func filterTruncatechars(in *Value, param *Value) (*Value, *Error) { +func filterTruncatechars(in *Value, param *Value, bind map[string]any) (*Value, *Error) { s := in.String() newLen := param.Integer() return AsValue(filterTruncatecharsHelper(s, newLen)), nil } -func filterTruncatecharsHTML(in *Value, param *Value) (*Value, *Error) { +func filterTruncatecharsHTML(in *Value, param *Value, bind map[string]any) (*Value, *Error) { value := in.String() newLen := max(param.Integer()-3, 0) @@ -248,7 +248,7 @@ func filterTruncatecharsHTML(in *Value, param *Value) (*Value, *Error) { return AsSafeValue(newOutput.String()), nil } -func filterTruncatewords(in *Value, param *Value) (*Value, *Error) { +func filterTruncatewords(in *Value, param *Value, bind map[string]any) (*Value, *Error) { words := strings.Fields(in.String()) n := param.Integer() if n <= 0 { @@ -267,7 +267,7 @@ func filterTruncatewords(in *Value, param *Value) (*Value, *Error) { return AsValue(strings.Join(out, " ")), nil } -func filterTruncatewordsHTML(in *Value, param *Value) (*Value, *Error) { +func filterTruncatewordsHTML(in *Value, param *Value, bind map[string]any) (*Value, *Error) { value := in.String() newLen := max(param.Integer(), 0) @@ -318,7 +318,7 @@ func filterTruncatewordsHTML(in *Value, param *Value) (*Value, *Error) { return AsSafeValue(newOutput.String()), nil } -func filterEscape(in *Value, param *Value) (*Value, *Error) { +func filterEscape(in *Value, param *Value, bind map[string]any) (*Value, *Error) { output := strings.Replace(in.String(), "&", "&", -1) output = strings.Replace(output, ">", ">", -1) output = strings.Replace(output, "<", "<", -1) @@ -327,11 +327,11 @@ func filterEscape(in *Value, param *Value) (*Value, *Error) { return AsValue(output), nil } -func filterSafe(in *Value, param *Value) (*Value, *Error) { +func filterSafe(in *Value, param *Value, bind map[string]any) (*Value, *Error) { return in, nil // nothing to do here, just to keep track of the safe application } -func filterEscapejs(in *Value, param *Value) (*Value, *Error) { +func filterEscapejs(in *Value, param *Value, bind map[string]any) (*Value, *Error) { sin := in.String() var b bytes.Buffer @@ -380,7 +380,7 @@ func filterEscapejs(in *Value, param *Value) (*Value, *Error) { return AsValue(b.String()), nil } -func filterAdd(in *Value, param *Value) (*Value, *Error) { +func filterAdd(in *Value, param *Value, bind map[string]any) (*Value, *Error) { if in.IsNumber() && param.IsNumber() { if in.IsFloat() || param.IsFloat() { return AsValue(in.Float() + param.Float()), nil @@ -392,47 +392,47 @@ func filterAdd(in *Value, param *Value) (*Value, *Error) { return AsValue(in.String() + param.String()), nil } -func filterAddslashes(in *Value, param *Value) (*Value, *Error) { +func filterAddslashes(in *Value, param *Value, bind map[string]any) (*Value, *Error) { output := strings.Replace(in.String(), "\\", "\\\\", -1) output = strings.Replace(output, "\"", "\\\"", -1) output = strings.Replace(output, "'", "\\'", -1) return AsValue(output), nil } -func filterCut(in *Value, param *Value) (*Value, *Error) { +func filterCut(in *Value, param *Value, bind map[string]any) (*Value, *Error) { return AsValue(strings.Replace(in.String(), param.String(), "", -1)), nil } -func filterLength(in *Value, param *Value) (*Value, *Error) { +func filterLength(in *Value, param *Value, bind map[string]any) (*Value, *Error) { return AsValue(in.Len()), nil } -func filterLengthis(in *Value, param *Value) (*Value, *Error) { +func filterLengthis(in *Value, param *Value, bind map[string]any) (*Value, *Error) { return AsValue(in.Len() == param.Integer()), nil } -func filterDefault(in *Value, param *Value) (*Value, *Error) { +func filterDefault(in *Value, param *Value, bind map[string]any) (*Value, *Error) { if !in.IsTrue() { return param, nil } return in, nil } -func filterDefaultIfNone(in *Value, param *Value) (*Value, *Error) { +func filterDefaultIfNone(in *Value, param *Value, bind map[string]any) (*Value, *Error) { if in.IsNil() { return param, nil } return in, nil } -func filterDivisibleby(in *Value, param *Value) (*Value, *Error) { +func filterDivisibleby(in *Value, param *Value, bind map[string]any) (*Value, *Error) { if param.Integer() == 0 { return AsValue(false), nil } return AsValue(in.Integer()%param.Integer() == 0), nil } -func filterFirst(in *Value, param *Value) (*Value, *Error) { +func filterFirst(in *Value, param *Value, bind map[string]any) (*Value, *Error) { if in.CanSlice() && in.Len() > 0 { return in.Index(0), nil } @@ -441,7 +441,7 @@ func filterFirst(in *Value, param *Value) (*Value, *Error) { const maxFloatFormatDecimals = 1000 -func filterFloatformat(in *Value, param *Value) (*Value, *Error) { +func filterFloatformat(in *Value, param *Value, bind map[string]any) (*Value, *Error) { val := in.Float() decimals := -1 @@ -478,7 +478,7 @@ func filterFloatformat(in *Value, param *Value) (*Value, *Error) { return AsValue(strconv.FormatFloat(val, 'f', decimals, 64)), nil } -func filterGetdigit(in *Value, param *Value) (*Value, *Error) { +func filterGetdigit(in *Value, param *Value, bind map[string]any) (*Value, *Error) { i := param.Integer() l := len(in.String()) // do NOT use in.Len() here! if i <= 0 || i > l { @@ -489,7 +489,7 @@ func filterGetdigit(in *Value, param *Value) (*Value, *Error) { const filterIRIChars = "/#%[]=:;$&()+,!?*@'~" -func filterIriencode(in *Value, param *Value) (*Value, *Error) { +func filterIriencode(in *Value, param *Value, bind map[string]any) (*Value, *Error) { var b bytes.Buffer sin := in.String() @@ -504,7 +504,7 @@ func filterIriencode(in *Value, param *Value) (*Value, *Error) { return AsValue(b.String()), nil } -func filterJoin(in *Value, param *Value) (*Value, *Error) { +func filterJoin(in *Value, param *Value, bind map[string]any) (*Value, *Error) { if !in.CanSlice() { return in, nil } @@ -532,22 +532,22 @@ func filterJoin(in *Value, param *Value) (*Value, *Error) { return AsValue(strings.Join(sl, sep)), nil } -func filterLast(in *Value, param *Value) (*Value, *Error) { +func filterLast(in *Value, param *Value, bind map[string]any) (*Value, *Error) { if in.CanSlice() && in.Len() > 0 { return in.Index(in.Len() - 1), nil } return AsValue(""), nil } -func filterUpper(in *Value, param *Value) (*Value, *Error) { +func filterUpper(in *Value, param *Value, bind map[string]any) (*Value, *Error) { return AsValue(strings.ToUpper(in.String())), nil } -func filterLower(in *Value, param *Value) (*Value, *Error) { +func filterLower(in *Value, param *Value, bind map[string]any) (*Value, *Error) { return AsValue(strings.ToLower(in.String())), nil } -func filterMakelist(in *Value, param *Value) (*Value, *Error) { +func filterMakelist(in *Value, param *Value, bind map[string]any) (*Value, *Error) { s := in.String() result := make([]string, 0, len(s)) for _, c := range s { @@ -556,7 +556,7 @@ func filterMakelist(in *Value, param *Value) (*Value, *Error) { return AsValue(result), nil } -func filterCapfirst(in *Value, param *Value) (*Value, *Error) { +func filterCapfirst(in *Value, param *Value, bind map[string]any) (*Value, *Error) { if in.Len() <= 0 { return AsValue(""), nil } @@ -567,7 +567,7 @@ func filterCapfirst(in *Value, param *Value) (*Value, *Error) { const maxCharPadding = 10000 -func filterCenter(in *Value, param *Value) (*Value, *Error) { +func filterCenter(in *Value, param *Value, bind map[string]any) (*Value, *Error) { width := param.Integer() slen := in.Len() if width <= slen { @@ -590,7 +590,7 @@ func filterCenter(in *Value, param *Value) (*Value, *Error) { in.String(), strings.Repeat(" ", right))), nil } -func filterDate(in *Value, param *Value) (*Value, *Error) { +func filterDate(in *Value, param *Value, bind map[string]any) (*Value, *Error) { t, isTime := in.Interface().(time.Time) if !isTime { return nil, &Error{ @@ -601,15 +601,15 @@ func filterDate(in *Value, param *Value) (*Value, *Error) { return AsValue(t.Format(param.String())), nil } -func filterFloat(in *Value, param *Value) (*Value, *Error) { +func filterFloat(in *Value, param *Value, bind map[string]any) (*Value, *Error) { return AsValue(in.Float()), nil } -func filterInteger(in *Value, param *Value) (*Value, *Error) { +func filterInteger(in *Value, param *Value, bind map[string]any) (*Value, *Error) { return AsValue(in.Integer()), nil } -func filterLinebreaks(in *Value, param *Value) (*Value, *Error) { +func filterLinebreaks(in *Value, param *Value, bind map[string]any) (*Value, *Error) { if in.Len() == 0 { return in, nil } @@ -653,17 +653,17 @@ func filterLinebreaks(in *Value, param *Value) (*Value, *Error) { return AsValue(b.String()), nil } -func filterSplit(in *Value, param *Value) (*Value, *Error) { +func filterSplit(in *Value, param *Value, bind map[string]any) (*Value, *Error) { chunks := strings.Split(in.String(), param.String()) return AsValue(chunks), nil } -func filterLinebreaksbr(in *Value, param *Value) (*Value, *Error) { +func filterLinebreaksbr(in *Value, param *Value, bind map[string]any) (*Value, *Error) { return AsValue(strings.Replace(in.String(), "\n", "
", -1)), nil } -func filterLinenumbers(in *Value, param *Value) (*Value, *Error) { +func filterLinenumbers(in *Value, param *Value, bind map[string]any) (*Value, *Error) { lines := strings.Split(in.String(), "\n") output := make([]string, 0, len(lines)) for idx, line := range lines { @@ -672,7 +672,7 @@ func filterLinenumbers(in *Value, param *Value) (*Value, *Error) { return AsValue(strings.Join(output, "\n")), nil } -func filterLjust(in *Value, param *Value) (*Value, *Error) { +func filterLjust(in *Value, param *Value, bind map[string]any) (*Value, *Error) { times := param.Integer() - in.Len() if times < 0 { times = 0 @@ -686,7 +686,7 @@ func filterLjust(in *Value, param *Value) (*Value, *Error) { return AsValue(fmt.Sprintf("%s%s", in.String(), strings.Repeat(" ", times))), nil } -func filterUrlencode(in *Value, param *Value) (*Value, *Error) { +func filterUrlencode(in *Value, param *Value, bind map[string]any) (*Value, *Error) { return AsValue(url.QueryEscape(in.String())), nil } @@ -710,7 +710,7 @@ func filterUrlizeHelper(input string, autoescape bool, trunc int) (string, error raw_url = strings.TrimSpace(raw_url) - t, err := ApplyFilter("iriencode", AsValue(raw_url), nil) + t, err := ApplyFilter("iriencode", AsValue(raw_url), nil, nil) if err != nil { soutErr = err return "" @@ -728,7 +728,7 @@ func filterUrlizeHelper(input string, autoescape bool, trunc int) (string, error } if autoescape { - t, err := ApplyFilter("escape", AsValue(title), nil) + t, err := ApplyFilter("escape", AsValue(title), nil, nil) if err != nil { soutErr = err return "" @@ -755,7 +755,7 @@ func filterUrlizeHelper(input string, autoescape bool, trunc int) (string, error return sout, nil } -func filterUrlize(in *Value, param *Value) (*Value, *Error) { +func filterUrlize(in *Value, param *Value, bind map[string]any) (*Value, *Error) { autoescape := true if param.IsBool() { autoescape = param.Bool() @@ -772,7 +772,7 @@ func filterUrlize(in *Value, param *Value) (*Value, *Error) { return AsValue(s), nil } -func filterUrlizetrunc(in *Value, param *Value) (*Value, *Error) { +func filterUrlizetrunc(in *Value, param *Value, bind map[string]any) (*Value, *Error) { s, err := filterUrlizeHelper(in.String(), true, param.Integer()) if err != nil { return nil, &Error{ @@ -783,13 +783,13 @@ func filterUrlizetrunc(in *Value, param *Value) (*Value, *Error) { return AsValue(s), nil } -func filterStringformat(in *Value, param *Value) (*Value, *Error) { +func filterStringformat(in *Value, param *Value, bind map[string]any) (*Value, *Error) { return AsValue(fmt.Sprintf(param.String(), in.Interface())), nil } var reStriptags = regexp.MustCompile("<[^>]*?>") -func filterStriptags(in *Value, param *Value) (*Value, *Error) { +func filterStriptags(in *Value, param *Value, bind map[string]any) (*Value, *Error) { s := in.String() // Strip all tags @@ -805,7 +805,7 @@ var filterPhone2numericMap = map[string]string{ "w": "9", "x": "9", "y": "9", "z": "9", } -func filterPhone2numeric(in *Value, param *Value) (*Value, *Error) { +func filterPhone2numeric(in *Value, param *Value, bind map[string]any) (*Value, *Error) { sin := in.String() for k, v := range filterPhone2numericMap { sin = strings.Replace(sin, k, v, -1) @@ -814,7 +814,7 @@ func filterPhone2numeric(in *Value, param *Value) (*Value, *Error) { return AsValue(sin), nil } -func filterPluralize(in *Value, param *Value) (*Value, *Error) { +func filterPluralize(in *Value, param *Value, bind map[string]any) (*Value, *Error) { if in.IsNumber() { // Works only on numbers if param.Len() > 0 { @@ -852,7 +852,7 @@ func filterPluralize(in *Value, param *Value) (*Value, *Error) { } } -func filterRandom(in *Value, param *Value) (*Value, *Error) { +func filterRandom(in *Value, param *Value, bind map[string]any) (*Value, *Error) { if !in.CanSlice() || in.Len() <= 0 { return in, nil } @@ -862,7 +862,7 @@ func filterRandom(in *Value, param *Value) (*Value, *Error) { var reTag = regexp.MustCompile(`^[a-zA-Z]$`) -func filterRemovetags(in *Value, param *Value) (*Value, *Error) { +func filterRemovetags(in *Value, param *Value, bind map[string]any) (*Value, *Error) { s := in.String() tags := strings.Split(param.String(), ",") @@ -888,7 +888,7 @@ func filterRemovetags(in *Value, param *Value) (*Value, *Error) { return AsValue(strings.TrimSpace(s)), nil } -func filterRjust(in *Value, param *Value) (*Value, *Error) { +func filterRjust(in *Value, param *Value, bind map[string]any) (*Value, *Error) { padding := param.Integer() if padding > maxCharPadding { return nil, &Error{ @@ -899,7 +899,7 @@ func filterRjust(in *Value, param *Value) (*Value, *Error) { return AsValue(fmt.Sprintf(fmt.Sprintf("%%%ds", padding), in.String())), nil } -func filterSlice(in *Value, param *Value) (*Value, *Error) { +func filterSlice(in *Value, param *Value, bind map[string]any) (*Value, *Error) { comp := strings.Split(param.String(), ":") if len(comp) != 2 { return nil, &Error{ @@ -950,18 +950,18 @@ func filterSlice(in *Value, param *Value) (*Value, *Error) { return in.Slice(from, to), nil } -func filterTitle(in *Value, param *Value) (*Value, *Error) { +func filterTitle(in *Value, param *Value, bind map[string]any) (*Value, *Error) { if !in.IsString() { return AsValue(""), nil } return AsValue(strings.Title(strings.ToLower(in.String()))), nil } -func filterWordcount(in *Value, param *Value) (*Value, *Error) { +func filterWordcount(in *Value, param *Value, bind map[string]any) (*Value, *Error) { return AsValue(len(strings.Fields(in.String()))), nil } -func filterWordwrap(in *Value, param *Value) (*Value, *Error) { +func filterWordwrap(in *Value, param *Value, bind map[string]any) (*Value, *Error) { words := strings.Fields(in.String()) wordsLen := len(words) wrapAt := param.Integer() @@ -980,7 +980,7 @@ func filterWordwrap(in *Value, param *Value) (*Value, *Error) { return AsValue(strings.Join(lines, "\n")), nil } -func filterYesno(in *Value, param *Value) (*Value, *Error) { +func filterYesno(in *Value, param *Value, bind map[string]any) (*Value, *Error) { choices := map[int]string{ 0: "yes", 1: "no", diff --git a/tags_filter.go b/tags_filter.go index b38fd92..a72ef95 100644 --- a/tags_filter.go +++ b/tags_filter.go @@ -35,7 +35,7 @@ func (node *tagFilterNode) Execute(ctx *ExecutionContext, writer TemplateWriter) } else { param = AsValue(nil) } - value, err = ApplyFilter(call.name, value, param) + value, err = ApplyFilter(call.name, value, param, ctx.Public) if err != nil { return ctx.Error(err.Error(), node.position) } diff --git a/tags_firstof.go b/tags_firstof.go index 5b2888e..deebfbe 100644 --- a/tags_firstof.go +++ b/tags_firstof.go @@ -14,7 +14,7 @@ func (node *tagFirstofNode) Execute(ctx *ExecutionContext, writer TemplateWriter if val.IsTrue() { if ctx.Autoescape && !arg.FilterApplied("safe") { - val, err = ApplyFilter("escape", val, nil) + val, err = ApplyFilter("escape", val, nil, ctx.Public) if err != nil { return err } diff --git a/variable.go b/variable.go index 51c30f5..3584892 100644 --- a/variable.go +++ b/variable.go @@ -220,7 +220,7 @@ func (nv *nodeVariable) Execute(ctx *ExecutionContext, writer TemplateWriter) *E } fn, _ := storedValue.(FilterFunction) - value, err = fn(value, nil) + value, err = fn(value, nil, ctx.Public) if err != nil { return err }