Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: safe funcs, follow go template standards and sprout conventions #65

Merged
merged 43 commits into from
Sep 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
bcf119b
chore(pesticide): simplify the must used test case
42atomys Aug 23, 2024
05868f9
docs: add all register functions to _example
42atomys Aug 23, 2024
6bd44d6
chore: conversion package now respect functions convention
42atomys Aug 23, 2024
5726aa8
chore: create deprecated package
42atomys Aug 28, 2024
58ad523
feat: create errors helpers
42atomys Aug 28, 2024
e629e42
chore: migrate encoding registry
42atomys Aug 28, 2024
16d7202
chore: migrate env registry
42atomys Aug 28, 2024
478373e
chore: migrate filesystem registry
42atomys Aug 28, 2024
cbf20f5
chore: migrate map registry and separate deprecated signature
42atomys Aug 28, 2024
80a7c6a
chore: migrate numeric registry
42atomys Aug 28, 2024
01ea63c
chore: migrate random registry
42atomys Aug 28, 2024
b46df8b
chore: migrate reflect registry
42atomys Aug 28, 2024
de41b57
(wip) not migrated packages yet
42atomys Aug 28, 2024
4b3b935
chore: migrate maps registry
42atomys Sep 1, 2024
5b1e374
chore: migrate slices registry
42atomys Sep 1, 2024
fbeee42
chore: migrate std registry
42atomys Sep 1, 2024
65a68b2
chore: migrate strings registry
42atomys Sep 1, 2024
95cbbb3
chore: migrate time registry
42atomys Sep 1, 2024
64029bb
chore: various fixes
42atomys Sep 1, 2024
1baa6d5
chore: move safe call in an internal package
42atomys Sep 1, 2024
8cabea0
fix: resolve invalid compare template
42atomys Sep 1, 2024
b9f7b71
chore: drop pesticide safe test
42atomys Sep 1, 2024
bec98d0
fix(backward): sprigin needs to still align with sprig no error
42atomys Sep 1, 2024
e5a2539
Merge branch 'main' into chore/follow-conventions
42atomys Sep 1, 2024
dcc451a
fix: resolve function signature for hello test
42atomys Sep 1, 2024
804a164
chore: remove reaming panic in crypto and backward package
42atomys Sep 1, 2024
6c9e03b
chore: drop useless function error
42atomys Sep 2, 2024
3bbf7b5
feat: add safe funcs
42atomys Sep 2, 2024
14b9c54
fix: resolve issue with new error handling on time registry
42atomys Sep 2, 2024
270cae4
chore: somes clean
42atomys Sep 2, 2024
c710793
doc: init new page
42atomys Sep 2, 2024
8521819
chore: fix all linting issue with testifylint
42atomys Sep 4, 2024
1a00d0e
chore: integrate review suggestion
42atomys Sep 4, 2024
16438bc
chore: integrate golangci yaml config file and run all linters
42atomys Sep 4, 2024
dcd43ac
chore(ci): add golangci-linter and run a fix
42atomys Sep 4, 2024
0ec5552
chore: support 1.23 go version
42atomys Sep 4, 2024
d49eeba
fix(ci): prevent linter to crash
42atomys Sep 4, 2024
7623dc6
chore: rename jobs and steps
42atomys Sep 4, 2024
ed15ded
chore: enable linters only on pull request
42atomys Sep 4, 2024
bcfa9e2
chore: do somes reviews fixes
42atomys Sep 5, 2024
b5d4858
chore: increase robustness of safe call
42atomys Sep 5, 2024
2b05434
fix: remove invalid line on example registry
42atomys Sep 7, 2024
ef3a656
chore: implement somes proposal from reviews
42atomys Sep 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
on: [pull_request]
name: Linters
permissions:
# Required: allow read access to the content for analysis.
contents: read
pull-requests: read
# Allow write access to checks to allow the action to annotate code in the PR.
checks: write
jobs:
lint:
name: Golang CI Lint
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: stable
- name: Install testifylint
run: go install github.com/Antonboom/testifylint@v1.4.0
- name: golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: v1.60
4 changes: 2 additions & 2 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
on: [push, pull_request]
on: [push]
name: Tests
jobs:
test:
strategy:
matrix:
go-version: [1.21.x, 1.22.x]
go-version: [1.21.x, 1.22.x, 1.23.x]
platform: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.platform }}
steps:
Expand Down
47 changes: 47 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
# Thanks to @ccoVeille for the configuration template from
# https://github.com/ccoVeille/golangci-lint-config-examples
linters:
enable:
- errorlint
- gci
- gocritic
- gofumpt
- gosimple
- govet
- ineffassign
- staticcheck
- misspell
- testifylint
- errcheck
- thelper
- mirror
- usestdlibvars

linters-settings:
gofumpt:
module-path: github.com/go-sprout/sprout
misspell:
ignore-words:
- "nto" # Used in the codebase in format "\nto" (as a newline)
gci:
sections:
- standard
- default
- prefix(github.com/go-sprout)
testifylint:
enable:
- float-compare
- go-require
- bool-compare
- compares
- empty
- error-is-as
- error-nil
- expected-actual
- len
- require-error
- suite-dont-use-pkg
- suite-extra-assert-call
run:
timeout: 5m
9 changes: 5 additions & 4 deletions alias_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

// TestWithAlias checks that aliases are correctly added to a function.
Expand Down Expand Up @@ -78,8 +79,8 @@ func TestRegisterAliases(t *testing.T) {
AssignAliases(handler)

// Check that the aliases are mapped to the same function as the original function in funcsRegistry.
assert.True(t, reflect.ValueOf(handler.cachedFuncsMap[originalFunc]).Pointer() == reflect.ValueOf(handler.cachedFuncsMap[alias1]).Pointer())
assert.True(t, reflect.ValueOf(handler.cachedFuncsMap[originalFunc]).Pointer() == reflect.ValueOf(handler.cachedFuncsMap[alias2]).Pointer())
assert.Equal(t, reflect.ValueOf(handler.cachedFuncsMap[originalFunc]).Pointer(), reflect.ValueOf(handler.cachedFuncsMap[alias1]).Pointer())
assert.Equal(t, reflect.ValueOf(handler.cachedFuncsMap[originalFunc]).Pointer(), reflect.ValueOf(handler.cachedFuncsMap[alias2]).Pointer())
}

func TestAliasesInTemplate(t *testing.T) {
Expand All @@ -97,10 +98,10 @@ func TestAliasesInTemplate(t *testing.T) {

// Create a template with the aliases.
tmpl, err := template.New("test").Funcs(handler.Build()).Parse(`{{originalFunc}} {{alias1}} {{alias2}}`)
assert.NoError(t, err)
require.NoError(t, err)

var buf bytes.Buffer
err = tmpl.ExecuteTemplate(&buf, "test", nil)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, "cheese cheese cheese", buf.String())
}
2 changes: 1 addition & 1 deletion benchmarks/allFunctions.sprig.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
{{$v := toString .int }}{{typeOf $v}}-{{$v}}
{{$v := toString .float }}{{typeOf $v}}-{{$v}}
{{$v := toString .bool }}{{typeOf $v}}-{{$v}}
{{$v := toString .objectrray }}{{typeOf $v}}-{{$v}}
{{$v := toString .array }}{{typeOf $v}}-{{$v}}
{{$v := toString .time }}{{typeOf $v}}-{{$v}}
{{$v := toString .duration }}{{typeOf $v}}-{{$v}}
{{$v := toString .object }}{{typeOf $v}}-{{$v}}
Expand Down
44 changes: 19 additions & 25 deletions benchmarks/allFunctions.sprout.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -13,44 +13,40 @@
{{md5sum ""}}
{{md5sum "a"}}
{{md5sum "hello world"}}
{{$v := toBool .string }}{{kindOf $v}}-{{$v}}
{{$v := toBool .intString }}{{kindOf $v}}-{{$v}}
{{$v := toBool .int }}{{kindOf $v}}-{{$v}}
{{$v := toBool .float }}{{kindOf $v}}-{{$v}}
{{$v := toBool .bool }}{{kindOf $v}}-{{$v}}
{{$v := toBool .objectrray }}{{kindOf $v}}-{{$v}}
{{$v := toInt .string }}{{kindOf $v}}-{{$v}}
{{$v := toInt .intString }}{{kindOf $v}}-{{$v}}
{{$v := toInt .float }}{{kindOf $v}}-{{$v}}
{{$v := toInt .bool }}{{kindOf $v}}-{{$v}}
{{$v := toInt64 .string }}{{typeOf $v}}-{{$v}}
{{$v := toInt64 .intString }}{{typeOf $v}}-{{$v}}
{{$v := toInt64 .float }}{{typeOf $v}}-{{$v}}
{{$v := toInt64 .int }}{{typeOf $v}}-{{$v}}
{{$v := toInt64 .bool }}{{typeOf $v}}-{{$v}}
{{$v := toUint .string }}{{kindOf $v}}-{{$v}}
{{$v := toUint .intString }}{{kindOf $v}}-{{$v}}
{{$v := toUint .float }}{{kindOf $v}}-{{$v}}
{{$v := toUint .int }}{{kindOf $v}}-{{$v}}
{{$v := toUint .bool }}{{kindOf $v}}-{{$v}}
{{$v := toUint64 .string }}{{typeOf $v}}-{{$v}}
{{$v := toUint64 .intString }}{{typeOf $v}}-{{$v}}
{{$v := toUint64 .float }}{{typeOf $v}}-{{$v}}
{{$v := toUint64 .int }}{{typeOf $v}}-{{$v}}
{{$v := toUint64 .bool }}{{typeOf $v}}-{{$v}}
{{$v := toFloat64 .string }}{{typeOf $v}}-{{$v}}
{{$v := toFloat64 .intString }}{{typeOf $v}}-{{$v}}
{{$v := toFloat64 .float }}{{typeOf $v}}-{{$v}}
{{$v := toFloat64 .int }}{{typeOf $v}}-{{$v}}
{{$v := toFloat64 .bool }}{{typeOf $v}}-{{$v}}
{{$v := toOctal .string }}{{typeOf $v}}-{{$v}}
{{$v := toOctal .float }}{{typeOf $v}}-{{$v}}
{{$v := toOctal .intString }}{{typeOf $v}}-{{$v}}
{{$v := toOctal .int }}{{typeOf $v}}-{{$v}}
{{$v := toOctal .bool }}{{typeOf $v}}-{{$v}}
{{$v := toString .string }}{{typeOf $v}}-{{$v}}
{{$v := toString .int }}{{typeOf $v}}-{{$v}}
{{$v := toString .float }}{{typeOf $v}}-{{$v}}
{{$v := toString .bool }}{{typeOf $v}}-{{$v}}
{{$v := toString .objectrray }}{{typeOf $v}}-{{$v}}
{{$v := toString .array }}{{typeOf $v}}-{{$v}}
{{$v := toString .time }}{{typeOf $v}}-{{$v}}
{{$v := toString .duration }}{{typeOf $v}}-{{$v}}
{{$v := toString .object }}{{typeOf $v}}-{{$v}}
{{$v := toDate "2006-01-02" (.time | toString) }}{{typeOf $v}}-{{$v}}
{{$v := toDuration .time }}{{typeOf $v}}-{{$v}}
{{$v := .time | toString | splitList " " | initial | join " " | toDate "2006-01-02 15:04:05.999999999 -0700 MST" }}{{typeOf $v}}-{{$v}}
{{$v := toDuration .int }}{{typeOf $v}}-{{$v}}
{{$v := toDuration .float }}{{typeOf $v}}-{{$v}}
{{$v := toDuration .duration }}{{typeOf $v}}-{{$v}}
Expand All @@ -59,13 +55,12 @@
{{ "Hello World" | base64Encode }}
{{ "=" | base64Encode }}
{{ "" | base64Decode }}
{{ "SGVsbG8gV29ybGQ" | base64Decode }}
{{ "SGVsbG8gV29ybGQ=" | base64Decode }}
{{ "" | base32Encode }}
{{ "Hello World" | base32Encode }}
{{ "" | base32Decode }}
{{ "JBSWY3DPEBLW64TMMQ======" | base32Decode }}
{{ "JBSWY3DPEBLW64TMMQ" | base32Decode }}
{{ "" | fromJson }}
{{ "" | safeFromJson }}
{{ .json | fromJson }}
{{ (.json | fromJson).foo }}
{{ "" | toJson }}
Expand Down Expand Up @@ -251,11 +246,11 @@
{{- $d := dict "a" 1 "b" 2 | deepCopy }}{{ keys $d | sortAlpha | join "," }}
{{- $one := dict "foo" (dict "bar" "baz") "qux" true -}}{{ deepCopy $one }}
{{ regexFind "a(b+)" "aaabbb" }}
{{ regexFind "a(b+" "aaabbb" }}
{{ safeRegexFind "a(b+" "aaabbb" }}
{{ regexFindAll "a(b+)" "aaabbb" -1 }}
{{ regexFindAll "a{2}" "aaaabbb" -1 }}
{{ regexFindAll "a{2}" "none" -1 }}
{{ regexFindAll "a(b+" "aaabbb" -1 }}
{{ safeRegexFindAll "a(b+" "aaabbb" -1 }}
{{ regexMatch "^[a-zA-Z]+$" "Hello" }}
{{ regexMatch "^[a-zA-Z]+$" "Hello123" }}
{{ regexMatch "^[a-zA-Z]+$" "123" }}
Expand Down Expand Up @@ -323,11 +318,10 @@
{{ slice .array 1 }}
{{ slice .array 1 3 }}
{{ slice .array 0 1 }}
{{ .map | has "foo" }}
{{ .map | has "a" }}
{{ .map | has 1 }}
{{ .map | has .nil }}
{{ .map | has "nope" }}
{{ .map | safeHas "foo" }}
{{ .map | safeHas "a" }}
{{ .map | safeHas 1 }}
{{ .map | safeHas .nil }}
{{ without .array "a" }}
{{ rest .array }}
{{ initial .array }}
Expand Down Expand Up @@ -649,7 +643,7 @@
{{ dateInZone "02 Jan 06 15:04 -0700" .data272 "UTC" }}
{{ dateInZone "02 Jan 06 15:04 -0700" .data273 "UTC" }}
{{ dateInZone "02 Jan 06 15:04 -0700" .data274 "UTC" }}
{{ dateInZone "02 Jan 06 15:04 -0700" .data275 "invalid" }}
{{ safeDateInZone "02 Jan 06 15:04 -0700" .data275 "invalid" }}
{{ .duration | duration }}
{{ .time | dateAgo | substr 0 5 }}
{{ now | date "02 Jan 06 15:04 -0700" }}
Expand All @@ -659,7 +653,7 @@
{{ .time | dateModify "-1h" | date "02 Jan 06 15:04 -0700" }}
{{ .time | dateModify "10m" | date "02 Jan 06 15:04 -0700" }}
{{ .time | dateModify "-10s" | date "02 Jan 06 15:04 -0700" }}
{{ .time | dateModify "zz" | date "02 Jan 06 15:04 -0700" }}
{{ .time | safeDateModify "zz" | date "02 Jan 06 15:04 -0700" }}
{{ .duration | durationRound }}
{{ .time | htmlDate }}
{{ htmlDateInZone .time "UTC" }}
Expand Down
35 changes: 17 additions & 18 deletions benchmarks/allFunctionsAsSprig.sprout.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -10,41 +10,40 @@
{{adler32sum ""}}
{{adler32sum "a"}}
{{adler32sum "hello world"}}
{{$v := toInt .string }}{{kindOf $v}}-{{$v}}
{{$v := toInt .intString }}{{kindOf $v}}-{{$v}}
{{$v := toInt .float }}{{kindOf $v}}-{{$v}}
{{$v := toInt .bool }}{{kindOf $v}}-{{$v}}
{{$v := toInt64 .string }}{{typeOf $v}}-{{$v}}
{{$v := toInt64 .intString }}{{typeOf $v}}-{{$v}}
{{$v := toInt64 .float }}{{typeOf $v}}-{{$v}}
{{$v := toInt64 .int }}{{typeOf $v}}-{{$v}}
{{$v := toInt64 .bool }}{{typeOf $v}}-{{$v}}
{{$v := toFloat64 .string }}{{typeOf $v}}-{{$v}}
{{$v := toFloat64 .intString }}{{typeOf $v}}-{{$v}}
{{$v := toFloat64 .float }}{{typeOf $v}}-{{$v}}
{{$v := toFloat64 .int }}{{typeOf $v}}-{{$v}}
{{$v := toFloat64 .bool }}{{typeOf $v}}-{{$v}}
{{$v := toOctal .string }}{{typeOf $v}}-{{$v}}
{{$v := toOctal .float }}{{typeOf $v}}-{{$v}}
{{$v := toOctal .intString }}{{typeOf $v}}-{{$v}}
{{$v := safeToOctal .float }}{{typeOf $v}}-{{$v}}
{{$v := toOctal .int }}{{typeOf $v}}-{{$v}}
{{$v := toOctal .bool }}{{typeOf $v}}-{{$v}}
{{$v := safeToOctal .bool }}{{typeOf $v}}-{{$v}}
{{$v := toString .string }}{{typeOf $v}}-{{$v}}
{{$v := toString .int }}{{typeOf $v}}-{{$v}}
{{$v := toString .float }}{{typeOf $v}}-{{$v}}
{{$v := toString .bool }}{{typeOf $v}}-{{$v}}
{{$v := toString .objectrray }}{{typeOf $v}}-{{$v}}
{{$v := toString .array }}{{typeOf $v}}-{{$v}}
{{$v := toString .time }}{{typeOf $v}}-{{$v}}
{{$v := toString .duration }}{{typeOf $v}}-{{$v}}
{{$v := toString .object }}{{typeOf $v}}-{{$v}}
{{$v := toDate "2006-01-02" (.time | toString) }}{{typeOf $v}}-{{$v}}
{{$v := .time | toString | splitList " " | initial | join " " | toDate "2006-01-02 15:04:05.999999999 -0700 MST" }}{{typeOf $v}}-{{$v}}
{{ "" | base64Encode }}
{{ "Hello World" | base64Encode }}
{{ "=" | base64Encode }}
{{ "" | base64Decode }}
{{ "SGVsbG8gV29ybGQ" | base64Decode }}
{{ "SGVsbG8gV29ybGQ=" | base64Decode }}
{{ "" | base32Encode }}
{{ "Hello World" | base32Encode }}
{{ "" | base32Decode }}
{{ "JBSWY3DPEBLW64TMMQ======" | base32Decode }}
{{ "JBSWY3DPEBLW64TMMQ" | base32Decode }}
{{ "" | fromJson }}
{{ "" | safeFromJson }}
{{ .json | fromJson }}
{{ (.json | fromJson).foo }}
{{ "" | toJson }}
Expand Down Expand Up @@ -292,11 +291,11 @@
{{ slice .array 1 }}
{{ slice .array 1 3 }}
{{ slice .array 0 1 }}
{{ .map | has "foo" }}
{{ .map | has "a" }}
{{ .map | has 1 }}
{{ .map | has .nil }}
{{ .map | has "nope" }}
{{ .map | safeHas "foo" }}
{{ .map | safeHas "a" }}
{{ .map | safeHas 1 }}
{{ .map | safeHas .nil }}
{{ .map | safeHas "nope" }}
{{ without .array "a" }}
{{ rest .array }}
{{ initial .array }}
Expand Down Expand Up @@ -591,7 +590,7 @@
{{ dateInZone "02 Jan 06 15:04 -0700" .data272 "UTC" }}
{{ dateInZone "02 Jan 06 15:04 -0700" .data273 "UTC" }}
{{ dateInZone "02 Jan 06 15:04 -0700" .data274 "UTC" }}
{{ dateInZone "02 Jan 06 15:04 -0700" .data275 "invalid" }}
{{ safeDateInZone "02 Jan 06 15:04 -0700" .data275 "invalid" }}
{{ .duration | duration }}
{{ .time | dateAgo | substr 0 5 }}
{{ now | date "02 Jan 06 15:04 -0700" }}
Expand All @@ -601,7 +600,7 @@
{{ .time | dateModify "-1h" | date "02 Jan 06 15:04 -0700" }}
{{ .time | dateModify "10m" | date "02 Jan 06 15:04 -0700" }}
{{ .time | dateModify "-10s" | date "02 Jan 06 15:04 -0700" }}
{{ .time | dateModify "zz" | date "02 Jan 06 15:04 -0700" }}
{{ .time | safeDateModify "zz" | date "02 Jan 06 15:04 -0700" }}
{{ .duration | durationRound }}
{{ .time | htmlDate }}
{{ htmlDateInZone .time "UTC" }}
Expand Down
4 changes: 3 additions & 1 deletion benchmarks/comparaison_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (

var data = map[string]any{
"string": "example string value",
"intString": "1",
"url": "https://example.com",
"arrayCommas": "a,b,c",
"int": 123,
Expand Down Expand Up @@ -92,7 +93,7 @@ func BenchmarkComparison(b *testing.B) {
func BenchmarkAllSprout(b *testing.B) {
runtime.GOMAXPROCS(1)

b.Run("SproutWiothNewFeatures", func(b *testing.B) {
b.Run("SproutWithNewFeatures", func(b *testing.B) {
for i := 0; i < b.N; i++ {
sproutBench("allFunctions.sprout.tmpl")
}
Expand Down Expand Up @@ -126,6 +127,7 @@ func sprigBench() {
func sproutBench(templatePath string) {
fnHandler := sprout.New(
sprout.WithLogger(slog.New(&noopHandler{})),
sprout.WithSafeFuncs(true),
)

_ = fnHandler.AddRegistries(
Expand Down
21 changes: 10 additions & 11 deletions benchmarks/compare.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ this is because the output of the function is fixed in Sprout due to bugs not fi
[CODE_000041] {{$v := toString .int }}{{typeOf $v}}-{{$v}}
[CODE_000042] {{$v := toString .float }}{{typeOf $v}}-{{$v}}
[CODE_000043] {{$v := toString .bool }}{{typeOf $v}}-{{$v}}
[CODE_000044] {{$v := toString .objectrray }}{{typeOf $v}}-{{$v}}
[CODE_000044] {{$v := toString .array }}{{typeOf $v}}-{{$v}}
[CODE_000045] {{$v := toString .time }}{{typeOf $v}}-{{$v}}
[CODE_000046] {{$v := toString .duration }}{{typeOf $v}}-{{$v}}
[CODE_000047] {{$v := toString .object }}{{typeOf $v}}-{{$v}}
Expand Down Expand Up @@ -335,7 +335,7 @@ this is because the output of the function is fixed in Sprout due to bugs not fi
[CODE_000335] {{ .array | mustHas "foo" }}
[CODE_000336] {{ .array | mustHas "a" }}
[CODE_000337] {{ .array | mustHas 1 }}
[CODE_000338] {{ .array | mustHas .Nil }}
[CODE_000338] {{ .array | mustHas .nil }}
[CODE_000339] {{ .array | mustHas "nope" }}
[CODE_000340] {{ .array | mustHas 1 }}
[CODE_000341] {{ mustWithout .array "a" }}
Expand Down Expand Up @@ -609,12 +609,11 @@ this is because the output of the function is fixed in Sprout due to bugs not fi
[CODE_000609] {{ .time | dateModify "-1h" | date "02 Jan 06 15:04 -0700" }}
[CODE_000610] {{ .time | dateModify "10m" | date "02 Jan 06 15:04 -0700" }}
[CODE_000611] {{ .time | dateModify "-10s" | date "02 Jan 06 15:04 -0700" }}
[CODE_000612] {{ .time | dateModify "zz" | date "02 Jan 06 15:04 -0700" }}
[CODE_000613] {{ .duration | duration | durationRound }}
[CODE_000614] {{ .time | htmlDate }}
[CODE_000615] {{ htmlDateInZone .time "UTC" }}
[CODE_000616] {{ .time | mustDateModify "1h" | date "02 Jan 06 15:04 -0700" }}
[CODE_000617] {{ .time | mustDateModify "+1h" | date "02 Jan 06 15:04 -0700" }}
[CODE_000618] {{ .time | mustDateModify "-1h" | date "02 Jan 06 15:04 -0700" }}
[CODE_000619] {{ .time | mustDateModify "10m" | date "02 Jan 06 15:04 -0700" }}
[CODE_000620] {{ .time | mustDateModify "-10s" | date "02 Jan 06 15:04 -0700" }}
[CODE_000612] {{ .duration | duration | durationRound }}
[CODE_000613] {{ .time | htmlDate }}
[CODE_000614] {{ htmlDateInZone .time "UTC" }}
[CODE_000615] {{ .time | mustDateModify "1h" | date "02 Jan 06 15:04 -0700" }}
[CODE_000616] {{ .time | mustDateModify "+1h" | date "02 Jan 06 15:04 -0700" }}
[CODE_000617] {{ .time | mustDateModify "-1h" | date "02 Jan 06 15:04 -0700" }}
[CODE_000618] {{ .time | mustDateModify "10m" | date "02 Jan 06 15:04 -0700" }}
[CODE_000619] {{ .time | mustDateModify "-10s" | date "02 Jan 06 15:04 -0700" }}
Loading
Loading