mirror of
https://github.com/Luzifer/promcertcheck.git
synced 2024-11-09 16:30:04 +00:00
Update vendored libs
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
dd7d942f30
commit
ce6a18fbf3
1137 changed files with 37335 additions and 167090 deletions
76
Gopkg.lock
generated
76
Gopkg.lock
generated
|
@ -11,43 +11,37 @@
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/beorn7/perks"
|
name = "github.com/beorn7/perks"
|
||||||
packages = ["quantile"]
|
packages = ["quantile"]
|
||||||
revision = "4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9"
|
revision = "3a771d992973f24aa725d07868b467d1ddfceafb"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
|
||||||
name = "github.com/flosch/pongo2"
|
name = "github.com/flosch/pongo2"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "1f4be1efe3b3529b7e58861f75d70120a9567dc4"
|
revision = "5e81b817a0c48c1c57cdf1a9056cf76bdee02ca9"
|
||||||
|
version = "v3.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
|
||||||
name = "github.com/golang/protobuf"
|
name = "github.com/golang/protobuf"
|
||||||
packages = ["proto"]
|
packages = ["proto"]
|
||||||
revision = "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9"
|
revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265"
|
||||||
|
version = "v1.1.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/gorilla/context"
|
name = "github.com/gorilla/context"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "1ea25387ff6f684839d82767c1733ff4d4d15d0a"
|
revision = "08b5f424b9271eedf6f9f0ce86cb9396ed337a42"
|
||||||
version = "v1.1"
|
version = "v1.1.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/gorilla/mux"
|
name = "github.com/gorilla/mux"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "24fca303ac6da784b9e8269f724ddeb0b2eea5e7"
|
revision = "e3702bed27f0d39777b0b37b664b6280e8ef8fbf"
|
||||||
version = "v1.5.0"
|
version = "v1.6.2"
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/juju/errors"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "c7d06af17c68cd34c835053720b21f6549d9b0ee"
|
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/matttproud/golang_protobuf_extensions"
|
name = "github.com/matttproud/golang_protobuf_extensions"
|
||||||
packages = ["pbutil"]
|
packages = ["pbutil"]
|
||||||
revision = "3247c84500bff8d9fb6d579d800f20b3e091582c"
|
revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c"
|
||||||
version = "v1.0.0"
|
version = "v1.0.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/prometheus/client_golang"
|
name = "github.com/prometheus/client_golang"
|
||||||
|
@ -59,65 +53,77 @@
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/prometheus/client_model"
|
name = "github.com/prometheus/client_model"
|
||||||
packages = ["go"]
|
packages = ["go"]
|
||||||
revision = "6f3806018612930941127f2a7c6c453ba2c527d2"
|
revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/prometheus/common"
|
name = "github.com/prometheus/common"
|
||||||
packages = ["expfmt","internal/bitbucket.org/ww/goautoneg","model"]
|
packages = [
|
||||||
revision = "e3fb1a1acd7605367a2b378bc2e2f893c05174b7"
|
"expfmt",
|
||||||
|
"internal/bitbucket.org/ww/goautoneg",
|
||||||
|
"model"
|
||||||
|
]
|
||||||
|
revision = "7600349dcfe1abd18d72d3a1770870d9800a7801"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/prometheus/procfs"
|
name = "github.com/prometheus/procfs"
|
||||||
packages = [".","xfs"]
|
packages = [
|
||||||
revision = "a6e9df898b1336106c743392c48ee0b71f5c4efa"
|
".",
|
||||||
|
"internal/util",
|
||||||
|
"nfs",
|
||||||
|
"xfs"
|
||||||
|
]
|
||||||
|
revision = "94663424ae5ae9856b40a9f170762b4197024661"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/robfig/cron"
|
name = "github.com/robfig/cron"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "b024fc5ea0e34bc3f83d9941c8d60b0622bfaca4"
|
revision = "b41be1df696709bb6395fe435af20370037c0b4c"
|
||||||
version = "v1"
|
version = "v1.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/sirupsen/logrus"
|
name = "github.com/sirupsen/logrus"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "f006c2ac4710855cf0f916dd6b77acf6b048dc6e"
|
revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc"
|
||||||
version = "v1.0.3"
|
version = "v1.0.5"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/spf13/pflag"
|
name = "github.com/spf13/pflag"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66"
|
revision = "583c0c0531f06d5278b7d917446061adc344b5cd"
|
||||||
version = "v1.0.0"
|
version = "v1.0.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "golang.org/x/crypto"
|
name = "golang.org/x/crypto"
|
||||||
packages = ["ssh/terminal"]
|
packages = ["ssh/terminal"]
|
||||||
revision = "bd6f299fb381e4c3393d1c4b1f0b94f5e77650c8"
|
revision = "df8d4716b3472e4a531c33cedbe537dae921a1a9"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "golang.org/x/sys"
|
name = "golang.org/x/sys"
|
||||||
packages = ["unix","windows"]
|
packages = [
|
||||||
revision = "8eb05f94d449fdf134ec24630ce69ada5b469c1c"
|
"unix",
|
||||||
|
"windows"
|
||||||
|
]
|
||||||
|
revision = "c11f84a56e43e20a78cee75a7c034031ecf57d1f"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "v2"
|
branch = "v2"
|
||||||
name = "gopkg.in/validator.v2"
|
name = "gopkg.in/validator.v2"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "460c83432a98c35224a6fe352acf8b23e067ad06"
|
revision = "135c24b11c19e52befcae2ec3fca5d9b78c4e98e"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "v2"
|
|
||||||
name = "gopkg.in/yaml.v2"
|
name = "gopkg.in/yaml.v2"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "eb3733d160e74a9c7e442f435eb3bea458e1d19f"
|
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
|
||||||
|
version = "v2.2.1"
|
||||||
|
|
||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
inputs-digest = "f88f786b9ff5e99b5589aea171923fd8d9dcef123a4d6be68d7659b923e8dc1e"
|
inputs-digest = "9e9921ed070369ec5c66299d9403b1d7dd184332dbf7f7e36c5d1ff493b88216"
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
|
23
Gopkg.toml
23
Gopkg.toml
|
@ -1,7 +1,6 @@
|
||||||
|
|
||||||
# Gopkg.toml example
|
# Gopkg.toml example
|
||||||
#
|
#
|
||||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
|
||||||
# for detailed Gopkg.toml documentation.
|
# for detailed Gopkg.toml documentation.
|
||||||
#
|
#
|
||||||
# required = ["github.com/user/thing/cmd/thing"]
|
# required = ["github.com/user/thing/cmd/thing"]
|
||||||
|
@ -17,8 +16,13 @@
|
||||||
# source = "github.com/myfork/project2"
|
# source = "github.com/myfork/project2"
|
||||||
#
|
#
|
||||||
# [[override]]
|
# [[override]]
|
||||||
# name = "github.com/x/y"
|
# name = "github.com/x/y"
|
||||||
# version = "2.4.0"
|
# version = "2.4.0"
|
||||||
|
#
|
||||||
|
# [prune]
|
||||||
|
# non-go = false
|
||||||
|
# go-tests = true
|
||||||
|
# unused-packages = true
|
||||||
|
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
|
@ -27,17 +31,24 @@
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/flosch/pongo2"
|
name = "github.com/flosch/pongo2"
|
||||||
branch = "master"
|
version = "3.0.0"
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/gorilla/mux"
|
name = "github.com/gorilla/mux"
|
||||||
|
version = "1.6.2"
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/prometheus/client_golang"
|
name = "github.com/prometheus/client_golang"
|
||||||
|
version = "0.8.0"
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/robfig/cron"
|
name = "github.com/robfig/cron"
|
||||||
|
version = "1.1.0"
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/sirupsen/logrus"
|
name = "github.com/sirupsen/logrus"
|
||||||
version = "1.0.3"
|
version = "1.0.5"
|
||||||
|
|
||||||
|
[prune]
|
||||||
|
go-tests = true
|
||||||
|
unused-packages = true
|
||||||
|
|
70
vendor/github.com/Luzifer/rconfig/bool_test.go
generated
vendored
70
vendor/github.com/Luzifer/rconfig/bool_test.go
generated
vendored
|
@ -1,70 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Testing bool parsing", func() {
|
|
||||||
type t struct {
|
|
||||||
Test1 bool `default:"true"`
|
|
||||||
Test2 bool `default:"false" flag:"test2"`
|
|
||||||
Test3 bool `default:"true" flag:"test3,t"`
|
|
||||||
Test4 bool `flag:"test4"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
args []string
|
|
||||||
cfg t
|
|
||||||
)
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{
|
|
||||||
"--test2",
|
|
||||||
"-t",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.Test1).To(Equal(true))
|
|
||||||
Expect(cfg.Test2).To(Equal(true))
|
|
||||||
Expect(cfg.Test3).To(Equal(true))
|
|
||||||
Expect(cfg.Test4).To(Equal(false))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
var _ = Describe("Testing to set bool from ENV with default", func() {
|
|
||||||
type t struct {
|
|
||||||
Test1 bool `default:"true" env:"TEST1"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
args []string
|
|
||||||
cfg t
|
|
||||||
)
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
os.Unsetenv("TEST1")
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.Test1).To(Equal(true))
|
|
||||||
})
|
|
||||||
})
|
|
41
vendor/github.com/Luzifer/rconfig/duration_test.go
generated
vendored
41
vendor/github.com/Luzifer/rconfig/duration_test.go
generated
vendored
|
@ -1,41 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Duration", func() {
|
|
||||||
type t struct {
|
|
||||||
Test time.Duration `flag:"duration"`
|
|
||||||
TestS time.Duration `flag:"other-duration,o"`
|
|
||||||
TestDef time.Duration `default:"30h"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
args []string
|
|
||||||
cfg t
|
|
||||||
)
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{
|
|
||||||
"--duration=23s", "-o", "45m",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.Test).To(Equal(23 * time.Second))
|
|
||||||
Expect(cfg.TestS).To(Equal(45 * time.Minute))
|
|
||||||
|
|
||||||
Expect(cfg.TestDef).To(Equal(30 * time.Hour))
|
|
||||||
})
|
|
||||||
})
|
|
56
vendor/github.com/Luzifer/rconfig/errors_test.go
generated
vendored
56
vendor/github.com/Luzifer/rconfig/errors_test.go
generated
vendored
|
@ -1,56 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Testing errors", func() {
|
|
||||||
|
|
||||||
It("should not accept string as int", func() {
|
|
||||||
Expect(parse(&struct {
|
|
||||||
A int `default:"a"`
|
|
||||||
}{}, []string{})).To(HaveOccurred())
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not accept string as float", func() {
|
|
||||||
Expect(parse(&struct {
|
|
||||||
A float32 `default:"a"`
|
|
||||||
}{}, []string{})).To(HaveOccurred())
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not accept string as uint", func() {
|
|
||||||
Expect(parse(&struct {
|
|
||||||
A uint `default:"a"`
|
|
||||||
}{}, []string{})).To(HaveOccurred())
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not accept string as uint in sub-struct", func() {
|
|
||||||
Expect(parse(&struct {
|
|
||||||
B struct {
|
|
||||||
A uint `default:"a"`
|
|
||||||
}
|
|
||||||
}{}, []string{})).To(HaveOccurred())
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not accept string slice as int slice", func() {
|
|
||||||
Expect(parse(&struct {
|
|
||||||
A []int `default:"a,bn"`
|
|
||||||
}{}, []string{})).To(HaveOccurred())
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not accept variables not being pointers", func() {
|
|
||||||
cfg := struct {
|
|
||||||
A string `default:"a"`
|
|
||||||
}{}
|
|
||||||
|
|
||||||
Expect(parse(cfg, []string{})).To(HaveOccurred())
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not accept variables not being pointers to structs", func() {
|
|
||||||
cfg := "test"
|
|
||||||
|
|
||||||
Expect(parse(cfg, []string{})).To(HaveOccurred())
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
37
vendor/github.com/Luzifer/rconfig/example_test.go
generated
vendored
37
vendor/github.com/Luzifer/rconfig/example_test.go
generated
vendored
|
@ -1,37 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ExampleParse() {
|
|
||||||
// We're building an example configuration with a sub-struct to be filled
|
|
||||||
// by the Parse command.
|
|
||||||
config := struct {
|
|
||||||
Username string `default:"unknown" flag:"user,u" description:"Your name"`
|
|
||||||
Details struct {
|
|
||||||
Age int `default:"25" flag:"age" description:"Your age"`
|
|
||||||
}
|
|
||||||
}{}
|
|
||||||
|
|
||||||
// To have more relieable results we're setting os.Args to a known value.
|
|
||||||
// In real-life use cases you wouldn't do this but parse the original
|
|
||||||
// commandline arguments.
|
|
||||||
os.Args = []string{
|
|
||||||
"example",
|
|
||||||
"--user=Luzifer",
|
|
||||||
}
|
|
||||||
|
|
||||||
Parse(&config)
|
|
||||||
|
|
||||||
fmt.Printf("Hello %s, happy birthday for your %dth birthday.",
|
|
||||||
config.Username,
|
|
||||||
config.Details.Age)
|
|
||||||
|
|
||||||
// You can also show an usage message for your user
|
|
||||||
Usage()
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// Hello Luzifer, happy birthday for your 25th birthday.
|
|
||||||
}
|
|
44
vendor/github.com/Luzifer/rconfig/float_test.go
generated
vendored
44
vendor/github.com/Luzifer/rconfig/float_test.go
generated
vendored
|
@ -1,44 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Testing float parsing", func() {
|
|
||||||
type t struct {
|
|
||||||
Test32 float32 `flag:"float32"`
|
|
||||||
Test32P float32 `flag:"float32p,3"`
|
|
||||||
Test64 float64 `flag:"float64"`
|
|
||||||
Test64P float64 `flag:"float64p,6"`
|
|
||||||
TestDef float32 `default:"66.256"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
args []string
|
|
||||||
cfg t
|
|
||||||
)
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{
|
|
||||||
"--float32=5.5", "-3", "6.6",
|
|
||||||
"--float64=7.7", "-6", "8.8",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.Test32).To(Equal(float32(5.5)))
|
|
||||||
Expect(cfg.Test32P).To(Equal(float32(6.6)))
|
|
||||||
Expect(cfg.Test64).To(Equal(float64(7.7)))
|
|
||||||
Expect(cfg.Test64P).To(Equal(float64(8.8)))
|
|
||||||
|
|
||||||
Expect(cfg.TestDef).To(Equal(float32(66.256)))
|
|
||||||
})
|
|
||||||
})
|
|
128
vendor/github.com/Luzifer/rconfig/general_test.go
generated
vendored
128
vendor/github.com/Luzifer/rconfig/general_test.go
generated
vendored
|
@ -1,128 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Testing general parsing", func() {
|
|
||||||
type t struct {
|
|
||||||
Test string `default:"foo" env:"shell" flag:"shell" description:"Test"`
|
|
||||||
Test2 string `default:"blub" env:"testvar" flag:"testvar,t" description:"Test"`
|
|
||||||
DefaultFlag string `default:"goo"`
|
|
||||||
SadFlag string
|
|
||||||
}
|
|
||||||
|
|
||||||
type tValidated struct {
|
|
||||||
Test string `flag:"test" default:"" validate:"nonzero"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
args []string
|
|
||||||
cfg t
|
|
||||||
)
|
|
||||||
|
|
||||||
Context("with defined arguments", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{
|
|
||||||
"--shell=test23",
|
|
||||||
"-t", "bla",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have parsed the expected values", func() {
|
|
||||||
Expect(cfg.Test).To(Equal("test23"))
|
|
||||||
Expect(cfg.Test2).To(Equal("bla"))
|
|
||||||
Expect(cfg.SadFlag).To(Equal(""))
|
|
||||||
Expect(cfg.DefaultFlag).To(Equal("goo"))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("with no arguments", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have used the default value", func() {
|
|
||||||
Expect(cfg.Test).To(Equal("foo"))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("with no arguments and set env", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{}
|
|
||||||
os.Setenv("shell", "test546")
|
|
||||||
})
|
|
||||||
|
|
||||||
AfterEach(func() {
|
|
||||||
os.Unsetenv("shell")
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have used the value from env", func() {
|
|
||||||
Expect(cfg.Test).To(Equal("test546"))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("with additional arguments", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{
|
|
||||||
"--shell=test23",
|
|
||||||
"-t", "bla",
|
|
||||||
"positional1", "positional2",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have parsed the expected values", func() {
|
|
||||||
Expect(cfg.Test).To(Equal("test23"))
|
|
||||||
Expect(cfg.Test2).To(Equal("bla"))
|
|
||||||
Expect(cfg.SadFlag).To(Equal(""))
|
|
||||||
Expect(cfg.DefaultFlag).To(Equal("goo"))
|
|
||||||
})
|
|
||||||
It("should have detected the positional arguments", func() {
|
|
||||||
Expect(Args()).To(Equal([]string{"positional1", "positional2"}))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("making use of the validator package", func() {
|
|
||||||
var cfgValidated tValidated
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfgValidated = tValidated{}
|
|
||||||
args = []string{}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parseAndValidate(&cfgValidated, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should have errored", func() { Expect(err).To(HaveOccurred()) })
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
54
vendor/github.com/Luzifer/rconfig/int_test.go
generated
vendored
54
vendor/github.com/Luzifer/rconfig/int_test.go
generated
vendored
|
@ -1,54 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Testing int parsing", func() {
|
|
||||||
type t struct {
|
|
||||||
Test int `flag:"int"`
|
|
||||||
TestP int `flag:"intp,i"`
|
|
||||||
Test8 int8 `flag:"int8"`
|
|
||||||
Test8P int8 `flag:"int8p,8"`
|
|
||||||
Test32 int32 `flag:"int32"`
|
|
||||||
Test32P int32 `flag:"int32p,3"`
|
|
||||||
Test64 int64 `flag:"int64"`
|
|
||||||
Test64P int64 `flag:"int64p,6"`
|
|
||||||
TestDef int8 `default:"66"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
args []string
|
|
||||||
cfg t
|
|
||||||
)
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{
|
|
||||||
"--int=1", "-i", "2",
|
|
||||||
"--int8=3", "-8", "4",
|
|
||||||
"--int32=5", "-3", "6",
|
|
||||||
"--int64=7", "-6", "8",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.Test).To(Equal(1))
|
|
||||||
Expect(cfg.TestP).To(Equal(2))
|
|
||||||
Expect(cfg.Test8).To(Equal(int8(3)))
|
|
||||||
Expect(cfg.Test8P).To(Equal(int8(4)))
|
|
||||||
Expect(cfg.Test32).To(Equal(int32(5)))
|
|
||||||
Expect(cfg.Test32P).To(Equal(int32(6)))
|
|
||||||
Expect(cfg.Test64).To(Equal(int64(7)))
|
|
||||||
Expect(cfg.Test64P).To(Equal(int64(8)))
|
|
||||||
|
|
||||||
Expect(cfg.TestDef).To(Equal(int8(66)))
|
|
||||||
})
|
|
||||||
})
|
|
40
vendor/github.com/Luzifer/rconfig/os-args_test.go
generated
vendored
40
vendor/github.com/Luzifer/rconfig/os-args_test.go
generated
vendored
|
@ -1,40 +0,0 @@
|
||||||
package rconfig_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
|
|
||||||
. "github.com/Luzifer/rconfig"
|
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Testing os.Args", func() {
|
|
||||||
type t struct {
|
|
||||||
A string `default:"a" flag:"a"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
cfg t
|
|
||||||
)
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = Parse(&cfg)
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("With only valid arguments", func() {
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
os.Args = []string{"--a=bar"}
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.A).To(Equal("bar"))
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
87
vendor/github.com/Luzifer/rconfig/precedence_test.go
generated
vendored
87
vendor/github.com/Luzifer/rconfig/precedence_test.go
generated
vendored
|
@ -1,87 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Precedence", func() {
|
|
||||||
|
|
||||||
type t struct {
|
|
||||||
A int `default:"1" vardefault:"a" env:"a" flag:"avar,a" description:"a"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
cfg t
|
|
||||||
args []string
|
|
||||||
vardefaults map[string]string
|
|
||||||
)
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
SetVariableDefaults(vardefaults)
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("Provided: Flag, Env, Default, VarDefault", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
args = []string{"-a", "5"}
|
|
||||||
os.Setenv("a", "8")
|
|
||||||
vardefaults = map[string]string{
|
|
||||||
"a": "3",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have used the flag value", func() {
|
|
||||||
Expect(cfg.A).To(Equal(5))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("Provided: Env, Default, VarDefault", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
args = []string{}
|
|
||||||
os.Setenv("a", "8")
|
|
||||||
vardefaults = map[string]string{
|
|
||||||
"a": "3",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have used the env value", func() {
|
|
||||||
Expect(cfg.A).To(Equal(8))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("Provided: Default, VarDefault", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
args = []string{}
|
|
||||||
os.Unsetenv("a")
|
|
||||||
vardefaults = map[string]string{
|
|
||||||
"a": "3",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have used the vardefault value", func() {
|
|
||||||
Expect(cfg.A).To(Equal(3))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("Provided: Default", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
args = []string{}
|
|
||||||
os.Unsetenv("a")
|
|
||||||
vardefaults = map[string]string{}
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have used the default value", func() {
|
|
||||||
Expect(cfg.A).To(Equal(1))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
13
vendor/github.com/Luzifer/rconfig/rconfig_suite_test.go
generated
vendored
13
vendor/github.com/Luzifer/rconfig/rconfig_suite_test.go
generated
vendored
|
@ -1,13 +0,0 @@
|
||||||
package rconfig_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestRconfig(t *testing.T) {
|
|
||||||
RegisterFailHandler(Fail)
|
|
||||||
RunSpecs(t, "Rconfig Suite")
|
|
||||||
}
|
|
51
vendor/github.com/Luzifer/rconfig/slice_test.go
generated
vendored
51
vendor/github.com/Luzifer/rconfig/slice_test.go
generated
vendored
|
@ -1,51 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Testing slices", func() {
|
|
||||||
type t struct {
|
|
||||||
Int []int `default:"1,2,3" flag:"int"`
|
|
||||||
String []string `default:"a,b,c" flag:"string"`
|
|
||||||
IntP []int `default:"1,2,3" flag:"intp,i"`
|
|
||||||
StringP []string `default:"a,b,c" flag:"stringp,s"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
args []string
|
|
||||||
cfg t
|
|
||||||
)
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{
|
|
||||||
"--int=4,5", "-s", "hallo,welt",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values for int-slice", func() {
|
|
||||||
Expect(len(cfg.Int)).To(Equal(2))
|
|
||||||
Expect(cfg.Int).To(Equal([]int{4, 5}))
|
|
||||||
Expect(cfg.Int).NotTo(Equal([]int{5, 4}))
|
|
||||||
})
|
|
||||||
It("should have the expected values for int-shorthand-slice", func() {
|
|
||||||
Expect(len(cfg.IntP)).To(Equal(3))
|
|
||||||
Expect(cfg.IntP).To(Equal([]int{1, 2, 3}))
|
|
||||||
})
|
|
||||||
It("should have the expected values for string-slice", func() {
|
|
||||||
Expect(len(cfg.String)).To(Equal(3))
|
|
||||||
Expect(cfg.String).To(Equal([]string{"a", "b", "c"}))
|
|
||||||
})
|
|
||||||
It("should have the expected values for string-shorthand-slice", func() {
|
|
||||||
Expect(len(cfg.StringP)).To(Equal(2))
|
|
||||||
Expect(cfg.StringP).To(Equal([]string{"hallo", "welt"}))
|
|
||||||
})
|
|
||||||
})
|
|
36
vendor/github.com/Luzifer/rconfig/sub-struct_test.go
generated
vendored
36
vendor/github.com/Luzifer/rconfig/sub-struct_test.go
generated
vendored
|
@ -1,36 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Testing sub-structs", func() {
|
|
||||||
type t struct {
|
|
||||||
Test string `default:"blubb"`
|
|
||||||
Sub struct {
|
|
||||||
Test string `default:"Hallo"`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
args []string
|
|
||||||
cfg t
|
|
||||||
)
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.Test).To(Equal("blubb"))
|
|
||||||
Expect(cfg.Sub.Test).To(Equal("Hallo"))
|
|
||||||
})
|
|
||||||
})
|
|
59
vendor/github.com/Luzifer/rconfig/uint_test.go
generated
vendored
59
vendor/github.com/Luzifer/rconfig/uint_test.go
generated
vendored
|
@ -1,59 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Testing uint parsing", func() {
|
|
||||||
type t struct {
|
|
||||||
Test uint `flag:"int"`
|
|
||||||
TestP uint `flag:"intp,i"`
|
|
||||||
Test8 uint8 `flag:"int8"`
|
|
||||||
Test8P uint8 `flag:"int8p,8"`
|
|
||||||
Test16 uint16 `flag:"int16"`
|
|
||||||
Test16P uint16 `flag:"int16p,1"`
|
|
||||||
Test32 uint32 `flag:"int32"`
|
|
||||||
Test32P uint32 `flag:"int32p,3"`
|
|
||||||
Test64 uint64 `flag:"int64"`
|
|
||||||
Test64P uint64 `flag:"int64p,6"`
|
|
||||||
TestDef uint8 `default:"66"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
args []string
|
|
||||||
cfg t
|
|
||||||
)
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
args = []string{
|
|
||||||
"--int=1", "-i", "2",
|
|
||||||
"--int8=3", "-8", "4",
|
|
||||||
"--int32=5", "-3", "6",
|
|
||||||
"--int64=7", "-6", "8",
|
|
||||||
"--int16=9", "-1", "10",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.Test).To(Equal(uint(1)))
|
|
||||||
Expect(cfg.TestP).To(Equal(uint(2)))
|
|
||||||
Expect(cfg.Test8).To(Equal(uint8(3)))
|
|
||||||
Expect(cfg.Test8P).To(Equal(uint8(4)))
|
|
||||||
Expect(cfg.Test32).To(Equal(uint32(5)))
|
|
||||||
Expect(cfg.Test32P).To(Equal(uint32(6)))
|
|
||||||
Expect(cfg.Test64).To(Equal(uint64(7)))
|
|
||||||
Expect(cfg.Test64P).To(Equal(uint64(8)))
|
|
||||||
Expect(cfg.Test16).To(Equal(uint16(9)))
|
|
||||||
Expect(cfg.Test16P).To(Equal(uint16(10)))
|
|
||||||
|
|
||||||
Expect(cfg.TestDef).To(Equal(uint8(66)))
|
|
||||||
})
|
|
||||||
})
|
|
122
vendor/github.com/Luzifer/rconfig/vardefault_test.go
generated
vendored
122
vendor/github.com/Luzifer/rconfig/vardefault_test.go
generated
vendored
|
@ -1,122 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Testing variable defaults", func() {
|
|
||||||
|
|
||||||
type t struct {
|
|
||||||
MySecretValue string `default:"secret" env:"foo" vardefault:"my_secret_value"`
|
|
||||||
MyUsername string `default:"luzifer" vardefault:"username"`
|
|
||||||
SomeVar string `flag:"var" description:"some variable"`
|
|
||||||
IntVar int64 `vardefault:"int_var" default:"23"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
cfg t
|
|
||||||
args = []string{}
|
|
||||||
vardefaults = map[string]string{
|
|
||||||
"my_secret_value": "veryverysecretkey",
|
|
||||||
"unkownkey": "hi there",
|
|
||||||
"int_var": "42",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
cfg = t{}
|
|
||||||
})
|
|
||||||
|
|
||||||
JustBeforeEach(func() {
|
|
||||||
err = parse(&cfg, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("With manually provided variables", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
SetVariableDefaults(vardefaults)
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.IntVar).To(Equal(int64(42)))
|
|
||||||
Expect(cfg.MySecretValue).To(Equal("veryverysecretkey"))
|
|
||||||
Expect(cfg.MyUsername).To(Equal("luzifer"))
|
|
||||||
Expect(cfg.SomeVar).To(Equal(""))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("With defaults from YAML data", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
yamlData := []byte("---\nmy_secret_value: veryverysecretkey\nunknownkey: hi there\nint_var: 42\n")
|
|
||||||
SetVariableDefaults(VarDefaultsFromYAML(yamlData))
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.IntVar).To(Equal(int64(42)))
|
|
||||||
Expect(cfg.MySecretValue).To(Equal("veryverysecretkey"))
|
|
||||||
Expect(cfg.MyUsername).To(Equal("luzifer"))
|
|
||||||
Expect(cfg.SomeVar).To(Equal(""))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("With defaults from YAML file", func() {
|
|
||||||
var tmp *os.File
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
tmp, _ = ioutil.TempFile("", "")
|
|
||||||
yamlData := "---\nmy_secret_value: veryverysecretkey\nunknownkey: hi there\nint_var: 42\n"
|
|
||||||
tmp.WriteString(yamlData)
|
|
||||||
SetVariableDefaults(VarDefaultsFromYAMLFile(tmp.Name()))
|
|
||||||
})
|
|
||||||
|
|
||||||
AfterEach(func() {
|
|
||||||
tmp.Close()
|
|
||||||
os.Remove(tmp.Name())
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.IntVar).To(Equal(int64(42)))
|
|
||||||
Expect(cfg.MySecretValue).To(Equal("veryverysecretkey"))
|
|
||||||
Expect(cfg.MyUsername).To(Equal("luzifer"))
|
|
||||||
Expect(cfg.SomeVar).To(Equal(""))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("With defaults from invalid YAML data", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
yamlData := []byte("---\nmy_secret_value = veryverysecretkey\nunknownkey = hi there\nint_var = 42\n")
|
|
||||||
SetVariableDefaults(VarDefaultsFromYAML(yamlData))
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.IntVar).To(Equal(int64(23)))
|
|
||||||
Expect(cfg.MySecretValue).To(Equal("secret"))
|
|
||||||
Expect(cfg.MyUsername).To(Equal("luzifer"))
|
|
||||||
Expect(cfg.SomeVar).To(Equal(""))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("With defaults from non existent YAML file", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
file := "/tmp/this_file_should_not_exist_146e26723r"
|
|
||||||
SetVariableDefaults(VarDefaultsFromYAMLFile(file))
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
|
||||||
It("should have the expected values", func() {
|
|
||||||
Expect(cfg.IntVar).To(Equal(int64(23)))
|
|
||||||
Expect(cfg.MySecretValue).To(Equal("secret"))
|
|
||||||
Expect(cfg.MyUsername).To(Equal("luzifer"))
|
|
||||||
Expect(cfg.SomeVar).To(Equal(""))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
2
vendor/github.com/beorn7/perks/.gitignore
generated
vendored
2
vendor/github.com/beorn7/perks/.gitignore
generated
vendored
|
@ -1,2 +0,0 @@
|
||||||
*.test
|
|
||||||
*.prof
|
|
31
vendor/github.com/beorn7/perks/README.md
generated
vendored
31
vendor/github.com/beorn7/perks/README.md
generated
vendored
|
@ -1,31 +0,0 @@
|
||||||
# Perks for Go (golang.org)
|
|
||||||
|
|
||||||
Perks contains the Go package quantile that computes approximate quantiles over
|
|
||||||
an unbounded data stream within low memory and CPU bounds.
|
|
||||||
|
|
||||||
For more information and examples, see:
|
|
||||||
http://godoc.org/github.com/bmizerany/perks
|
|
||||||
|
|
||||||
A very special thank you and shout out to Graham Cormode (Rutgers University),
|
|
||||||
Flip Korn (AT&T Labs–Research), S. Muthukrishnan (Rutgers University), and
|
|
||||||
Divesh Srivastava (AT&T Labs–Research) for their research and publication of
|
|
||||||
[Effective Computation of Biased Quantiles over Data Streams](http://www.cs.rutgers.edu/~muthu/bquant.pdf)
|
|
||||||
|
|
||||||
Thank you, also:
|
|
||||||
* Armon Dadgar (@armon)
|
|
||||||
* Andrew Gerrand (@nf)
|
|
||||||
* Brad Fitzpatrick (@bradfitz)
|
|
||||||
* Keith Rarick (@kr)
|
|
||||||
|
|
||||||
FAQ:
|
|
||||||
|
|
||||||
Q: Why not move the quantile package into the project root?
|
|
||||||
A: I want to add more packages to perks later.
|
|
||||||
|
|
||||||
Copyright (C) 2013 Blake Mizerany
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
26
vendor/github.com/beorn7/perks/histogram/bench_test.go
generated
vendored
26
vendor/github.com/beorn7/perks/histogram/bench_test.go
generated
vendored
|
@ -1,26 +0,0 @@
|
||||||
package histogram
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/rand"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func BenchmarkInsert10Bins(b *testing.B) {
|
|
||||||
b.StopTimer()
|
|
||||||
h := New(10)
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
f := rand.ExpFloat64()
|
|
||||||
h.Insert(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkInsert100Bins(b *testing.B) {
|
|
||||||
b.StopTimer()
|
|
||||||
h := New(100)
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
f := rand.ExpFloat64()
|
|
||||||
h.Insert(f)
|
|
||||||
}
|
|
||||||
}
|
|
108
vendor/github.com/beorn7/perks/histogram/histogram.go
generated
vendored
108
vendor/github.com/beorn7/perks/histogram/histogram.go
generated
vendored
|
@ -1,108 +0,0 @@
|
||||||
// Package histogram provides a Go implementation of BigML's histogram package
|
|
||||||
// for Clojure/Java. It is currently experimental.
|
|
||||||
package histogram
|
|
||||||
|
|
||||||
import (
|
|
||||||
"container/heap"
|
|
||||||
"math"
|
|
||||||
"sort"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Bin struct {
|
|
||||||
Count int
|
|
||||||
Sum float64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Bin) Update(x *Bin) {
|
|
||||||
b.Count += x.Count
|
|
||||||
b.Sum += x.Sum
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Bin) Mean() float64 {
|
|
||||||
return b.Sum / float64(b.Count)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Bins []*Bin
|
|
||||||
|
|
||||||
func (bs Bins) Len() int { return len(bs) }
|
|
||||||
func (bs Bins) Less(i, j int) bool { return bs[i].Mean() < bs[j].Mean() }
|
|
||||||
func (bs Bins) Swap(i, j int) { bs[i], bs[j] = bs[j], bs[i] }
|
|
||||||
|
|
||||||
func (bs *Bins) Push(x interface{}) {
|
|
||||||
*bs = append(*bs, x.(*Bin))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bs *Bins) Pop() interface{} {
|
|
||||||
return bs.remove(len(*bs) - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bs *Bins) remove(n int) *Bin {
|
|
||||||
if n < 0 || len(*bs) < n {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
x := (*bs)[n]
|
|
||||||
*bs = append((*bs)[:n], (*bs)[n+1:]...)
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
type Histogram struct {
|
|
||||||
res *reservoir
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(maxBins int) *Histogram {
|
|
||||||
return &Histogram{res: newReservoir(maxBins)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Histogram) Insert(f float64) {
|
|
||||||
h.res.insert(&Bin{1, f})
|
|
||||||
h.res.compress()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Histogram) Bins() Bins {
|
|
||||||
return h.res.bins
|
|
||||||
}
|
|
||||||
|
|
||||||
type reservoir struct {
|
|
||||||
n int
|
|
||||||
maxBins int
|
|
||||||
bins Bins
|
|
||||||
}
|
|
||||||
|
|
||||||
func newReservoir(maxBins int) *reservoir {
|
|
||||||
return &reservoir{maxBins: maxBins}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *reservoir) insert(bin *Bin) {
|
|
||||||
r.n += bin.Count
|
|
||||||
i := sort.Search(len(r.bins), func(i int) bool {
|
|
||||||
return r.bins[i].Mean() >= bin.Mean()
|
|
||||||
})
|
|
||||||
if i < 0 || i == r.bins.Len() {
|
|
||||||
// TODO(blake): Maybe use an .insert(i, bin) instead of
|
|
||||||
// performing the extra work of a heap.Push.
|
|
||||||
heap.Push(&r.bins, bin)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
r.bins[i].Update(bin)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *reservoir) compress() {
|
|
||||||
for r.bins.Len() > r.maxBins {
|
|
||||||
minGapIndex := -1
|
|
||||||
minGap := math.MaxFloat64
|
|
||||||
for i := 0; i < r.bins.Len()-1; i++ {
|
|
||||||
gap := gapWeight(r.bins[i], r.bins[i+1])
|
|
||||||
if minGap > gap {
|
|
||||||
minGap = gap
|
|
||||||
minGapIndex = i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prev := r.bins[minGapIndex]
|
|
||||||
next := r.bins.remove(minGapIndex + 1)
|
|
||||||
prev.Update(next)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func gapWeight(prev, next *Bin) float64 {
|
|
||||||
return next.Mean() - prev.Mean()
|
|
||||||
}
|
|
38
vendor/github.com/beorn7/perks/histogram/histogram_test.go
generated
vendored
38
vendor/github.com/beorn7/perks/histogram/histogram_test.go
generated
vendored
|
@ -1,38 +0,0 @@
|
||||||
package histogram
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/rand"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestHistogram(t *testing.T) {
|
|
||||||
const numPoints = 1e6
|
|
||||||
const maxBins = 3
|
|
||||||
|
|
||||||
h := New(maxBins)
|
|
||||||
for i := 0; i < numPoints; i++ {
|
|
||||||
f := rand.ExpFloat64()
|
|
||||||
h.Insert(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
bins := h.Bins()
|
|
||||||
if g := len(bins); g > maxBins {
|
|
||||||
t.Fatalf("got %d bins, wanted <= %d", g, maxBins)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, b := range bins {
|
|
||||||
t.Logf("%+v", b)
|
|
||||||
}
|
|
||||||
|
|
||||||
if g := count(h.Bins()); g != numPoints {
|
|
||||||
t.Fatalf("binned %d points, wanted %d", g, numPoints)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func count(bins Bins) int {
|
|
||||||
binCounts := 0
|
|
||||||
for _, b := range bins {
|
|
||||||
binCounts += b.Count
|
|
||||||
}
|
|
||||||
return binCounts
|
|
||||||
}
|
|
63
vendor/github.com/beorn7/perks/quantile/bench_test.go
generated
vendored
63
vendor/github.com/beorn7/perks/quantile/bench_test.go
generated
vendored
|
@ -1,63 +0,0 @@
|
||||||
package quantile
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func BenchmarkInsertTargeted(b *testing.B) {
|
|
||||||
b.ReportAllocs()
|
|
||||||
|
|
||||||
s := NewTargeted(Targets)
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := float64(0); i < float64(b.N); i++ {
|
|
||||||
s.Insert(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkInsertTargetedSmallEpsilon(b *testing.B) {
|
|
||||||
s := NewTargeted(TargetsSmallEpsilon)
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := float64(0); i < float64(b.N); i++ {
|
|
||||||
s.Insert(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkInsertBiased(b *testing.B) {
|
|
||||||
s := NewLowBiased(0.01)
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := float64(0); i < float64(b.N); i++ {
|
|
||||||
s.Insert(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkInsertBiasedSmallEpsilon(b *testing.B) {
|
|
||||||
s := NewLowBiased(0.0001)
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := float64(0); i < float64(b.N); i++ {
|
|
||||||
s.Insert(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkQuery(b *testing.B) {
|
|
||||||
s := NewTargeted(Targets)
|
|
||||||
for i := float64(0); i < 1e6; i++ {
|
|
||||||
s.Insert(i)
|
|
||||||
}
|
|
||||||
b.ResetTimer()
|
|
||||||
n := float64(b.N)
|
|
||||||
for i := float64(0); i < n; i++ {
|
|
||||||
s.Query(i / n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkQuerySmallEpsilon(b *testing.B) {
|
|
||||||
s := NewTargeted(TargetsSmallEpsilon)
|
|
||||||
for i := float64(0); i < 1e6; i++ {
|
|
||||||
s.Insert(i)
|
|
||||||
}
|
|
||||||
b.ResetTimer()
|
|
||||||
n := float64(b.N)
|
|
||||||
for i := float64(0); i < n; i++ {
|
|
||||||
s.Query(i / n)
|
|
||||||
}
|
|
||||||
}
|
|
121
vendor/github.com/beorn7/perks/quantile/example_test.go
generated
vendored
121
vendor/github.com/beorn7/perks/quantile/example_test.go
generated
vendored
|
@ -1,121 +0,0 @@
|
||||||
// +build go1.1
|
|
||||||
|
|
||||||
package quantile_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/beorn7/perks/quantile"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Example_simple() {
|
|
||||||
ch := make(chan float64)
|
|
||||||
go sendFloats(ch)
|
|
||||||
|
|
||||||
// Compute the 50th, 90th, and 99th percentile.
|
|
||||||
q := quantile.NewTargeted(map[float64]float64{
|
|
||||||
0.50: 0.005,
|
|
||||||
0.90: 0.001,
|
|
||||||
0.99: 0.0001,
|
|
||||||
})
|
|
||||||
for v := range ch {
|
|
||||||
q.Insert(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("perc50:", q.Query(0.50))
|
|
||||||
fmt.Println("perc90:", q.Query(0.90))
|
|
||||||
fmt.Println("perc99:", q.Query(0.99))
|
|
||||||
fmt.Println("count:", q.Count())
|
|
||||||
// Output:
|
|
||||||
// perc50: 5
|
|
||||||
// perc90: 16
|
|
||||||
// perc99: 223
|
|
||||||
// count: 2388
|
|
||||||
}
|
|
||||||
|
|
||||||
func Example_mergeMultipleStreams() {
|
|
||||||
// Scenario:
|
|
||||||
// We have multiple database shards. On each shard, there is a process
|
|
||||||
// collecting query response times from the database logs and inserting
|
|
||||||
// them into a Stream (created via NewTargeted(0.90)), much like the
|
|
||||||
// Simple example. These processes expose a network interface for us to
|
|
||||||
// ask them to serialize and send us the results of their
|
|
||||||
// Stream.Samples so we may Merge and Query them.
|
|
||||||
//
|
|
||||||
// NOTES:
|
|
||||||
// * These sample sets are small, allowing us to get them
|
|
||||||
// across the network much faster than sending the entire list of data
|
|
||||||
// points.
|
|
||||||
//
|
|
||||||
// * For this to work correctly, we must supply the same quantiles
|
|
||||||
// a priori the process collecting the samples supplied to NewTargeted,
|
|
||||||
// even if we do not plan to query them all here.
|
|
||||||
ch := make(chan quantile.Samples)
|
|
||||||
getDBQuerySamples(ch)
|
|
||||||
q := quantile.NewTargeted(map[float64]float64{0.90: 0.001})
|
|
||||||
for samples := range ch {
|
|
||||||
q.Merge(samples)
|
|
||||||
}
|
|
||||||
fmt.Println("perc90:", q.Query(0.90))
|
|
||||||
}
|
|
||||||
|
|
||||||
func Example_window() {
|
|
||||||
// Scenario: We want the 90th, 95th, and 99th percentiles for each
|
|
||||||
// minute.
|
|
||||||
|
|
||||||
ch := make(chan float64)
|
|
||||||
go sendStreamValues(ch)
|
|
||||||
|
|
||||||
tick := time.NewTicker(1 * time.Minute)
|
|
||||||
q := quantile.NewTargeted(map[float64]float64{
|
|
||||||
0.90: 0.001,
|
|
||||||
0.95: 0.0005,
|
|
||||||
0.99: 0.0001,
|
|
||||||
})
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case t := <-tick.C:
|
|
||||||
flushToDB(t, q.Samples())
|
|
||||||
q.Reset()
|
|
||||||
case v := <-ch:
|
|
||||||
q.Insert(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func sendStreamValues(ch chan float64) {
|
|
||||||
// Use your imagination
|
|
||||||
}
|
|
||||||
|
|
||||||
func flushToDB(t time.Time, samples quantile.Samples) {
|
|
||||||
// Use your imagination
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a stub for the above example. In reality this would hit the remote
|
|
||||||
// servers via http or something like it.
|
|
||||||
func getDBQuerySamples(ch chan quantile.Samples) {}
|
|
||||||
|
|
||||||
func sendFloats(ch chan<- float64) {
|
|
||||||
f, err := os.Open("exampledata.txt")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
sc := bufio.NewScanner(f)
|
|
||||||
for sc.Scan() {
|
|
||||||
b := sc.Bytes()
|
|
||||||
v, err := strconv.ParseFloat(string(b), 64)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
ch <- v
|
|
||||||
}
|
|
||||||
if sc.Err() != nil {
|
|
||||||
log.Fatal(sc.Err())
|
|
||||||
}
|
|
||||||
close(ch)
|
|
||||||
}
|
|
34
vendor/github.com/beorn7/perks/quantile/stream.go
generated
vendored
34
vendor/github.com/beorn7/perks/quantile/stream.go
generated
vendored
|
@ -77,15 +77,20 @@ func NewHighBiased(epsilon float64) *Stream {
|
||||||
// is guaranteed to be within (Quantile±Epsilon).
|
// is guaranteed to be within (Quantile±Epsilon).
|
||||||
//
|
//
|
||||||
// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error properties.
|
// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error properties.
|
||||||
func NewTargeted(targets map[float64]float64) *Stream {
|
func NewTargeted(targetMap map[float64]float64) *Stream {
|
||||||
|
// Convert map to slice to avoid slow iterations on a map.
|
||||||
|
// ƒ is called on the hot path, so converting the map to a slice
|
||||||
|
// beforehand results in significant CPU savings.
|
||||||
|
targets := targetMapToSlice(targetMap)
|
||||||
|
|
||||||
ƒ := func(s *stream, r float64) float64 {
|
ƒ := func(s *stream, r float64) float64 {
|
||||||
var m = math.MaxFloat64
|
var m = math.MaxFloat64
|
||||||
var f float64
|
var f float64
|
||||||
for quantile, epsilon := range targets {
|
for _, t := range targets {
|
||||||
if quantile*s.n <= r {
|
if t.quantile*s.n <= r {
|
||||||
f = (2 * epsilon * r) / quantile
|
f = (2 * t.epsilon * r) / t.quantile
|
||||||
} else {
|
} else {
|
||||||
f = (2 * epsilon * (s.n - r)) / (1 - quantile)
|
f = (2 * t.epsilon * (s.n - r)) / (1 - t.quantile)
|
||||||
}
|
}
|
||||||
if f < m {
|
if f < m {
|
||||||
m = f
|
m = f
|
||||||
|
@ -96,6 +101,25 @@ func NewTargeted(targets map[float64]float64) *Stream {
|
||||||
return newStream(ƒ)
|
return newStream(ƒ)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type target struct {
|
||||||
|
quantile float64
|
||||||
|
epsilon float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func targetMapToSlice(targetMap map[float64]float64) []target {
|
||||||
|
targets := make([]target, 0, len(targetMap))
|
||||||
|
|
||||||
|
for quantile, epsilon := range targetMap {
|
||||||
|
t := target{
|
||||||
|
quantile: quantile,
|
||||||
|
epsilon: epsilon,
|
||||||
|
}
|
||||||
|
targets = append(targets, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
return targets
|
||||||
|
}
|
||||||
|
|
||||||
// Stream computes quantiles for a stream of float64s. It is not thread-safe by
|
// Stream computes quantiles for a stream of float64s. It is not thread-safe by
|
||||||
// design. Take care when using across multiple goroutines.
|
// design. Take care when using across multiple goroutines.
|
||||||
type Stream struct {
|
type Stream struct {
|
||||||
|
|
215
vendor/github.com/beorn7/perks/quantile/stream_test.go
generated
vendored
215
vendor/github.com/beorn7/perks/quantile/stream_test.go
generated
vendored
|
@ -1,215 +0,0 @@
|
||||||
package quantile
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math"
|
|
||||||
"math/rand"
|
|
||||||
"sort"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
Targets = map[float64]float64{
|
|
||||||
0.01: 0.001,
|
|
||||||
0.10: 0.01,
|
|
||||||
0.50: 0.05,
|
|
||||||
0.90: 0.01,
|
|
||||||
0.99: 0.001,
|
|
||||||
}
|
|
||||||
TargetsSmallEpsilon = map[float64]float64{
|
|
||||||
0.01: 0.0001,
|
|
||||||
0.10: 0.001,
|
|
||||||
0.50: 0.005,
|
|
||||||
0.90: 0.001,
|
|
||||||
0.99: 0.0001,
|
|
||||||
}
|
|
||||||
LowQuantiles = []float64{0.01, 0.1, 0.5}
|
|
||||||
HighQuantiles = []float64{0.99, 0.9, 0.5}
|
|
||||||
)
|
|
||||||
|
|
||||||
const RelativeEpsilon = 0.01
|
|
||||||
|
|
||||||
func verifyPercsWithAbsoluteEpsilon(t *testing.T, a []float64, s *Stream) {
|
|
||||||
sort.Float64s(a)
|
|
||||||
for quantile, epsilon := range Targets {
|
|
||||||
n := float64(len(a))
|
|
||||||
k := int(quantile * n)
|
|
||||||
if k < 1 {
|
|
||||||
k = 1
|
|
||||||
}
|
|
||||||
lower := int((quantile - epsilon) * n)
|
|
||||||
if lower < 1 {
|
|
||||||
lower = 1
|
|
||||||
}
|
|
||||||
upper := int(math.Ceil((quantile + epsilon) * n))
|
|
||||||
if upper > len(a) {
|
|
||||||
upper = len(a)
|
|
||||||
}
|
|
||||||
w, min, max := a[k-1], a[lower-1], a[upper-1]
|
|
||||||
if g := s.Query(quantile); g < min || g > max {
|
|
||||||
t.Errorf("q=%f: want %v [%f,%f], got %v", quantile, w, min, max, g)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func verifyLowPercsWithRelativeEpsilon(t *testing.T, a []float64, s *Stream) {
|
|
||||||
sort.Float64s(a)
|
|
||||||
for _, qu := range LowQuantiles {
|
|
||||||
n := float64(len(a))
|
|
||||||
k := int(qu * n)
|
|
||||||
|
|
||||||
lowerRank := int((1 - RelativeEpsilon) * qu * n)
|
|
||||||
upperRank := int(math.Ceil((1 + RelativeEpsilon) * qu * n))
|
|
||||||
w, min, max := a[k-1], a[lowerRank-1], a[upperRank-1]
|
|
||||||
if g := s.Query(qu); g < min || g > max {
|
|
||||||
t.Errorf("q=%f: want %v [%f,%f], got %v", qu, w, min, max, g)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func verifyHighPercsWithRelativeEpsilon(t *testing.T, a []float64, s *Stream) {
|
|
||||||
sort.Float64s(a)
|
|
||||||
for _, qu := range HighQuantiles {
|
|
||||||
n := float64(len(a))
|
|
||||||
k := int(qu * n)
|
|
||||||
|
|
||||||
lowerRank := int((1 - (1+RelativeEpsilon)*(1-qu)) * n)
|
|
||||||
upperRank := int(math.Ceil((1 - (1-RelativeEpsilon)*(1-qu)) * n))
|
|
||||||
w, min, max := a[k-1], a[lowerRank-1], a[upperRank-1]
|
|
||||||
if g := s.Query(qu); g < min || g > max {
|
|
||||||
t.Errorf("q=%f: want %v [%f,%f], got %v", qu, w, min, max, g)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func populateStream(s *Stream) []float64 {
|
|
||||||
a := make([]float64, 0, 1e5+100)
|
|
||||||
for i := 0; i < cap(a); i++ {
|
|
||||||
v := rand.NormFloat64()
|
|
||||||
// Add 5% asymmetric outliers.
|
|
||||||
if i%20 == 0 {
|
|
||||||
v = v*v + 1
|
|
||||||
}
|
|
||||||
s.Insert(v)
|
|
||||||
a = append(a, v)
|
|
||||||
}
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTargetedQuery(t *testing.T) {
|
|
||||||
rand.Seed(42)
|
|
||||||
s := NewTargeted(Targets)
|
|
||||||
a := populateStream(s)
|
|
||||||
verifyPercsWithAbsoluteEpsilon(t, a, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTargetedQuerySmallSampleSize(t *testing.T) {
|
|
||||||
rand.Seed(42)
|
|
||||||
s := NewTargeted(TargetsSmallEpsilon)
|
|
||||||
a := []float64{1, 2, 3, 4, 5}
|
|
||||||
for _, v := range a {
|
|
||||||
s.Insert(v)
|
|
||||||
}
|
|
||||||
verifyPercsWithAbsoluteEpsilon(t, a, s)
|
|
||||||
// If not yet flushed, results should be precise:
|
|
||||||
if !s.flushed() {
|
|
||||||
for φ, want := range map[float64]float64{
|
|
||||||
0.01: 1,
|
|
||||||
0.10: 1,
|
|
||||||
0.50: 3,
|
|
||||||
0.90: 5,
|
|
||||||
0.99: 5,
|
|
||||||
} {
|
|
||||||
if got := s.Query(φ); got != want {
|
|
||||||
t.Errorf("want %f for φ=%f, got %f", want, φ, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLowBiasedQuery(t *testing.T) {
|
|
||||||
rand.Seed(42)
|
|
||||||
s := NewLowBiased(RelativeEpsilon)
|
|
||||||
a := populateStream(s)
|
|
||||||
verifyLowPercsWithRelativeEpsilon(t, a, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHighBiasedQuery(t *testing.T) {
|
|
||||||
rand.Seed(42)
|
|
||||||
s := NewHighBiased(RelativeEpsilon)
|
|
||||||
a := populateStream(s)
|
|
||||||
verifyHighPercsWithRelativeEpsilon(t, a, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BrokenTestTargetedMerge is broken, see Merge doc comment.
|
|
||||||
func BrokenTestTargetedMerge(t *testing.T) {
|
|
||||||
rand.Seed(42)
|
|
||||||
s1 := NewTargeted(Targets)
|
|
||||||
s2 := NewTargeted(Targets)
|
|
||||||
a := populateStream(s1)
|
|
||||||
a = append(a, populateStream(s2)...)
|
|
||||||
s1.Merge(s2.Samples())
|
|
||||||
verifyPercsWithAbsoluteEpsilon(t, a, s1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BrokenTestLowBiasedMerge is broken, see Merge doc comment.
|
|
||||||
func BrokenTestLowBiasedMerge(t *testing.T) {
|
|
||||||
rand.Seed(42)
|
|
||||||
s1 := NewLowBiased(RelativeEpsilon)
|
|
||||||
s2 := NewLowBiased(RelativeEpsilon)
|
|
||||||
a := populateStream(s1)
|
|
||||||
a = append(a, populateStream(s2)...)
|
|
||||||
s1.Merge(s2.Samples())
|
|
||||||
verifyLowPercsWithRelativeEpsilon(t, a, s2)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BrokenTestHighBiasedMerge is broken, see Merge doc comment.
|
|
||||||
func BrokenTestHighBiasedMerge(t *testing.T) {
|
|
||||||
rand.Seed(42)
|
|
||||||
s1 := NewHighBiased(RelativeEpsilon)
|
|
||||||
s2 := NewHighBiased(RelativeEpsilon)
|
|
||||||
a := populateStream(s1)
|
|
||||||
a = append(a, populateStream(s2)...)
|
|
||||||
s1.Merge(s2.Samples())
|
|
||||||
verifyHighPercsWithRelativeEpsilon(t, a, s2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUncompressed(t *testing.T) {
|
|
||||||
q := NewTargeted(Targets)
|
|
||||||
for i := 100; i > 0; i-- {
|
|
||||||
q.Insert(float64(i))
|
|
||||||
}
|
|
||||||
if g := q.Count(); g != 100 {
|
|
||||||
t.Errorf("want count 100, got %d", g)
|
|
||||||
}
|
|
||||||
// Before compression, Query should have 100% accuracy.
|
|
||||||
for quantile := range Targets {
|
|
||||||
w := quantile * 100
|
|
||||||
if g := q.Query(quantile); g != w {
|
|
||||||
t.Errorf("want %f, got %f", w, g)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUncompressedSamples(t *testing.T) {
|
|
||||||
q := NewTargeted(map[float64]float64{0.99: 0.001})
|
|
||||||
for i := 1; i <= 100; i++ {
|
|
||||||
q.Insert(float64(i))
|
|
||||||
}
|
|
||||||
if g := q.Samples().Len(); g != 100 {
|
|
||||||
t.Errorf("want count 100, got %d", g)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUncompressedOne(t *testing.T) {
|
|
||||||
q := NewTargeted(map[float64]float64{0.99: 0.01})
|
|
||||||
q.Insert(3.14)
|
|
||||||
if g := q.Query(0.90); g != 3.14 {
|
|
||||||
t.Error("want PI, got", g)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDefaults(t *testing.T) {
|
|
||||||
if g := NewTargeted(map[float64]float64{0.99: 0.001}).Query(0.99); g != 0 {
|
|
||||||
t.Errorf("want 0, got %f", g)
|
|
||||||
}
|
|
||||||
}
|
|
90
vendor/github.com/beorn7/perks/topk/topk.go
generated
vendored
90
vendor/github.com/beorn7/perks/topk/topk.go
generated
vendored
|
@ -1,90 +0,0 @@
|
||||||
package topk
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sort"
|
|
||||||
)
|
|
||||||
|
|
||||||
// http://www.cs.ucsb.edu/research/tech_reports/reports/2005-23.pdf
|
|
||||||
|
|
||||||
type Element struct {
|
|
||||||
Value string
|
|
||||||
Count int
|
|
||||||
}
|
|
||||||
|
|
||||||
type Samples []*Element
|
|
||||||
|
|
||||||
func (sm Samples) Len() int {
|
|
||||||
return len(sm)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sm Samples) Less(i, j int) bool {
|
|
||||||
return sm[i].Count < sm[j].Count
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sm Samples) Swap(i, j int) {
|
|
||||||
sm[i], sm[j] = sm[j], sm[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
type Stream struct {
|
|
||||||
k int
|
|
||||||
mon map[string]*Element
|
|
||||||
|
|
||||||
// the minimum Element
|
|
||||||
min *Element
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(k int) *Stream {
|
|
||||||
s := new(Stream)
|
|
||||||
s.k = k
|
|
||||||
s.mon = make(map[string]*Element)
|
|
||||||
s.min = &Element{}
|
|
||||||
|
|
||||||
// Track k+1 so that less frequenet items contended for that spot,
|
|
||||||
// resulting in k being more accurate.
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Stream) Insert(x string) {
|
|
||||||
s.insert(&Element{x, 1})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Stream) Merge(sm Samples) {
|
|
||||||
for _, e := range sm {
|
|
||||||
s.insert(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Stream) insert(in *Element) {
|
|
||||||
e := s.mon[in.Value]
|
|
||||||
if e != nil {
|
|
||||||
e.Count++
|
|
||||||
} else {
|
|
||||||
if len(s.mon) < s.k+1 {
|
|
||||||
e = &Element{in.Value, in.Count}
|
|
||||||
s.mon[in.Value] = e
|
|
||||||
} else {
|
|
||||||
e = s.min
|
|
||||||
delete(s.mon, e.Value)
|
|
||||||
e.Value = in.Value
|
|
||||||
e.Count += in.Count
|
|
||||||
s.min = e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if e.Count < s.min.Count {
|
|
||||||
s.min = e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Stream) Query() Samples {
|
|
||||||
var sm Samples
|
|
||||||
for _, e := range s.mon {
|
|
||||||
sm = append(sm, e)
|
|
||||||
}
|
|
||||||
sort.Sort(sort.Reverse(sm))
|
|
||||||
|
|
||||||
if len(sm) < s.k {
|
|
||||||
return sm
|
|
||||||
}
|
|
||||||
|
|
||||||
return sm[:s.k]
|
|
||||||
}
|
|
57
vendor/github.com/beorn7/perks/topk/topk_test.go
generated
vendored
57
vendor/github.com/beorn7/perks/topk/topk_test.go
generated
vendored
|
@ -1,57 +0,0 @@
|
||||||
package topk
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"math/rand"
|
|
||||||
"sort"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestTopK(t *testing.T) {
|
|
||||||
stream := New(10)
|
|
||||||
ss := []*Stream{New(10), New(10), New(10)}
|
|
||||||
m := make(map[string]int)
|
|
||||||
for _, s := range ss {
|
|
||||||
for i := 0; i < 1e6; i++ {
|
|
||||||
v := fmt.Sprintf("%x", int8(rand.ExpFloat64()))
|
|
||||||
s.Insert(v)
|
|
||||||
m[v]++
|
|
||||||
}
|
|
||||||
stream.Merge(s.Query())
|
|
||||||
}
|
|
||||||
|
|
||||||
var sm Samples
|
|
||||||
for x, s := range m {
|
|
||||||
sm = append(sm, &Element{x, s})
|
|
||||||
}
|
|
||||||
sort.Sort(sort.Reverse(sm))
|
|
||||||
|
|
||||||
g := stream.Query()
|
|
||||||
if len(g) != 10 {
|
|
||||||
t.Fatalf("got %d, want 10", len(g))
|
|
||||||
}
|
|
||||||
for i, e := range g {
|
|
||||||
if sm[i].Value != e.Value {
|
|
||||||
t.Errorf("at %d: want %q, got %q", i, sm[i].Value, e.Value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestQuery(t *testing.T) {
|
|
||||||
queryTests := []struct {
|
|
||||||
value string
|
|
||||||
expected int
|
|
||||||
}{
|
|
||||||
{"a", 1},
|
|
||||||
{"b", 2},
|
|
||||||
{"c", 2},
|
|
||||||
}
|
|
||||||
|
|
||||||
stream := New(2)
|
|
||||||
for _, tt := range queryTests {
|
|
||||||
stream.Insert(tt.value)
|
|
||||||
if n := len(stream.Query()); n != tt.expected {
|
|
||||||
t.Errorf("want %d, got %d", tt.expected, n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
1
vendor/github.com/flosch/pongo2/.gitignore
generated
vendored
1
vendor/github.com/flosch/pongo2/.gitignore
generated
vendored
|
@ -7,7 +7,6 @@
|
||||||
_obj
|
_obj
|
||||||
_test
|
_test
|
||||||
.idea
|
.idea
|
||||||
.vscode
|
|
||||||
|
|
||||||
# Architecture specific extensions/prefixes
|
# Architecture specific extensions/prefixes
|
||||||
*.[568vq]
|
*.[568vq]
|
||||||
|
|
5
vendor/github.com/flosch/pongo2/.travis.yml
generated
vendored
5
vendor/github.com/flosch/pongo2/.travis.yml
generated
vendored
|
@ -1,13 +1,12 @@
|
||||||
language: go
|
language: go
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.7
|
- 1.3
|
||||||
- tip
|
- tip
|
||||||
install:
|
install:
|
||||||
- go get golang.org/x/tools/cmd/cover
|
- go get code.google.com/p/go.tools/cmd/cover
|
||||||
- go get github.com/mattn/goveralls
|
- go get github.com/mattn/goveralls
|
||||||
- go get gopkg.in/check.v1
|
- go get gopkg.in/check.v1
|
||||||
- go get github.com/juju/errors
|
|
||||||
script:
|
script:
|
||||||
- go test -v -covermode=count -coverprofile=coverage.out -bench . -cpu 1,4
|
- go test -v -covermode=count -coverprofile=coverage.out -bench . -cpu 1,4
|
||||||
- '[ "${TRAVIS_PULL_REQUEST}" = "false" ] && $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci -repotoken $COVERALLS_TOKEN || true'
|
- '[ "${TRAVIS_PULL_REQUEST}" = "false" ] && $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci -repotoken $COVERALLS_TOKEN || true'
|
||||||
|
|
19
vendor/github.com/flosch/pongo2/README.md
generated
vendored
19
vendor/github.com/flosch/pongo2/README.md
generated
vendored
|
@ -1,9 +1,8 @@
|
||||||
# [pongo](https://en.wikipedia.org/wiki/Pongo_%28genus%29)2
|
# [pongo](https://en.wikipedia.org/wiki/Pongo_%28genus%29)2
|
||||||
|
|
||||||
[![Join the chat at https://gitter.im/flosch/pongo2](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/flosch/pongo2)
|
[![GoDoc](https://godoc.org/github.com/flosch/pongo2?status.png)](https://godoc.org/github.com/flosch/pongo2)
|
||||||
[![GoDoc](https://godoc.org/github.com/flosch/pongo2?status.svg)](https://godoc.org/github.com/flosch/pongo2)
|
|
||||||
[![Build Status](https://travis-ci.org/flosch/pongo2.svg?branch=master)](https://travis-ci.org/flosch/pongo2)
|
[![Build Status](https://travis-ci.org/flosch/pongo2.svg?branch=master)](https://travis-ci.org/flosch/pongo2)
|
||||||
[![Coverage Status](https://coveralls.io/repos/flosch/pongo2/badge.svg?branch=master)](https://coveralls.io/r/flosch/pongo2?branch=master)
|
[![Coverage Status](https://coveralls.io/repos/flosch/pongo2/badge.png?branch=master)](https://coveralls.io/r/flosch/pongo2?branch=master)
|
||||||
[![gratipay](http://img.shields.io/badge/gratipay-support%20pongo-brightgreen.svg)](https://gratipay.com/flosch/)
|
[![gratipay](http://img.shields.io/badge/gratipay-support%20pongo-brightgreen.svg)](https://gratipay.com/flosch/)
|
||||||
[![Bountysource](https://www.bountysource.com/badge/tracker?tracker_id=3654947)](https://www.bountysource.com/trackers/3654947-pongo2?utm_source=3654947&utm_medium=shield&utm_campaign=TRACKER_BADGE)
|
[![Bountysource](https://www.bountysource.com/badge/tracker?tracker_id=3654947)](https://www.bountysource.com/trackers/3654947-pongo2?utm_source=3654947&utm_medium=shield&utm_campaign=TRACKER_BADGE)
|
||||||
|
|
||||||
|
@ -96,7 +95,6 @@ Please also have a look on the [caveats](https://github.com/flosch/pongo2#caveat
|
||||||
|
|
||||||
If you're using the `master`-branch of pongo2, you might be interested in this section. Since pongo2 is still in development (even though there is a first stable release!), there could be (backwards-incompatible) API changes over time. To keep track of these and therefore make it painless for you to adapt your codebase, I'll list them here.
|
If you're using the `master`-branch of pongo2, you might be interested in this section. Since pongo2 is still in development (even though there is a first stable release!), there could be (backwards-incompatible) API changes over time. To keep track of these and therefore make it painless for you to adapt your codebase, I'll list them here.
|
||||||
|
|
||||||
* Function signature for tag execution changed: not taking a `bytes.Buffer` anymore; instead `Execute()`-functions are now taking a `TemplateWriter` interface.
|
|
||||||
* Function signature for tag and filter parsing/execution changed (`error` return type changed to `*Error`).
|
* Function signature for tag and filter parsing/execution changed (`error` return type changed to `*Error`).
|
||||||
* `INodeEvaluator` has been removed and got replaced by `IEvaluator`. You can change your existing tags/filters by simply replacing the interface.
|
* `INodeEvaluator` has been removed and got replaced by `IEvaluator`. You can change your existing tags/filters by simply replacing the interface.
|
||||||
* Two new helper functions: [`RenderTemplateFile()`](https://godoc.org/github.com/flosch/pongo2#RenderTemplateFile) and [`RenderTemplateString()`](https://godoc.org/github.com/flosch/pongo2#RenderTemplateString).
|
* Two new helper functions: [`RenderTemplateFile()`](https://godoc.org/github.com/flosch/pongo2#RenderTemplateFile) and [`RenderTemplateString()`](https://godoc.org/github.com/flosch/pongo2#RenderTemplateString).
|
||||||
|
@ -106,7 +104,7 @@ If you're using the `master`-branch of pongo2, you might be interested in this s
|
||||||
## How you can help
|
## How you can help
|
||||||
|
|
||||||
* Write [filters](https://github.com/flosch/pongo2/blob/master/filters_builtin.go#L3) / [tags](https://github.com/flosch/pongo2/blob/master/tags.go#L4) (see [tutorial](https://www.florian-schlachter.de/post/pongo2/)) by forking pongo2 and sending pull requests
|
* Write [filters](https://github.com/flosch/pongo2/blob/master/filters_builtin.go#L3) / [tags](https://github.com/flosch/pongo2/blob/master/tags.go#L4) (see [tutorial](https://www.florian-schlachter.de/post/pongo2/)) by forking pongo2 and sending pull requests
|
||||||
* Write/improve code tests (use the following command to see what tests are missing: `go test -v -cover -covermode=count -coverprofile=cover.out && go tool cover -html=cover.out` or have a look on [gocover.io/github.com/flosch/pongo2](http://gocover.io/github.com/flosch/pongo2))
|
* Write/improve code tests (use the following command to see what tests are missing: `go test -v -cover -covermode=count -coverprofile=cover.out && go tool cover -html=cover.out`)
|
||||||
* Write/improve template tests (see the `template_tests/` directory)
|
* Write/improve template tests (see the `template_tests/` directory)
|
||||||
* Write middleware, libraries and websites using pongo2. :-)
|
* Write middleware, libraries and websites using pongo2. :-)
|
||||||
|
|
||||||
|
@ -117,8 +115,7 @@ For a documentation on how the templating language works you can [head over to t
|
||||||
You can access pongo2's API documentation on [godoc](https://godoc.org/github.com/flosch/pongo2).
|
You can access pongo2's API documentation on [godoc](https://godoc.org/github.com/flosch/pongo2).
|
||||||
|
|
||||||
## Blog post series
|
## Blog post series
|
||||||
|
|
||||||
* [pongo2 v3 released](https://www.florian-schlachter.de/post/pongo2-v3/)
|
|
||||||
* [pongo2 v2 released](https://www.florian-schlachter.de/post/pongo2-v2/)
|
* [pongo2 v2 released](https://www.florian-schlachter.de/post/pongo2-v2/)
|
||||||
* [pongo2 1.0 released](https://www.florian-schlachter.de/post/pongo2-10/) [August 8th 2014]
|
* [pongo2 1.0 released](https://www.florian-schlachter.de/post/pongo2-10/) [August 8th 2014]
|
||||||
* [pongo2 playground](https://www.florian-schlachter.de/post/pongo2-playground/) [August 1st 2014]
|
* [pongo2 playground](https://www.florian-schlachter.de/post/pongo2-playground/) [August 1st 2014]
|
||||||
|
@ -157,12 +154,8 @@ You can access pongo2's API documentation on [godoc](https://godoc.org/github.co
|
||||||
* [beego-pongo2.v2](https://github.com/ipfans/beego-pongo2.v2) - Same as `beego-pongo2`, but for pongo2 v2.
|
* [beego-pongo2.v2](https://github.com/ipfans/beego-pongo2.v2) - Same as `beego-pongo2`, but for pongo2 v2.
|
||||||
* [macaron-pongo2](https://github.com/macaron-contrib/pongo2) - pongo2 support for [Macaron](https://github.com/Unknwon/macaron), a modular web framework.
|
* [macaron-pongo2](https://github.com/macaron-contrib/pongo2) - pongo2 support for [Macaron](https://github.com/Unknwon/macaron), a modular web framework.
|
||||||
* [ginpongo2](https://github.com/ngerakines/ginpongo2) - middleware for [gin](github.com/gin-gonic/gin) to use pongo2 templates
|
* [ginpongo2](https://github.com/ngerakines/ginpongo2) - middleware for [gin](github.com/gin-gonic/gin) to use pongo2 templates
|
||||||
* [Build'n support for Iris' template engine](https://github.com/kataras/iris)
|
* [pongo2-trans](https://github.com/fromYukki/pongo2trans) - `trans`-tag implementation for internationalization
|
||||||
* [pongo2gin](https://github.com/robvdl/pongo2gin) - alternative renderer for [gin](github.com/gin-gonic/gin) to use pongo2 templates
|
|
||||||
* [pongo2-trans](https://github.com/digitalcrab/pongo2trans) - `trans`-tag implementation for internationalization
|
|
||||||
* [tpongo2](https://github.com/tango-contrib/tpongo2) - pongo2 support for [Tango](https://github.com/lunny/tango), a micro-kernel & pluggable web framework.
|
|
||||||
* [p2cli](https://github.com/wrouesnel/p2cli) - command line templating utility based on pongo2
|
|
||||||
|
|
||||||
Please add your project to this list and send me a pull request when you've developed something nice for pongo2.
|
Please add your project to this list and send me a pull request when you've developed something nice for pongo2.
|
||||||
|
|
||||||
# API-usage examples
|
# API-usage examples
|
||||||
|
|
30
vendor/github.com/flosch/pongo2/context.go
generated
vendored
30
vendor/github.com/flosch/pongo2/context.go
generated
vendored
|
@ -1,14 +1,13 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"github.com/juju/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var reIdentifiers = regexp.MustCompile("^[a-zA-Z0-9_]+$")
|
var reIdentifiers = regexp.MustCompile("^[a-zA-Z0-9_]+$")
|
||||||
|
|
||||||
// A Context type provides constants, variables, instances or functions to a template.
|
// Use this Context type to provide constants, variables, instances or functions to your template.
|
||||||
//
|
//
|
||||||
// pongo2 automatically provides meta-information or functions through the "pongo2"-key.
|
// pongo2 automatically provides meta-information or functions through the "pongo2"-key.
|
||||||
// Currently, context["pongo2"] contains the following keys:
|
// Currently, context["pongo2"] contains the following keys:
|
||||||
|
@ -25,15 +24,14 @@ func (c Context) checkForValidIdentifiers() *Error {
|
||||||
for k, v := range c {
|
for k, v := range c {
|
||||||
if !reIdentifiers.MatchString(k) {
|
if !reIdentifiers.MatchString(k) {
|
||||||
return &Error{
|
return &Error{
|
||||||
Sender: "checkForValidIdentifiers",
|
Sender: "checkForValidIdentifiers",
|
||||||
OrigError: errors.Errorf("context-key '%s' (value: '%+v') is not a valid identifier", k, v),
|
ErrorMsg: fmt.Sprintf("Context-key '%s' (value: '%+v') is not a valid identifier.", k, v),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update updates this context with the key/value-pairs from another context.
|
|
||||||
func (c Context) Update(other Context) Context {
|
func (c Context) Update(other Context) Context {
|
||||||
for k, v := range other {
|
for k, v := range other {
|
||||||
c[k] = v
|
c[k] = v
|
||||||
|
@ -41,8 +39,6 @@ func (c Context) Update(other Context) Context {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecutionContext contains all data important for the current rendering state.
|
|
||||||
//
|
|
||||||
// If you're writing a custom tag, your tag's Execute()-function will
|
// If you're writing a custom tag, your tag's Execute()-function will
|
||||||
// have access to the ExecutionContext. This struct stores anything
|
// have access to the ExecutionContext. This struct stores anything
|
||||||
// about the current rendering process's Context including
|
// about the current rendering process's Context including
|
||||||
|
@ -101,10 +97,6 @@ func NewChildExecutionContext(parent *ExecutionContext) *ExecutionContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *ExecutionContext) Error(msg string, token *Token) *Error {
|
func (ctx *ExecutionContext) Error(msg string, token *Token) *Error {
|
||||||
return ctx.OrigError(errors.New(msg), token)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *ExecutionContext) OrigError(err error, token *Token) *Error {
|
|
||||||
filename := ctx.template.name
|
filename := ctx.template.name
|
||||||
var line, col int
|
var line, col int
|
||||||
if token != nil {
|
if token != nil {
|
||||||
|
@ -115,13 +107,13 @@ func (ctx *ExecutionContext) OrigError(err error, token *Token) *Error {
|
||||||
col = token.Col
|
col = token.Col
|
||||||
}
|
}
|
||||||
return &Error{
|
return &Error{
|
||||||
Template: ctx.template,
|
Template: ctx.template,
|
||||||
Filename: filename,
|
Filename: filename,
|
||||||
Line: line,
|
Line: line,
|
||||||
Column: col,
|
Column: col,
|
||||||
Token: token,
|
Token: token,
|
||||||
Sender: "execution",
|
Sender: "execution",
|
||||||
OrigError: err,
|
ErrorMsg: msg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
vendor/github.com/flosch/pongo2/docs/examples.md
generated
vendored
1
vendor/github.com/flosch/pongo2/docs/examples.md
generated
vendored
|
@ -1 +0,0 @@
|
||||||
(Stub, TBA)
|
|
68
vendor/github.com/flosch/pongo2/docs/filters.md
generated
vendored
68
vendor/github.com/flosch/pongo2/docs/filters.md
generated
vendored
|
@ -1,68 +0,0 @@
|
||||||
TODO:
|
|
||||||
|
|
||||||
* What are filters?
|
|
||||||
* List+explain all existing filters (pongo2 + pongo2-addons)
|
|
||||||
|
|
||||||
Implemented filters so far which needs documentation:
|
|
||||||
|
|
||||||
* escape
|
|
||||||
* safe
|
|
||||||
* escapejs
|
|
||||||
* add
|
|
||||||
* addslashes
|
|
||||||
* capfirst
|
|
||||||
* center
|
|
||||||
* cut
|
|
||||||
* date
|
|
||||||
* default
|
|
||||||
* default_if_none
|
|
||||||
* divisibleby
|
|
||||||
* first
|
|
||||||
* floatformat
|
|
||||||
* get_digit
|
|
||||||
* iriencode
|
|
||||||
* join
|
|
||||||
* last
|
|
||||||
* length
|
|
||||||
* length_is
|
|
||||||
* linebreaks
|
|
||||||
* linebreaksbr
|
|
||||||
* linenumbers
|
|
||||||
* ljust
|
|
||||||
* lower
|
|
||||||
* make_list
|
|
||||||
* phone2numeric
|
|
||||||
* pluralize
|
|
||||||
* random
|
|
||||||
* removetags
|
|
||||||
* rjust
|
|
||||||
* slice
|
|
||||||
* stringformat
|
|
||||||
* striptags
|
|
||||||
* time
|
|
||||||
* title
|
|
||||||
* truncatechars
|
|
||||||
* truncatechars_html
|
|
||||||
* truncatewords
|
|
||||||
* truncatewords_html
|
|
||||||
* upper
|
|
||||||
* urlencode
|
|
||||||
* urlize
|
|
||||||
* urlizetrunc
|
|
||||||
* wordcount
|
|
||||||
* wordwrap
|
|
||||||
* yesno
|
|
||||||
|
|
||||||
* filesizeformat*
|
|
||||||
* slugify*
|
|
||||||
* truncatesentences*
|
|
||||||
* truncatesentences_html*
|
|
||||||
* markdown*
|
|
||||||
* intcomma*
|
|
||||||
* ordinal*
|
|
||||||
* naturalday*
|
|
||||||
* timesince*
|
|
||||||
* timeuntil*
|
|
||||||
* naturaltime*
|
|
||||||
|
|
||||||
Filters marked with * are available through [pongo2-addons](https://github.com/flosch/pongo2-addons).
|
|
1
vendor/github.com/flosch/pongo2/docs/index.md
generated
vendored
1
vendor/github.com/flosch/pongo2/docs/index.md
generated
vendored
|
@ -1 +0,0 @@
|
||||||
(Stub, TBA)
|
|
1
vendor/github.com/flosch/pongo2/docs/macros.md
generated
vendored
1
vendor/github.com/flosch/pongo2/docs/macros.md
generated
vendored
|
@ -1 +0,0 @@
|
||||||
(Stub, TBA)
|
|
31
vendor/github.com/flosch/pongo2/docs/tags.md
generated
vendored
31
vendor/github.com/flosch/pongo2/docs/tags.md
generated
vendored
|
@ -1,31 +0,0 @@
|
||||||
TODO:
|
|
||||||
|
|
||||||
* What are tags?
|
|
||||||
* List+explain all existing tags (pongo2 + pongo2-addons)
|
|
||||||
|
|
||||||
Implemented tags so far which needs documentation:
|
|
||||||
|
|
||||||
* autoescape
|
|
||||||
* block
|
|
||||||
* comment
|
|
||||||
* cycle
|
|
||||||
* extends
|
|
||||||
* filter
|
|
||||||
* firstof
|
|
||||||
* for
|
|
||||||
* if
|
|
||||||
* ifchanged
|
|
||||||
* ifequal
|
|
||||||
* ifnotequal
|
|
||||||
* import
|
|
||||||
* include
|
|
||||||
* lorem
|
|
||||||
* macro
|
|
||||||
* now
|
|
||||||
* set
|
|
||||||
* spaceless
|
|
||||||
* ssi
|
|
||||||
* templatetag
|
|
||||||
* verbatim
|
|
||||||
* widthratio
|
|
||||||
* with
|
|
1
vendor/github.com/flosch/pongo2/docs/template_sets.md
generated
vendored
1
vendor/github.com/flosch/pongo2/docs/template_sets.md
generated
vendored
|
@ -1 +0,0 @@
|
||||||
(Stub, TBA)
|
|
0
vendor/github.com/flosch/pongo2/docs/write_filters.md
generated
vendored
0
vendor/github.com/flosch/pongo2/docs/write_filters.md
generated
vendored
0
vendor/github.com/flosch/pongo2/docs/write_tags.md
generated
vendored
0
vendor/github.com/flosch/pongo2/docs/write_tags.md
generated
vendored
37
vendor/github.com/flosch/pongo2/error.go
generated
vendored
37
vendor/github.com/flosch/pongo2/error.go
generated
vendored
|
@ -6,20 +6,20 @@ import (
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The Error type is being used to address an error during lexing, parsing or
|
// This Error type is being used to address an error during lexing, parsing or
|
||||||
// execution. If you want to return an error object (for example in your own
|
// execution. If you want to return an error object (for example in your own
|
||||||
// tag or filter) fill this object with as much information as you have.
|
// tag or filter) fill this object with as much information as you have.
|
||||||
// Make sure "Sender" is always given (if you're returning an error within
|
// Make sure "Sender" is always given (if you're returning an error within
|
||||||
// a filter, make Sender equals 'filter:yourfilter'; same goes for tags: 'tag:mytag').
|
// a filter, make Sender equals 'filter:yourfilter'; same goes for tags: 'tag:mytag').
|
||||||
// It's okay if you only fill in ErrorMsg if you don't have any other details at hand.
|
// It's okay if you only fill in ErrorMsg if you don't have any other details at hand.
|
||||||
type Error struct {
|
type Error struct {
|
||||||
Template *Template
|
Template *Template
|
||||||
Filename string
|
Filename string
|
||||||
Line int
|
Line int
|
||||||
Column int
|
Column int
|
||||||
Token *Token
|
Token *Token
|
||||||
Sender string
|
Sender string
|
||||||
OrigError error
|
ErrorMsg string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Error) updateFromTokenIfNeeded(template *Template, t *Token) *Error {
|
func (e *Error) updateFromTokenIfNeeded(template *Template, t *Token) *Error {
|
||||||
|
@ -54,14 +54,14 @@ func (e *Error) Error() string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s += "] "
|
s += "] "
|
||||||
s += e.OrigError.Error()
|
s += e.ErrorMsg
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// RawLine returns the affected line from the original template, if available.
|
// Returns the affected line from the original template, if available.
|
||||||
func (e *Error) RawLine() (line string, available bool, outErr error) {
|
func (e *Error) RawLine() (line string, available bool) {
|
||||||
if e.Line <= 0 || e.Filename == "<string>" {
|
if e.Line <= 0 || e.Filename == "<string>" {
|
||||||
return "", false, nil
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
filename := e.Filename
|
filename := e.Filename
|
||||||
|
@ -70,22 +70,17 @@ func (e *Error) RawLine() (line string, available bool, outErr error) {
|
||||||
}
|
}
|
||||||
file, err := os.Open(filename)
|
file, err := os.Open(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", false, err
|
panic(err)
|
||||||
}
|
}
|
||||||
defer func() {
|
defer file.Close()
|
||||||
err := file.Close()
|
|
||||||
if err != nil && outErr == nil {
|
|
||||||
outErr = err
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
scanner := bufio.NewScanner(file)
|
scanner := bufio.NewScanner(file)
|
||||||
l := 0
|
l := 0
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
l++
|
l++
|
||||||
if l == e.Line {
|
if l == e.Line {
|
||||||
return scanner.Text(), true, nil
|
return scanner.Text(), true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "", false, nil
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
54
vendor/github.com/flosch/pongo2/filters.go
generated
vendored
54
vendor/github.com/flosch/pongo2/filters.go
generated
vendored
|
@ -2,11 +2,8 @@ package pongo2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/juju/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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) (out *Value, err *Error)
|
||||||
|
|
||||||
var filters map[string]FilterFunction
|
var filters map[string]FilterFunction
|
||||||
|
@ -15,38 +12,32 @@ func init() {
|
||||||
filters = make(map[string]FilterFunction)
|
filters = make(map[string]FilterFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterExists returns true if the given filter is already registered
|
// Registers a new filter. If there's already a filter with the same
|
||||||
func FilterExists(name string) bool {
|
|
||||||
_, existing := filters[name]
|
|
||||||
return existing
|
|
||||||
}
|
|
||||||
|
|
||||||
// RegisterFilter registers a new filter. If there's already a filter with the same
|
|
||||||
// name, RegisterFilter will panic. You usually want to call this
|
// name, RegisterFilter will panic. You usually want to call this
|
||||||
// function in the filter's init() function:
|
// function in the filter's init() function:
|
||||||
// http://golang.org/doc/effective_go.html#init
|
// http://golang.org/doc/effective_go.html#init
|
||||||
//
|
//
|
||||||
// See http://www.florian-schlachter.de/post/pongo2/ for more about
|
// See http://www.florian-schlachter.de/post/pongo2/ for more about
|
||||||
// writing filters and tags.
|
// writing filters and tags.
|
||||||
func RegisterFilter(name string, fn FilterFunction) error {
|
func RegisterFilter(name string, fn FilterFunction) {
|
||||||
if FilterExists(name) {
|
_, existing := filters[name]
|
||||||
return errors.Errorf("filter with name '%s' is already registered", name)
|
if existing {
|
||||||
|
panic(fmt.Sprintf("Filter with name '%s' is already registered.", name))
|
||||||
}
|
}
|
||||||
filters[name] = fn
|
filters[name] = fn
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReplaceFilter replaces an already registered filter with a new implementation. Use this
|
// Replaces an already registered filter with a new implementation. Use this
|
||||||
// function with caution since it allows you to change existing filter behaviour.
|
// function with caution since it allows you to change existing filter behaviour.
|
||||||
func ReplaceFilter(name string, fn FilterFunction) error {
|
func ReplaceFilter(name string, fn FilterFunction) {
|
||||||
if !FilterExists(name) {
|
_, existing := filters[name]
|
||||||
return errors.Errorf("filter with name '%s' does not exist (therefore cannot be overridden)", name)
|
if !existing {
|
||||||
|
panic(fmt.Sprintf("Filter with name '%s' does not exist (therefore cannot be overridden).", name))
|
||||||
}
|
}
|
||||||
filters[name] = fn
|
filters[name] = fn
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustApplyFilter behaves like ApplyFilter, but panics on an error.
|
// Like ApplyFilter, but panics on an error
|
||||||
func MustApplyFilter(name string, value *Value, param *Value) *Value {
|
func MustApplyFilter(name string, value *Value, param *Value) *Value {
|
||||||
val, err := ApplyFilter(name, value, param)
|
val, err := ApplyFilter(name, value, param)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -55,14 +46,13 @@ func MustApplyFilter(name string, value *Value, param *Value) *Value {
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApplyFilter applies a filter to a given value using the given parameters.
|
// Applies a filter to a given value using the given parameters. Returns a *pongo2.Value or an error.
|
||||||
// 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) (*Value, *Error) {
|
||||||
fn, existing := filters[name]
|
fn, existing := filters[name]
|
||||||
if !existing {
|
if !existing {
|
||||||
return nil, &Error{
|
return nil, &Error{
|
||||||
Sender: "applyfilter",
|
Sender: "applyfilter",
|
||||||
OrigError: errors.Errorf("Filter with name '%s' not found.", name),
|
ErrorMsg: fmt.Sprintf("Filter with name '%s' not found.", name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,31 +86,31 @@ func (fc *filterCall) Execute(v *Value, ctx *ExecutionContext) (*Value, *Error)
|
||||||
param = AsValue(nil)
|
param = AsValue(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
filteredValue, err := fc.filterFunc(v, param)
|
filtered_value, err := fc.filterFunc(v, param)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err.updateFromTokenIfNeeded(ctx.template, fc.token)
|
return nil, err.updateFromTokenIfNeeded(ctx.template, fc.token)
|
||||||
}
|
}
|
||||||
return filteredValue, nil
|
return filtered_value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter = IDENT | IDENT ":" FilterArg | IDENT "|" Filter
|
// Filter = IDENT | IDENT ":" FilterArg | IDENT "|" Filter
|
||||||
func (p *Parser) parseFilter() (*filterCall, *Error) {
|
func (p *Parser) parseFilter() (*filterCall, *Error) {
|
||||||
identToken := p.MatchType(TokenIdentifier)
|
ident_token := p.MatchType(TokenIdentifier)
|
||||||
|
|
||||||
// Check filter ident
|
// Check filter ident
|
||||||
if identToken == nil {
|
if ident_token == nil {
|
||||||
return nil, p.Error("Filter name must be an identifier.", nil)
|
return nil, p.Error("Filter name must be an identifier.", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
filter := &filterCall{
|
filter := &filterCall{
|
||||||
token: identToken,
|
token: ident_token,
|
||||||
name: identToken.Val,
|
name: ident_token.Val,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the appropriate filter function and bind it
|
// Get the appropriate filter function and bind it
|
||||||
filterFn, exists := filters[identToken.Val]
|
filterFn, exists := filters[ident_token.Val]
|
||||||
if !exists {
|
if !exists {
|
||||||
return nil, p.Error(fmt.Sprintf("Filter '%s' does not exist.", identToken.Val), identToken)
|
return nil, p.Error(fmt.Sprintf("Filter '%s' does not exist.", ident_token.Val), ident_token)
|
||||||
}
|
}
|
||||||
|
|
||||||
filter.filterFunc = filterFn
|
filter.filterFunc = filterFn
|
||||||
|
|
178
vendor/github.com/flosch/pongo2/filters_builtin.go
generated
vendored
178
vendor/github.com/flosch/pongo2/filters_builtin.go
generated
vendored
|
@ -35,8 +35,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/juju/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -75,15 +73,14 @@ func init() {
|
||||||
RegisterFilter("removetags", filterRemovetags)
|
RegisterFilter("removetags", filterRemovetags)
|
||||||
RegisterFilter("rjust", filterRjust)
|
RegisterFilter("rjust", filterRjust)
|
||||||
RegisterFilter("slice", filterSlice)
|
RegisterFilter("slice", filterSlice)
|
||||||
RegisterFilter("split", filterSplit)
|
|
||||||
RegisterFilter("stringformat", filterStringformat)
|
RegisterFilter("stringformat", filterStringformat)
|
||||||
RegisterFilter("striptags", filterStriptags)
|
RegisterFilter("striptags", filterStriptags)
|
||||||
RegisterFilter("time", filterDate) // time uses filterDate (same golang-format)
|
RegisterFilter("time", filterDate) // time uses filterDate (same golang-format)
|
||||||
RegisterFilter("title", filterTitle)
|
RegisterFilter("title", filterTitle)
|
||||||
RegisterFilter("truncatechars", filterTruncatechars)
|
RegisterFilter("truncatechars", filterTruncatechars)
|
||||||
RegisterFilter("truncatechars_html", filterTruncatecharsHTML)
|
RegisterFilter("truncatechars_html", filterTruncatecharsHtml)
|
||||||
RegisterFilter("truncatewords", filterTruncatewords)
|
RegisterFilter("truncatewords", filterTruncatewords)
|
||||||
RegisterFilter("truncatewords_html", filterTruncatewordsHTML)
|
RegisterFilter("truncatewords_html", filterTruncatewordsHtml)
|
||||||
RegisterFilter("upper", filterUpper)
|
RegisterFilter("upper", filterUpper)
|
||||||
RegisterFilter("urlencode", filterUrlencode)
|
RegisterFilter("urlencode", filterUrlencode)
|
||||||
RegisterFilter("urlize", filterUrlize)
|
RegisterFilter("urlize", filterUrlize)
|
||||||
|
@ -108,9 +105,9 @@ func filterTruncatecharsHelper(s string, newLen int) string {
|
||||||
return string(runes)
|
return string(runes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterTruncateHTMLHelper(value string, newOutput *bytes.Buffer, cond func() bool, fn func(c rune, s int, idx int) int, finalize func()) {
|
func filterTruncateHtmlHelper(value string, new_output *bytes.Buffer, cond func() bool, fn func(c rune, s int, idx int) int, finalize func()) {
|
||||||
vLen := len(value)
|
vLen := len(value)
|
||||||
var tagStack []string
|
tag_stack := make([]string, 0)
|
||||||
idx := 0
|
idx := 0
|
||||||
|
|
||||||
for idx < vLen && !cond() {
|
for idx < vLen && !cond() {
|
||||||
|
@ -121,17 +118,17 @@ func filterTruncateHTMLHelper(value string, newOutput *bytes.Buffer, cond func()
|
||||||
}
|
}
|
||||||
|
|
||||||
if c == '<' {
|
if c == '<' {
|
||||||
newOutput.WriteRune(c)
|
new_output.WriteRune(c)
|
||||||
idx += s // consume "<"
|
idx += s // consume "<"
|
||||||
|
|
||||||
if idx+1 < vLen {
|
if idx+1 < vLen {
|
||||||
if value[idx] == '/' {
|
if value[idx] == '/' {
|
||||||
// Close tag
|
// Close tag
|
||||||
|
|
||||||
newOutput.WriteString("/")
|
new_output.WriteString("/")
|
||||||
|
|
||||||
tag := ""
|
tag := ""
|
||||||
idx++ // consume "/"
|
idx += 1 // consume "/"
|
||||||
|
|
||||||
for idx < vLen {
|
for idx < vLen {
|
||||||
c2, size2 := utf8.DecodeRuneInString(value[idx:])
|
c2, size2 := utf8.DecodeRuneInString(value[idx:])
|
||||||
|
@ -149,21 +146,21 @@ func filterTruncateHTMLHelper(value string, newOutput *bytes.Buffer, cond func()
|
||||||
idx += size2
|
idx += size2
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(tagStack) > 0 {
|
if len(tag_stack) > 0 {
|
||||||
// Ideally, the close tag is TOP of tag stack
|
// Ideally, the close tag is TOP of tag stack
|
||||||
// In malformed HTML, it must not be, so iterate through the stack and remove the tag
|
// In malformed HTML, it must not be, so iterate through the stack and remove the tag
|
||||||
for i := len(tagStack) - 1; i >= 0; i-- {
|
for i := len(tag_stack) - 1; i >= 0; i-- {
|
||||||
if tagStack[i] == tag {
|
if tag_stack[i] == tag {
|
||||||
// Found the tag
|
// Found the tag
|
||||||
tagStack[i] = tagStack[len(tagStack)-1]
|
tag_stack[i] = tag_stack[len(tag_stack)-1]
|
||||||
tagStack = tagStack[:len(tagStack)-1]
|
tag_stack = tag_stack[:len(tag_stack)-1]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newOutput.WriteString(tag)
|
new_output.WriteString(tag)
|
||||||
newOutput.WriteString(">")
|
new_output.WriteString(">")
|
||||||
} else {
|
} else {
|
||||||
// Open tag
|
// Open tag
|
||||||
|
|
||||||
|
@ -177,7 +174,7 @@ func filterTruncateHTMLHelper(value string, newOutput *bytes.Buffer, cond func()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
newOutput.WriteRune(c2)
|
new_output.WriteRune(c2)
|
||||||
|
|
||||||
// End of tag found
|
// End of tag found
|
||||||
if c2 == '>' {
|
if c2 == '>' {
|
||||||
|
@ -197,7 +194,7 @@ func filterTruncateHTMLHelper(value string, newOutput *bytes.Buffer, cond func()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add tag to stack
|
// Add tag to stack
|
||||||
tagStack = append(tagStack, tag)
|
tag_stack = append(tag_stack, tag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -207,10 +204,10 @@ func filterTruncateHTMLHelper(value string, newOutput *bytes.Buffer, cond func()
|
||||||
|
|
||||||
finalize()
|
finalize()
|
||||||
|
|
||||||
for i := len(tagStack) - 1; i >= 0; i-- {
|
for i := len(tag_stack) - 1; i >= 0; i-- {
|
||||||
tag := tagStack[i]
|
tag := tag_stack[i]
|
||||||
// Close everything from the regular tag stack
|
// Close everything from the regular tag stack
|
||||||
newOutput.WriteString(fmt.Sprintf("</%s>", tag))
|
new_output.WriteString(fmt.Sprintf("</%s>", tag))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,28 +217,28 @@ func filterTruncatechars(in *Value, param *Value) (*Value, *Error) {
|
||||||
return AsValue(filterTruncatecharsHelper(s, newLen)), nil
|
return AsValue(filterTruncatecharsHelper(s, newLen)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterTruncatecharsHTML(in *Value, param *Value) (*Value, *Error) {
|
func filterTruncatecharsHtml(in *Value, param *Value) (*Value, *Error) {
|
||||||
value := in.String()
|
value := in.String()
|
||||||
newLen := max(param.Integer()-3, 0)
|
newLen := max(param.Integer()-3, 0)
|
||||||
|
|
||||||
newOutput := bytes.NewBuffer(nil)
|
new_output := bytes.NewBuffer(nil)
|
||||||
|
|
||||||
textcounter := 0
|
textcounter := 0
|
||||||
|
|
||||||
filterTruncateHTMLHelper(value, newOutput, func() bool {
|
filterTruncateHtmlHelper(value, new_output, func() bool {
|
||||||
return textcounter >= newLen
|
return textcounter >= newLen
|
||||||
}, func(c rune, s int, idx int) int {
|
}, func(c rune, s int, idx int) int {
|
||||||
textcounter++
|
textcounter++
|
||||||
newOutput.WriteRune(c)
|
new_output.WriteRune(c)
|
||||||
|
|
||||||
return idx + s
|
return idx + s
|
||||||
}, func() {
|
}, func() {
|
||||||
if textcounter >= newLen && textcounter < len(value) {
|
if textcounter >= newLen && textcounter < len(value) {
|
||||||
newOutput.WriteString("...")
|
new_output.WriteString("...")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return AsSafeValue(newOutput.String()), nil
|
return AsSafeValue(new_output.String()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterTruncatewords(in *Value, param *Value) (*Value, *Error) {
|
func filterTruncatewords(in *Value, param *Value) (*Value, *Error) {
|
||||||
|
@ -263,19 +260,19 @@ func filterTruncatewords(in *Value, param *Value) (*Value, *Error) {
|
||||||
return AsValue(strings.Join(out, " ")), nil
|
return AsValue(strings.Join(out, " ")), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterTruncatewordsHTML(in *Value, param *Value) (*Value, *Error) {
|
func filterTruncatewordsHtml(in *Value, param *Value) (*Value, *Error) {
|
||||||
value := in.String()
|
value := in.String()
|
||||||
newLen := max(param.Integer(), 0)
|
newLen := max(param.Integer(), 0)
|
||||||
|
|
||||||
newOutput := bytes.NewBuffer(nil)
|
new_output := bytes.NewBuffer(nil)
|
||||||
|
|
||||||
wordcounter := 0
|
wordcounter := 0
|
||||||
|
|
||||||
filterTruncateHTMLHelper(value, newOutput, func() bool {
|
filterTruncateHtmlHelper(value, new_output, func() bool {
|
||||||
return wordcounter >= newLen
|
return wordcounter >= newLen
|
||||||
}, func(_ rune, _ int, idx int) int {
|
}, func(_ rune, _ int, idx int) int {
|
||||||
// Get next word
|
// Get next word
|
||||||
wordFound := false
|
word_found := false
|
||||||
|
|
||||||
for idx < len(value) {
|
for idx < len(value) {
|
||||||
c2, size2 := utf8.DecodeRuneInString(value[idx:])
|
c2, size2 := utf8.DecodeRuneInString(value[idx:])
|
||||||
|
@ -289,29 +286,29 @@ func filterTruncatewordsHTML(in *Value, param *Value) (*Value, *Error) {
|
||||||
return idx
|
return idx
|
||||||
}
|
}
|
||||||
|
|
||||||
newOutput.WriteRune(c2)
|
new_output.WriteRune(c2)
|
||||||
idx += size2
|
idx += size2
|
||||||
|
|
||||||
if c2 == ' ' || c2 == '.' || c2 == ',' || c2 == ';' {
|
if c2 == ' ' || c2 == '.' || c2 == ',' || c2 == ';' {
|
||||||
// Word ends here, stop capturing it now
|
// Word ends here, stop capturing it now
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
wordFound = true
|
word_found = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if wordFound {
|
if word_found {
|
||||||
wordcounter++
|
wordcounter++
|
||||||
}
|
}
|
||||||
|
|
||||||
return idx
|
return idx
|
||||||
}, func() {
|
}, func() {
|
||||||
if wordcounter >= newLen {
|
if wordcounter >= newLen {
|
||||||
newOutput.WriteString("...")
|
new_output.WriteString("...")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return AsSafeValue(newOutput.String()), nil
|
return AsSafeValue(new_output.String()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterEscape(in *Value, param *Value) (*Value, *Error) {
|
func filterEscape(in *Value, param *Value) (*Value, *Error) {
|
||||||
|
@ -380,11 +377,12 @@ func filterAdd(in *Value, param *Value) (*Value, *Error) {
|
||||||
if in.IsNumber() && param.IsNumber() {
|
if in.IsNumber() && param.IsNumber() {
|
||||||
if in.IsFloat() || param.IsFloat() {
|
if in.IsFloat() || param.IsFloat() {
|
||||||
return AsValue(in.Float() + param.Float()), nil
|
return AsValue(in.Float() + param.Float()), nil
|
||||||
|
} else {
|
||||||
|
return AsValue(in.Integer() + param.Integer()), nil
|
||||||
}
|
}
|
||||||
return AsValue(in.Integer() + param.Integer()), nil
|
|
||||||
}
|
}
|
||||||
// If in/param is not a number, we're relying on the
|
// If in/param is not a number, we're relying on the
|
||||||
// Value's String() conversion and just add them both together
|
// Value's String() convertion and just add them both together
|
||||||
return AsValue(in.String() + param.String()), nil
|
return AsValue(in.String() + param.String()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,11 +550,11 @@ func filterCenter(in *Value, param *Value) (*Value, *Error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterDate(in *Value, param *Value) (*Value, *Error) {
|
func filterDate(in *Value, param *Value) (*Value, *Error) {
|
||||||
t, isTime := in.Interface().(time.Time)
|
t, is_time := in.Interface().(time.Time)
|
||||||
if !isTime {
|
if !is_time {
|
||||||
return nil, &Error{
|
return nil, &Error{
|
||||||
Sender: "filter:date",
|
Sender: "filter:date",
|
||||||
OrigError: errors.New("filter input argument must be of type 'time.Time'"),
|
ErrorMsg: "Filter input argument must be of type 'time.Time'.",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return AsValue(t.Format(param.String())), nil
|
return AsValue(t.Format(param.String())), nil
|
||||||
|
@ -614,12 +612,6 @@ func filterLinebreaks(in *Value, param *Value) (*Value, *Error) {
|
||||||
return AsValue(b.String()), nil
|
return AsValue(b.String()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterSplit(in *Value, param *Value) (*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) (*Value, *Error) {
|
||||||
return AsValue(strings.Replace(in.String(), "\n", "<br />", -1)), nil
|
return AsValue(strings.Replace(in.String(), "\n", "<br />", -1)), nil
|
||||||
}
|
}
|
||||||
|
@ -649,8 +641,7 @@ func filterUrlencode(in *Value, param *Value) (*Value, *Error) {
|
||||||
var filterUrlizeURLRegexp = regexp.MustCompile(`((((http|https)://)|www\.|((^|[ ])[0-9A-Za-z_\-]+(\.com|\.net|\.org|\.info|\.biz|\.de))))(?U:.*)([ ]+|$)`)
|
var filterUrlizeURLRegexp = regexp.MustCompile(`((((http|https)://)|www\.|((^|[ ])[0-9A-Za-z_\-]+(\.com|\.net|\.org|\.info|\.biz|\.de))))(?U:.*)([ ]+|$)`)
|
||||||
var filterUrlizeEmailRegexp = regexp.MustCompile(`(\w+@\w+\.\w{2,4})`)
|
var filterUrlizeEmailRegexp = regexp.MustCompile(`(\w+@\w+\.\w{2,4})`)
|
||||||
|
|
||||||
func filterUrlizeHelper(input string, autoescape bool, trunc int) (string, error) {
|
func filterUrlizeHelper(input string, autoescape bool, trunc int) string {
|
||||||
var soutErr error
|
|
||||||
sout := filterUrlizeURLRegexp.ReplaceAllStringFunc(input, func(raw_url string) string {
|
sout := filterUrlizeURLRegexp.ReplaceAllStringFunc(input, func(raw_url string) string {
|
||||||
var prefix string
|
var prefix string
|
||||||
var suffix string
|
var suffix string
|
||||||
|
@ -665,8 +656,7 @@ func filterUrlizeHelper(input string, autoescape bool, trunc int) (string, error
|
||||||
|
|
||||||
t, err := ApplyFilter("iriencode", AsValue(raw_url), nil)
|
t, err := ApplyFilter("iriencode", AsValue(raw_url), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
soutErr = err
|
panic(err)
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
url := t.String()
|
url := t.String()
|
||||||
|
|
||||||
|
@ -683,19 +673,16 @@ func filterUrlizeHelper(input string, autoescape bool, trunc int) (string, error
|
||||||
if autoescape {
|
if autoescape {
|
||||||
t, err := ApplyFilter("escape", AsValue(title), nil)
|
t, err := ApplyFilter("escape", AsValue(title), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
soutErr = err
|
panic(err)
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
title = t.String()
|
title = t.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf(`%s<a href="%s" rel="nofollow">%s</a>%s`, prefix, url, title, suffix)
|
return fmt.Sprintf(`%s<a href="%s" rel="nofollow">%s</a>%s`, prefix, url, title, suffix)
|
||||||
})
|
})
|
||||||
if soutErr != nil {
|
|
||||||
return "", soutErr
|
|
||||||
}
|
|
||||||
|
|
||||||
sout = filterUrlizeEmailRegexp.ReplaceAllStringFunc(sout, func(mail string) string {
|
sout = filterUrlizeEmailRegexp.ReplaceAllStringFunc(sout, func(mail string) string {
|
||||||
|
|
||||||
title := mail
|
title := mail
|
||||||
|
|
||||||
if trunc > 3 && len(title) > trunc {
|
if trunc > 3 && len(title) > trunc {
|
||||||
|
@ -705,7 +692,7 @@ func filterUrlizeHelper(input string, autoescape bool, trunc int) (string, error
|
||||||
return fmt.Sprintf(`<a href="mailto:%s">%s</a>`, mail, title)
|
return fmt.Sprintf(`<a href="mailto:%s">%s</a>`, mail, title)
|
||||||
})
|
})
|
||||||
|
|
||||||
return sout, nil
|
return sout
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterUrlize(in *Value, param *Value) (*Value, *Error) {
|
func filterUrlize(in *Value, param *Value) (*Value, *Error) {
|
||||||
|
@ -714,36 +701,24 @@ func filterUrlize(in *Value, param *Value) (*Value, *Error) {
|
||||||
autoescape = param.Bool()
|
autoescape = param.Bool()
|
||||||
}
|
}
|
||||||
|
|
||||||
s, err := filterUrlizeHelper(in.String(), autoescape, -1)
|
return AsValue(filterUrlizeHelper(in.String(), autoescape, -1)), nil
|
||||||
if err != nil {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return AsValue(s), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterUrlizetrunc(in *Value, param *Value) (*Value, *Error) {
|
func filterUrlizetrunc(in *Value, param *Value) (*Value, *Error) {
|
||||||
s, err := filterUrlizeHelper(in.String(), true, param.Integer())
|
return AsValue(filterUrlizeHelper(in.String(), true, param.Integer())), nil
|
||||||
if err != nil {
|
|
||||||
return nil, &Error{
|
|
||||||
Sender: "filter:urlizetrunc",
|
|
||||||
OrigError: errors.New("you cannot pass more than 2 arguments to filter 'pluralize'"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return AsValue(s), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterStringformat(in *Value, param *Value) (*Value, *Error) {
|
func filterStringformat(in *Value, param *Value) (*Value, *Error) {
|
||||||
return AsValue(fmt.Sprintf(param.String(), in.Interface())), nil
|
return AsValue(fmt.Sprintf(param.String(), in.Interface())), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var reStriptags = regexp.MustCompile("<[^>]*?>")
|
var re_striptags = regexp.MustCompile("<[^>]*?>")
|
||||||
|
|
||||||
func filterStriptags(in *Value, param *Value) (*Value, *Error) {
|
func filterStriptags(in *Value, param *Value) (*Value, *Error) {
|
||||||
s := in.String()
|
s := in.String()
|
||||||
|
|
||||||
// Strip all tags
|
// Strip all tags
|
||||||
s = reStriptags.ReplaceAllString(s, "")
|
s = re_striptags.ReplaceAllString(s, "")
|
||||||
|
|
||||||
return AsValue(strings.TrimSpace(s)), nil
|
return AsValue(strings.TrimSpace(s)), nil
|
||||||
}
|
}
|
||||||
|
@ -771,8 +746,8 @@ func filterPluralize(in *Value, param *Value) (*Value, *Error) {
|
||||||
endings := strings.Split(param.String(), ",")
|
endings := strings.Split(param.String(), ",")
|
||||||
if len(endings) > 2 {
|
if len(endings) > 2 {
|
||||||
return nil, &Error{
|
return nil, &Error{
|
||||||
Sender: "filter:pluralize",
|
Sender: "filter:pluralize",
|
||||||
OrigError: errors.New("you cannot pass more than 2 arguments to filter 'pluralize'"),
|
ErrorMsg: "You cannot pass more than 2 arguments to filter 'pluralize'.",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(endings) == 1 {
|
if len(endings) == 1 {
|
||||||
|
@ -795,10 +770,11 @@ func filterPluralize(in *Value, param *Value) (*Value, *Error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return AsValue(""), nil
|
return AsValue(""), nil
|
||||||
}
|
} else {
|
||||||
return nil, &Error{
|
return nil, &Error{
|
||||||
Sender: "filter:pluralize",
|
Sender: "filter:pluralize",
|
||||||
OrigError: errors.New("filter 'pluralize' does only work on numbers"),
|
ErrorMsg: "Filter 'pluralize' does only work on numbers.",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -831,8 +807,8 @@ func filterSlice(in *Value, param *Value) (*Value, *Error) {
|
||||||
comp := strings.Split(param.String(), ":")
|
comp := strings.Split(param.String(), ":")
|
||||||
if len(comp) != 2 {
|
if len(comp) != 2 {
|
||||||
return nil, &Error{
|
return nil, &Error{
|
||||||
Sender: "filter:slice",
|
Sender: "filter:slice",
|
||||||
OrigError: errors.New("Slice string must have the format 'from:to' [from/to can be omitted, but the ':' is required]"),
|
ErrorMsg: "Slice string must have the format 'from:to' [from/to can be omitted, but the ':' is required]",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -868,16 +844,16 @@ func filterWordcount(in *Value, param *Value) (*Value, *Error) {
|
||||||
|
|
||||||
func filterWordwrap(in *Value, param *Value) (*Value, *Error) {
|
func filterWordwrap(in *Value, param *Value) (*Value, *Error) {
|
||||||
words := strings.Fields(in.String())
|
words := strings.Fields(in.String())
|
||||||
wordsLen := len(words)
|
words_len := len(words)
|
||||||
wrapAt := param.Integer()
|
wrap_at := param.Integer()
|
||||||
if wrapAt <= 0 {
|
if wrap_at <= 0 {
|
||||||
return in, nil
|
return in, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
linecount := wordsLen/wrapAt + wordsLen%wrapAt
|
linecount := words_len/wrap_at + words_len%wrap_at
|
||||||
lines := make([]string, 0, linecount)
|
lines := make([]string, 0, linecount)
|
||||||
for i := 0; i < linecount; i++ {
|
for i := 0; i < linecount; i++ {
|
||||||
lines = append(lines, strings.Join(words[wrapAt*i:min(wrapAt*(i+1), wordsLen)], " "))
|
lines = append(lines, strings.Join(words[wrap_at*i:min(wrap_at*(i+1), words_len)], " "))
|
||||||
}
|
}
|
||||||
return AsValue(strings.Join(lines, "\n")), nil
|
return AsValue(strings.Join(lines, "\n")), nil
|
||||||
}
|
}
|
||||||
|
@ -888,27 +864,27 @@ func filterYesno(in *Value, param *Value) (*Value, *Error) {
|
||||||
1: "no",
|
1: "no",
|
||||||
2: "maybe",
|
2: "maybe",
|
||||||
}
|
}
|
||||||
paramString := param.String()
|
param_string := param.String()
|
||||||
customChoices := strings.Split(paramString, ",")
|
custom_choices := strings.Split(param_string, ",")
|
||||||
if len(paramString) > 0 {
|
if len(param_string) > 0 {
|
||||||
if len(customChoices) > 3 {
|
if len(custom_choices) > 3 {
|
||||||
return nil, &Error{
|
return nil, &Error{
|
||||||
Sender: "filter:yesno",
|
Sender: "filter:yesno",
|
||||||
OrigError: errors.Errorf("You cannot pass more than 3 options to the 'yesno'-filter (got: '%s').", paramString),
|
ErrorMsg: fmt.Sprintf("You cannot pass more than 3 options to the 'yesno'-filter (got: '%s').", param_string),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(customChoices) < 2 {
|
if len(custom_choices) < 2 {
|
||||||
return nil, &Error{
|
return nil, &Error{
|
||||||
Sender: "filter:yesno",
|
Sender: "filter:yesno",
|
||||||
OrigError: errors.Errorf("You must pass either no or at least 2 arguments to the 'yesno'-filter (got: '%s').", paramString),
|
ErrorMsg: fmt.Sprintf("You must pass either no or at least 2 arguments to the 'yesno'-filter (got: '%s').", param_string),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map to the options now
|
// Map to the options now
|
||||||
choices[0] = customChoices[0]
|
choices[0] = custom_choices[0]
|
||||||
choices[1] = customChoices[1]
|
choices[1] = custom_choices[1]
|
||||||
if len(customChoices) == 3 {
|
if len(custom_choices) == 3 {
|
||||||
choices[2] = customChoices[2]
|
choices[2] = custom_choices[2]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
44
vendor/github.com/flosch/pongo2/lexer.go
generated
vendored
44
vendor/github.com/flosch/pongo2/lexer.go
generated
vendored
|
@ -4,8 +4,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/juju/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -65,8 +63,8 @@ type lexer struct {
|
||||||
line int
|
line int
|
||||||
col int
|
col int
|
||||||
|
|
||||||
inVerbatim bool
|
in_verbatim bool
|
||||||
verbatimName string
|
verbatim_name string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Token) String() string {
|
func (t *Token) String() string {
|
||||||
|
@ -113,11 +111,11 @@ func lex(name string, input string) ([]*Token, *Error) {
|
||||||
if l.errored {
|
if l.errored {
|
||||||
errtoken := l.tokens[len(l.tokens)-1]
|
errtoken := l.tokens[len(l.tokens)-1]
|
||||||
return nil, &Error{
|
return nil, &Error{
|
||||||
Filename: name,
|
Filename: name,
|
||||||
Line: errtoken.Line,
|
Line: errtoken.Line,
|
||||||
Column: errtoken.Col,
|
Column: errtoken.Col,
|
||||||
Sender: "lexer",
|
Sender: "lexer",
|
||||||
OrigError: errors.New(errtoken.Val),
|
ErrorMsg: errtoken.Val,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return l.tokens, nil
|
return l.tokens, nil
|
||||||
|
@ -218,8 +216,8 @@ func (l *lexer) run() {
|
||||||
for {
|
for {
|
||||||
// TODO: Support verbatim tag names
|
// TODO: Support verbatim tag names
|
||||||
// https://docs.djangoproject.com/en/dev/ref/templates/builtins/#verbatim
|
// https://docs.djangoproject.com/en/dev/ref/templates/builtins/#verbatim
|
||||||
if l.inVerbatim {
|
if l.in_verbatim {
|
||||||
name := l.verbatimName
|
name := l.verbatim_name
|
||||||
if name != "" {
|
if name != "" {
|
||||||
name += " "
|
name += " "
|
||||||
}
|
}
|
||||||
|
@ -231,20 +229,20 @@ func (l *lexer) run() {
|
||||||
l.pos += w
|
l.pos += w
|
||||||
l.col += w
|
l.col += w
|
||||||
l.ignore()
|
l.ignore()
|
||||||
l.inVerbatim = false
|
l.in_verbatim = false
|
||||||
}
|
}
|
||||||
} else if strings.HasPrefix(l.input[l.pos:], "{% verbatim %}") { // tag
|
} else if strings.HasPrefix(l.input[l.pos:], "{% verbatim %}") { // tag
|
||||||
if l.pos > l.start {
|
if l.pos > l.start {
|
||||||
l.emit(TokenHTML)
|
l.emit(TokenHTML)
|
||||||
}
|
}
|
||||||
l.inVerbatim = true
|
l.in_verbatim = true
|
||||||
w := len("{% verbatim %}")
|
w := len("{% verbatim %}")
|
||||||
l.pos += w
|
l.pos += w
|
||||||
l.col += w
|
l.col += w
|
||||||
l.ignore()
|
l.ignore()
|
||||||
}
|
}
|
||||||
|
|
||||||
if !l.inVerbatim {
|
if !l.in_verbatim {
|
||||||
// Ignore single-line comments {# ... #}
|
// Ignore single-line comments {# ... #}
|
||||||
if strings.HasPrefix(l.input[l.pos:], "{#") {
|
if strings.HasPrefix(l.input[l.pos:], "{#") {
|
||||||
if l.pos > l.start {
|
if l.pos > l.start {
|
||||||
|
@ -305,7 +303,7 @@ func (l *lexer) run() {
|
||||||
l.emit(TokenHTML)
|
l.emit(TokenHTML)
|
||||||
}
|
}
|
||||||
|
|
||||||
if l.inVerbatim {
|
if l.in_verbatim {
|
||||||
l.errorf("verbatim-tag not closed, got EOF.")
|
l.errorf("verbatim-tag not closed, got EOF.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,7 +328,7 @@ outer_loop:
|
||||||
return l.stateIdentifier
|
return l.stateIdentifier
|
||||||
case l.accept(tokenDigits):
|
case l.accept(tokenDigits):
|
||||||
return l.stateNumber
|
return l.stateNumber
|
||||||
case l.accept(`"'`):
|
case l.accept(`"`):
|
||||||
return l.stateString
|
return l.stateString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,6 +348,10 @@ outer_loop:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if l.pos < len(l.input) {
|
||||||
|
return l.errorf("Unknown character: %q (%d)", l.peek(), l.peek())
|
||||||
|
}
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,11 +374,6 @@ func (l *lexer) stateIdentifier() lexerStateFn {
|
||||||
|
|
||||||
func (l *lexer) stateNumber() lexerStateFn {
|
func (l *lexer) stateNumber() lexerStateFn {
|
||||||
l.acceptRun(tokenDigits)
|
l.acceptRun(tokenDigits)
|
||||||
if l.accept(tokenIdentifierCharsWithDigits) {
|
|
||||||
// This seems to be an identifier starting with a number.
|
|
||||||
// See https://github.com/flosch/pongo2/issues/151
|
|
||||||
return l.stateIdentifier()
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
Maybe context-sensitive number lexing?
|
Maybe context-sensitive number lexing?
|
||||||
* comments.0.Text // first comment
|
* comments.0.Text // first comment
|
||||||
|
@ -396,10 +393,9 @@ func (l *lexer) stateNumber() lexerStateFn {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *lexer) stateString() lexerStateFn {
|
func (l *lexer) stateString() lexerStateFn {
|
||||||
quotationMark := l.value()
|
|
||||||
l.ignore()
|
l.ignore()
|
||||||
l.startcol-- // we're starting the position at the first "
|
l.startcol -= 1 // we're starting the position at the first "
|
||||||
for !l.accept(quotationMark) {
|
for !l.accept(`"`) {
|
||||||
switch l.next() {
|
switch l.next() {
|
||||||
case '\\':
|
case '\\':
|
||||||
// escape sequence
|
// escape sequence
|
||||||
|
|
8
vendor/github.com/flosch/pongo2/nodes.go
generated
vendored
8
vendor/github.com/flosch/pongo2/nodes.go
generated
vendored
|
@ -1,13 +1,17 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
)
|
||||||
|
|
||||||
// The root document
|
// The root document
|
||||||
type nodeDocument struct {
|
type nodeDocument struct {
|
||||||
Nodes []INode
|
Nodes []INode
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *nodeDocument) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (doc *nodeDocument) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
for _, n := range doc.Nodes {
|
for _, n := range doc.Nodes {
|
||||||
err := n.Execute(ctx, writer)
|
err := n.Execute(ctx, buffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
8
vendor/github.com/flosch/pongo2/nodes_html.go
generated
vendored
8
vendor/github.com/flosch/pongo2/nodes_html.go
generated
vendored
|
@ -1,10 +1,14 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
)
|
||||||
|
|
||||||
type nodeHTML struct {
|
type nodeHTML struct {
|
||||||
token *Token
|
token *Token
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *nodeHTML) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (n *nodeHTML) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
writer.WriteString(n.token.Val)
|
buffer.WriteString(n.token.Val)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
8
vendor/github.com/flosch/pongo2/nodes_wrapper.go
generated
vendored
8
vendor/github.com/flosch/pongo2/nodes_wrapper.go
generated
vendored
|
@ -1,13 +1,17 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
)
|
||||||
|
|
||||||
type NodeWrapper struct {
|
type NodeWrapper struct {
|
||||||
Endtag string
|
Endtag string
|
||||||
nodes []INode
|
nodes []INode
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wrapper *NodeWrapper) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (wrapper *NodeWrapper) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
for _, n := range wrapper.nodes {
|
for _, n := range wrapper.nodes {
|
||||||
err := n.Execute(ctx, writer)
|
err := n.Execute(ctx, buffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
98
vendor/github.com/flosch/pongo2/parser.go
generated
vendored
98
vendor/github.com/flosch/pongo2/parser.go
generated
vendored
|
@ -1,14 +1,13 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/juju/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type INode interface {
|
type INode interface {
|
||||||
Execute(*ExecutionContext, TemplateWriter) *Error
|
Execute(*ExecutionContext, *bytes.Buffer) *Error
|
||||||
}
|
}
|
||||||
|
|
||||||
type IEvaluator interface {
|
type IEvaluator interface {
|
||||||
|
@ -28,10 +27,10 @@ type IEvaluator interface {
|
||||||
//
|
//
|
||||||
// (See Token's documentation for more about tokens)
|
// (See Token's documentation for more about tokens)
|
||||||
type Parser struct {
|
type Parser struct {
|
||||||
name string
|
name string
|
||||||
idx int
|
idx int
|
||||||
tokens []*Token
|
tokens []*Token
|
||||||
lastToken *Token
|
last_token *Token
|
||||||
|
|
||||||
// if the parser parses a template document, here will be
|
// if the parser parses a template document, here will be
|
||||||
// a reference to it (needed to access the template through Tags)
|
// a reference to it (needed to access the template through Tags)
|
||||||
|
@ -48,7 +47,7 @@ func newParser(name string, tokens []*Token, template *Template) *Parser {
|
||||||
template: template,
|
template: template,
|
||||||
}
|
}
|
||||||
if len(tokens) > 0 {
|
if len(tokens) > 0 {
|
||||||
p.lastToken = tokens[len(tokens)-1]
|
p.last_token = tokens[len(tokens)-1]
|
||||||
}
|
}
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
@ -176,7 +175,7 @@ func (p *Parser) GetR(shift int) *Token {
|
||||||
return p.Get(i)
|
return p.Get(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error produces a nice error message and returns an error-object.
|
// Produces a nice error message and returns an error-object.
|
||||||
// The 'token'-argument is optional. If provided, it will take
|
// The 'token'-argument is optional. If provided, it will take
|
||||||
// the token's position information. If not provided, it will
|
// the token's position information. If not provided, it will
|
||||||
// automatically use the CURRENT token's position information.
|
// automatically use the CURRENT token's position information.
|
||||||
|
@ -197,13 +196,13 @@ func (p *Parser) Error(msg string, token *Token) *Error {
|
||||||
col = token.Col
|
col = token.Col
|
||||||
}
|
}
|
||||||
return &Error{
|
return &Error{
|
||||||
Template: p.template,
|
Template: p.template,
|
||||||
Filename: p.name,
|
Filename: p.name,
|
||||||
Sender: "parser",
|
Sender: "parser",
|
||||||
Line: line,
|
Line: line,
|
||||||
Column: col,
|
Column: col,
|
||||||
Token: token,
|
Token: token,
|
||||||
OrigError: errors.New(msg),
|
ErrorMsg: msg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,19 +212,19 @@ func (p *Parser) Error(msg string, token *Token) *Error {
|
||||||
func (p *Parser) WrapUntilTag(names ...string) (*NodeWrapper, *Parser, *Error) {
|
func (p *Parser) WrapUntilTag(names ...string) (*NodeWrapper, *Parser, *Error) {
|
||||||
wrapper := &NodeWrapper{}
|
wrapper := &NodeWrapper{}
|
||||||
|
|
||||||
var tagArgs []*Token
|
tagArgs := make([]*Token, 0)
|
||||||
|
|
||||||
for p.Remaining() > 0 {
|
for p.Remaining() > 0 {
|
||||||
// New tag, check whether we have to stop wrapping here
|
// New tag, check whether we have to stop wrapping here
|
||||||
if p.Peek(TokenSymbol, "{%") != nil {
|
if p.Peek(TokenSymbol, "{%") != nil {
|
||||||
tagIdent := p.PeekTypeN(1, TokenIdentifier)
|
tag_ident := p.PeekTypeN(1, TokenIdentifier)
|
||||||
|
|
||||||
if tagIdent != nil {
|
if tag_ident != nil {
|
||||||
// We've found a (!) end-tag
|
// We've found a (!) end-tag
|
||||||
|
|
||||||
found := false
|
found := false
|
||||||
for _, n := range names {
|
for _, n := range names {
|
||||||
if tagIdent.Val == n {
|
if tag_ident.Val == n {
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -239,15 +238,16 @@ func (p *Parser) WrapUntilTag(names ...string) (*NodeWrapper, *Parser, *Error) {
|
||||||
for {
|
for {
|
||||||
if p.Match(TokenSymbol, "%}") != nil {
|
if p.Match(TokenSymbol, "%}") != nil {
|
||||||
// Okay, end the wrapping here
|
// Okay, end the wrapping here
|
||||||
wrapper.Endtag = tagIdent.Val
|
wrapper.Endtag = tag_ident.Val
|
||||||
return wrapper, newParser(p.template.name, tagArgs, p.template), nil
|
return wrapper, newParser(p.template.name, tagArgs, p.template), nil
|
||||||
|
} else {
|
||||||
|
t := p.Current()
|
||||||
|
p.Consume()
|
||||||
|
if t == nil {
|
||||||
|
return nil, nil, p.Error("Unexpected EOF.", p.last_token)
|
||||||
|
}
|
||||||
|
tagArgs = append(tagArgs, t)
|
||||||
}
|
}
|
||||||
t := p.Current()
|
|
||||||
p.Consume()
|
|
||||||
if t == nil {
|
|
||||||
return nil, nil, p.Error("Unexpected EOF.", p.lastToken)
|
|
||||||
}
|
|
||||||
tagArgs = append(tagArgs, t)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -263,47 +263,5 @@ func (p *Parser) WrapUntilTag(names ...string) (*NodeWrapper, *Parser, *Error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil, p.Error(fmt.Sprintf("Unexpected EOF, expected tag %s.", strings.Join(names, " or ")),
|
return nil, nil, p.Error(fmt.Sprintf("Unexpected EOF, expected tag %s.", strings.Join(names, " or ")),
|
||||||
p.lastToken)
|
p.last_token)
|
||||||
}
|
|
||||||
|
|
||||||
// Skips all nodes between starting tag and "{% endtag %}"
|
|
||||||
func (p *Parser) SkipUntilTag(names ...string) *Error {
|
|
||||||
for p.Remaining() > 0 {
|
|
||||||
// New tag, check whether we have to stop wrapping here
|
|
||||||
if p.Peek(TokenSymbol, "{%") != nil {
|
|
||||||
tagIdent := p.PeekTypeN(1, TokenIdentifier)
|
|
||||||
|
|
||||||
if tagIdent != nil {
|
|
||||||
// We've found a (!) end-tag
|
|
||||||
|
|
||||||
found := false
|
|
||||||
for _, n := range names {
|
|
||||||
if tagIdent.Val == n {
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We only process the tag if we've found an end tag
|
|
||||||
if found {
|
|
||||||
// Okay, endtag found.
|
|
||||||
p.ConsumeN(2) // '{%' tagname
|
|
||||||
|
|
||||||
for {
|
|
||||||
if p.Match(TokenSymbol, "%}") != nil {
|
|
||||||
// Done skipping, exit.
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
t := p.Current()
|
|
||||||
p.Consume()
|
|
||||||
if t == nil {
|
|
||||||
return p.Error("Unexpected EOF.", p.lastToken)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return p.Error(fmt.Sprintf("Unexpected EOF, expected tag %s.", strings.Join(names, " or ")), p.lastToken)
|
|
||||||
}
|
}
|
||||||
|
|
156
vendor/github.com/flosch/pongo2/parser_expression.go
generated
vendored
156
vendor/github.com/flosch/pongo2/parser_expression.go
generated
vendored
|
@ -1,37 +1,38 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Expression struct {
|
type Expression struct {
|
||||||
// TODO: Add location token?
|
// TODO: Add location token?
|
||||||
expr1 IEvaluator
|
expr1 IEvaluator
|
||||||
expr2 IEvaluator
|
expr2 IEvaluator
|
||||||
opToken *Token
|
op_token *Token
|
||||||
}
|
}
|
||||||
|
|
||||||
type relationalExpression struct {
|
type relationalExpression struct {
|
||||||
// TODO: Add location token?
|
// TODO: Add location token?
|
||||||
expr1 IEvaluator
|
expr1 IEvaluator
|
||||||
expr2 IEvaluator
|
expr2 IEvaluator
|
||||||
opToken *Token
|
op_token *Token
|
||||||
}
|
}
|
||||||
|
|
||||||
type simpleExpression struct {
|
type simpleExpression struct {
|
||||||
negate bool
|
negate bool
|
||||||
negativeSign bool
|
negative_sign bool
|
||||||
term1 IEvaluator
|
term1 IEvaluator
|
||||||
term2 IEvaluator
|
term2 IEvaluator
|
||||||
opToken *Token
|
op_token *Token
|
||||||
}
|
}
|
||||||
|
|
||||||
type term struct {
|
type term struct {
|
||||||
// TODO: Add location token?
|
// TODO: Add location token?
|
||||||
factor1 IEvaluator
|
factor1 IEvaluator
|
||||||
factor2 IEvaluator
|
factor2 IEvaluator
|
||||||
opToken *Token
|
op_token *Token
|
||||||
}
|
}
|
||||||
|
|
||||||
type power struct {
|
type power struct {
|
||||||
|
@ -55,14 +56,14 @@ func (expr *simpleExpression) FilterApplied(name string) bool {
|
||||||
(expr.term2 != nil && expr.term2.FilterApplied(name)))
|
(expr.term2 != nil && expr.term2.FilterApplied(name)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (expr *term) FilterApplied(name string) bool {
|
func (t *term) FilterApplied(name string) bool {
|
||||||
return expr.factor1.FilterApplied(name) && (expr.factor2 == nil ||
|
return t.factor1.FilterApplied(name) && (t.factor2 == nil ||
|
||||||
(expr.factor2 != nil && expr.factor2.FilterApplied(name)))
|
(t.factor2 != nil && t.factor2.FilterApplied(name)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (expr *power) FilterApplied(name string) bool {
|
func (p *power) FilterApplied(name string) bool {
|
||||||
return expr.power1.FilterApplied(name) && (expr.power2 == nil ||
|
return p.power1.FilterApplied(name) && (p.power2 == nil ||
|
||||||
(expr.power2 != nil && expr.power2.FilterApplied(name)))
|
(p.power2 != nil && p.power2.FilterApplied(name)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (expr *Expression) GetPositionToken() *Token {
|
func (expr *Expression) GetPositionToken() *Token {
|
||||||
|
@ -85,48 +86,48 @@ func (expr *power) GetPositionToken() *Token {
|
||||||
return expr.power1.GetPositionToken()
|
return expr.power1.GetPositionToken()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (expr *Expression) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (expr *Expression) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
value, err := expr.Evaluate(ctx)
|
value, err := expr.Evaluate(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
writer.WriteString(value.String())
|
buffer.WriteString(value.String())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (expr *relationalExpression) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (expr *relationalExpression) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
value, err := expr.Evaluate(ctx)
|
value, err := expr.Evaluate(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
writer.WriteString(value.String())
|
buffer.WriteString(value.String())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (expr *simpleExpression) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (expr *simpleExpression) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
value, err := expr.Evaluate(ctx)
|
value, err := expr.Evaluate(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
writer.WriteString(value.String())
|
buffer.WriteString(value.String())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (expr *term) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (expr *term) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
value, err := expr.Evaluate(ctx)
|
value, err := expr.Evaluate(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
writer.WriteString(value.String())
|
buffer.WriteString(value.String())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (expr *power) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (expr *power) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
value, err := expr.Evaluate(ctx)
|
value, err := expr.Evaluate(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
writer.WriteString(value.String())
|
buffer.WriteString(value.String())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,13 +141,13 @@ func (expr *Expression) Evaluate(ctx *ExecutionContext) (*Value, *Error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
switch expr.opToken.Val {
|
switch expr.op_token.Val {
|
||||||
case "and", "&&":
|
case "and", "&&":
|
||||||
return AsValue(v1.IsTrue() && v2.IsTrue()), nil
|
return AsValue(v1.IsTrue() && v2.IsTrue()), nil
|
||||||
case "or", "||":
|
case "or", "||":
|
||||||
return AsValue(v1.IsTrue() || v2.IsTrue()), nil
|
return AsValue(v1.IsTrue() || v2.IsTrue()), nil
|
||||||
default:
|
default:
|
||||||
return nil, ctx.Error(fmt.Sprintf("unimplemented: %s", expr.opToken.Val), expr.opToken)
|
panic(fmt.Sprintf("unimplemented: %s", expr.op_token.Val))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return v1, nil
|
return v1, nil
|
||||||
|
@ -163,35 +164,39 @@ func (expr *relationalExpression) Evaluate(ctx *ExecutionContext) (*Value, *Erro
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
switch expr.opToken.Val {
|
switch expr.op_token.Val {
|
||||||
case "<=":
|
case "<=":
|
||||||
if v1.IsFloat() || v2.IsFloat() {
|
if v1.IsFloat() || v2.IsFloat() {
|
||||||
return AsValue(v1.Float() <= v2.Float()), nil
|
return AsValue(v1.Float() <= v2.Float()), nil
|
||||||
|
} else {
|
||||||
|
return AsValue(v1.Integer() <= v2.Integer()), nil
|
||||||
}
|
}
|
||||||
return AsValue(v1.Integer() <= v2.Integer()), nil
|
|
||||||
case ">=":
|
case ">=":
|
||||||
if v1.IsFloat() || v2.IsFloat() {
|
if v1.IsFloat() || v2.IsFloat() {
|
||||||
return AsValue(v1.Float() >= v2.Float()), nil
|
return AsValue(v1.Float() >= v2.Float()), nil
|
||||||
|
} else {
|
||||||
|
return AsValue(v1.Integer() >= v2.Integer()), nil
|
||||||
}
|
}
|
||||||
return AsValue(v1.Integer() >= v2.Integer()), nil
|
|
||||||
case "==":
|
case "==":
|
||||||
return AsValue(v1.EqualValueTo(v2)), nil
|
return AsValue(v1.EqualValueTo(v2)), nil
|
||||||
case ">":
|
case ">":
|
||||||
if v1.IsFloat() || v2.IsFloat() {
|
if v1.IsFloat() || v2.IsFloat() {
|
||||||
return AsValue(v1.Float() > v2.Float()), nil
|
return AsValue(v1.Float() > v2.Float()), nil
|
||||||
|
} else {
|
||||||
|
return AsValue(v1.Integer() > v2.Integer()), nil
|
||||||
}
|
}
|
||||||
return AsValue(v1.Integer() > v2.Integer()), nil
|
|
||||||
case "<":
|
case "<":
|
||||||
if v1.IsFloat() || v2.IsFloat() {
|
if v1.IsFloat() || v2.IsFloat() {
|
||||||
return AsValue(v1.Float() < v2.Float()), nil
|
return AsValue(v1.Float() < v2.Float()), nil
|
||||||
|
} else {
|
||||||
|
return AsValue(v1.Integer() < v2.Integer()), nil
|
||||||
}
|
}
|
||||||
return AsValue(v1.Integer() < v2.Integer()), nil
|
|
||||||
case "!=", "<>":
|
case "!=", "<>":
|
||||||
return AsValue(!v1.EqualValueTo(v2)), nil
|
return AsValue(!v1.EqualValueTo(v2)), nil
|
||||||
case "in":
|
case "in":
|
||||||
return AsValue(v2.Contains(v1)), nil
|
return AsValue(v2.Contains(v1)), nil
|
||||||
default:
|
default:
|
||||||
return nil, ctx.Error(fmt.Sprintf("unimplemented: %s", expr.opToken.Val), expr.opToken)
|
panic(fmt.Sprintf("unimplemented: %s", expr.op_token.Val))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return v1, nil
|
return v1, nil
|
||||||
|
@ -209,7 +214,7 @@ func (expr *simpleExpression) Evaluate(ctx *ExecutionContext) (*Value, *Error) {
|
||||||
result = result.Negate()
|
result = result.Negate()
|
||||||
}
|
}
|
||||||
|
|
||||||
if expr.negativeSign {
|
if expr.negative_sign {
|
||||||
if result.IsNumber() {
|
if result.IsNumber() {
|
||||||
switch {
|
switch {
|
||||||
case result.IsFloat():
|
case result.IsFloat():
|
||||||
|
@ -217,7 +222,7 @@ func (expr *simpleExpression) Evaluate(ctx *ExecutionContext) (*Value, *Error) {
|
||||||
case result.IsInteger():
|
case result.IsInteger():
|
||||||
result = AsValue(-1 * result.Integer())
|
result = AsValue(-1 * result.Integer())
|
||||||
default:
|
default:
|
||||||
return nil, ctx.Error("Operation between a number and a non-(float/integer) is not possible", nil)
|
panic("not possible")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil, ctx.Error("Negative sign on a non-number expression", expr.GetPositionToken())
|
return nil, ctx.Error("Negative sign on a non-number expression", expr.GetPositionToken())
|
||||||
|
@ -229,40 +234,42 @@ func (expr *simpleExpression) Evaluate(ctx *ExecutionContext) (*Value, *Error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
switch expr.opToken.Val {
|
switch expr.op_token.Val {
|
||||||
case "+":
|
case "+":
|
||||||
if result.IsFloat() || t2.IsFloat() {
|
if result.IsFloat() || t2.IsFloat() {
|
||||||
// Result will be a float
|
// Result will be a float
|
||||||
return AsValue(result.Float() + t2.Float()), nil
|
return AsValue(result.Float() + t2.Float()), nil
|
||||||
|
} else {
|
||||||
|
// Result will be an integer
|
||||||
|
return AsValue(result.Integer() + t2.Integer()), nil
|
||||||
}
|
}
|
||||||
// Result will be an integer
|
|
||||||
return AsValue(result.Integer() + t2.Integer()), nil
|
|
||||||
case "-":
|
case "-":
|
||||||
if result.IsFloat() || t2.IsFloat() {
|
if result.IsFloat() || t2.IsFloat() {
|
||||||
// Result will be a float
|
// Result will be a float
|
||||||
return AsValue(result.Float() - t2.Float()), nil
|
return AsValue(result.Float() - t2.Float()), nil
|
||||||
|
} else {
|
||||||
|
// Result will be an integer
|
||||||
|
return AsValue(result.Integer() - t2.Integer()), nil
|
||||||
}
|
}
|
||||||
// Result will be an integer
|
|
||||||
return AsValue(result.Integer() - t2.Integer()), nil
|
|
||||||
default:
|
default:
|
||||||
return nil, ctx.Error("Unimplemented", expr.GetPositionToken())
|
panic("unimplemented")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (expr *term) Evaluate(ctx *ExecutionContext) (*Value, *Error) {
|
func (t *term) Evaluate(ctx *ExecutionContext) (*Value, *Error) {
|
||||||
f1, err := expr.factor1.Evaluate(ctx)
|
f1, err := t.factor1.Evaluate(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if expr.factor2 != nil {
|
if t.factor2 != nil {
|
||||||
f2, err := expr.factor2.Evaluate(ctx)
|
f2, err := t.factor2.Evaluate(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
switch expr.opToken.Val {
|
switch t.op_token.Val {
|
||||||
case "*":
|
case "*":
|
||||||
if f1.IsFloat() || f2.IsFloat() {
|
if f1.IsFloat() || f2.IsFloat() {
|
||||||
// Result will be float
|
// Result will be float
|
||||||
|
@ -281,26 +288,27 @@ func (expr *term) Evaluate(ctx *ExecutionContext) (*Value, *Error) {
|
||||||
// Result will be int
|
// Result will be int
|
||||||
return AsValue(f1.Integer() % f2.Integer()), nil
|
return AsValue(f1.Integer() % f2.Integer()), nil
|
||||||
default:
|
default:
|
||||||
return nil, ctx.Error("unimplemented", expr.opToken)
|
panic("unimplemented")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return f1, nil
|
return f1, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (expr *power) Evaluate(ctx *ExecutionContext) (*Value, *Error) {
|
func (pw *power) Evaluate(ctx *ExecutionContext) (*Value, *Error) {
|
||||||
p1, err := expr.power1.Evaluate(ctx)
|
p1, err := pw.power1.Evaluate(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if expr.power2 != nil {
|
if pw.power2 != nil {
|
||||||
p2, err := expr.power2.Evaluate(ctx)
|
p2, err := pw.power2.Evaluate(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return AsValue(math.Pow(p1.Float(), p2.Float())), nil
|
return AsValue(math.Pow(p1.Float(), p2.Float())), nil
|
||||||
|
} else {
|
||||||
|
return p1, nil
|
||||||
}
|
}
|
||||||
return p1, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) parseFactor() (IEvaluator, *Error) {
|
func (p *Parser) parseFactor() (IEvaluator, *Error) {
|
||||||
|
@ -344,19 +352,19 @@ func (p *Parser) parsePower() (IEvaluator, *Error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) parseTerm() (IEvaluator, *Error) {
|
func (p *Parser) parseTerm() (IEvaluator, *Error) {
|
||||||
returnTerm := new(term)
|
return_term := new(term)
|
||||||
|
|
||||||
factor1, err := p.parsePower()
|
factor1, err := p.parsePower()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
returnTerm.factor1 = factor1
|
return_term.factor1 = factor1
|
||||||
|
|
||||||
for p.PeekOne(TokenSymbol, "*", "/", "%") != nil {
|
for p.PeekOne(TokenSymbol, "*", "/", "%") != nil {
|
||||||
if returnTerm.opToken != nil {
|
if return_term.op_token != nil {
|
||||||
// Create new sub-term
|
// Create new sub-term
|
||||||
returnTerm = &term{
|
return_term = &term{
|
||||||
factor1: returnTerm,
|
factor1: return_term,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,16 +376,16 @@ func (p *Parser) parseTerm() (IEvaluator, *Error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
returnTerm.opToken = op
|
return_term.op_token = op
|
||||||
returnTerm.factor2 = factor2
|
return_term.factor2 = factor2
|
||||||
}
|
}
|
||||||
|
|
||||||
if returnTerm.opToken == nil {
|
if return_term.op_token == nil {
|
||||||
// Shortcut for faster evaluation
|
// Shortcut for faster evaluation
|
||||||
return returnTerm.factor1, nil
|
return return_term.factor1, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnTerm, nil
|
return return_term, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) parseSimpleExpression() (IEvaluator, *Error) {
|
func (p *Parser) parseSimpleExpression() (IEvaluator, *Error) {
|
||||||
|
@ -385,7 +393,7 @@ func (p *Parser) parseSimpleExpression() (IEvaluator, *Error) {
|
||||||
|
|
||||||
if sign := p.MatchOne(TokenSymbol, "+", "-"); sign != nil {
|
if sign := p.MatchOne(TokenSymbol, "+", "-"); sign != nil {
|
||||||
if sign.Val == "-" {
|
if sign.Val == "-" {
|
||||||
expr.negativeSign = true
|
expr.negative_sign = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,7 +408,7 @@ func (p *Parser) parseSimpleExpression() (IEvaluator, *Error) {
|
||||||
expr.term1 = term1
|
expr.term1 = term1
|
||||||
|
|
||||||
for p.PeekOne(TokenSymbol, "+", "-") != nil {
|
for p.PeekOne(TokenSymbol, "+", "-") != nil {
|
||||||
if expr.opToken != nil {
|
if expr.op_token != nil {
|
||||||
// New sub expr
|
// New sub expr
|
||||||
expr = &simpleExpression{
|
expr = &simpleExpression{
|
||||||
term1: expr,
|
term1: expr,
|
||||||
|
@ -416,10 +424,10 @@ func (p *Parser) parseSimpleExpression() (IEvaluator, *Error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
expr.term2 = term2
|
expr.term2 = term2
|
||||||
expr.opToken = op
|
expr.op_token = op
|
||||||
}
|
}
|
||||||
|
|
||||||
if expr.negate == false && expr.negativeSign == false && expr.term2 == nil {
|
if expr.negate == false && expr.negative_sign == false && expr.term2 == nil {
|
||||||
// Shortcut for faster evaluation
|
// Shortcut for faster evaluation
|
||||||
return expr.term1, nil
|
return expr.term1, nil
|
||||||
}
|
}
|
||||||
|
@ -442,14 +450,14 @@ func (p *Parser) parseRelationalExpression() (IEvaluator, *Error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
expr.opToken = t
|
expr.op_token = t
|
||||||
expr.expr2 = expr2
|
expr.expr2 = expr2
|
||||||
} else if t := p.MatchOne(TokenKeyword, "in"); t != nil {
|
} else if t := p.MatchOne(TokenKeyword, "in"); t != nil {
|
||||||
expr2, err := p.parseSimpleExpression()
|
expr2, err := p.parseSimpleExpression()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
expr.opToken = t
|
expr.op_token = t
|
||||||
expr.expr2 = expr2
|
expr.expr2 = expr2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,7 +487,7 @@ func (p *Parser) ParseExpression() (IEvaluator, *Error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
exp.expr2 = expr2
|
exp.expr2 = expr2
|
||||||
exp.opToken = op
|
exp.op_token = op
|
||||||
}
|
}
|
||||||
|
|
||||||
if exp.expr2 == nil {
|
if exp.expr2 == nil {
|
||||||
|
|
6
vendor/github.com/flosch/pongo2/pongo2.go
generated
vendored
6
vendor/github.com/flosch/pongo2/pongo2.go
generated
vendored
|
@ -1,10 +1,10 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
// Version string
|
// Version string
|
||||||
const Version = "dev"
|
const Version = "v3"
|
||||||
|
|
||||||
// Must panics, if a Template couldn't successfully parsed. This is how you
|
// Helper function which panics, if a Template couldn't
|
||||||
// would use it:
|
// successfully parsed. This is how you would use it:
|
||||||
// var baseTemplate = pongo2.Must(pongo2.FromFile("templates/base.html"))
|
// var baseTemplate = pongo2.Must(pongo2.FromFile("templates/base.html"))
|
||||||
func Must(tpl *Template, err error) *Template {
|
func Must(tpl *Template, err error) *Template {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
29
vendor/github.com/flosch/pongo2/pongo2_issues_test.go
generated
vendored
29
vendor/github.com/flosch/pongo2/pongo2_issues_test.go
generated
vendored
|
@ -1,29 +0,0 @@
|
||||||
package pongo2_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/flosch/pongo2"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestIssue151(t *testing.T) {
|
|
||||||
tpl, err := pongo2.FromString("{{ mydict.51232_3 }}{{ 12345_123}}{{ 995189baz }}")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
str, err := tpl.Execute(pongo2.Context{
|
|
||||||
"mydict": map[string]string{
|
|
||||||
"51232_3": "foo",
|
|
||||||
},
|
|
||||||
"12345_123": "bar",
|
|
||||||
"995189baz": "baz",
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if str != "foobarbaz" {
|
|
||||||
t.Fatalf("Expected output 'foobarbaz', but got '%s'.", str)
|
|
||||||
}
|
|
||||||
}
|
|
534
vendor/github.com/flosch/pongo2/pongo2_template_test.go
generated
vendored
534
vendor/github.com/flosch/pongo2/pongo2_template_test.go
generated
vendored
|
@ -1,534 +0,0 @@
|
||||||
package pongo2_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"path/filepath"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/flosch/pongo2"
|
|
||||||
)
|
|
||||||
|
|
||||||
var adminList = []string{"user2"}
|
|
||||||
|
|
||||||
var time1 = time.Date(2014, 06, 10, 15, 30, 15, 0, time.UTC)
|
|
||||||
var time2 = time.Date(2011, 03, 21, 8, 37, 56, 12, time.UTC)
|
|
||||||
|
|
||||||
type post struct {
|
|
||||||
Text string
|
|
||||||
Created time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
type user struct {
|
|
||||||
Name string
|
|
||||||
Validated bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type comment struct {
|
|
||||||
Author *user
|
|
||||||
Date time.Time
|
|
||||||
Text string
|
|
||||||
}
|
|
||||||
|
|
||||||
func isAdmin(u *user) bool {
|
|
||||||
for _, a := range adminList {
|
|
||||||
if a == u.Name {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *user) Is_admin() *pongo2.Value {
|
|
||||||
return pongo2.AsValue(isAdmin(u))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *user) Is_admin2() bool {
|
|
||||||
return isAdmin(u)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *post) String() string {
|
|
||||||
return ":-)"
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Start setup sandbox
|
|
||||||
*/
|
|
||||||
|
|
||||||
type tagSandboxDemoTag struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (node *tagSandboxDemoTag) Execute(ctx *pongo2.ExecutionContext, writer pongo2.TemplateWriter) *pongo2.Error {
|
|
||||||
writer.WriteString("hello")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func tagSandboxDemoTagParser(doc *pongo2.Parser, start *pongo2.Token, arguments *pongo2.Parser) (pongo2.INodeTag, *pongo2.Error) {
|
|
||||||
return &tagSandboxDemoTag{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func BannedFilterFn(in *pongo2.Value, params *pongo2.Value) (*pongo2.Value, *pongo2.Error) {
|
|
||||||
return in, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
pongo2.DefaultSet.Debug = true
|
|
||||||
|
|
||||||
pongo2.RegisterFilter("banned_filter", BannedFilterFn)
|
|
||||||
pongo2.RegisterFilter("unbanned_filter", BannedFilterFn)
|
|
||||||
pongo2.RegisterTag("banned_tag", tagSandboxDemoTagParser)
|
|
||||||
pongo2.RegisterTag("unbanned_tag", tagSandboxDemoTagParser)
|
|
||||||
|
|
||||||
pongo2.DefaultSet.BanFilter("banned_filter")
|
|
||||||
pongo2.DefaultSet.BanTag("banned_tag")
|
|
||||||
|
|
||||||
f, err := ioutil.TempFile("/tmp/", "pongo2_")
|
|
||||||
if err != nil {
|
|
||||||
panic("cannot write to /tmp/")
|
|
||||||
}
|
|
||||||
f.Write([]byte("Hello from pongo2"))
|
|
||||||
pongo2.DefaultSet.Globals["temp_file"] = f.Name()
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* End setup sandbox
|
|
||||||
*/
|
|
||||||
|
|
||||||
var tplContext = pongo2.Context{
|
|
||||||
"number": 11,
|
|
||||||
"simple": map[string]interface{}{
|
|
||||||
"number": 42,
|
|
||||||
"name": "john doe",
|
|
||||||
"included_file": "INCLUDES.helper",
|
|
||||||
"included_file_not_exists": "INCLUDES.helper.not_exists",
|
|
||||||
"nil": nil,
|
|
||||||
"uint": uint(8),
|
|
||||||
"float": float64(3.1415),
|
|
||||||
"str": "string",
|
|
||||||
"chinese_hello_world": "你好世界",
|
|
||||||
"bool_true": true,
|
|
||||||
"bool_false": false,
|
|
||||||
"newline_text": `this is a text
|
|
||||||
with a new line in it`,
|
|
||||||
"long_text": `This is a simple text.
|
|
||||||
|
|
||||||
This too, as a paragraph.
|
|
||||||
Right?
|
|
||||||
|
|
||||||
Yep!`,
|
|
||||||
"escape_js_test": `escape sequences \r\n\'\" special chars "?!=$<>`,
|
|
||||||
"one_item_list": []int{99},
|
|
||||||
"multiple_item_list": []int{1, 1, 2, 3, 5, 8, 13, 21, 34, 55},
|
|
||||||
"unsorted_int_list": []int{192, 581, 22, 1, 249, 9999, 1828591, 8271},
|
|
||||||
"fixed_item_list": [...]int{1, 2, 3, 4},
|
|
||||||
"misc_list": []interface{}{"Hello", 99, 3.14, "good"},
|
|
||||||
"escape_text": "This is \\a Test. \"Yep\". 'Yep'.",
|
|
||||||
"xss": "<script>alert(\"uh oh\");</script>",
|
|
||||||
"intmap": map[int]string{
|
|
||||||
1: "one",
|
|
||||||
5: "five",
|
|
||||||
2: "two",
|
|
||||||
},
|
|
||||||
"strmap": map[string]string{
|
|
||||||
"abc": "def",
|
|
||||||
"bcd": "efg",
|
|
||||||
"zab": "cde",
|
|
||||||
"gh": "kqm",
|
|
||||||
"ukq": "qqa",
|
|
||||||
"aab": "aba",
|
|
||||||
},
|
|
||||||
"func_add": func(a, b int) int {
|
|
||||||
return a + b
|
|
||||||
},
|
|
||||||
"func_add_iface": func(a, b interface{}) interface{} {
|
|
||||||
return a.(int) + b.(int)
|
|
||||||
},
|
|
||||||
"func_variadic": func(msg string, args ...interface{}) string {
|
|
||||||
return fmt.Sprintf(msg, args...)
|
|
||||||
},
|
|
||||||
"func_variadic_sum_int": func(args ...int) int {
|
|
||||||
// Create a sum
|
|
||||||
s := 0
|
|
||||||
for _, i := range args {
|
|
||||||
s += i
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
},
|
|
||||||
"func_variadic_sum_int2": func(args ...*pongo2.Value) *pongo2.Value {
|
|
||||||
// Create a sum
|
|
||||||
s := 0
|
|
||||||
for _, i := range args {
|
|
||||||
s += i.Integer()
|
|
||||||
}
|
|
||||||
return pongo2.AsValue(s)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"complex": map[string]interface{}{
|
|
||||||
"is_admin": isAdmin,
|
|
||||||
"post": post{
|
|
||||||
Text: "<h2>Hello!</h2><p>Welcome to my new blog page. I'm using pongo2 which supports {{ variables }} and {% tags %}.</p>",
|
|
||||||
Created: time2,
|
|
||||||
},
|
|
||||||
"comments": []*comment{
|
|
||||||
&comment{
|
|
||||||
Author: &user{
|
|
||||||
Name: "user1",
|
|
||||||
Validated: true,
|
|
||||||
},
|
|
||||||
Date: time1,
|
|
||||||
Text: "\"pongo2 is nice!\"",
|
|
||||||
},
|
|
||||||
&comment{
|
|
||||||
Author: &user{
|
|
||||||
Name: "user2",
|
|
||||||
Validated: true,
|
|
||||||
},
|
|
||||||
Date: time2,
|
|
||||||
Text: "comment2 with <script>unsafe</script> tags in it",
|
|
||||||
},
|
|
||||||
&comment{
|
|
||||||
Author: &user{
|
|
||||||
Name: "user3",
|
|
||||||
Validated: false,
|
|
||||||
},
|
|
||||||
Date: time1,
|
|
||||||
Text: "<b>hello!</b> there",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"comments2": []*comment{
|
|
||||||
&comment{
|
|
||||||
Author: &user{
|
|
||||||
Name: "user1",
|
|
||||||
Validated: true,
|
|
||||||
},
|
|
||||||
Date: time2,
|
|
||||||
Text: "\"pongo2 is nice!\"",
|
|
||||||
},
|
|
||||||
&comment{
|
|
||||||
Author: &user{
|
|
||||||
Name: "user1",
|
|
||||||
Validated: true,
|
|
||||||
},
|
|
||||||
Date: time1,
|
|
||||||
Text: "comment2 with <script>unsafe</script> tags in it",
|
|
||||||
},
|
|
||||||
&comment{
|
|
||||||
Author: &user{
|
|
||||||
Name: "user3",
|
|
||||||
Validated: false,
|
|
||||||
},
|
|
||||||
Date: time1,
|
|
||||||
Text: "<b>hello!</b> there",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplates(t *testing.T) {
|
|
||||||
// Add a global to the default set
|
|
||||||
pongo2.Globals["this_is_a_global_variable"] = "this is a global text"
|
|
||||||
|
|
||||||
matches, err := filepath.Glob("./template_tests/*.tpl")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
for idx, match := range matches {
|
|
||||||
t.Logf("[Template %3d] Testing '%s'", idx+1, match)
|
|
||||||
tpl, err := pongo2.FromFile(match)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error on FromFile('%s'): %s", match, err.Error())
|
|
||||||
}
|
|
||||||
testFilename := fmt.Sprintf("%s.out", match)
|
|
||||||
testOut, rerr := ioutil.ReadFile(testFilename)
|
|
||||||
if rerr != nil {
|
|
||||||
t.Fatalf("Error on ReadFile('%s'): %s", testFilename, rerr.Error())
|
|
||||||
}
|
|
||||||
tplOut, err := tpl.ExecuteBytes(tplContext)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error on Execute('%s'): %s", match, err.Error())
|
|
||||||
}
|
|
||||||
if bytes.Compare(testOut, tplOut) != 0 {
|
|
||||||
t.Logf("Template (rendered) '%s': '%s'", match, tplOut)
|
|
||||||
errFilename := filepath.Base(fmt.Sprintf("%s.error", match))
|
|
||||||
err := ioutil.WriteFile(errFilename, []byte(tplOut), 0600)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf(err.Error())
|
|
||||||
}
|
|
||||||
t.Logf("get a complete diff with command: 'diff -ya %s %s'", testFilename, errFilename)
|
|
||||||
t.Errorf("Failed: test_out != tpl_out for %s", match)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestExecutionErrors(t *testing.T) {
|
|
||||||
//debug = true
|
|
||||||
|
|
||||||
matches, err := filepath.Glob("./template_tests/*-execution.err")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
for idx, match := range matches {
|
|
||||||
t.Logf("[Errors %3d] Testing '%s'", idx+1, match)
|
|
||||||
|
|
||||||
testData, err := ioutil.ReadFile(match)
|
|
||||||
tests := strings.Split(string(testData), "\n")
|
|
||||||
|
|
||||||
checkFilename := fmt.Sprintf("%s.out", match)
|
|
||||||
checkData, err := ioutil.ReadFile(checkFilename)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error on ReadFile('%s'): %s", checkFilename, err.Error())
|
|
||||||
}
|
|
||||||
checks := strings.Split(string(checkData), "\n")
|
|
||||||
|
|
||||||
if len(checks) != len(tests) {
|
|
||||||
t.Fatal("Template lines != Checks lines")
|
|
||||||
}
|
|
||||||
|
|
||||||
for idx, test := range tests {
|
|
||||||
if strings.TrimSpace(test) == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if strings.TrimSpace(checks[idx]) == "" {
|
|
||||||
t.Fatalf("[%s Line %d] Check is empty (must contain an regular expression).",
|
|
||||||
match, idx+1)
|
|
||||||
}
|
|
||||||
|
|
||||||
tpl, err := pongo2.FromString(test)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error on FromString('%s'): %s", test, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
tpl, err = pongo2.FromBytes([]byte(test))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error on FromBytes('%s'): %s", test, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = tpl.ExecuteBytes(tplContext)
|
|
||||||
if err == nil {
|
|
||||||
t.Fatalf("[%s Line %d] Expected error for (got none): %s",
|
|
||||||
match, idx+1, tests[idx])
|
|
||||||
}
|
|
||||||
|
|
||||||
re := regexp.MustCompile(fmt.Sprintf("^%s$", checks[idx]))
|
|
||||||
if !re.MatchString(err.Error()) {
|
|
||||||
t.Fatalf("[%s Line %d] Error for '%s' (err = '%s') does not match the (regexp-)check: %s",
|
|
||||||
match, idx+1, test, err.Error(), checks[idx])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCompilationErrors(t *testing.T) {
|
|
||||||
//debug = true
|
|
||||||
|
|
||||||
matches, err := filepath.Glob("./template_tests/*-compilation.err")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
for idx, match := range matches {
|
|
||||||
t.Logf("[Errors %3d] Testing '%s'", idx+1, match)
|
|
||||||
|
|
||||||
testData, err := ioutil.ReadFile(match)
|
|
||||||
tests := strings.Split(string(testData), "\n")
|
|
||||||
|
|
||||||
checkFilename := fmt.Sprintf("%s.out", match)
|
|
||||||
checkData, err := ioutil.ReadFile(checkFilename)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error on ReadFile('%s'): %s", checkFilename, err.Error())
|
|
||||||
}
|
|
||||||
checks := strings.Split(string(checkData), "\n")
|
|
||||||
|
|
||||||
if len(checks) != len(tests) {
|
|
||||||
t.Fatal("Template lines != Checks lines")
|
|
||||||
}
|
|
||||||
|
|
||||||
for idx, test := range tests {
|
|
||||||
if strings.TrimSpace(test) == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if strings.TrimSpace(checks[idx]) == "" {
|
|
||||||
t.Fatalf("[%s Line %d] Check is empty (must contain an regular expression).",
|
|
||||||
match, idx+1)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = pongo2.FromString(test)
|
|
||||||
if err == nil {
|
|
||||||
t.Fatalf("[%s | Line %d] Expected error for (got none): %s", match, idx+1, tests[idx])
|
|
||||||
}
|
|
||||||
re := regexp.MustCompile(fmt.Sprintf("^%s$", checks[idx]))
|
|
||||||
if !re.MatchString(err.Error()) {
|
|
||||||
t.Fatalf("[%s | Line %d] Error for '%s' (err = '%s') does not match the (regexp-)check: %s",
|
|
||||||
match, idx+1, test, err.Error(), checks[idx])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBaseDirectory(t *testing.T) {
|
|
||||||
mustStr := "Hello from template_tests/base_dir_test/"
|
|
||||||
|
|
||||||
fs := pongo2.MustNewLocalFileSystemLoader("")
|
|
||||||
s := pongo2.NewSet("test set with base directory", fs)
|
|
||||||
s.Globals["base_directory"] = "template_tests/base_dir_test/"
|
|
||||||
if err := fs.SetBaseDir(s.Globals["base_directory"].(string)); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
matches, err := filepath.Glob("./template_tests/base_dir_test/subdir/*")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
for _, match := range matches {
|
|
||||||
match = strings.Replace(match, "template_tests/base_dir_test/", "", -1)
|
|
||||||
|
|
||||||
tpl, err := s.FromFile(match)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
out, err := tpl.Execute(nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if out != mustStr {
|
|
||||||
t.Errorf("%s: out ('%s') != mustStr ('%s')", match, out, mustStr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkCache(b *testing.B) {
|
|
||||||
cacheSet := pongo2.NewSet("cache set", pongo2.MustNewLocalFileSystemLoader(""))
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
tpl, err := cacheSet.FromCache("template_tests/complex.tpl")
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
err = tpl.ExecuteWriterUnbuffered(tplContext, ioutil.Discard)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkCacheDebugOn(b *testing.B) {
|
|
||||||
cacheDebugSet := pongo2.NewSet("cache set", pongo2.MustNewLocalFileSystemLoader(""))
|
|
||||||
cacheDebugSet.Debug = true
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
tpl, err := cacheDebugSet.FromFile("template_tests/complex.tpl")
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
err = tpl.ExecuteWriterUnbuffered(tplContext, ioutil.Discard)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkExecuteComplexWithSandboxActive(b *testing.B) {
|
|
||||||
tpl, err := pongo2.FromFile("template_tests/complex.tpl")
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
err = tpl.ExecuteWriterUnbuffered(tplContext, ioutil.Discard)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkCompileAndExecuteComplexWithSandboxActive(b *testing.B) {
|
|
||||||
buf, err := ioutil.ReadFile("template_tests/complex.tpl")
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
preloadedTpl := string(buf)
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
tpl, err := pongo2.FromString(preloadedTpl)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = tpl.ExecuteWriterUnbuffered(tplContext, ioutil.Discard)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkParallelExecuteComplexWithSandboxActive(b *testing.B) {
|
|
||||||
tpl, err := pongo2.FromFile("template_tests/complex.tpl")
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
b.ResetTimer()
|
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
|
||||||
for pb.Next() {
|
|
||||||
err := tpl.ExecuteWriterUnbuffered(tplContext, ioutil.Discard)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkExecuteComplexWithoutSandbox(b *testing.B) {
|
|
||||||
s := pongo2.NewSet("set without sandbox", pongo2.MustNewLocalFileSystemLoader(""))
|
|
||||||
tpl, err := s.FromFile("template_tests/complex.tpl")
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
err = tpl.ExecuteWriterUnbuffered(tplContext, ioutil.Discard)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkCompileAndExecuteComplexWithoutSandbox(b *testing.B) {
|
|
||||||
buf, err := ioutil.ReadFile("template_tests/complex.tpl")
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
preloadedTpl := string(buf)
|
|
||||||
|
|
||||||
s := pongo2.NewSet("set without sandbox", pongo2.MustNewLocalFileSystemLoader(""))
|
|
||||||
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
tpl, err := s.FromString(preloadedTpl)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = tpl.ExecuteWriterUnbuffered(tplContext, ioutil.Discard)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkParallelExecuteComplexWithoutSandbox(b *testing.B) {
|
|
||||||
s := pongo2.NewSet("set without sandbox", pongo2.MustNewLocalFileSystemLoader(""))
|
|
||||||
tpl, err := s.FromFile("template_tests/complex.tpl")
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
b.ResetTimer()
|
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
|
||||||
for pb.Next() {
|
|
||||||
err := tpl.ExecuteWriterUnbuffered(tplContext, ioutil.Discard)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
103
vendor/github.com/flosch/pongo2/pongo2_test.go
generated
vendored
103
vendor/github.com/flosch/pongo2/pongo2_test.go
generated
vendored
|
@ -1,103 +0,0 @@
|
||||||
package pongo2_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/flosch/pongo2"
|
|
||||||
. "gopkg.in/check.v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Hook up gocheck into the "go test" runner.
|
|
||||||
func Test(t *testing.T) { TestingT(t) }
|
|
||||||
|
|
||||||
type TestSuite struct {
|
|
||||||
tpl *pongo2.Template
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
_ = Suite(&TestSuite{})
|
|
||||||
testSuite2 = pongo2.NewSet("test suite 2", pongo2.MustNewLocalFileSystemLoader(""))
|
|
||||||
)
|
|
||||||
|
|
||||||
func parseTemplate(s string, c pongo2.Context) string {
|
|
||||||
t, err := testSuite2.FromString(s)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
out, err := t.Execute(c)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseTemplateFn(s string, c pongo2.Context) func() {
|
|
||||||
return func() {
|
|
||||||
parseTemplate(s, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *TestSuite) TestMisc(c *C) {
|
|
||||||
// Must
|
|
||||||
// TODO: Add better error message (see issue #18)
|
|
||||||
c.Check(
|
|
||||||
func() { pongo2.Must(testSuite2.FromFile("template_tests/inheritance/base2.tpl")) },
|
|
||||||
PanicMatches,
|
|
||||||
`\[Error \(where: fromfile\) in .*template_tests/inheritance/doesnotexist.tpl | Line 1 Col 12 near 'doesnotexist.tpl'\] open .*template_tests/inheritance/doesnotexist.tpl: no such file or directory`,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Context
|
|
||||||
c.Check(parseTemplateFn("", pongo2.Context{"'illegal": nil}), PanicMatches, ".*not a valid identifier.*")
|
|
||||||
|
|
||||||
// Registers
|
|
||||||
c.Check(pongo2.RegisterFilter("escape", nil).Error(), Matches, ".*is already registered")
|
|
||||||
c.Check(pongo2.RegisterTag("for", nil).Error(), Matches, ".*is already registered")
|
|
||||||
|
|
||||||
// ApplyFilter
|
|
||||||
v, err := pongo2.ApplyFilter("title", pongo2.AsValue("this is a title"), nil)
|
|
||||||
if err != nil {
|
|
||||||
c.Fatal(err)
|
|
||||||
}
|
|
||||||
c.Check(v.String(), Equals, "This Is A Title")
|
|
||||||
c.Check(func() {
|
|
||||||
_, err := pongo2.ApplyFilter("doesnotexist", nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}, PanicMatches, `\[Error \(where: applyfilter\)\] Filter with name 'doesnotexist' not found.`)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *TestSuite) TestImplicitExecCtx(c *C) {
|
|
||||||
tpl, err := pongo2.FromString("{{ ImplicitExec }}")
|
|
||||||
if err != nil {
|
|
||||||
c.Fatalf("Error in FromString: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
val := "a stringy thing"
|
|
||||||
|
|
||||||
res, err := tpl.Execute(pongo2.Context{
|
|
||||||
"Value": val,
|
|
||||||
"ImplicitExec": func(ctx *pongo2.ExecutionContext) string {
|
|
||||||
return ctx.Public["Value"].(string)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
c.Fatalf("Error executing template: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Check(res, Equals, val)
|
|
||||||
|
|
||||||
// The implicit ctx should not be persisted from call-to-call
|
|
||||||
res, err = tpl.Execute(pongo2.Context{
|
|
||||||
"ImplicitExec": func() string {
|
|
||||||
return val
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
c.Fatalf("Error executing template: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Check(res, Equals, val)
|
|
||||||
}
|
|
41
vendor/github.com/flosch/pongo2/tags.go
generated
vendored
41
vendor/github.com/flosch/pongo2/tags.go
generated
vendored
|
@ -21,8 +21,6 @@ package pongo2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/juju/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type INodeTag interface {
|
type INodeTag interface {
|
||||||
|
@ -55,81 +53,80 @@ func init() {
|
||||||
tags = make(map[string]*tag)
|
tags = make(map[string]*tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Registers a new tag. You usually want to call this
|
// Registers a new tag. If there's already a tag with the same
|
||||||
|
// name, RegisterTag will panic. You usually want to call this
|
||||||
// function in the tag's init() function:
|
// function in the tag's init() function:
|
||||||
// http://golang.org/doc/effective_go.html#init
|
// http://golang.org/doc/effective_go.html#init
|
||||||
//
|
//
|
||||||
// See http://www.florian-schlachter.de/post/pongo2/ for more about
|
// See http://www.florian-schlachter.de/post/pongo2/ for more about
|
||||||
// writing filters and tags.
|
// writing filters and tags.
|
||||||
func RegisterTag(name string, parserFn TagParser) error {
|
func RegisterTag(name string, parserFn TagParser) {
|
||||||
_, existing := tags[name]
|
_, existing := tags[name]
|
||||||
if existing {
|
if existing {
|
||||||
return errors.Errorf("tag with name '%s' is already registered", name)
|
panic(fmt.Sprintf("Tag with name '%s' is already registered.", name))
|
||||||
}
|
}
|
||||||
tags[name] = &tag{
|
tags[name] = &tag{
|
||||||
name: name,
|
name: name,
|
||||||
parser: parserFn,
|
parser: parserFn,
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replaces an already registered tag with a new implementation. Use this
|
// Replaces an already registered tag with a new implementation. Use this
|
||||||
// function with caution since it allows you to change existing tag behaviour.
|
// function with caution since it allows you to change existing tag behaviour.
|
||||||
func ReplaceTag(name string, parserFn TagParser) error {
|
func ReplaceTag(name string, parserFn TagParser) {
|
||||||
_, existing := tags[name]
|
_, existing := tags[name]
|
||||||
if !existing {
|
if !existing {
|
||||||
return errors.Errorf("tag with name '%s' does not exist (therefore cannot be overridden)", name)
|
panic(fmt.Sprintf("Tag with name '%s' does not exist (therefore cannot be overridden).", name))
|
||||||
}
|
}
|
||||||
tags[name] = &tag{
|
tags[name] = &tag{
|
||||||
name: name,
|
name: name,
|
||||||
parser: parserFn,
|
parser: parserFn,
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tag = "{%" IDENT ARGS "%}"
|
// Tag = "{%" IDENT ARGS "%}"
|
||||||
func (p *Parser) parseTagElement() (INodeTag, *Error) {
|
func (p *Parser) parseTagElement() (INodeTag, *Error) {
|
||||||
p.Consume() // consume "{%"
|
p.Consume() // consume "{%"
|
||||||
tokenName := p.MatchType(TokenIdentifier)
|
token_name := p.MatchType(TokenIdentifier)
|
||||||
|
|
||||||
// Check for identifier
|
// Check for identifier
|
||||||
if tokenName == nil {
|
if token_name == nil {
|
||||||
return nil, p.Error("Tag name must be an identifier.", nil)
|
return nil, p.Error("Tag name must be an identifier.", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for the existing tag
|
// Check for the existing tag
|
||||||
tag, exists := tags[tokenName.Val]
|
tag, exists := tags[token_name.Val]
|
||||||
if !exists {
|
if !exists {
|
||||||
// Does not exists
|
// Does not exists
|
||||||
return nil, p.Error(fmt.Sprintf("Tag '%s' not found (or beginning tag not provided)", tokenName.Val), tokenName)
|
return nil, p.Error(fmt.Sprintf("Tag '%s' not found (or beginning tag not provided)", token_name.Val), token_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check sandbox tag restriction
|
// Check sandbox tag restriction
|
||||||
if _, isBanned := p.template.set.bannedTags[tokenName.Val]; isBanned {
|
if _, is_banned := p.template.set.bannedTags[token_name.Val]; is_banned {
|
||||||
return nil, p.Error(fmt.Sprintf("Usage of tag '%s' is not allowed (sandbox restriction active).", tokenName.Val), tokenName)
|
return nil, p.Error(fmt.Sprintf("Usage of tag '%s' is not allowed (sandbox restriction active).", token_name.Val), token_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
var argsToken []*Token
|
args_token := make([]*Token, 0)
|
||||||
for p.Peek(TokenSymbol, "%}") == nil && p.Remaining() > 0 {
|
for p.Peek(TokenSymbol, "%}") == nil && p.Remaining() > 0 {
|
||||||
// Add token to args
|
// Add token to args
|
||||||
argsToken = append(argsToken, p.Current())
|
args_token = append(args_token, p.Current())
|
||||||
p.Consume() // next token
|
p.Consume() // next token
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF?
|
// EOF?
|
||||||
if p.Remaining() == 0 {
|
if p.Remaining() == 0 {
|
||||||
return nil, p.Error("Unexpectedly reached EOF, no tag end found.", p.lastToken)
|
return nil, p.Error("Unexpectedly reached EOF, no tag end found.", p.last_token)
|
||||||
}
|
}
|
||||||
|
|
||||||
p.Match(TokenSymbol, "%}")
|
p.Match(TokenSymbol, "%}")
|
||||||
|
|
||||||
argParser := newParser(p.name, argsToken, p.template)
|
arg_parser := newParser(p.name, args_token, p.template)
|
||||||
if len(argsToken) == 0 {
|
if len(args_token) == 0 {
|
||||||
// This is done to have nice EOF error messages
|
// This is done to have nice EOF error messages
|
||||||
argParser.lastToken = tokenName
|
arg_parser.last_token = token_name
|
||||||
}
|
}
|
||||||
|
|
||||||
p.template.level++
|
p.template.level++
|
||||||
defer func() { p.template.level-- }()
|
defer func() { p.template.level-- }()
|
||||||
return tag.parser(p, tokenName, argParser)
|
return tag.parser(p, token_name, arg_parser)
|
||||||
}
|
}
|
||||||
|
|
26
vendor/github.com/flosch/pongo2/tags_autoescape.go
generated
vendored
26
vendor/github.com/flosch/pongo2/tags_autoescape.go
generated
vendored
|
@ -1,15 +1,19 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
)
|
||||||
|
|
||||||
type tagAutoescapeNode struct {
|
type tagAutoescapeNode struct {
|
||||||
wrapper *NodeWrapper
|
wrapper *NodeWrapper
|
||||||
autoescape bool
|
autoescape bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *tagAutoescapeNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (node *tagAutoescapeNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
old := ctx.Autoescape
|
old := ctx.Autoescape
|
||||||
ctx.Autoescape = node.autoescape
|
ctx.Autoescape = node.autoescape
|
||||||
|
|
||||||
err := node.wrapper.Execute(ctx, writer)
|
err := node.wrapper.Execute(ctx, buffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -20,22 +24,22 @@ func (node *tagAutoescapeNode) Execute(ctx *ExecutionContext, writer TemplateWri
|
||||||
}
|
}
|
||||||
|
|
||||||
func tagAutoescapeParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
func tagAutoescapeParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
||||||
autoescapeNode := &tagAutoescapeNode{}
|
autoescape_node := &tagAutoescapeNode{}
|
||||||
|
|
||||||
wrapper, _, err := doc.WrapUntilTag("endautoescape")
|
wrapper, _, err := doc.WrapUntilTag("endautoescape")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
autoescapeNode.wrapper = wrapper
|
autoescape_node.wrapper = wrapper
|
||||||
|
|
||||||
modeToken := arguments.MatchType(TokenIdentifier)
|
mode_token := arguments.MatchType(TokenIdentifier)
|
||||||
if modeToken == nil {
|
if mode_token == nil {
|
||||||
return nil, arguments.Error("A mode is required for autoescape-tag.", nil)
|
return nil, arguments.Error("A mode is required for autoescape-tag.", nil)
|
||||||
}
|
}
|
||||||
if modeToken.Val == "on" {
|
if mode_token.Val == "on" {
|
||||||
autoescapeNode.autoescape = true
|
autoescape_node.autoescape = true
|
||||||
} else if modeToken.Val == "off" {
|
} else if mode_token.Val == "off" {
|
||||||
autoescapeNode.autoescape = false
|
autoescape_node.autoescape = false
|
||||||
} else {
|
} else {
|
||||||
return nil, arguments.Error("Only 'on' or 'off' is valid as an autoescape-mode.", nil)
|
return nil, arguments.Error("Only 'on' or 'off' is valid as an autoescape-mode.", nil)
|
||||||
}
|
}
|
||||||
|
@ -44,7 +48,7 @@ func tagAutoescapeParser(doc *Parser, start *Token, arguments *Parser) (INodeTag
|
||||||
return nil, arguments.Error("Malformed autoescape-tag arguments.", nil)
|
return nil, arguments.Error("Malformed autoescape-tag arguments.", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return autoescapeNode, nil
|
return autoescape_node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
93
vendor/github.com/flosch/pongo2/tags_block.go
generated
vendored
93
vendor/github.com/flosch/pongo2/tags_block.go
generated
vendored
|
@ -9,82 +9,47 @@ type tagBlockNode struct {
|
||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *tagBlockNode) getBlockWrappers(tpl *Template) []*NodeWrapper {
|
func (node *tagBlockNode) getBlockWrapperByName(tpl *Template) *NodeWrapper {
|
||||||
nodeWrappers := make([]*NodeWrapper, 0)
|
|
||||||
var t *NodeWrapper
|
var t *NodeWrapper
|
||||||
|
if tpl.child != nil {
|
||||||
for tpl != nil {
|
// First ask the child for the block
|
||||||
t = tpl.blocks[node.name]
|
t = node.getBlockWrapperByName(tpl.child)
|
||||||
if t != nil {
|
|
||||||
nodeWrappers = append(nodeWrappers, t)
|
|
||||||
}
|
|
||||||
tpl = tpl.child
|
|
||||||
}
|
}
|
||||||
|
if t == nil {
|
||||||
return nodeWrappers
|
// Child has no block, lets look up here at parent
|
||||||
|
t = tpl.blocks[node.name]
|
||||||
|
}
|
||||||
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *tagBlockNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (node *tagBlockNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
tpl := ctx.template
|
tpl := ctx.template
|
||||||
if tpl == nil {
|
if tpl == nil {
|
||||||
panic("internal error: tpl == nil")
|
panic("internal error: tpl == nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the block to execute
|
// Determine the block to execute
|
||||||
blockWrappers := node.getBlockWrappers(tpl)
|
block_wrapper := node.getBlockWrapperByName(tpl)
|
||||||
lenBlockWrappers := len(blockWrappers)
|
if block_wrapper == nil {
|
||||||
|
// fmt.Printf("could not find: %s\n", node.name)
|
||||||
if lenBlockWrappers == 0 {
|
return ctx.Error("internal error: block_wrapper == nil in tagBlockNode.Execute()", nil)
|
||||||
return ctx.Error("internal error: len(block_wrappers) == 0 in tagBlockNode.Execute()", nil)
|
|
||||||
}
|
}
|
||||||
|
err := block_wrapper.Execute(ctx, buffer)
|
||||||
blockWrapper := blockWrappers[lenBlockWrappers-1]
|
|
||||||
ctx.Private["block"] = tagBlockInformation{
|
|
||||||
ctx: ctx,
|
|
||||||
wrappers: blockWrappers[0 : lenBlockWrappers-1],
|
|
||||||
}
|
|
||||||
err := blockWrapper.Execute(ctx, writer)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Add support for {{ block.super }}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type tagBlockInformation struct {
|
|
||||||
ctx *ExecutionContext
|
|
||||||
wrappers []*NodeWrapper
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t tagBlockInformation) Super() string {
|
|
||||||
lenWrappers := len(t.wrappers)
|
|
||||||
|
|
||||||
if lenWrappers == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
superCtx := NewChildExecutionContext(t.ctx)
|
|
||||||
superCtx.Private["block"] = tagBlockInformation{
|
|
||||||
ctx: t.ctx,
|
|
||||||
wrappers: t.wrappers[0 : lenWrappers-1],
|
|
||||||
}
|
|
||||||
|
|
||||||
blockWrapper := t.wrappers[lenWrappers-1]
|
|
||||||
buf := bytes.NewBufferString("")
|
|
||||||
err := blockWrapper.Execute(superCtx, &templateWriter{buf})
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func tagBlockParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
func tagBlockParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
||||||
if arguments.Count() == 0 {
|
if arguments.Count() == 0 {
|
||||||
return nil, arguments.Error("Tag 'block' requires an identifier.", nil)
|
return nil, arguments.Error("Tag 'block' requires an identifier.", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
nameToken := arguments.MatchType(TokenIdentifier)
|
name_token := arguments.MatchType(TokenIdentifier)
|
||||||
if nameToken == nil {
|
if name_token == nil {
|
||||||
return nil, arguments.Error("First argument for tag 'block' must be an identifier.", nil)
|
return nil, arguments.Error("First argument for tag 'block' must be an identifier.", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,15 +62,15 @@ func tagBlockParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Er
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if endtagargs.Remaining() > 0 {
|
if endtagargs.Remaining() > 0 {
|
||||||
endtagnameToken := endtagargs.MatchType(TokenIdentifier)
|
endtagname_token := endtagargs.MatchType(TokenIdentifier)
|
||||||
if endtagnameToken != nil {
|
if endtagname_token != nil {
|
||||||
if endtagnameToken.Val != nameToken.Val {
|
if endtagname_token.Val != name_token.Val {
|
||||||
return nil, endtagargs.Error(fmt.Sprintf("Name for 'endblock' must equal to 'block'-tag's name ('%s' != '%s').",
|
return nil, endtagargs.Error(fmt.Sprintf("Name for 'endblock' must equal to 'block'-tag's name ('%s' != '%s').",
|
||||||
nameToken.Val, endtagnameToken.Val), nil)
|
name_token.Val, endtagname_token.Val), nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if endtagnameToken == nil || endtagargs.Remaining() > 0 {
|
if endtagname_token == nil || endtagargs.Remaining() > 0 {
|
||||||
return nil, endtagargs.Error("Either no or only one argument (identifier) allowed for 'endblock'.", nil)
|
return nil, endtagargs.Error("Either no or only one argument (identifier) allowed for 'endblock'.", nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,14 +79,14 @@ func tagBlockParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Er
|
||||||
if tpl == nil {
|
if tpl == nil {
|
||||||
panic("internal error: tpl == nil")
|
panic("internal error: tpl == nil")
|
||||||
}
|
}
|
||||||
_, hasBlock := tpl.blocks[nameToken.Val]
|
_, has_block := tpl.blocks[name_token.Val]
|
||||||
if !hasBlock {
|
if !has_block {
|
||||||
tpl.blocks[nameToken.Val] = wrapper
|
tpl.blocks[name_token.Val] = wrapper
|
||||||
} else {
|
} else {
|
||||||
return nil, arguments.Error(fmt.Sprintf("Block named '%s' already defined", nameToken.Val), nil)
|
return nil, arguments.Error(fmt.Sprintf("Block named '%s' already defined", name_token.Val), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &tagBlockNode{name: nameToken.Val}, nil
|
return &tagBlockNode{name: name_token.Val}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
12
vendor/github.com/flosch/pongo2/tags_comment.go
generated
vendored
12
vendor/github.com/flosch/pongo2/tags_comment.go
generated
vendored
|
@ -1,16 +1,20 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
)
|
||||||
|
|
||||||
type tagCommentNode struct{}
|
type tagCommentNode struct{}
|
||||||
|
|
||||||
func (node *tagCommentNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (node *tagCommentNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func tagCommentParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
func tagCommentParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
||||||
commentNode := &tagCommentNode{}
|
comment_node := &tagCommentNode{}
|
||||||
|
|
||||||
// TODO: Process the endtag's arguments (see django 'comment'-tag documentation)
|
// TODO: Process the endtag's arguments (see django 'comment'-tag documentation)
|
||||||
err := doc.SkipUntilTag("endcomment")
|
_, _, err := doc.WrapUntilTag("endcomment")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -19,7 +23,7 @@ func tagCommentParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *
|
||||||
return nil, arguments.Error("Tag 'comment' does not take any argument.", nil)
|
return nil, arguments.Error("Tag 'comment' does not take any argument.", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return commentNode, nil
|
return comment_node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
34
vendor/github.com/flosch/pongo2/tags_cycle.go
generated
vendored
34
vendor/github.com/flosch/pongo2/tags_cycle.go
generated
vendored
|
@ -1,5 +1,9 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
)
|
||||||
|
|
||||||
type tagCycleValue struct {
|
type tagCycleValue struct {
|
||||||
node *tagCycleNode
|
node *tagCycleNode
|
||||||
value *Value
|
value *Value
|
||||||
|
@ -9,7 +13,7 @@ type tagCycleNode struct {
|
||||||
position *Token
|
position *Token
|
||||||
args []IEvaluator
|
args []IEvaluator
|
||||||
idx int
|
idx int
|
||||||
asName string
|
as_name string
|
||||||
silent bool
|
silent bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +21,7 @@ func (cv *tagCycleValue) String() string {
|
||||||
return cv.value.String()
|
return cv.value.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *tagCycleNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (node *tagCycleNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
item := node.args[node.idx%len(node.args)]
|
item := node.args[node.idx%len(node.args)]
|
||||||
node.idx++
|
node.idx++
|
||||||
|
|
||||||
|
@ -42,30 +46,30 @@ func (node *tagCycleNode) Execute(ctx *ExecutionContext, writer TemplateWriter)
|
||||||
t.value = val
|
t.value = val
|
||||||
|
|
||||||
if !t.node.silent {
|
if !t.node.silent {
|
||||||
writer.WriteString(val.String())
|
buffer.WriteString(val.String())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Regular call
|
// Regular call
|
||||||
|
|
||||||
cycleValue := &tagCycleValue{
|
cycle_value := &tagCycleValue{
|
||||||
node: node,
|
node: node,
|
||||||
value: val,
|
value: val,
|
||||||
}
|
}
|
||||||
|
|
||||||
if node.asName != "" {
|
if node.as_name != "" {
|
||||||
ctx.Private[node.asName] = cycleValue
|
ctx.Private[node.as_name] = cycle_value
|
||||||
}
|
}
|
||||||
if !node.silent {
|
if !node.silent {
|
||||||
writer.WriteString(val.String())
|
buffer.WriteString(val.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// HINT: We're not supporting the old comma-separated list of expressions argument-style
|
// HINT: We're not supporting the old comma-seperated list of expresions argument-style
|
||||||
func tagCycleParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
func tagCycleParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
||||||
cycleNode := &tagCycleNode{
|
cycle_node := &tagCycleNode{
|
||||||
position: start,
|
position: start,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,19 +78,19 @@ func tagCycleParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Er
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
cycleNode.args = append(cycleNode.args, node)
|
cycle_node.args = append(cycle_node.args, node)
|
||||||
|
|
||||||
if arguments.MatchOne(TokenKeyword, "as") != nil {
|
if arguments.MatchOne(TokenKeyword, "as") != nil {
|
||||||
// as
|
// as
|
||||||
|
|
||||||
nameToken := arguments.MatchType(TokenIdentifier)
|
name_token := arguments.MatchType(TokenIdentifier)
|
||||||
if nameToken == nil {
|
if name_token == nil {
|
||||||
return nil, arguments.Error("Name (identifier) expected after 'as'.", nil)
|
return nil, arguments.Error("Name (identifier) expected after 'as'.", nil)
|
||||||
}
|
}
|
||||||
cycleNode.asName = nameToken.Val
|
cycle_node.as_name = name_token.Val
|
||||||
|
|
||||||
if arguments.MatchOne(TokenIdentifier, "silent") != nil {
|
if arguments.MatchOne(TokenIdentifier, "silent") != nil {
|
||||||
cycleNode.silent = true
|
cycle_node.silent = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we're finished
|
// Now we're finished
|
||||||
|
@ -98,7 +102,7 @@ func tagCycleParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Er
|
||||||
return nil, arguments.Error("Malformed cycle-tag.", nil)
|
return nil, arguments.Error("Malformed cycle-tag.", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return cycleNode, nil
|
return cycle_node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
22
vendor/github.com/flosch/pongo2/tags_extends.go
generated
vendored
22
vendor/github.com/flosch/pongo2/tags_extends.go
generated
vendored
|
@ -1,15 +1,19 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
)
|
||||||
|
|
||||||
type tagExtendsNode struct {
|
type tagExtendsNode struct {
|
||||||
filename string
|
filename string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *tagExtendsNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (node *tagExtendsNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func tagExtendsParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
func tagExtendsParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
||||||
extendsNode := &tagExtendsNode{}
|
extends_node := &tagExtendsNode{}
|
||||||
|
|
||||||
if doc.template.level > 1 {
|
if doc.template.level > 1 {
|
||||||
return nil, arguments.Error("The 'extends' tag can only defined on root level.", start)
|
return nil, arguments.Error("The 'extends' tag can only defined on root level.", start)
|
||||||
|
@ -20,22 +24,22 @@ func tagExtendsParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *
|
||||||
return nil, arguments.Error("This template has already one parent.", start)
|
return nil, arguments.Error("This template has already one parent.", start)
|
||||||
}
|
}
|
||||||
|
|
||||||
if filenameToken := arguments.MatchType(TokenString); filenameToken != nil {
|
if filename_token := arguments.MatchType(TokenString); filename_token != nil {
|
||||||
// prepared, static template
|
// prepared, static template
|
||||||
|
|
||||||
// Get parent's filename
|
// Get parent's filename
|
||||||
parentFilename := doc.template.set.resolveFilename(doc.template, filenameToken.Val)
|
parent_filename := doc.template.set.resolveFilename(doc.template, filename_token.Val)
|
||||||
|
|
||||||
// Parse the parent
|
// Parse the parent
|
||||||
parentTemplate, err := doc.template.set.FromFile(parentFilename)
|
parent_template, err := doc.template.set.FromFile(parent_filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err.(*Error)
|
return nil, err.(*Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep track of things
|
// Keep track of things
|
||||||
parentTemplate.child = doc.template
|
parent_template.child = doc.template
|
||||||
doc.template.parent = parentTemplate
|
doc.template.parent = parent_template
|
||||||
extendsNode.filename = parentFilename
|
extends_node.filename = parent_filename
|
||||||
} else {
|
} else {
|
||||||
return nil, arguments.Error("Tag 'extends' requires a template filename as string.", nil)
|
return nil, arguments.Error("Tag 'extends' requires a template filename as string.", nil)
|
||||||
}
|
}
|
||||||
|
@ -44,7 +48,7 @@ func tagExtendsParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *
|
||||||
return nil, arguments.Error("Tag 'extends' does only take 1 argument.", nil)
|
return nil, arguments.Error("Tag 'extends' does only take 1 argument.", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return extendsNode, nil
|
return extends_node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
28
vendor/github.com/flosch/pongo2/tags_filter.go
generated
vendored
28
vendor/github.com/flosch/pongo2/tags_filter.go
generated
vendored
|
@ -5,8 +5,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type nodeFilterCall struct {
|
type nodeFilterCall struct {
|
||||||
name string
|
name string
|
||||||
paramExpr IEvaluator
|
param_expr IEvaluator
|
||||||
}
|
}
|
||||||
|
|
||||||
type tagFilterNode struct {
|
type tagFilterNode struct {
|
||||||
|
@ -15,7 +15,7 @@ type tagFilterNode struct {
|
||||||
filterChain []*nodeFilterCall
|
filterChain []*nodeFilterCall
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *tagFilterNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (node *tagFilterNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
temp := bytes.NewBuffer(make([]byte, 0, 1024)) // 1 KiB size
|
temp := bytes.NewBuffer(make([]byte, 0, 1024)) // 1 KiB size
|
||||||
|
|
||||||
err := node.bodyWrapper.Execute(ctx, temp)
|
err := node.bodyWrapper.Execute(ctx, temp)
|
||||||
|
@ -27,8 +27,8 @@ func (node *tagFilterNode) Execute(ctx *ExecutionContext, writer TemplateWriter)
|
||||||
|
|
||||||
for _, call := range node.filterChain {
|
for _, call := range node.filterChain {
|
||||||
var param *Value
|
var param *Value
|
||||||
if call.paramExpr != nil {
|
if call.param_expr != nil {
|
||||||
param, err = call.paramExpr.Evaluate(ctx)
|
param, err = call.param_expr.Evaluate(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -41,13 +41,13 @@ func (node *tagFilterNode) Execute(ctx *ExecutionContext, writer TemplateWriter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.WriteString(value.String())
|
buffer.WriteString(value.String())
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func tagFilterParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
func tagFilterParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
||||||
filterNode := &tagFilterNode{
|
filter_node := &tagFilterNode{
|
||||||
position: start,
|
position: start,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,16 +55,16 @@ func tagFilterParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *E
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
filterNode.bodyWrapper = wrapper
|
filter_node.bodyWrapper = wrapper
|
||||||
|
|
||||||
for arguments.Remaining() > 0 {
|
for arguments.Remaining() > 0 {
|
||||||
filterCall := &nodeFilterCall{}
|
filterCall := &nodeFilterCall{}
|
||||||
|
|
||||||
nameToken := arguments.MatchType(TokenIdentifier)
|
name_token := arguments.MatchType(TokenIdentifier)
|
||||||
if nameToken == nil {
|
if name_token == nil {
|
||||||
return nil, arguments.Error("Expected a filter name (identifier).", nil)
|
return nil, arguments.Error("Expected a filter name (identifier).", nil)
|
||||||
}
|
}
|
||||||
filterCall.name = nameToken.Val
|
filterCall.name = name_token.Val
|
||||||
|
|
||||||
if arguments.MatchOne(TokenSymbol, ":") != nil {
|
if arguments.MatchOne(TokenSymbol, ":") != nil {
|
||||||
// Filter parameter
|
// Filter parameter
|
||||||
|
@ -73,10 +73,10 @@ func tagFilterParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *E
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
filterCall.paramExpr = expr
|
filterCall.param_expr = expr
|
||||||
}
|
}
|
||||||
|
|
||||||
filterNode.filterChain = append(filterNode.filterChain, filterCall)
|
filter_node.filterChain = append(filter_node.filterChain, filterCall)
|
||||||
|
|
||||||
if arguments.MatchOne(TokenSymbol, "|") == nil {
|
if arguments.MatchOne(TokenSymbol, "|") == nil {
|
||||||
break
|
break
|
||||||
|
@ -87,7 +87,7 @@ func tagFilterParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *E
|
||||||
return nil, arguments.Error("Malformed filter-tag arguments.", nil)
|
return nil, arguments.Error("Malformed filter-tag arguments.", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return filterNode, nil
|
return filter_node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
14
vendor/github.com/flosch/pongo2/tags_firstof.go
generated
vendored
14
vendor/github.com/flosch/pongo2/tags_firstof.go
generated
vendored
|
@ -1,11 +1,15 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
)
|
||||||
|
|
||||||
type tagFirstofNode struct {
|
type tagFirstofNode struct {
|
||||||
position *Token
|
position *Token
|
||||||
args []IEvaluator
|
args []IEvaluator
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *tagFirstofNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (node *tagFirstofNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
for _, arg := range node.args {
|
for _, arg := range node.args {
|
||||||
val, err := arg.Evaluate(ctx)
|
val, err := arg.Evaluate(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -20,7 +24,7 @@ func (node *tagFirstofNode) Execute(ctx *ExecutionContext, writer TemplateWriter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.WriteString(val.String())
|
buffer.WriteString(val.String())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +33,7 @@ func (node *tagFirstofNode) Execute(ctx *ExecutionContext, writer TemplateWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
func tagFirstofParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
func tagFirstofParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
||||||
firstofNode := &tagFirstofNode{
|
firstof_node := &tagFirstofNode{
|
||||||
position: start,
|
position: start,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,10 +42,10 @@ func tagFirstofParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
firstofNode.args = append(firstofNode.args, node)
|
firstof_node.args = append(firstof_node.args, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
return firstofNode, nil
|
return firstof_node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
59
vendor/github.com/flosch/pongo2/tags_for.go
generated
vendored
59
vendor/github.com/flosch/pongo2/tags_for.go
generated
vendored
|
@ -1,11 +1,14 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
)
|
||||||
|
|
||||||
type tagForNode struct {
|
type tagForNode struct {
|
||||||
key string
|
key string
|
||||||
value string // only for maps: for key, value in map
|
value string // only for maps: for key, value in map
|
||||||
objectEvaluator IEvaluator
|
object_evaluator IEvaluator
|
||||||
reversed bool
|
reversed bool
|
||||||
sorted bool
|
|
||||||
|
|
||||||
bodyWrapper *NodeWrapper
|
bodyWrapper *NodeWrapper
|
||||||
emptyWrapper *NodeWrapper
|
emptyWrapper *NodeWrapper
|
||||||
|
@ -21,7 +24,7 @@ type tagForLoopInformation struct {
|
||||||
Parentloop *tagForLoopInformation
|
Parentloop *tagForLoopInformation
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *tagForNode) Execute(ctx *ExecutionContext, writer TemplateWriter) (forError *Error) {
|
func (node *tagForNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) (forError *Error) {
|
||||||
// Backup forloop (as parentloop in public context), key-name and value-name
|
// Backup forloop (as parentloop in public context), key-name and value-name
|
||||||
forCtx := NewChildExecutionContext(ctx)
|
forCtx := NewChildExecutionContext(ctx)
|
||||||
parentloop := forCtx.Private["forloop"]
|
parentloop := forCtx.Private["forloop"]
|
||||||
|
@ -39,7 +42,7 @@ func (node *tagForNode) Execute(ctx *ExecutionContext, writer TemplateWriter) (f
|
||||||
// Register loopInfo in public context
|
// Register loopInfo in public context
|
||||||
forCtx.Private["forloop"] = loopInfo
|
forCtx.Private["forloop"] = loopInfo
|
||||||
|
|
||||||
obj, err := node.objectEvaluator.Evaluate(forCtx)
|
obj, err := node.object_evaluator.Evaluate(forCtx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -64,7 +67,7 @@ func (node *tagForNode) Execute(ctx *ExecutionContext, writer TemplateWriter) (f
|
||||||
loopInfo.Revcounter0 = count - (idx + 1) // TODO: Not sure about this, have to look it up
|
loopInfo.Revcounter0 = count - (idx + 1) // TODO: Not sure about this, have to look it up
|
||||||
|
|
||||||
// Render elements with updated context
|
// Render elements with updated context
|
||||||
err := node.bodyWrapper.Execute(forCtx, writer)
|
err := node.bodyWrapper.Execute(forCtx, buffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
forError = err
|
forError = err
|
||||||
return false
|
return false
|
||||||
|
@ -73,30 +76,30 @@ func (node *tagForNode) Execute(ctx *ExecutionContext, writer TemplateWriter) (f
|
||||||
}, func() {
|
}, func() {
|
||||||
// Nothing to iterate over (maybe wrong type or no items)
|
// Nothing to iterate over (maybe wrong type or no items)
|
||||||
if node.emptyWrapper != nil {
|
if node.emptyWrapper != nil {
|
||||||
err := node.emptyWrapper.Execute(forCtx, writer)
|
err := node.emptyWrapper.Execute(forCtx, buffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
forError = err
|
forError = err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, node.reversed, node.sorted)
|
}, node.reversed)
|
||||||
|
|
||||||
return forError
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func tagForParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
func tagForParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
||||||
forNode := &tagForNode{}
|
for_node := &tagForNode{}
|
||||||
|
|
||||||
// Arguments parsing
|
// Arguments parsing
|
||||||
var valueToken *Token
|
var value_token *Token
|
||||||
keyToken := arguments.MatchType(TokenIdentifier)
|
key_token := arguments.MatchType(TokenIdentifier)
|
||||||
if keyToken == nil {
|
if key_token == nil {
|
||||||
return nil, arguments.Error("Expected an key identifier as first argument for 'for'-tag", nil)
|
return nil, arguments.Error("Expected an key identifier as first argument for 'for'-tag", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
if arguments.Match(TokenSymbol, ",") != nil {
|
if arguments.Match(TokenSymbol, ",") != nil {
|
||||||
// Value name is provided
|
// Value name is provided
|
||||||
valueToken = arguments.MatchType(TokenIdentifier)
|
value_token = arguments.MatchType(TokenIdentifier)
|
||||||
if valueToken == nil {
|
if value_token == nil {
|
||||||
return nil, arguments.Error("Value name must be an identifier.", nil)
|
return nil, arguments.Error("Value name must be an identifier.", nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,22 +108,18 @@ func tagForParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Erro
|
||||||
return nil, arguments.Error("Expected keyword 'in'.", nil)
|
return nil, arguments.Error("Expected keyword 'in'.", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
objectEvaluator, err := arguments.ParseExpression()
|
object_evaluator, err := arguments.ParseExpression()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
forNode.objectEvaluator = objectEvaluator
|
for_node.object_evaluator = object_evaluator
|
||||||
forNode.key = keyToken.Val
|
for_node.key = key_token.Val
|
||||||
if valueToken != nil {
|
if value_token != nil {
|
||||||
forNode.value = valueToken.Val
|
for_node.value = value_token.Val
|
||||||
}
|
}
|
||||||
|
|
||||||
if arguments.MatchOne(TokenIdentifier, "reversed") != nil {
|
if arguments.MatchOne(TokenIdentifier, "reversed") != nil {
|
||||||
forNode.reversed = true
|
for_node.reversed = true
|
||||||
}
|
|
||||||
|
|
||||||
if arguments.MatchOne(TokenIdentifier, "sorted") != nil {
|
|
||||||
forNode.sorted = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if arguments.Remaining() > 0 {
|
if arguments.Remaining() > 0 {
|
||||||
|
@ -132,7 +131,7 @@ func tagForParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Erro
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
forNode.bodyWrapper = wrapper
|
for_node.bodyWrapper = wrapper
|
||||||
|
|
||||||
if endargs.Count() > 0 {
|
if endargs.Count() > 0 {
|
||||||
return nil, endargs.Error("Arguments not allowed here.", nil)
|
return nil, endargs.Error("Arguments not allowed here.", nil)
|
||||||
|
@ -144,14 +143,14 @@ func tagForParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Erro
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
forNode.emptyWrapper = wrapper
|
for_node.emptyWrapper = wrapper
|
||||||
|
|
||||||
if endargs.Count() > 0 {
|
if endargs.Count() > 0 {
|
||||||
return nil, endargs.Error("Arguments not allowed here.", nil)
|
return nil, endargs.Error("Arguments not allowed here.", nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return forNode, nil
|
return for_node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
39
vendor/github.com/flosch/pongo2/tags_if.go
generated
vendored
39
vendor/github.com/flosch/pongo2/tags_if.go
generated
vendored
|
@ -1,11 +1,15 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
)
|
||||||
|
|
||||||
type tagIfNode struct {
|
type tagIfNode struct {
|
||||||
conditions []IEvaluator
|
conditions []IEvaluator
|
||||||
wrappers []*NodeWrapper
|
wrappers []*NodeWrapper
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *tagIfNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (node *tagIfNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
for i, condition := range node.conditions {
|
for i, condition := range node.conditions {
|
||||||
result, err := condition.Evaluate(ctx)
|
result, err := condition.Evaluate(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -13,25 +17,26 @@ func (node *tagIfNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Er
|
||||||
}
|
}
|
||||||
|
|
||||||
if result.IsTrue() {
|
if result.IsTrue() {
|
||||||
return node.wrappers[i].Execute(ctx, writer)
|
return node.wrappers[i].Execute(ctx, buffer)
|
||||||
}
|
} else {
|
||||||
// Last condition?
|
// Last condition?
|
||||||
if len(node.conditions) == i+1 && len(node.wrappers) > i+1 {
|
if len(node.conditions) == i+1 && len(node.wrappers) > i+1 {
|
||||||
return node.wrappers[i+1].Execute(ctx, writer)
|
return node.wrappers[i+1].Execute(ctx, buffer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func tagIfParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
func tagIfParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
||||||
ifNode := &tagIfNode{}
|
if_node := &tagIfNode{}
|
||||||
|
|
||||||
// Parse first and main IF condition
|
// Parse first and main IF condition
|
||||||
condition, err := arguments.ParseExpression()
|
condition, err := arguments.ParseExpression()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ifNode.conditions = append(ifNode.conditions, condition)
|
if_node.conditions = append(if_node.conditions, condition)
|
||||||
|
|
||||||
if arguments.Remaining() > 0 {
|
if arguments.Remaining() > 0 {
|
||||||
return nil, arguments.Error("If-condition is malformed.", nil)
|
return nil, arguments.Error("If-condition is malformed.", nil)
|
||||||
|
@ -39,27 +44,27 @@ func tagIfParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error
|
||||||
|
|
||||||
// Check the rest
|
// Check the rest
|
||||||
for {
|
for {
|
||||||
wrapper, tagArgs, err := doc.WrapUntilTag("elif", "else", "endif")
|
wrapper, tag_args, err := doc.WrapUntilTag("elif", "else", "endif")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ifNode.wrappers = append(ifNode.wrappers, wrapper)
|
if_node.wrappers = append(if_node.wrappers, wrapper)
|
||||||
|
|
||||||
if wrapper.Endtag == "elif" {
|
if wrapper.Endtag == "elif" {
|
||||||
// elif can take a condition
|
// elif can take a condition
|
||||||
condition, err = tagArgs.ParseExpression()
|
condition, err := tag_args.ParseExpression()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ifNode.conditions = append(ifNode.conditions, condition)
|
if_node.conditions = append(if_node.conditions, condition)
|
||||||
|
|
||||||
if tagArgs.Remaining() > 0 {
|
if tag_args.Remaining() > 0 {
|
||||||
return nil, tagArgs.Error("Elif-condition is malformed.", nil)
|
return nil, tag_args.Error("Elif-condition is malformed.", nil)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if tagArgs.Count() > 0 {
|
if tag_args.Count() > 0 {
|
||||||
// else/endif can't take any conditions
|
// else/endif can't take any conditions
|
||||||
return nil, tagArgs.Error("Arguments not allowed here.", nil)
|
return nil, tag_args.Error("Arguments not allowed here.", nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +73,7 @@ func tagIfParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ifNode, nil
|
return if_node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
51
vendor/github.com/flosch/pongo2/tags_ifchanged.go
generated
vendored
51
vendor/github.com/flosch/pongo2/tags_ifchanged.go
generated
vendored
|
@ -5,15 +5,16 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type tagIfchangedNode struct {
|
type tagIfchangedNode struct {
|
||||||
watchedExpr []IEvaluator
|
watched_expr []IEvaluator
|
||||||
lastValues []*Value
|
last_values []*Value
|
||||||
lastContent []byte
|
last_content []byte
|
||||||
thenWrapper *NodeWrapper
|
thenWrapper *NodeWrapper
|
||||||
elseWrapper *NodeWrapper
|
elseWrapper *NodeWrapper
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *tagIfchangedNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (node *tagIfchangedNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
if len(node.watchedExpr) == 0 {
|
|
||||||
|
if len(node.watched_expr) == 0 {
|
||||||
// Check against own rendered body
|
// Check against own rendered body
|
||||||
|
|
||||||
buf := bytes.NewBuffer(make([]byte, 0, 1024)) // 1 KiB
|
buf := bytes.NewBuffer(make([]byte, 0, 1024)) // 1 KiB
|
||||||
|
@ -22,43 +23,43 @@ func (node *tagIfchangedNode) Execute(ctx *ExecutionContext, writer TemplateWrit
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
bufBytes := buf.Bytes()
|
buf_bytes := buf.Bytes()
|
||||||
if !bytes.Equal(node.lastContent, bufBytes) {
|
if !bytes.Equal(node.last_content, buf_bytes) {
|
||||||
// Rendered content changed, output it
|
// Rendered content changed, output it
|
||||||
writer.Write(bufBytes)
|
buffer.Write(buf_bytes)
|
||||||
node.lastContent = bufBytes
|
node.last_content = buf_bytes
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nowValues := make([]*Value, 0, len(node.watchedExpr))
|
now_values := make([]*Value, 0, len(node.watched_expr))
|
||||||
for _, expr := range node.watchedExpr {
|
for _, expr := range node.watched_expr {
|
||||||
val, err := expr.Evaluate(ctx)
|
val, err := expr.Evaluate(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
nowValues = append(nowValues, val)
|
now_values = append(now_values, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare old to new values now
|
// Compare old to new values now
|
||||||
changed := len(node.lastValues) == 0
|
changed := len(node.last_values) == 0
|
||||||
|
|
||||||
for idx, oldVal := range node.lastValues {
|
for idx, old_val := range node.last_values {
|
||||||
if !oldVal.EqualValueTo(nowValues[idx]) {
|
if !old_val.EqualValueTo(now_values[idx]) {
|
||||||
changed = true
|
changed = true
|
||||||
break // we can stop here because ONE value changed
|
break // we can stop here because ONE value changed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
node.lastValues = nowValues
|
node.last_values = now_values
|
||||||
|
|
||||||
if changed {
|
if changed {
|
||||||
// Render thenWrapper
|
// Render thenWrapper
|
||||||
err := node.thenWrapper.Execute(ctx, writer)
|
err := node.thenWrapper.Execute(ctx, buffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Render elseWrapper
|
// Render elseWrapper
|
||||||
err := node.elseWrapper.Execute(ctx, writer)
|
err := node.elseWrapper.Execute(ctx, buffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -69,7 +70,7 @@ func (node *tagIfchangedNode) Execute(ctx *ExecutionContext, writer TemplateWrit
|
||||||
}
|
}
|
||||||
|
|
||||||
func tagIfchangedParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
func tagIfchangedParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
||||||
ifchangedNode := &tagIfchangedNode{}
|
ifchanged_node := &tagIfchangedNode{}
|
||||||
|
|
||||||
for arguments.Remaining() > 0 {
|
for arguments.Remaining() > 0 {
|
||||||
// Parse condition
|
// Parse condition
|
||||||
|
@ -77,7 +78,7 @@ func tagIfchangedParser(doc *Parser, start *Token, arguments *Parser) (INodeTag,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ifchangedNode.watchedExpr = append(ifchangedNode.watchedExpr, expr)
|
ifchanged_node.watched_expr = append(ifchanged_node.watched_expr, expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if arguments.Remaining() > 0 {
|
if arguments.Remaining() > 0 {
|
||||||
|
@ -89,7 +90,7 @@ func tagIfchangedParser(doc *Parser, start *Token, arguments *Parser) (INodeTag,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ifchangedNode.thenWrapper = wrapper
|
ifchanged_node.thenWrapper = wrapper
|
||||||
|
|
||||||
if endargs.Count() > 0 {
|
if endargs.Count() > 0 {
|
||||||
return nil, endargs.Error("Arguments not allowed here.", nil)
|
return nil, endargs.Error("Arguments not allowed here.", nil)
|
||||||
|
@ -101,14 +102,14 @@ func tagIfchangedParser(doc *Parser, start *Token, arguments *Parser) (INodeTag,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ifchangedNode.elseWrapper = wrapper
|
ifchanged_node.elseWrapper = wrapper
|
||||||
|
|
||||||
if endargs.Count() > 0 {
|
if endargs.Count() > 0 {
|
||||||
return nil, endargs.Error("Arguments not allowed here.", nil)
|
return nil, endargs.Error("Arguments not allowed here.", nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ifchangedNode, nil
|
return ifchanged_node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
27
vendor/github.com/flosch/pongo2/tags_ifequal.go
generated
vendored
27
vendor/github.com/flosch/pongo2/tags_ifequal.go
generated
vendored
|
@ -1,12 +1,16 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
)
|
||||||
|
|
||||||
type tagIfEqualNode struct {
|
type tagIfEqualNode struct {
|
||||||
var1, var2 IEvaluator
|
var1, var2 IEvaluator
|
||||||
thenWrapper *NodeWrapper
|
thenWrapper *NodeWrapper
|
||||||
elseWrapper *NodeWrapper
|
elseWrapper *NodeWrapper
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *tagIfEqualNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (node *tagIfEqualNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
r1, err := node.var1.Evaluate(ctx)
|
r1, err := node.var1.Evaluate(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -19,16 +23,17 @@ func (node *tagIfEqualNode) Execute(ctx *ExecutionContext, writer TemplateWriter
|
||||||
result := r1.EqualValueTo(r2)
|
result := r1.EqualValueTo(r2)
|
||||||
|
|
||||||
if result {
|
if result {
|
||||||
return node.thenWrapper.Execute(ctx, writer)
|
return node.thenWrapper.Execute(ctx, buffer)
|
||||||
}
|
} else {
|
||||||
if node.elseWrapper != nil {
|
if node.elseWrapper != nil {
|
||||||
return node.elseWrapper.Execute(ctx, writer)
|
return node.elseWrapper.Execute(ctx, buffer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func tagIfEqualParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
func tagIfEqualParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
||||||
ifequalNode := &tagIfEqualNode{}
|
ifequal_node := &tagIfEqualNode{}
|
||||||
|
|
||||||
// Parse two expressions
|
// Parse two expressions
|
||||||
var1, err := arguments.ParseExpression()
|
var1, err := arguments.ParseExpression()
|
||||||
|
@ -39,8 +44,8 @@ func tagIfEqualParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ifequalNode.var1 = var1
|
ifequal_node.var1 = var1
|
||||||
ifequalNode.var2 = var2
|
ifequal_node.var2 = var2
|
||||||
|
|
||||||
if arguments.Remaining() > 0 {
|
if arguments.Remaining() > 0 {
|
||||||
return nil, arguments.Error("ifequal only takes 2 arguments.", nil)
|
return nil, arguments.Error("ifequal only takes 2 arguments.", nil)
|
||||||
|
@ -51,7 +56,7 @@ func tagIfEqualParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ifequalNode.thenWrapper = wrapper
|
ifequal_node.thenWrapper = wrapper
|
||||||
|
|
||||||
if endargs.Count() > 0 {
|
if endargs.Count() > 0 {
|
||||||
return nil, endargs.Error("Arguments not allowed here.", nil)
|
return nil, endargs.Error("Arguments not allowed here.", nil)
|
||||||
|
@ -63,14 +68,14 @@ func tagIfEqualParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ifequalNode.elseWrapper = wrapper
|
ifequal_node.elseWrapper = wrapper
|
||||||
|
|
||||||
if endargs.Count() > 0 {
|
if endargs.Count() > 0 {
|
||||||
return nil, endargs.Error("Arguments not allowed here.", nil)
|
return nil, endargs.Error("Arguments not allowed here.", nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ifequalNode, nil
|
return ifequal_node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
31
vendor/github.com/flosch/pongo2/tags_ifnotequal.go
generated
vendored
31
vendor/github.com/flosch/pongo2/tags_ifnotequal.go
generated
vendored
|
@ -1,12 +1,16 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
)
|
||||||
|
|
||||||
type tagIfNotEqualNode struct {
|
type tagIfNotEqualNode struct {
|
||||||
var1, var2 IEvaluator
|
var1, var2 IEvaluator
|
||||||
thenWrapper *NodeWrapper
|
thenWrapper *NodeWrapper
|
||||||
elseWrapper *NodeWrapper
|
elseWrapper *NodeWrapper
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *tagIfNotEqualNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (node *tagIfNotEqualNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
r1, err := node.var1.Evaluate(ctx)
|
r1, err := node.var1.Evaluate(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -19,16 +23,17 @@ func (node *tagIfNotEqualNode) Execute(ctx *ExecutionContext, writer TemplateWri
|
||||||
result := !r1.EqualValueTo(r2)
|
result := !r1.EqualValueTo(r2)
|
||||||
|
|
||||||
if result {
|
if result {
|
||||||
return node.thenWrapper.Execute(ctx, writer)
|
return node.thenWrapper.Execute(ctx, buffer)
|
||||||
}
|
} else {
|
||||||
if node.elseWrapper != nil {
|
if node.elseWrapper != nil {
|
||||||
return node.elseWrapper.Execute(ctx, writer)
|
return node.elseWrapper.Execute(ctx, buffer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func tagIfNotEqualParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
func tagIfNotEqualParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
||||||
ifnotequalNode := &tagIfNotEqualNode{}
|
ifnotequal_node := &tagIfNotEqualNode{}
|
||||||
|
|
||||||
// Parse two expressions
|
// Parse two expressions
|
||||||
var1, err := arguments.ParseExpression()
|
var1, err := arguments.ParseExpression()
|
||||||
|
@ -39,19 +44,19 @@ func tagIfNotEqualParser(doc *Parser, start *Token, arguments *Parser) (INodeTag
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ifnotequalNode.var1 = var1
|
ifnotequal_node.var1 = var1
|
||||||
ifnotequalNode.var2 = var2
|
ifnotequal_node.var2 = var2
|
||||||
|
|
||||||
if arguments.Remaining() > 0 {
|
if arguments.Remaining() > 0 {
|
||||||
return nil, arguments.Error("ifequal only takes 2 arguments.", nil)
|
return nil, arguments.Error("ifequal only takes 2 arguments.", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrap then/else-blocks
|
// Wrap then/else-blocks
|
||||||
wrapper, endargs, err := doc.WrapUntilTag("else", "endifnotequal")
|
wrapper, endargs, err := doc.WrapUntilTag("else", "endifequal")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ifnotequalNode.thenWrapper = wrapper
|
ifnotequal_node.thenWrapper = wrapper
|
||||||
|
|
||||||
if endargs.Count() > 0 {
|
if endargs.Count() > 0 {
|
||||||
return nil, endargs.Error("Arguments not allowed here.", nil)
|
return nil, endargs.Error("Arguments not allowed here.", nil)
|
||||||
|
@ -59,18 +64,18 @@ func tagIfNotEqualParser(doc *Parser, start *Token, arguments *Parser) (INodeTag
|
||||||
|
|
||||||
if wrapper.Endtag == "else" {
|
if wrapper.Endtag == "else" {
|
||||||
// if there's an else in the if-statement, we need the else-Block as well
|
// if there's an else in the if-statement, we need the else-Block as well
|
||||||
wrapper, endargs, err = doc.WrapUntilTag("endifnotequal")
|
wrapper, endargs, err = doc.WrapUntilTag("endifequal")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ifnotequalNode.elseWrapper = wrapper
|
ifnotequal_node.elseWrapper = wrapper
|
||||||
|
|
||||||
if endargs.Count() > 0 {
|
if endargs.Count() > 0 {
|
||||||
return nil, endargs.Error("Arguments not allowed here.", nil)
|
return nil, endargs.Error("Arguments not allowed here.", nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ifnotequalNode, nil
|
return ifnotequal_node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
36
vendor/github.com/flosch/pongo2/tags_import.go
generated
vendored
36
vendor/github.com/flosch/pongo2/tags_import.go
generated
vendored
|
@ -1,16 +1,18 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
type tagImportNode struct {
|
type tagImportNode struct {
|
||||||
position *Token
|
position *Token
|
||||||
filename string
|
filename string
|
||||||
|
template *Template
|
||||||
macros map[string]*tagMacroNode // alias/name -> macro instance
|
macros map[string]*tagMacroNode // alias/name -> macro instance
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *tagImportNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (node *tagImportNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
for name, macro := range node.macros {
|
for name, macro := range node.macros {
|
||||||
func(name string, macro *tagMacroNode) {
|
func(name string, macro *tagMacroNode) {
|
||||||
ctx.Private[name] = func(args ...*Value) *Value {
|
ctx.Private[name] = func(args ...*Value) *Value {
|
||||||
|
@ -22,50 +24,50 @@ func (node *tagImportNode) Execute(ctx *ExecutionContext, writer TemplateWriter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func tagImportParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
func tagImportParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
||||||
importNode := &tagImportNode{
|
import_node := &tagImportNode{
|
||||||
position: start,
|
position: start,
|
||||||
macros: make(map[string]*tagMacroNode),
|
macros: make(map[string]*tagMacroNode),
|
||||||
}
|
}
|
||||||
|
|
||||||
filenameToken := arguments.MatchType(TokenString)
|
filename_token := arguments.MatchType(TokenString)
|
||||||
if filenameToken == nil {
|
if filename_token == nil {
|
||||||
return nil, arguments.Error("Import-tag needs a filename as string.", nil)
|
return nil, arguments.Error("Import-tag needs a filename as string.", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
importNode.filename = doc.template.set.resolveFilename(doc.template, filenameToken.Val)
|
import_node.filename = doc.template.set.resolveFilename(doc.template, filename_token.Val)
|
||||||
|
|
||||||
if arguments.Remaining() == 0 {
|
if arguments.Remaining() == 0 {
|
||||||
return nil, arguments.Error("You must at least specify one macro to import.", nil)
|
return nil, arguments.Error("You must at least specify one macro to import.", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compile the given template
|
// Compile the given template
|
||||||
tpl, err := doc.template.set.FromFile(importNode.filename)
|
tpl, err := doc.template.set.FromFile(import_node.filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err.(*Error).updateFromTokenIfNeeded(doc.template, start)
|
return nil, err.(*Error).updateFromTokenIfNeeded(doc.template, start)
|
||||||
}
|
}
|
||||||
|
|
||||||
for arguments.Remaining() > 0 {
|
for arguments.Remaining() > 0 {
|
||||||
macroNameToken := arguments.MatchType(TokenIdentifier)
|
macro_name_token := arguments.MatchType(TokenIdentifier)
|
||||||
if macroNameToken == nil {
|
if macro_name_token == nil {
|
||||||
return nil, arguments.Error("Expected macro name (identifier).", nil)
|
return nil, arguments.Error("Expected macro name (identifier).", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
asName := macroNameToken.Val
|
as_name := macro_name_token.Val
|
||||||
if arguments.Match(TokenKeyword, "as") != nil {
|
if arguments.Match(TokenKeyword, "as") != nil {
|
||||||
aliasToken := arguments.MatchType(TokenIdentifier)
|
alias_token := arguments.MatchType(TokenIdentifier)
|
||||||
if aliasToken == nil {
|
if alias_token == nil {
|
||||||
return nil, arguments.Error("Expected macro alias name (identifier).", nil)
|
return nil, arguments.Error("Expected macro alias name (identifier).", nil)
|
||||||
}
|
}
|
||||||
asName = aliasToken.Val
|
as_name = alias_token.Val
|
||||||
}
|
}
|
||||||
|
|
||||||
macroInstance, has := tpl.exportedMacros[macroNameToken.Val]
|
macro_instance, has := tpl.exported_macros[macro_name_token.Val]
|
||||||
if !has {
|
if !has {
|
||||||
return nil, arguments.Error(fmt.Sprintf("Macro '%s' not found (or not exported) in '%s'.", macroNameToken.Val,
|
return nil, arguments.Error(fmt.Sprintf("Macro '%s' not found (or not exported) in '%s'.", macro_name_token.Val,
|
||||||
importNode.filename), macroNameToken)
|
import_node.filename), macro_name_token)
|
||||||
}
|
}
|
||||||
|
|
||||||
importNode.macros[asName] = macroInstance
|
import_node.macros[as_name] = macro_instance
|
||||||
|
|
||||||
if arguments.Remaining() == 0 {
|
if arguments.Remaining() == 0 {
|
||||||
break
|
break
|
||||||
|
@ -76,7 +78,7 @@ func tagImportParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *E
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return importNode, nil
|
return import_node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
106
vendor/github.com/flosch/pongo2/tags_include.go
generated
vendored
106
vendor/github.com/flosch/pongo2/tags_include.go
generated
vendored
|
@ -1,38 +1,41 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
)
|
||||||
|
|
||||||
type tagIncludeNode struct {
|
type tagIncludeNode struct {
|
||||||
tpl *Template
|
tpl *Template
|
||||||
filenameEvaluator IEvaluator
|
filename_evaluator IEvaluator
|
||||||
lazy bool
|
lazy bool
|
||||||
only bool
|
only bool
|
||||||
filename string
|
filename string
|
||||||
withPairs map[string]IEvaluator
|
with_pairs map[string]IEvaluator
|
||||||
ifExists bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *tagIncludeNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (node *tagIncludeNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
// Building the context for the template
|
// Building the context for the template
|
||||||
includeCtx := make(Context)
|
include_ctx := make(Context)
|
||||||
|
|
||||||
// Fill the context with all data from the parent
|
// Fill the context with all data from the parent
|
||||||
if !node.only {
|
if !node.only {
|
||||||
includeCtx.Update(ctx.Public)
|
include_ctx.Update(ctx.Public)
|
||||||
includeCtx.Update(ctx.Private)
|
include_ctx.Update(ctx.Private)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put all custom with-pairs into the context
|
// Put all custom with-pairs into the context
|
||||||
for key, value := range node.withPairs {
|
for key, value := range node.with_pairs {
|
||||||
val, err := value.Evaluate(ctx)
|
val, err := value.Evaluate(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
includeCtx[key] = val
|
include_ctx[key] = val
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the template
|
// Execute the template
|
||||||
if node.lazy {
|
if node.lazy {
|
||||||
// Evaluate the filename
|
// Evaluate the filename
|
||||||
filename, err := node.filenameEvaluator.Evaluate(ctx)
|
filename, err := node.filename_evaluator.Evaluate(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -42,93 +45,76 @@ func (node *tagIncludeNode) Execute(ctx *ExecutionContext, writer TemplateWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get include-filename
|
// Get include-filename
|
||||||
includedFilename := ctx.template.set.resolveFilename(ctx.template, filename.String())
|
included_filename := ctx.template.set.resolveFilename(ctx.template, filename.String())
|
||||||
|
|
||||||
includedTpl, err2 := ctx.template.set.FromFile(includedFilename)
|
included_tpl, err2 := ctx.template.set.FromFile(included_filename)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
// if this is ReadFile error, and "if_exists" flag is enabled
|
|
||||||
if node.ifExists && err2.(*Error).Sender == "fromfile" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return err2.(*Error)
|
return err2.(*Error)
|
||||||
}
|
}
|
||||||
err2 = includedTpl.ExecuteWriter(includeCtx, writer)
|
err2 = included_tpl.ExecuteWriter(include_ctx, buffer)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
return err2.(*Error)
|
return err2.(*Error)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
} else {
|
||||||
|
// Template is already parsed with static filename
|
||||||
|
err := node.tpl.ExecuteWriter(include_ctx, buffer)
|
||||||
|
if err != nil {
|
||||||
|
return err.(*Error)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
// Template is already parsed with static filename
|
|
||||||
err := node.tpl.ExecuteWriter(includeCtx, writer)
|
|
||||||
if err != nil {
|
|
||||||
return err.(*Error)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type tagIncludeEmptyNode struct{}
|
|
||||||
|
|
||||||
func (node *tagIncludeEmptyNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func tagIncludeParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
func tagIncludeParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
||||||
includeNode := &tagIncludeNode{
|
include_node := &tagIncludeNode{
|
||||||
withPairs: make(map[string]IEvaluator),
|
with_pairs: make(map[string]IEvaluator),
|
||||||
}
|
}
|
||||||
|
|
||||||
if filenameToken := arguments.MatchType(TokenString); filenameToken != nil {
|
if filename_token := arguments.MatchType(TokenString); filename_token != nil {
|
||||||
// prepared, static template
|
// prepared, static template
|
||||||
|
|
||||||
// "if_exists" flag
|
|
||||||
ifExists := arguments.Match(TokenIdentifier, "if_exists") != nil
|
|
||||||
|
|
||||||
// Get include-filename
|
// Get include-filename
|
||||||
includedFilename := doc.template.set.resolveFilename(doc.template, filenameToken.Val)
|
included_filename := doc.template.set.resolveFilename(doc.template, filename_token.Val)
|
||||||
|
|
||||||
// Parse the parent
|
// Parse the parent
|
||||||
includeNode.filename = includedFilename
|
include_node.filename = included_filename
|
||||||
includedTpl, err := doc.template.set.FromFile(includedFilename)
|
included_tpl, err := doc.template.set.FromFile(included_filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// if this is ReadFile error, and "if_exists" token presents we should create and empty node
|
return nil, err.(*Error).updateFromTokenIfNeeded(doc.template, filename_token)
|
||||||
if err.(*Error).Sender == "fromfile" && ifExists {
|
|
||||||
return &tagIncludeEmptyNode{}, nil
|
|
||||||
}
|
|
||||||
return nil, err.(*Error).updateFromTokenIfNeeded(doc.template, filenameToken)
|
|
||||||
}
|
}
|
||||||
includeNode.tpl = includedTpl
|
include_node.tpl = included_tpl
|
||||||
} else {
|
} else {
|
||||||
// No String, then the user wants to use lazy-evaluation (slower, but possible)
|
// No String, then the user wants to use lazy-evaluation (slower, but possible)
|
||||||
filenameEvaluator, err := arguments.ParseExpression()
|
filename_evaluator, err := arguments.ParseExpression()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err.updateFromTokenIfNeeded(doc.template, filenameToken)
|
return nil, err.updateFromTokenIfNeeded(doc.template, filename_token)
|
||||||
}
|
}
|
||||||
includeNode.filenameEvaluator = filenameEvaluator
|
include_node.filename_evaluator = filename_evaluator
|
||||||
includeNode.lazy = true
|
include_node.lazy = true
|
||||||
includeNode.ifExists = arguments.Match(TokenIdentifier, "if_exists") != nil // "if_exists" flag
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// After having parsed the filename we're gonna parse the with+only options
|
// After having parsed the filename we're gonna parse the with+only options
|
||||||
if arguments.Match(TokenIdentifier, "with") != nil {
|
if arguments.Match(TokenIdentifier, "with") != nil {
|
||||||
for arguments.Remaining() > 0 {
|
for arguments.Remaining() > 0 {
|
||||||
// We have at least one key=expr pair (because of starting "with")
|
// We have at least one key=expr pair (because of starting "with")
|
||||||
keyToken := arguments.MatchType(TokenIdentifier)
|
key_token := arguments.MatchType(TokenIdentifier)
|
||||||
if keyToken == nil {
|
if key_token == nil {
|
||||||
return nil, arguments.Error("Expected an identifier", nil)
|
return nil, arguments.Error("Expected an identifier", nil)
|
||||||
}
|
}
|
||||||
if arguments.Match(TokenSymbol, "=") == nil {
|
if arguments.Match(TokenSymbol, "=") == nil {
|
||||||
return nil, arguments.Error("Expected '='.", nil)
|
return nil, arguments.Error("Expected '='.", nil)
|
||||||
}
|
}
|
||||||
valueExpr, err := arguments.ParseExpression()
|
value_expr, err := arguments.ParseExpression()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err.updateFromTokenIfNeeded(doc.template, keyToken)
|
return nil, err.updateFromTokenIfNeeded(doc.template, key_token)
|
||||||
}
|
}
|
||||||
|
|
||||||
includeNode.withPairs[keyToken.Val] = valueExpr
|
include_node.with_pairs[key_token.Val] = value_expr
|
||||||
|
|
||||||
// Only?
|
// Only?
|
||||||
if arguments.Match(TokenIdentifier, "only") != nil {
|
if arguments.Match(TokenIdentifier, "only") != nil {
|
||||||
includeNode.only = true
|
include_node.only = true
|
||||||
break // stop parsing arguments because it's the last option
|
break // stop parsing arguments because it's the last option
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,7 +124,7 @@ func tagIncludeParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *
|
||||||
return nil, arguments.Error("Malformed 'include'-tag arguments.", nil)
|
return nil, arguments.Error("Malformed 'include'-tag arguments.", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return includeNode, nil
|
return include_node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
55
vendor/github.com/flosch/pongo2/tags_lorem.go
generated
vendored
55
vendor/github.com/flosch/pongo2/tags_lorem.go
generated
vendored
|
@ -1,11 +1,10 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/juju/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -20,102 +19,102 @@ type tagLoremNode struct {
|
||||||
random bool // does not use the default paragraph "Lorem ipsum dolor sit amet, ..."
|
random bool // does not use the default paragraph "Lorem ipsum dolor sit amet, ..."
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *tagLoremNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (node *tagLoremNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
switch node.method {
|
switch node.method {
|
||||||
case "b":
|
case "b":
|
||||||
if node.random {
|
if node.random {
|
||||||
for i := 0; i < node.count; i++ {
|
for i := 0; i < node.count; i++ {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
writer.WriteString("\n")
|
buffer.WriteString("\n")
|
||||||
}
|
}
|
||||||
par := tagLoremParagraphs[rand.Intn(len(tagLoremParagraphs))]
|
par := tagLoremParagraphs[rand.Intn(len(tagLoremParagraphs))]
|
||||||
writer.WriteString(par)
|
buffer.WriteString(par)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for i := 0; i < node.count; i++ {
|
for i := 0; i < node.count; i++ {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
writer.WriteString("\n")
|
buffer.WriteString("\n")
|
||||||
}
|
}
|
||||||
par := tagLoremParagraphs[i%len(tagLoremParagraphs)]
|
par := tagLoremParagraphs[i%len(tagLoremParagraphs)]
|
||||||
writer.WriteString(par)
|
buffer.WriteString(par)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "w":
|
case "w":
|
||||||
if node.random {
|
if node.random {
|
||||||
for i := 0; i < node.count; i++ {
|
for i := 0; i < node.count; i++ {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
writer.WriteString(" ")
|
buffer.WriteString(" ")
|
||||||
}
|
}
|
||||||
word := tagLoremWords[rand.Intn(len(tagLoremWords))]
|
word := tagLoremWords[rand.Intn(len(tagLoremWords))]
|
||||||
writer.WriteString(word)
|
buffer.WriteString(word)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for i := 0; i < node.count; i++ {
|
for i := 0; i < node.count; i++ {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
writer.WriteString(" ")
|
buffer.WriteString(" ")
|
||||||
}
|
}
|
||||||
word := tagLoremWords[i%len(tagLoremWords)]
|
word := tagLoremWords[i%len(tagLoremWords)]
|
||||||
writer.WriteString(word)
|
buffer.WriteString(word)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "p":
|
case "p":
|
||||||
if node.random {
|
if node.random {
|
||||||
for i := 0; i < node.count; i++ {
|
for i := 0; i < node.count; i++ {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
writer.WriteString("\n")
|
buffer.WriteString("\n")
|
||||||
}
|
}
|
||||||
writer.WriteString("<p>")
|
buffer.WriteString("<p>")
|
||||||
par := tagLoremParagraphs[rand.Intn(len(tagLoremParagraphs))]
|
par := tagLoremParagraphs[rand.Intn(len(tagLoremParagraphs))]
|
||||||
writer.WriteString(par)
|
buffer.WriteString(par)
|
||||||
writer.WriteString("</p>")
|
buffer.WriteString("</p>")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for i := 0; i < node.count; i++ {
|
for i := 0; i < node.count; i++ {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
writer.WriteString("\n")
|
buffer.WriteString("\n")
|
||||||
}
|
}
|
||||||
writer.WriteString("<p>")
|
buffer.WriteString("<p>")
|
||||||
par := tagLoremParagraphs[i%len(tagLoremParagraphs)]
|
par := tagLoremParagraphs[i%len(tagLoremParagraphs)]
|
||||||
writer.WriteString(par)
|
buffer.WriteString(par)
|
||||||
writer.WriteString("</p>")
|
buffer.WriteString("</p>")
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return ctx.OrigError(errors.Errorf("unsupported method: %s", node.method), nil)
|
panic("unsupported method")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func tagLoremParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
func tagLoremParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
||||||
loremNode := &tagLoremNode{
|
lorem_node := &tagLoremNode{
|
||||||
position: start,
|
position: start,
|
||||||
count: 1,
|
count: 1,
|
||||||
method: "b",
|
method: "b",
|
||||||
}
|
}
|
||||||
|
|
||||||
if countToken := arguments.MatchType(TokenNumber); countToken != nil {
|
if count_token := arguments.MatchType(TokenNumber); count_token != nil {
|
||||||
loremNode.count = AsValue(countToken.Val).Integer()
|
lorem_node.count = AsValue(count_token.Val).Integer()
|
||||||
}
|
}
|
||||||
|
|
||||||
if methodToken := arguments.MatchType(TokenIdentifier); methodToken != nil {
|
if method_token := arguments.MatchType(TokenIdentifier); method_token != nil {
|
||||||
if methodToken.Val != "w" && methodToken.Val != "p" && methodToken.Val != "b" {
|
if method_token.Val != "w" && method_token.Val != "p" && method_token.Val != "b" {
|
||||||
return nil, arguments.Error("lorem-method must be either 'w', 'p' or 'b'.", nil)
|
return nil, arguments.Error("lorem-method must be either 'w', 'p' or 'b'.", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
loremNode.method = methodToken.Val
|
lorem_node.method = method_token.Val
|
||||||
}
|
}
|
||||||
|
|
||||||
if arguments.MatchOne(TokenIdentifier, "random") != nil {
|
if arguments.MatchOne(TokenIdentifier, "random") != nil {
|
||||||
loremNode.random = true
|
lorem_node.random = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if arguments.Remaining() > 0 {
|
if arguments.Remaining() > 0 {
|
||||||
return nil, arguments.Error("Malformed lorem-tag arguments.", nil)
|
return nil, arguments.Error("Malformed lorem-tag arguments.", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return loremNode, nil
|
return lorem_node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
64
vendor/github.com/flosch/pongo2/tags_macro.go
generated
vendored
64
vendor/github.com/flosch/pongo2/tags_macro.go
generated
vendored
|
@ -6,16 +6,16 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type tagMacroNode struct {
|
type tagMacroNode struct {
|
||||||
position *Token
|
position *Token
|
||||||
name string
|
name string
|
||||||
argsOrder []string
|
args_order []string
|
||||||
args map[string]IEvaluator
|
args map[string]IEvaluator
|
||||||
exported bool
|
exported bool
|
||||||
|
|
||||||
wrapper *NodeWrapper
|
wrapper *NodeWrapper
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *tagMacroNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (node *tagMacroNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
ctx.Private[node.name] = func(args ...*Value) *Value {
|
ctx.Private[node.name] = func(args ...*Value) *Value {
|
||||||
return node.call(ctx, args...)
|
return node.call(ctx, args...)
|
||||||
}
|
}
|
||||||
|
@ -24,28 +24,28 @@ func (node *tagMacroNode) Execute(ctx *ExecutionContext, writer TemplateWriter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *tagMacroNode) call(ctx *ExecutionContext, args ...*Value) *Value {
|
func (node *tagMacroNode) call(ctx *ExecutionContext, args ...*Value) *Value {
|
||||||
argsCtx := make(Context)
|
args_ctx := make(Context)
|
||||||
|
|
||||||
for k, v := range node.args {
|
for k, v := range node.args {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
// User did not provided a default value
|
// User did not provided a default value
|
||||||
argsCtx[k] = nil
|
args_ctx[k] = nil
|
||||||
} else {
|
} else {
|
||||||
// Evaluate the default value
|
// Evaluate the default value
|
||||||
valueExpr, err := v.Evaluate(ctx)
|
value_expr, err := v.Evaluate(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Logf(err.Error())
|
ctx.Logf(err.Error())
|
||||||
return AsSafeValue(err.Error())
|
return AsSafeValue(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
argsCtx[k] = valueExpr
|
args_ctx[k] = value_expr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(args) > len(node.argsOrder) {
|
if len(args) > len(node.args_order) {
|
||||||
// Too many arguments, we're ignoring them and just logging into debug mode.
|
// Too many arguments, we're ignoring them and just logging into debug mode.
|
||||||
err := ctx.Error(fmt.Sprintf("Macro '%s' called with too many arguments (%d instead of %d).",
|
err := ctx.Error(fmt.Sprintf("Macro '%s' called with too many arguments (%d instead of %d).",
|
||||||
node.name, len(args), len(node.argsOrder)), nil).updateFromTokenIfNeeded(ctx.template, node.position)
|
node.name, len(args), len(node.args_order)), nil).updateFromTokenIfNeeded(ctx.template, node.position)
|
||||||
|
|
||||||
ctx.Logf(err.Error()) // TODO: This is a workaround, because the error is not returned yet to the Execution()-methods
|
ctx.Logf(err.Error()) // TODO: This is a workaround, because the error is not returned yet to the Execution()-methods
|
||||||
return AsSafeValue(err.Error())
|
return AsSafeValue(err.Error())
|
||||||
|
@ -55,10 +55,10 @@ func (node *tagMacroNode) call(ctx *ExecutionContext, args ...*Value) *Value {
|
||||||
macroCtx := NewChildExecutionContext(ctx)
|
macroCtx := NewChildExecutionContext(ctx)
|
||||||
|
|
||||||
// Register all arguments in the private context
|
// Register all arguments in the private context
|
||||||
macroCtx.Private.Update(argsCtx)
|
macroCtx.Private.Update(args_ctx)
|
||||||
|
|
||||||
for idx, argValue := range args {
|
for idx, arg_value := range args {
|
||||||
macroCtx.Private[node.argsOrder[idx]] = argValue.Interface()
|
macroCtx.Private[node.args_order[idx]] = arg_value.Interface()
|
||||||
}
|
}
|
||||||
|
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
|
@ -71,38 +71,38 @@ func (node *tagMacroNode) call(ctx *ExecutionContext, args ...*Value) *Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
func tagMacroParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
func tagMacroParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
||||||
macroNode := &tagMacroNode{
|
macro_node := &tagMacroNode{
|
||||||
position: start,
|
position: start,
|
||||||
args: make(map[string]IEvaluator),
|
args: make(map[string]IEvaluator),
|
||||||
}
|
}
|
||||||
|
|
||||||
nameToken := arguments.MatchType(TokenIdentifier)
|
name_token := arguments.MatchType(TokenIdentifier)
|
||||||
if nameToken == nil {
|
if name_token == nil {
|
||||||
return nil, arguments.Error("Macro-tag needs at least an identifier as name.", nil)
|
return nil, arguments.Error("Macro-tag needs at least an identifier as name.", nil)
|
||||||
}
|
}
|
||||||
macroNode.name = nameToken.Val
|
macro_node.name = name_token.Val
|
||||||
|
|
||||||
if arguments.MatchOne(TokenSymbol, "(") == nil {
|
if arguments.MatchOne(TokenSymbol, "(") == nil {
|
||||||
return nil, arguments.Error("Expected '('.", nil)
|
return nil, arguments.Error("Expected '('.", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
for arguments.Match(TokenSymbol, ")") == nil {
|
for arguments.Match(TokenSymbol, ")") == nil {
|
||||||
argNameToken := arguments.MatchType(TokenIdentifier)
|
arg_name_token := arguments.MatchType(TokenIdentifier)
|
||||||
if argNameToken == nil {
|
if arg_name_token == nil {
|
||||||
return nil, arguments.Error("Expected argument name as identifier.", nil)
|
return nil, arguments.Error("Expected argument name as identifier.", nil)
|
||||||
}
|
}
|
||||||
macroNode.argsOrder = append(macroNode.argsOrder, argNameToken.Val)
|
macro_node.args_order = append(macro_node.args_order, arg_name_token.Val)
|
||||||
|
|
||||||
if arguments.Match(TokenSymbol, "=") != nil {
|
if arguments.Match(TokenSymbol, "=") != nil {
|
||||||
// Default expression follows
|
// Default expression follows
|
||||||
argDefaultExpr, err := arguments.ParseExpression()
|
arg_default_expr, err := arguments.ParseExpression()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
macroNode.args[argNameToken.Val] = argDefaultExpr
|
macro_node.args[arg_name_token.Val] = arg_default_expr
|
||||||
} else {
|
} else {
|
||||||
// No default expression
|
// No default expression
|
||||||
macroNode.args[argNameToken.Val] = nil
|
macro_node.args[arg_name_token.Val] = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if arguments.Match(TokenSymbol, ")") != nil {
|
if arguments.Match(TokenSymbol, ")") != nil {
|
||||||
|
@ -114,7 +114,7 @@ func tagMacroParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Er
|
||||||
}
|
}
|
||||||
|
|
||||||
if arguments.Match(TokenKeyword, "export") != nil {
|
if arguments.Match(TokenKeyword, "export") != nil {
|
||||||
macroNode.exported = true
|
macro_node.exported = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if arguments.Remaining() > 0 {
|
if arguments.Remaining() > 0 {
|
||||||
|
@ -126,22 +126,22 @@ func tagMacroParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Er
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
macroNode.wrapper = wrapper
|
macro_node.wrapper = wrapper
|
||||||
|
|
||||||
if endargs.Count() > 0 {
|
if endargs.Count() > 0 {
|
||||||
return nil, endargs.Error("Arguments not allowed here.", nil)
|
return nil, endargs.Error("Arguments not allowed here.", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
if macroNode.exported {
|
if macro_node.exported {
|
||||||
// Now register the macro if it wants to be exported
|
// Now register the macro if it wants to be exported
|
||||||
_, has := doc.template.exportedMacros[macroNode.name]
|
_, has := doc.template.exported_macros[macro_node.name]
|
||||||
if has {
|
if has {
|
||||||
return nil, doc.Error(fmt.Sprintf("another macro with name '%s' already exported", macroNode.name), start)
|
return nil, doc.Error(fmt.Sprintf("Another macro with name '%s' already exported.", macro_node.name), start)
|
||||||
}
|
}
|
||||||
doc.template.exportedMacros[macroNode.name] = macroNode
|
doc.template.exported_macros[macro_node.name] = macro_node
|
||||||
}
|
}
|
||||||
|
|
||||||
return macroNode, nil
|
return macro_node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
17
vendor/github.com/flosch/pongo2/tags_now.go
generated
vendored
17
vendor/github.com/flosch/pongo2/tags_now.go
generated
vendored
|
@ -1,6 +1,7 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -10,7 +11,7 @@ type tagNowNode struct {
|
||||||
fake bool
|
fake bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *tagNowNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (node *tagNowNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
var t time.Time
|
var t time.Time
|
||||||
if node.fake {
|
if node.fake {
|
||||||
t = time.Date(2014, time.February, 05, 18, 31, 45, 00, time.UTC)
|
t = time.Date(2014, time.February, 05, 18, 31, 45, 00, time.UTC)
|
||||||
|
@ -18,31 +19,31 @@ func (node *tagNowNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *E
|
||||||
t = time.Now()
|
t = time.Now()
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.WriteString(t.Format(node.format))
|
buffer.WriteString(t.Format(node.format))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func tagNowParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
func tagNowParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
||||||
nowNode := &tagNowNode{
|
now_node := &tagNowNode{
|
||||||
position: start,
|
position: start,
|
||||||
}
|
}
|
||||||
|
|
||||||
formatToken := arguments.MatchType(TokenString)
|
format_token := arguments.MatchType(TokenString)
|
||||||
if formatToken == nil {
|
if format_token == nil {
|
||||||
return nil, arguments.Error("Expected a format string.", nil)
|
return nil, arguments.Error("Expected a format string.", nil)
|
||||||
}
|
}
|
||||||
nowNode.format = formatToken.Val
|
now_node.format = format_token.Val
|
||||||
|
|
||||||
if arguments.MatchOne(TokenIdentifier, "fake") != nil {
|
if arguments.MatchOne(TokenIdentifier, "fake") != nil {
|
||||||
nowNode.fake = true
|
now_node.fake = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if arguments.Remaining() > 0 {
|
if arguments.Remaining() > 0 {
|
||||||
return nil, arguments.Error("Malformed now-tag arguments.", nil)
|
return nil, arguments.Error("Malformed now-tag arguments.", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nowNode, nil
|
return now_node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
4
vendor/github.com/flosch/pongo2/tags_set.go
generated
vendored
4
vendor/github.com/flosch/pongo2/tags_set.go
generated
vendored
|
@ -1,11 +1,13 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
|
import "bytes"
|
||||||
|
|
||||||
type tagSetNode struct {
|
type tagSetNode struct {
|
||||||
name string
|
name string
|
||||||
expression IEvaluator
|
expression IEvaluator
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *tagSetNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (node *tagSetNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
// Evaluate expression
|
// Evaluate expression
|
||||||
value, err := node.expression.Evaluate(ctx)
|
value, err := node.expression.Evaluate(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
10
vendor/github.com/flosch/pongo2/tags_spaceless.go
generated
vendored
10
vendor/github.com/flosch/pongo2/tags_spaceless.go
generated
vendored
|
@ -11,7 +11,7 @@ type tagSpacelessNode struct {
|
||||||
|
|
||||||
var tagSpacelessRegexp = regexp.MustCompile(`(?U:(<.*>))([\t\n\v\f\r ]+)(?U:(<.*>))`)
|
var tagSpacelessRegexp = regexp.MustCompile(`(?U:(<.*>))([\t\n\v\f\r ]+)(?U:(<.*>))`)
|
||||||
|
|
||||||
func (node *tagSpacelessNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (node *tagSpacelessNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
b := bytes.NewBuffer(make([]byte, 0, 1024)) // 1 KiB
|
b := bytes.NewBuffer(make([]byte, 0, 1024)) // 1 KiB
|
||||||
|
|
||||||
err := node.wrapper.Execute(ctx, b)
|
err := node.wrapper.Execute(ctx, b)
|
||||||
|
@ -28,25 +28,25 @@ func (node *tagSpacelessNode) Execute(ctx *ExecutionContext, writer TemplateWrit
|
||||||
s = s2
|
s = s2
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.WriteString(s)
|
buffer.WriteString(s)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func tagSpacelessParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
func tagSpacelessParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
||||||
spacelessNode := &tagSpacelessNode{}
|
spaceless_node := &tagSpacelessNode{}
|
||||||
|
|
||||||
wrapper, _, err := doc.WrapUntilTag("endspaceless")
|
wrapper, _, err := doc.WrapUntilTag("endspaceless")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
spacelessNode.wrapper = wrapper
|
spaceless_node.wrapper = wrapper
|
||||||
|
|
||||||
if arguments.Remaining() > 0 {
|
if arguments.Remaining() > 0 {
|
||||||
return nil, arguments.Error("Malformed spaceless-tag arguments.", nil)
|
return nil, arguments.Error("Malformed spaceless-tag arguments.", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return spacelessNode, nil
|
return spaceless_node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
31
vendor/github.com/flosch/pongo2/tags_ssi.go
generated
vendored
31
vendor/github.com/flosch/pongo2/tags_ssi.go
generated
vendored
|
@ -1,6 +1,7 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -10,47 +11,47 @@ type tagSSINode struct {
|
||||||
template *Template
|
template *Template
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *tagSSINode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (node *tagSSINode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
if node.template != nil {
|
if node.template != nil {
|
||||||
// Execute the template within the current context
|
// Execute the template within the current context
|
||||||
includeCtx := make(Context)
|
includeCtx := make(Context)
|
||||||
includeCtx.Update(ctx.Public)
|
includeCtx.Update(ctx.Public)
|
||||||
includeCtx.Update(ctx.Private)
|
includeCtx.Update(ctx.Private)
|
||||||
|
|
||||||
err := node.template.execute(includeCtx, writer)
|
err := node.template.ExecuteWriter(includeCtx, buffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err.(*Error)
|
return err.(*Error)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Just print out the content
|
// Just print out the content
|
||||||
writer.WriteString(node.content)
|
buffer.WriteString(node.content)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func tagSSIParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
func tagSSIParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
||||||
SSINode := &tagSSINode{}
|
ssi_node := &tagSSINode{}
|
||||||
|
|
||||||
if fileToken := arguments.MatchType(TokenString); fileToken != nil {
|
if file_token := arguments.MatchType(TokenString); file_token != nil {
|
||||||
SSINode.filename = fileToken.Val
|
ssi_node.filename = file_token.Val
|
||||||
|
|
||||||
if arguments.Match(TokenIdentifier, "parsed") != nil {
|
if arguments.Match(TokenIdentifier, "parsed") != nil {
|
||||||
// parsed
|
// parsed
|
||||||
temporaryTpl, err := doc.template.set.FromFile(doc.template.set.resolveFilename(doc.template, fileToken.Val))
|
temporary_tpl, err := doc.template.set.FromFile(doc.template.set.resolveFilename(doc.template, file_token.Val))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err.(*Error).updateFromTokenIfNeeded(doc.template, fileToken)
|
return nil, err.(*Error).updateFromTokenIfNeeded(doc.template, file_token)
|
||||||
}
|
}
|
||||||
SSINode.template = temporaryTpl
|
ssi_node.template = temporary_tpl
|
||||||
} else {
|
} else {
|
||||||
// plaintext
|
// plaintext
|
||||||
buf, err := ioutil.ReadFile(doc.template.set.resolveFilename(doc.template, fileToken.Val))
|
buf, err := ioutil.ReadFile(doc.template.set.resolveFilename(doc.template, file_token.Val))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, (&Error{
|
return nil, (&Error{
|
||||||
Sender: "tag:ssi",
|
Sender: "tag:ssi",
|
||||||
OrigError: err,
|
ErrorMsg: err.Error(),
|
||||||
}).updateFromTokenIfNeeded(doc.template, fileToken)
|
}).updateFromTokenIfNeeded(doc.template, file_token)
|
||||||
}
|
}
|
||||||
SSINode.content = string(buf)
|
ssi_node.content = string(buf)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil, arguments.Error("First argument must be a string.", nil)
|
return nil, arguments.Error("First argument must be a string.", nil)
|
||||||
|
@ -60,7 +61,7 @@ func tagSSIParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Erro
|
||||||
return nil, arguments.Error("Malformed SSI-tag argument.", nil)
|
return nil, arguments.Error("Malformed SSI-tag argument.", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return SSINode, nil
|
return ssi_node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
20
vendor/github.com/flosch/pongo2/tags_templatetag.go
generated
vendored
20
vendor/github.com/flosch/pongo2/tags_templatetag.go
generated
vendored
|
@ -1,5 +1,9 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
)
|
||||||
|
|
||||||
type tagTemplateTagNode struct {
|
type tagTemplateTagNode struct {
|
||||||
content string
|
content string
|
||||||
}
|
}
|
||||||
|
@ -15,20 +19,20 @@ var templateTagMapping = map[string]string{
|
||||||
"closecomment": "#}",
|
"closecomment": "#}",
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *tagTemplateTagNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (node *tagTemplateTagNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
writer.WriteString(node.content)
|
buffer.WriteString(node.content)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func tagTemplateTagParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
func tagTemplateTagParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
||||||
ttNode := &tagTemplateTagNode{}
|
tt_node := &tagTemplateTagNode{}
|
||||||
|
|
||||||
if argToken := arguments.MatchType(TokenIdentifier); argToken != nil {
|
if arg_token := arguments.MatchType(TokenIdentifier); arg_token != nil {
|
||||||
output, found := templateTagMapping[argToken.Val]
|
output, found := templateTagMapping[arg_token.Val]
|
||||||
if !found {
|
if !found {
|
||||||
return nil, arguments.Error("Argument not found", argToken)
|
return nil, arguments.Error("Argument not found", arg_token)
|
||||||
}
|
}
|
||||||
ttNode.content = output
|
tt_node.content = output
|
||||||
} else {
|
} else {
|
||||||
return nil, arguments.Error("Identifier expected.", nil)
|
return nil, arguments.Error("Identifier expected.", nil)
|
||||||
}
|
}
|
||||||
|
@ -37,7 +41,7 @@ func tagTemplateTagParser(doc *Parser, start *Token, arguments *Parser) (INodeTa
|
||||||
return nil, arguments.Error("Malformed templatetag-tag argument.", nil)
|
return nil, arguments.Error("Malformed templatetag-tag argument.", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ttNode, nil
|
return tt_node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
27
vendor/github.com/flosch/pongo2/tags_widthratio.go
generated
vendored
27
vendor/github.com/flosch/pongo2/tags_widthratio.go
generated
vendored
|
@ -1,6 +1,7 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
)
|
)
|
||||||
|
@ -9,10 +10,10 @@ type tagWidthratioNode struct {
|
||||||
position *Token
|
position *Token
|
||||||
current, max IEvaluator
|
current, max IEvaluator
|
||||||
width IEvaluator
|
width IEvaluator
|
||||||
ctxName string
|
ctx_name string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *tagWidthratioNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (node *tagWidthratioNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
current, err := node.current.Evaluate(ctx)
|
current, err := node.current.Evaluate(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -30,17 +31,17 @@ func (node *tagWidthratioNode) Execute(ctx *ExecutionContext, writer TemplateWri
|
||||||
|
|
||||||
value := int(math.Ceil(current.Float()/max.Float()*width.Float() + 0.5))
|
value := int(math.Ceil(current.Float()/max.Float()*width.Float() + 0.5))
|
||||||
|
|
||||||
if node.ctxName == "" {
|
if node.ctx_name == "" {
|
||||||
writer.WriteString(fmt.Sprintf("%d", value))
|
buffer.WriteString(fmt.Sprintf("%d", value))
|
||||||
} else {
|
} else {
|
||||||
ctx.Private[node.ctxName] = value
|
ctx.Private[node.ctx_name] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func tagWidthratioParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
func tagWidthratioParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
||||||
widthratioNode := &tagWidthratioNode{
|
widthratio_node := &tagWidthratioNode{
|
||||||
position: start,
|
position: start,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,34 +49,34 @@ func tagWidthratioParser(doc *Parser, start *Token, arguments *Parser) (INodeTag
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
widthratioNode.current = current
|
widthratio_node.current = current
|
||||||
|
|
||||||
max, err := arguments.ParseExpression()
|
max, err := arguments.ParseExpression()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
widthratioNode.max = max
|
widthratio_node.max = max
|
||||||
|
|
||||||
width, err := arguments.ParseExpression()
|
width, err := arguments.ParseExpression()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
widthratioNode.width = width
|
widthratio_node.width = width
|
||||||
|
|
||||||
if arguments.MatchOne(TokenKeyword, "as") != nil {
|
if arguments.MatchOne(TokenKeyword, "as") != nil {
|
||||||
// Name follows
|
// Name follows
|
||||||
nameToken := arguments.MatchType(TokenIdentifier)
|
name_token := arguments.MatchType(TokenIdentifier)
|
||||||
if nameToken == nil {
|
if name_token == nil {
|
||||||
return nil, arguments.Error("Expected name (identifier).", nil)
|
return nil, arguments.Error("Expected name (identifier).", nil)
|
||||||
}
|
}
|
||||||
widthratioNode.ctxName = nameToken.Val
|
widthratio_node.ctx_name = name_token.Val
|
||||||
}
|
}
|
||||||
|
|
||||||
if arguments.Remaining() > 0 {
|
if arguments.Remaining() > 0 {
|
||||||
return nil, arguments.Error("Malformed widthratio-tag arguments.", nil)
|
return nil, arguments.Error("Malformed widthratio-tag arguments.", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return widthratioNode, nil
|
return widthratio_node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
44
vendor/github.com/flosch/pongo2/tags_with.go
generated
vendored
44
vendor/github.com/flosch/pongo2/tags_with.go
generated
vendored
|
@ -1,16 +1,20 @@
|
||||||
package pongo2
|
package pongo2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
)
|
||||||
|
|
||||||
type tagWithNode struct {
|
type tagWithNode struct {
|
||||||
withPairs map[string]IEvaluator
|
with_pairs map[string]IEvaluator
|
||||||
wrapper *NodeWrapper
|
wrapper *NodeWrapper
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *tagWithNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
|
func (node *tagWithNode) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
|
||||||
//new context for block
|
//new context for block
|
||||||
withctx := NewChildExecutionContext(ctx)
|
withctx := NewChildExecutionContext(ctx)
|
||||||
|
|
||||||
// Put all custom with-pairs into the context
|
// Put all custom with-pairs into the context
|
||||||
for key, value := range node.withPairs {
|
for key, value := range node.with_pairs {
|
||||||
val, err := value.Evaluate(ctx)
|
val, err := value.Evaluate(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -18,12 +22,12 @@ func (node *tagWithNode) Execute(ctx *ExecutionContext, writer TemplateWriter) *
|
||||||
withctx.Private[key] = val
|
withctx.Private[key] = val
|
||||||
}
|
}
|
||||||
|
|
||||||
return node.wrapper.Execute(withctx, writer)
|
return node.wrapper.Execute(withctx, buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func tagWithParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
func tagWithParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Error) {
|
||||||
withNode := &tagWithNode{
|
with_node := &tagWithNode{
|
||||||
withPairs: make(map[string]IEvaluator),
|
with_pairs: make(map[string]IEvaluator),
|
||||||
}
|
}
|
||||||
|
|
||||||
if arguments.Count() == 0 {
|
if arguments.Count() == 0 {
|
||||||
|
@ -34,7 +38,7 @@ func tagWithParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Err
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
withNode.wrapper = wrapper
|
with_node.wrapper = wrapper
|
||||||
|
|
||||||
if endargs.Count() > 0 {
|
if endargs.Count() > 0 {
|
||||||
return nil, endargs.Error("Arguments not allowed here.", nil)
|
return nil, endargs.Error("Arguments not allowed here.", nil)
|
||||||
|
@ -42,45 +46,45 @@ func tagWithParser(doc *Parser, start *Token, arguments *Parser) (INodeTag, *Err
|
||||||
|
|
||||||
// Scan through all arguments to see which style the user uses (old or new style).
|
// Scan through all arguments to see which style the user uses (old or new style).
|
||||||
// If we find any "as" keyword we will enforce old style; otherwise we will use new style.
|
// If we find any "as" keyword we will enforce old style; otherwise we will use new style.
|
||||||
oldStyle := false // by default we're using the new_style
|
old_style := false // by default we're using the new_style
|
||||||
for i := 0; i < arguments.Count(); i++ {
|
for i := 0; i < arguments.Count(); i++ {
|
||||||
if arguments.PeekN(i, TokenKeyword, "as") != nil {
|
if arguments.PeekN(i, TokenKeyword, "as") != nil {
|
||||||
oldStyle = true
|
old_style = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for arguments.Remaining() > 0 {
|
for arguments.Remaining() > 0 {
|
||||||
if oldStyle {
|
if old_style {
|
||||||
valueExpr, err := arguments.ParseExpression()
|
value_expr, err := arguments.ParseExpression()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if arguments.Match(TokenKeyword, "as") == nil {
|
if arguments.Match(TokenKeyword, "as") == nil {
|
||||||
return nil, arguments.Error("Expected 'as' keyword.", nil)
|
return nil, arguments.Error("Expected 'as' keyword.", nil)
|
||||||
}
|
}
|
||||||
keyToken := arguments.MatchType(TokenIdentifier)
|
key_token := arguments.MatchType(TokenIdentifier)
|
||||||
if keyToken == nil {
|
if key_token == nil {
|
||||||
return nil, arguments.Error("Expected an identifier", nil)
|
return nil, arguments.Error("Expected an identifier", nil)
|
||||||
}
|
}
|
||||||
withNode.withPairs[keyToken.Val] = valueExpr
|
with_node.with_pairs[key_token.Val] = value_expr
|
||||||
} else {
|
} else {
|
||||||
keyToken := arguments.MatchType(TokenIdentifier)
|
key_token := arguments.MatchType(TokenIdentifier)
|
||||||
if keyToken == nil {
|
if key_token == nil {
|
||||||
return nil, arguments.Error("Expected an identifier", nil)
|
return nil, arguments.Error("Expected an identifier", nil)
|
||||||
}
|
}
|
||||||
if arguments.Match(TokenSymbol, "=") == nil {
|
if arguments.Match(TokenSymbol, "=") == nil {
|
||||||
return nil, arguments.Error("Expected '='.", nil)
|
return nil, arguments.Error("Expected '='.", nil)
|
||||||
}
|
}
|
||||||
valueExpr, err := arguments.ParseExpression()
|
value_expr, err := arguments.ParseExpression()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
withNode.withPairs[keyToken.Val] = valueExpr
|
with_node.with_pairs[key_token.Val] = value_expr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return withNode, nil
|
return with_node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
128
vendor/github.com/flosch/pongo2/template.go
generated
vendored
128
vendor/github.com/flosch/pongo2/template.go
generated
vendored
|
@ -2,72 +2,52 @@ package pongo2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/juju/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type TemplateWriter interface {
|
|
||||||
io.Writer
|
|
||||||
WriteString(string) (int, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type templateWriter struct {
|
|
||||||
w io.Writer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tw *templateWriter) WriteString(s string) (int, error) {
|
|
||||||
return tw.w.Write([]byte(s))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tw *templateWriter) Write(b []byte) (int, error) {
|
|
||||||
return tw.w.Write(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Template struct {
|
type Template struct {
|
||||||
set *TemplateSet
|
set *TemplateSet
|
||||||
|
|
||||||
// Input
|
// Input
|
||||||
isTplString bool
|
is_tpl_string bool
|
||||||
name string
|
name string
|
||||||
tpl string
|
tpl string
|
||||||
size int
|
size int
|
||||||
|
|
||||||
// Calculation
|
// Calculation
|
||||||
tokens []*Token
|
tokens []*Token
|
||||||
parser *Parser
|
parser *Parser
|
||||||
|
|
||||||
// first come, first serve (it's important to not override existing entries in here)
|
// first come, first serve (it's important to not override existing entries in here)
|
||||||
level int
|
level int
|
||||||
parent *Template
|
parent *Template
|
||||||
child *Template
|
child *Template
|
||||||
blocks map[string]*NodeWrapper
|
blocks map[string]*NodeWrapper
|
||||||
exportedMacros map[string]*tagMacroNode
|
exported_macros map[string]*tagMacroNode
|
||||||
|
|
||||||
// Output
|
// Output
|
||||||
root *nodeDocument
|
root *nodeDocument
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTemplateString(set *TemplateSet, tpl []byte) (*Template, error) {
|
func newTemplateString(set *TemplateSet, tpl string) (*Template, error) {
|
||||||
return newTemplate(set, "<string>", true, tpl)
|
return newTemplate(set, "<string>", true, tpl)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTemplate(set *TemplateSet, name string, isTplString bool, tpl []byte) (*Template, error) {
|
func newTemplate(set *TemplateSet, name string, is_tpl_string bool, tpl string) (*Template, error) {
|
||||||
strTpl := string(tpl)
|
|
||||||
|
|
||||||
// Create the template
|
// Create the template
|
||||||
t := &Template{
|
t := &Template{
|
||||||
set: set,
|
set: set,
|
||||||
isTplString: isTplString,
|
is_tpl_string: is_tpl_string,
|
||||||
name: name,
|
name: name,
|
||||||
tpl: strTpl,
|
tpl: tpl,
|
||||||
size: len(strTpl),
|
size: len(tpl),
|
||||||
blocks: make(map[string]*NodeWrapper),
|
blocks: make(map[string]*NodeWrapper),
|
||||||
exportedMacros: make(map[string]*tagMacroNode),
|
exported_macros: make(map[string]*tagMacroNode),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tokenize it
|
// Tokenize it
|
||||||
tokens, err := lex(name, strTpl)
|
tokens, err := lex(name, tpl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -87,7 +67,11 @@ func newTemplate(set *TemplateSet, name string, isTplString bool, tpl []byte) (*
|
||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tpl *Template) execute(context Context, writer TemplateWriter) error {
|
func (tpl *Template) execute(context Context) (*bytes.Buffer, error) {
|
||||||
|
// Create output buffer
|
||||||
|
// We assume that the rendered template will be 30% larger
|
||||||
|
buffer := bytes.NewBuffer(make([]byte, 0, int(float64(tpl.size)*1.3)))
|
||||||
|
|
||||||
// Determine the parent to be executed (for template inheritance)
|
// Determine the parent to be executed (for template inheritance)
|
||||||
parent := tpl
|
parent := tpl
|
||||||
for parent.parent != nil {
|
for parent.parent != nil {
|
||||||
|
@ -105,17 +89,17 @@ func (tpl *Template) execute(context Context, writer TemplateWriter) error {
|
||||||
// Check for context name syntax
|
// Check for context name syntax
|
||||||
err := newContext.checkForValidIdentifiers()
|
err := newContext.checkForValidIdentifiers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for clashes with macro names
|
// Check for clashes with macro names
|
||||||
for k := range newContext {
|
for k, _ := range newContext {
|
||||||
_, has := tpl.exportedMacros[k]
|
_, has := tpl.exported_macros[k]
|
||||||
if has {
|
if has {
|
||||||
return &Error{
|
return nil, &Error{
|
||||||
Filename: tpl.name,
|
Filename: tpl.name,
|
||||||
Sender: "execution",
|
Sender: "execution",
|
||||||
OrigError: errors.Errorf("context key name '%s' clashes with macro '%s'", k, k),
|
ErrorMsg: fmt.Sprintf("Context key name '%s' clashes with macro '%s'.", k, k),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,22 +110,8 @@ func (tpl *Template) execute(context Context, writer TemplateWriter) error {
|
||||||
ctx := newExecutionContext(parent, newContext)
|
ctx := newExecutionContext(parent, newContext)
|
||||||
|
|
||||||
// Run the selected document
|
// Run the selected document
|
||||||
if err := parent.root.Execute(ctx, writer); err != nil {
|
err := parent.root.Execute(ctx, buffer)
|
||||||
return err
|
if err != nil {
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tpl *Template) newTemplateWriterAndExecute(context Context, writer io.Writer) error {
|
|
||||||
return tpl.execute(context, &templateWriter{w: writer})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tpl *Template) newBufferAndExecute(context Context) (*bytes.Buffer, error) {
|
|
||||||
// Create output buffer
|
|
||||||
// We assume that the rendered template will be 30% larger
|
|
||||||
buffer := bytes.NewBuffer(make([]byte, 0, int(float64(tpl.size)*1.3)))
|
|
||||||
if err := tpl.execute(context, buffer); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return buffer, nil
|
return buffer, nil
|
||||||
|
@ -151,30 +121,30 @@ func (tpl *Template) newBufferAndExecute(context Context) (*bytes.Buffer, error)
|
||||||
// on success. Context can be nil. Nothing is written on error; instead the error
|
// on success. Context can be nil. Nothing is written on error; instead the error
|
||||||
// is being returned.
|
// is being returned.
|
||||||
func (tpl *Template) ExecuteWriter(context Context, writer io.Writer) error {
|
func (tpl *Template) ExecuteWriter(context Context, writer io.Writer) error {
|
||||||
buf, err := tpl.newBufferAndExecute(context)
|
buffer, err := tpl.execute(context)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = buf.WriteTo(writer)
|
|
||||||
if err != nil {
|
l := buffer.Len()
|
||||||
return err
|
n, werr := buffer.WriteTo(writer)
|
||||||
|
if int(n) != l {
|
||||||
|
panic(fmt.Sprintf("error on writing template: n(%d) != buffer.Len(%d)", n, l))
|
||||||
|
}
|
||||||
|
if werr != nil {
|
||||||
|
return &Error{
|
||||||
|
Filename: tpl.name,
|
||||||
|
Sender: "execution",
|
||||||
|
ErrorMsg: werr.Error(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Same as ExecuteWriter. The only difference between both functions is that
|
|
||||||
// this function might already have written parts of the generated template in the
|
|
||||||
// case of an execution error because there's no intermediate buffer involved for
|
|
||||||
// performance reasons. This is handy if you need high performance template
|
|
||||||
// generation or if you want to manage your own pool of buffers.
|
|
||||||
func (tpl *Template) ExecuteWriterUnbuffered(context Context, writer io.Writer) error {
|
|
||||||
return tpl.newTemplateWriterAndExecute(context, writer)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Executes the template and returns the rendered template as a []byte
|
// Executes the template and returns the rendered template as a []byte
|
||||||
func (tpl *Template) ExecuteBytes(context Context) ([]byte, error) {
|
func (tpl *Template) ExecuteBytes(context Context) ([]byte, error) {
|
||||||
// Execute template
|
// Execute template
|
||||||
buffer, err := tpl.newBufferAndExecute(context)
|
buffer, err := tpl.execute(context)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -184,7 +154,7 @@ func (tpl *Template) ExecuteBytes(context Context) ([]byte, error) {
|
||||||
// Executes the template and returns the rendered template as a string
|
// Executes the template and returns the rendered template as a string
|
||||||
func (tpl *Template) Execute(context Context) (string, error) {
|
func (tpl *Template) Execute(context Context) (string, error) {
|
||||||
// Execute template
|
// Execute template
|
||||||
buffer, err := tpl.newBufferAndExecute(context)
|
buffer, err := tpl.execute(context)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
157
vendor/github.com/flosch/pongo2/template_loader.go
generated
vendored
157
vendor/github.com/flosch/pongo2/template_loader.go
generated
vendored
|
@ -1,157 +0,0 @@
|
||||||
package pongo2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/juju/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
// LocalFilesystemLoader represents a local filesystem loader with basic
|
|
||||||
// BaseDirectory capabilities. The access to the local filesystem is unrestricted.
|
|
||||||
type LocalFilesystemLoader struct {
|
|
||||||
baseDir string
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustNewLocalFileSystemLoader creates a new LocalFilesystemLoader instance
|
|
||||||
// and panics if there's any error during instantiation. The parameters
|
|
||||||
// are the same like NewLocalFileSystemLoader.
|
|
||||||
func MustNewLocalFileSystemLoader(baseDir string) *LocalFilesystemLoader {
|
|
||||||
fs, err := NewLocalFileSystemLoader(baseDir)
|
|
||||||
if err != nil {
|
|
||||||
log.Panic(err)
|
|
||||||
}
|
|
||||||
return fs
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewLocalFileSystemLoader creates a new LocalFilesystemLoader and allows
|
|
||||||
// templatesto be loaded from disk (unrestricted). If any base directory
|
|
||||||
// is given (or being set using SetBaseDir), this base directory is being used
|
|
||||||
// for path calculation in template inclusions/imports. Otherwise the path
|
|
||||||
// is calculated based relatively to the including template's path.
|
|
||||||
func NewLocalFileSystemLoader(baseDir string) (*LocalFilesystemLoader, error) {
|
|
||||||
fs := &LocalFilesystemLoader{}
|
|
||||||
if baseDir != "" {
|
|
||||||
if err := fs.SetBaseDir(baseDir); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetBaseDir sets the template's base directory. This directory will
|
|
||||||
// be used for any relative path in filters, tags and From*-functions to determine
|
|
||||||
// your template. See the comment for NewLocalFileSystemLoader as well.
|
|
||||||
func (fs *LocalFilesystemLoader) SetBaseDir(path string) error {
|
|
||||||
// Make the path absolute
|
|
||||||
if !filepath.IsAbs(path) {
|
|
||||||
abs, err := filepath.Abs(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
path = abs
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for existence
|
|
||||||
fi, err := os.Stat(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !fi.IsDir() {
|
|
||||||
return errors.Errorf("The given path '%s' is not a directory.", path)
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.baseDir = path
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get reads the path's content from your local filesystem.
|
|
||||||
func (fs *LocalFilesystemLoader) Get(path string) (io.Reader, error) {
|
|
||||||
buf, err := ioutil.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return bytes.NewReader(buf), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Abs resolves a filename relative to the base directory. Absolute paths are allowed.
|
|
||||||
// When there's no base dir set, the absolute path to the filename
|
|
||||||
// will be calculated based on either the provided base directory (which
|
|
||||||
// might be a path of a template which includes another template) or
|
|
||||||
// the current working directory.
|
|
||||||
func (fs *LocalFilesystemLoader) Abs(base, name string) string {
|
|
||||||
if filepath.IsAbs(name) {
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
|
|
||||||
// Our own base dir has always priority; if there's none
|
|
||||||
// we use the path provided in base.
|
|
||||||
var err error
|
|
||||||
if fs.baseDir == "" {
|
|
||||||
if base == "" {
|
|
||||||
base, err = os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return filepath.Join(base, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
return filepath.Join(filepath.Dir(base), name)
|
|
||||||
}
|
|
||||||
|
|
||||||
return filepath.Join(fs.baseDir, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SandboxedFilesystemLoader is still WIP.
|
|
||||||
type SandboxedFilesystemLoader struct {
|
|
||||||
*LocalFilesystemLoader
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSandboxedFilesystemLoader creates a new sandboxed local file system instance.
|
|
||||||
func NewSandboxedFilesystemLoader(baseDir string) (*SandboxedFilesystemLoader, error) {
|
|
||||||
fs, err := NewLocalFileSystemLoader(baseDir)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &SandboxedFilesystemLoader{
|
|
||||||
LocalFilesystemLoader: fs,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move sandbox to a virtual fs
|
|
||||||
|
|
||||||
/*
|
|
||||||
if len(set.SandboxDirectories) > 0 {
|
|
||||||
defer func() {
|
|
||||||
// Remove any ".." or other crap
|
|
||||||
resolvedPath = filepath.Clean(resolvedPath)
|
|
||||||
|
|
||||||
// Make the path absolute
|
|
||||||
absPath, err := filepath.Abs(resolvedPath)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
resolvedPath = absPath
|
|
||||||
|
|
||||||
// Check against the sandbox directories (once one pattern matches, we're done and can allow it)
|
|
||||||
for _, pattern := range set.SandboxDirectories {
|
|
||||||
matched, err := filepath.Match(pattern, resolvedPath)
|
|
||||||
if err != nil {
|
|
||||||
panic("Wrong sandbox directory match pattern (see http://golang.org/pkg/path/filepath/#Match).")
|
|
||||||
}
|
|
||||||
if matched {
|
|
||||||
// OK!
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// No pattern matched, we have to log+deny the request
|
|
||||||
set.logf("Access attempt outside of the sandbox directories (blocked): '%s'", resolvedPath)
|
|
||||||
resolvedPath = ""
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
*/
|
|
276
vendor/github.com/flosch/pongo2/template_sets.go
generated
vendored
276
vendor/github.com/flosch/pongo2/template_sets.go
generated
vendored
|
@ -2,49 +2,48 @@ package pongo2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/juju/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TemplateLoader allows to implement a virtual file system.
|
// A template set allows you to create your own group of templates with their own global context (which is shared
|
||||||
type TemplateLoader interface {
|
// among all members of the set), their own configuration (like a specific base directory) and their own sandbox.
|
||||||
// Abs calculates the path to a given template. Whenever a path must be resolved
|
// It's useful for a separation of different kind of templates (e. g. web templates vs. mail templates).
|
||||||
// due to an import from another template, the base equals the parent template's path.
|
|
||||||
Abs(base, name string) string
|
|
||||||
|
|
||||||
// Get returns an io.Reader where the template's content can be read from.
|
|
||||||
Get(path string) (io.Reader, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TemplateSet allows you to create your own group of templates with their own
|
|
||||||
// global context (which is shared among all members of the set) and their own
|
|
||||||
// configuration.
|
|
||||||
// It's useful for a separation of different kind of templates
|
|
||||||
// (e. g. web templates vs. mail templates).
|
|
||||||
type TemplateSet struct {
|
type TemplateSet struct {
|
||||||
name string
|
name string
|
||||||
loader TemplateLoader
|
|
||||||
|
|
||||||
// Globals will be provided to all templates created within this template set
|
// Globals will be provided to all templates created within this template set
|
||||||
Globals Context
|
Globals Context
|
||||||
|
|
||||||
// If debug is true (default false), ExecutionContext.Logf() will work and output
|
// If debug is true (default false), ExecutionContext.Logf() will work and output to STDOUT. Furthermore,
|
||||||
// to STDOUT. Furthermore, FromCache() won't cache the templates.
|
// FromCache() won't cache the templates. Make sure to synchronize the access to it in case you're changing this
|
||||||
// Make sure to synchronize the access to it in case you're changing this
|
|
||||||
// variable during program execution (and template compilation/execution).
|
// variable during program execution (and template compilation/execution).
|
||||||
Debug bool
|
Debug bool
|
||||||
|
|
||||||
|
// Base directory: If you set the base directory (string is non-empty), all filename lookups in tags/filters are
|
||||||
|
// relative to this directory. If it's empty, all lookups are relative to the current filename which is importing.
|
||||||
|
baseDirectory string
|
||||||
|
|
||||||
// Sandbox features
|
// Sandbox features
|
||||||
|
// - Limit access to directories (using SandboxDirectories)
|
||||||
// - Disallow access to specific tags and/or filters (using BanTag() and BanFilter())
|
// - Disallow access to specific tags and/or filters (using BanTag() and BanFilter())
|
||||||
//
|
//
|
||||||
// For efficiency reasons you can ban tags/filters only *before* you have
|
// You can limit file accesses (for all tags/filters which are using pongo2's file resolver technique)
|
||||||
// added your first template to the set (restrictions are statically checked).
|
// to these sandbox directories. All default pongo2 filters/tags are respecting these restrictions.
|
||||||
// After you added one, it's not possible anymore (for your personal security).
|
// For example, if you only have your base directory in the list, a {% ssi "/etc/passwd" %} will not work.
|
||||||
|
// No items in SandboxDirectories means no restrictions at all.
|
||||||
|
//
|
||||||
|
// For efficiency reasons you can ban tags/filters only *before* you have added your first
|
||||||
|
// template to the set (restrictions are statically checked). After you added one, it's not possible anymore
|
||||||
|
// (for your personal security).
|
||||||
|
//
|
||||||
|
// SandboxDirectories can be changed at runtime. Please synchronize the access to it if you need to change it
|
||||||
|
// after you've added your first template to the set. You *must* use this match pattern for your directories:
|
||||||
|
// http://golang.org/pkg/path/filepath/#Match
|
||||||
|
SandboxDirectories []string
|
||||||
firstTemplateCreated bool
|
firstTemplateCreated bool
|
||||||
bannedTags map[string]bool
|
bannedTags map[string]bool
|
||||||
bannedFilters map[string]bool
|
bannedFilters map[string]bool
|
||||||
|
@ -54,13 +53,11 @@ type TemplateSet struct {
|
||||||
templateCacheMutex sync.Mutex
|
templateCacheMutex sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSet can be used to create sets with different kind of templates
|
// Create your own template sets to separate different kind of templates (e. g. web from mail templates) with
|
||||||
// (e. g. web from mail templates), with different globals or
|
// different globals or other configurations (like base directories).
|
||||||
// other configurations.
|
func NewSet(name string) *TemplateSet {
|
||||||
func NewSet(name string, loader TemplateLoader) *TemplateSet {
|
|
||||||
return &TemplateSet{
|
return &TemplateSet{
|
||||||
name: name,
|
name: name,
|
||||||
loader: loader,
|
|
||||||
Globals: make(Context),
|
Globals: make(Context),
|
||||||
bannedTags: make(map[string]bool),
|
bannedTags: make(map[string]bool),
|
||||||
bannedFilters: make(map[string]bool),
|
bannedFilters: make(map[string]bool),
|
||||||
|
@ -68,157 +65,151 @@ func NewSet(name string, loader TemplateLoader) *TemplateSet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (set *TemplateSet) resolveFilename(tpl *Template, path string) string {
|
// Use this function to set your template set's base directory. This directory will be used for any relative
|
||||||
name := ""
|
// path in filters, tags and From*-functions to determine your template.
|
||||||
if tpl != nil && tpl.isTplString {
|
func (set *TemplateSet) SetBaseDirectory(name string) error {
|
||||||
return path
|
// Make the path absolute
|
||||||
|
if !filepath.IsAbs(name) {
|
||||||
|
abs, err := filepath.Abs(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
name = abs
|
||||||
}
|
}
|
||||||
if tpl != nil {
|
|
||||||
name = tpl.name
|
// Check for existence
|
||||||
|
fi, err := os.Stat(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
return set.loader.Abs(name, path)
|
if !fi.IsDir() {
|
||||||
|
return fmt.Errorf("The given path '%s' is not a directory.")
|
||||||
|
}
|
||||||
|
|
||||||
|
set.baseDirectory = name
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// BanTag bans a specific tag for this template set. See more in the documentation for TemplateSet.
|
func (set *TemplateSet) BaseDirectory() string {
|
||||||
func (set *TemplateSet) BanTag(name string) error {
|
return set.baseDirectory
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ban a specific tag for this template set. See more in the documentation for TemplateSet.
|
||||||
|
func (set *TemplateSet) BanTag(name string) {
|
||||||
_, has := tags[name]
|
_, has := tags[name]
|
||||||
if !has {
|
if !has {
|
||||||
return errors.Errorf("tag '%s' not found", name)
|
panic(fmt.Sprintf("Tag '%s' not found.", name))
|
||||||
}
|
}
|
||||||
if set.firstTemplateCreated {
|
if set.firstTemplateCreated {
|
||||||
return errors.New("you cannot ban any tags after you've added your first template to your template set")
|
panic("You cannot ban any tags after you've added your first template to your template set.")
|
||||||
}
|
}
|
||||||
_, has = set.bannedTags[name]
|
_, has = set.bannedTags[name]
|
||||||
if has {
|
if has {
|
||||||
return errors.Errorf("tag '%s' is already banned", name)
|
panic(fmt.Sprintf("Tag '%s' is already banned.", name))
|
||||||
}
|
}
|
||||||
set.bannedTags[name] = true
|
set.bannedTags[name] = true
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BanFilter bans a specific filter for this template set. See more in the documentation for TemplateSet.
|
// Ban a specific filter for this template set. See more in the documentation for TemplateSet.
|
||||||
func (set *TemplateSet) BanFilter(name string) error {
|
func (set *TemplateSet) BanFilter(name string) {
|
||||||
_, has := filters[name]
|
_, has := filters[name]
|
||||||
if !has {
|
if !has {
|
||||||
return errors.Errorf("filter '%s' not found", name)
|
panic(fmt.Sprintf("Filter '%s' not found.", name))
|
||||||
}
|
}
|
||||||
if set.firstTemplateCreated {
|
if set.firstTemplateCreated {
|
||||||
return errors.New("you cannot ban any filters after you've added your first template to your template set")
|
panic("You cannot ban any filters after you've added your first template to your template set.")
|
||||||
}
|
}
|
||||||
_, has = set.bannedFilters[name]
|
_, has = set.bannedFilters[name]
|
||||||
if has {
|
if has {
|
||||||
return errors.Errorf("filter '%s' is already banned", name)
|
panic(fmt.Sprintf("Filter '%s' is already banned.", name))
|
||||||
}
|
}
|
||||||
set.bannedFilters[name] = true
|
set.bannedFilters[name] = true
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromCache is a convenient method to cache templates. It is thread-safe
|
// FromCache() is a convenient method to cache templates. It is thread-safe
|
||||||
// and will only compile the template associated with a filename once.
|
// and will only compile the template associated with a filename once.
|
||||||
// If TemplateSet.Debug is true (for example during development phase),
|
// If TemplateSet.Debug is true (for example during development phase),
|
||||||
// FromCache() will not cache the template and instead recompile it on any
|
// FromCache() will not cache the template and instead recompile it on any
|
||||||
// call (to make changes to a template live instantaneously).
|
// call (to make changes to a template live instantaneously).
|
||||||
|
// Like FromFile(), FromCache() takes a relative path to a set base directory.
|
||||||
|
// Sandbox restrictions apply (if given).
|
||||||
func (set *TemplateSet) FromCache(filename string) (*Template, error) {
|
func (set *TemplateSet) FromCache(filename string) (*Template, error) {
|
||||||
if set.Debug {
|
if set.Debug {
|
||||||
// Recompile on any request
|
// Recompile on any request
|
||||||
return set.FromFile(filename)
|
return set.FromFile(filename)
|
||||||
}
|
} else {
|
||||||
// Cache the template
|
// Cache the template
|
||||||
cleanedFilename := set.resolveFilename(nil, filename)
|
cleaned_filename := set.resolveFilename(nil, filename)
|
||||||
|
|
||||||
set.templateCacheMutex.Lock()
|
set.templateCacheMutex.Lock()
|
||||||
defer set.templateCacheMutex.Unlock()
|
defer set.templateCacheMutex.Unlock()
|
||||||
|
|
||||||
tpl, has := set.templateCache[cleanedFilename]
|
tpl, has := set.templateCache[cleaned_filename]
|
||||||
|
|
||||||
// Cache miss
|
// Cache miss
|
||||||
if !has {
|
if !has {
|
||||||
tpl, err := set.FromFile(cleanedFilename)
|
tpl, err := set.FromFile(cleaned_filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
}
|
||||||
|
set.templateCache[cleaned_filename] = tpl
|
||||||
|
return tpl, nil
|
||||||
}
|
}
|
||||||
set.templateCache[cleanedFilename] = tpl
|
|
||||||
|
// Cache hit
|
||||||
return tpl, nil
|
return tpl, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache hit
|
|
||||||
return tpl, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromString loads a template from string and returns a Template instance.
|
// Loads a template from string and returns a Template instance.
|
||||||
func (set *TemplateSet) FromString(tpl string) (*Template, error) {
|
func (set *TemplateSet) FromString(tpl string) (*Template, error) {
|
||||||
set.firstTemplateCreated = true
|
set.firstTemplateCreated = true
|
||||||
|
|
||||||
return newTemplateString(set, []byte(tpl))
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromBytes loads a template from bytes and returns a Template instance.
|
|
||||||
func (set *TemplateSet) FromBytes(tpl []byte) (*Template, error) {
|
|
||||||
set.firstTemplateCreated = true
|
|
||||||
|
|
||||||
return newTemplateString(set, tpl)
|
return newTemplateString(set, tpl)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromFile loads a template from a filename and returns a Template instance.
|
// Loads a template from a filename and returns a Template instance.
|
||||||
|
// If a base directory is set, the filename must be either relative to it
|
||||||
|
// or be an absolute path. Sandbox restrictions (SandboxDirectories) apply
|
||||||
|
// if given.
|
||||||
func (set *TemplateSet) FromFile(filename string) (*Template, error) {
|
func (set *TemplateSet) FromFile(filename string) (*Template, error) {
|
||||||
set.firstTemplateCreated = true
|
set.firstTemplateCreated = true
|
||||||
|
|
||||||
fd, err := set.loader.Get(set.resolveFilename(nil, filename))
|
buf, err := ioutil.ReadFile(set.resolveFilename(nil, filename))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, &Error{
|
return nil, &Error{
|
||||||
Filename: filename,
|
Filename: filename,
|
||||||
Sender: "fromfile",
|
Sender: "fromfile",
|
||||||
OrigError: err,
|
ErrorMsg: err.Error(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buf, err := ioutil.ReadAll(fd)
|
return newTemplate(set, filename, false, string(buf))
|
||||||
if err != nil {
|
|
||||||
return nil, &Error{
|
|
||||||
Filename: filename,
|
|
||||||
Sender: "fromfile",
|
|
||||||
OrigError: err,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newTemplate(set, filename, false, buf)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RenderTemplateString is a shortcut and renders a template string directly.
|
// Shortcut; renders a template string directly. Panics when providing a
|
||||||
func (set *TemplateSet) RenderTemplateString(s string, ctx Context) (string, error) {
|
// malformed template or an error occurs during execution.
|
||||||
|
func (set *TemplateSet) RenderTemplateString(s string, ctx Context) string {
|
||||||
set.firstTemplateCreated = true
|
set.firstTemplateCreated = true
|
||||||
|
|
||||||
tpl := Must(set.FromString(s))
|
tpl := Must(set.FromString(s))
|
||||||
result, err := tpl.Execute(ctx)
|
result, err := tpl.Execute(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
panic(err)
|
||||||
}
|
}
|
||||||
return result, nil
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// RenderTemplateBytes is a shortcut and renders template bytes directly.
|
// Shortcut; renders a template file directly. Panics when providing a
|
||||||
func (set *TemplateSet) RenderTemplateBytes(b []byte, ctx Context) (string, error) {
|
// malformed template or an error occurs during execution.
|
||||||
set.firstTemplateCreated = true
|
func (set *TemplateSet) RenderTemplateFile(fn string, ctx Context) string {
|
||||||
|
|
||||||
tpl := Must(set.FromBytes(b))
|
|
||||||
result, err := tpl.Execute(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RenderTemplateFile is a shortcut and renders a template file directly.
|
|
||||||
func (set *TemplateSet) RenderTemplateFile(fn string, ctx Context) (string, error) {
|
|
||||||
set.firstTemplateCreated = true
|
set.firstTemplateCreated = true
|
||||||
|
|
||||||
tpl := Must(set.FromFile(fn))
|
tpl := Must(set.FromFile(fn))
|
||||||
result, err := tpl.Execute(ctx)
|
result, err := tpl.Execute(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
panic(err)
|
||||||
}
|
}
|
||||||
return result, nil
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (set *TemplateSet) logf(format string, args ...interface{}) {
|
func (set *TemplateSet) logf(format string, args ...interface{}) {
|
||||||
|
@ -227,6 +218,58 @@ func (set *TemplateSet) logf(format string, args ...interface{}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolves a filename relative to the base directory. Absolute paths are allowed.
|
||||||
|
// If sandbox restrictions are given (SandboxDirectories), they will be respected and checked.
|
||||||
|
// On sandbox restriction violation, resolveFilename() panics.
|
||||||
|
func (set *TemplateSet) resolveFilename(tpl *Template, filename string) (resolved_path string) {
|
||||||
|
if len(set.SandboxDirectories) > 0 {
|
||||||
|
defer func() {
|
||||||
|
// Remove any ".." or other crap
|
||||||
|
resolved_path = filepath.Clean(resolved_path)
|
||||||
|
|
||||||
|
// Make the path absolute
|
||||||
|
abs_path, err := filepath.Abs(resolved_path)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
resolved_path = abs_path
|
||||||
|
|
||||||
|
// Check against the sandbox directories (once one pattern matches, we're done and can allow it)
|
||||||
|
for _, pattern := range set.SandboxDirectories {
|
||||||
|
matched, err := filepath.Match(pattern, resolved_path)
|
||||||
|
if err != nil {
|
||||||
|
panic("Wrong sandbox directory match pattern (see http://golang.org/pkg/path/filepath/#Match).")
|
||||||
|
}
|
||||||
|
if matched {
|
||||||
|
// OK!
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No pattern matched, we have to log+deny the request
|
||||||
|
set.logf("Access attempt outside of the sandbox directories (blocked): '%s'", resolved_path)
|
||||||
|
resolved_path = ""
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
if filepath.IsAbs(filename) {
|
||||||
|
return filename
|
||||||
|
}
|
||||||
|
|
||||||
|
if set.baseDirectory == "" {
|
||||||
|
if tpl != nil {
|
||||||
|
if tpl.is_tpl_string {
|
||||||
|
return filename
|
||||||
|
}
|
||||||
|
base := filepath.Dir(tpl.name)
|
||||||
|
return filepath.Join(base, filename)
|
||||||
|
}
|
||||||
|
return filename
|
||||||
|
} else {
|
||||||
|
return filepath.Join(set.baseDirectory, filename)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Logging function (internally used)
|
// Logging function (internally used)
|
||||||
func logf(format string, items ...interface{}) {
|
func logf(format string, items ...interface{}) {
|
||||||
if debug {
|
if debug {
|
||||||
|
@ -236,18 +279,13 @@ func logf(format string, items ...interface{}) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
debug bool // internal debugging
|
debug bool // internal debugging
|
||||||
logger = log.New(os.Stdout, "[pongo2] ", log.LstdFlags|log.Lshortfile)
|
logger = log.New(os.Stdout, "[pongo2] ", log.LstdFlags)
|
||||||
|
|
||||||
// DefaultLoader allows the default un-sandboxed access to the local file
|
// Creating a default set
|
||||||
// system and is being used by the DefaultSet.
|
DefaultSet = NewSet("default")
|
||||||
DefaultLoader = MustNewLocalFileSystemLoader("")
|
|
||||||
|
|
||||||
// DefaultSet is a set created for you for convinience reasons.
|
|
||||||
DefaultSet = NewSet("default", DefaultLoader)
|
|
||||||
|
|
||||||
// Methods on the default set
|
// Methods on the default set
|
||||||
FromString = DefaultSet.FromString
|
FromString = DefaultSet.FromString
|
||||||
FromBytes = DefaultSet.FromBytes
|
|
||||||
FromFile = DefaultSet.FromFile
|
FromFile = DefaultSet.FromFile
|
||||||
FromCache = DefaultSet.FromCache
|
FromCache = DefaultSet.FromCache
|
||||||
RenderTemplateString = DefaultSet.RenderTemplateString
|
RenderTemplateString = DefaultSet.RenderTemplateString
|
||||||
|
|
10
vendor/github.com/flosch/pongo2/template_tests/autoescape.tpl
generated
vendored
10
vendor/github.com/flosch/pongo2/template_tests/autoescape.tpl
generated
vendored
|
@ -1,10 +0,0 @@
|
||||||
{{ "<script>alert('xss');</script>" }}
|
|
||||||
{% autoescape off %}
|
|
||||||
{{ "<script>alert('xss');</script>" }}
|
|
||||||
{% endautoescape %}
|
|
||||||
{% autoescape on %}
|
|
||||||
{{ "<script>alert('xss');</script>" }}
|
|
||||||
{% endautoescape %}
|
|
||||||
{% autoescape off %}
|
|
||||||
{{ "<script>alert('xss');</script>"|escape }}
|
|
||||||
{% endautoescape %}
|
|
9
vendor/github.com/flosch/pongo2/template_tests/autoescape.tpl.out
generated
vendored
9
vendor/github.com/flosch/pongo2/template_tests/autoescape.tpl.out
generated
vendored
|
@ -1,9 +0,0 @@
|
||||||
<script>alert('xss');</script>
|
|
||||||
|
|
||||||
<script>alert('xss');</script>
|
|
||||||
|
|
||||||
|
|
||||||
<script>alert('xss');</script>
|
|
||||||
|
|
||||||
|
|
||||||
<script>alert('xss');</script>
|
|
1
vendor/github.com/flosch/pongo2/template_tests/base_dir_test/base.html
generated
vendored
1
vendor/github.com/flosch/pongo2/template_tests/base_dir_test/base.html
generated
vendored
|
@ -1 +0,0 @@
|
||||||
Hello from {{ base_directory }}
|
|
1
vendor/github.com/flosch/pongo2/template_tests/base_dir_test/subdir/include.html
generated
vendored
1
vendor/github.com/flosch/pongo2/template_tests/base_dir_test/subdir/include.html
generated
vendored
|
@ -1 +0,0 @@
|
||||||
{% include "base.html" %}
|
|
1
vendor/github.com/flosch/pongo2/template_tests/base_dir_test/subdir/index.html
generated
vendored
1
vendor/github.com/flosch/pongo2/template_tests/base_dir_test/subdir/index.html
generated
vendored
|
@ -1 +0,0 @@
|
||||||
{% extends "base.html" %}
|
|
1
vendor/github.com/flosch/pongo2/template_tests/base_dir_test/subdir/ssi.html
generated
vendored
1
vendor/github.com/flosch/pongo2/template_tests/base_dir_test/subdir/ssi.html
generated
vendored
|
@ -1 +0,0 @@
|
||||||
{% ssi "base.html" parsed %}
|
|
50
vendor/github.com/flosch/pongo2/template_tests/comment.tpl
generated
vendored
50
vendor/github.com/flosch/pongo2/template_tests/comment.tpl
generated
vendored
|
@ -1,50 +0,0 @@
|
||||||
empty single line comment
|
|
||||||
{# #}
|
|
||||||
|
|
||||||
filled single line comment
|
|
||||||
{# testing single line comment #}
|
|
||||||
|
|
||||||
filled single line comment with valid tags
|
|
||||||
{# testing single line comment {% if thing %}{% endif %} #}
|
|
||||||
|
|
||||||
filled single line comment with invalid tags
|
|
||||||
{# testing single line comment {% if thing %} #}
|
|
||||||
|
|
||||||
filled single line comment with invalid syntax
|
|
||||||
{# testing single line comment {% if thing('') %}wow{% endif %} #}
|
|
||||||
|
|
||||||
empty block comment
|
|
||||||
{% comment %}{% endcomment %}
|
|
||||||
|
|
||||||
filled text single line block comment
|
|
||||||
{% comment %}filled block comment {% endcomment %}
|
|
||||||
|
|
||||||
empty multi line block comment
|
|
||||||
{% comment %}
|
|
||||||
|
|
||||||
|
|
||||||
{% endcomment %}
|
|
||||||
|
|
||||||
block comment with other tags inside of it
|
|
||||||
{% comment %}
|
|
||||||
{{ thing_goes_here }}
|
|
||||||
{% if stuff %}do stuff{% endif %}
|
|
||||||
{% endcomment %}
|
|
||||||
|
|
||||||
block comment with invalid tags inside of it
|
|
||||||
{% comment %}
|
|
||||||
{% if thing %}
|
|
||||||
{% endcomment %}
|
|
||||||
|
|
||||||
block comment with invalid syntax inside of it
|
|
||||||
{% comment %}
|
|
||||||
{% thing('') %}
|
|
||||||
{% endcomment %}
|
|
||||||
|
|
||||||
Regular tags between comments to verify it doesn't break in the lexer
|
|
||||||
{% if hello %}
|
|
||||||
{% endif %}
|
|
||||||
after if
|
|
||||||
{% comment %}All done{% endcomment %}
|
|
||||||
|
|
||||||
end of file
|
|
39
vendor/github.com/flosch/pongo2/template_tests/comment.tpl.out
generated
vendored
39
vendor/github.com/flosch/pongo2/template_tests/comment.tpl.out
generated
vendored
|
@ -1,39 +0,0 @@
|
||||||
empty single line comment
|
|
||||||
|
|
||||||
|
|
||||||
filled single line comment
|
|
||||||
|
|
||||||
|
|
||||||
filled single line comment with valid tags
|
|
||||||
|
|
||||||
|
|
||||||
filled single line comment with invalid tags
|
|
||||||
|
|
||||||
|
|
||||||
filled single line comment with invalid syntax
|
|
||||||
|
|
||||||
|
|
||||||
empty block comment
|
|
||||||
|
|
||||||
|
|
||||||
filled text single line block comment
|
|
||||||
|
|
||||||
|
|
||||||
empty multi line block comment
|
|
||||||
|
|
||||||
|
|
||||||
block comment with other tags inside of it
|
|
||||||
|
|
||||||
|
|
||||||
block comment with invalid tags inside of it
|
|
||||||
|
|
||||||
|
|
||||||
block comment with invalid syntax inside of it
|
|
||||||
|
|
||||||
|
|
||||||
Regular tags between comments to verify it doesn't break in the lexer
|
|
||||||
|
|
||||||
after if
|
|
||||||
|
|
||||||
|
|
||||||
end of file
|
|
32
vendor/github.com/flosch/pongo2/template_tests/complex.tpl
generated
vendored
32
vendor/github.com/flosch/pongo2/template_tests/complex.tpl
generated
vendored
|
@ -1,32 +0,0 @@
|
||||||
{# A more complex template using pongo2 (fully django-compatible template) #}
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<title>My blog page</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<h1>Blogpost</h1>
|
|
||||||
<div id="content">
|
|
||||||
{{ complex.post.Text|safe }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h1>Comments</h1>
|
|
||||||
|
|
||||||
{% for comment in complex.comments %}
|
|
||||||
<h2>{{ forloop.Counter }}. Comment ({{ forloop.Revcounter}} comment{{ forloop.Revcounter|pluralize:"s" }} left)</h2>
|
|
||||||
<p>From: {{ comment.Author.Name }} ({{ comment.Author.Validated|yesno:"validated,not validated,unknown validation status" }})</p>
|
|
||||||
|
|
||||||
{% if complex.is_admin(comment.Author) %}
|
|
||||||
<p>This user is an admin (verify: {{ comment.Author.Is_admin }})!</p>
|
|
||||||
{% else %}
|
|
||||||
<p>This user is not admin!</p>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<p>Written {{ comment.Date }}</p>
|
|
||||||
<p>{{ comment.Text|striptags }}</p>
|
|
||||||
{% endfor %}
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
50
vendor/github.com/flosch/pongo2/template_tests/complex.tpl.out
generated
vendored
50
vendor/github.com/flosch/pongo2/template_tests/complex.tpl.out
generated
vendored
|
@ -1,50 +0,0 @@
|
||||||
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<title>My blog page</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<h1>Blogpost</h1>
|
|
||||||
<div id="content">
|
|
||||||
<h2>Hello!</h2><p>Welcome to my new blog page. I'm using pongo2 which supports {{ variables }} and {% tags %}.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h1>Comments</h1>
|
|
||||||
|
|
||||||
|
|
||||||
<h2>1. Comment (3 comments left)</h2>
|
|
||||||
<p>From: user1 (validated)</p>
|
|
||||||
|
|
||||||
|
|
||||||
<p>This user is not admin!</p>
|
|
||||||
|
|
||||||
|
|
||||||
<p>Written 2014-06-10 15:30:15 +0000 UTC</p>
|
|
||||||
<p>"pongo2 is nice!"</p>
|
|
||||||
|
|
||||||
<h2>2. Comment (2 comments left)</h2>
|
|
||||||
<p>From: user2 (validated)</p>
|
|
||||||
|
|
||||||
|
|
||||||
<p>This user is an admin (verify: True)!</p>
|
|
||||||
|
|
||||||
|
|
||||||
<p>Written 2011-03-21 08:37:56.000000012 +0000 UTC</p>
|
|
||||||
<p>comment2 with unsafe tags in it</p>
|
|
||||||
|
|
||||||
<h2>3. Comment (1 comment left)</h2>
|
|
||||||
<p>From: user3 (not validated)</p>
|
|
||||||
|
|
||||||
|
|
||||||
<p>This user is not admin!</p>
|
|
||||||
|
|
||||||
|
|
||||||
<p>Written 2014-06-10 15:30:15 +0000 UTC</p>
|
|
||||||
<p>hello! there</p>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
22
vendor/github.com/flosch/pongo2/template_tests/cycle.tpl
generated
vendored
22
vendor/github.com/flosch/pongo2/template_tests/cycle.tpl
generated
vendored
|
@ -1,22 +0,0 @@
|
||||||
{% for item in simple.multiple_item_list %}
|
|
||||||
'{% cycle "item1" simple.name simple.number %}'
|
|
||||||
{% endfor %}
|
|
||||||
{% for item in simple.multiple_item_list %}
|
|
||||||
'{% cycle "item1" simple.name simple.number as cycleitem %}'
|
|
||||||
May I present the cycle item again: '{{ cycleitem }}'
|
|
||||||
{% endfor %}
|
|
||||||
{% for item in simple.multiple_item_list %}
|
|
||||||
'{% cycle "item1" simple.name simple.number as cycleitem silent %}'
|
|
||||||
May I present the cycle item: '{{ cycleitem }}'
|
|
||||||
{% endfor %}
|
|
||||||
{% for item in simple.multiple_item_list %}
|
|
||||||
'{% cycle "item1" simple.name simple.number as cycleitem silent %}'
|
|
||||||
May I present the cycle item: '{{ cycleitem }}'
|
|
||||||
{% include "inheritance/cycle_include.tpl" %}
|
|
||||||
{% endfor %}
|
|
||||||
'{% cycle "item1" simple.name simple.number as cycleitem %}'
|
|
||||||
'{% cycle cycleitem %}'
|
|
||||||
'{% cycle "item1" simple.name simple.number as cycleitem silent %}'
|
|
||||||
'{{ cycleitem }}'
|
|
||||||
'{% cycle cycleitem %}'
|
|
||||||
'{{ cycleitem }}'
|
|
130
vendor/github.com/flosch/pongo2/template_tests/cycle.tpl.out
generated
vendored
130
vendor/github.com/flosch/pongo2/template_tests/cycle.tpl.out
generated
vendored
|
@ -1,130 +0,0 @@
|
||||||
|
|
||||||
'item1'
|
|
||||||
|
|
||||||
'john doe'
|
|
||||||
|
|
||||||
'42'
|
|
||||||
|
|
||||||
'item1'
|
|
||||||
|
|
||||||
'john doe'
|
|
||||||
|
|
||||||
'42'
|
|
||||||
|
|
||||||
'item1'
|
|
||||||
|
|
||||||
'john doe'
|
|
||||||
|
|
||||||
'42'
|
|
||||||
|
|
||||||
'item1'
|
|
||||||
|
|
||||||
|
|
||||||
'item1'
|
|
||||||
May I present the cycle item again: 'item1'
|
|
||||||
|
|
||||||
'john doe'
|
|
||||||
May I present the cycle item again: 'john doe'
|
|
||||||
|
|
||||||
'42'
|
|
||||||
May I present the cycle item again: '42'
|
|
||||||
|
|
||||||
'item1'
|
|
||||||
May I present the cycle item again: 'item1'
|
|
||||||
|
|
||||||
'john doe'
|
|
||||||
May I present the cycle item again: 'john doe'
|
|
||||||
|
|
||||||
'42'
|
|
||||||
May I present the cycle item again: '42'
|
|
||||||
|
|
||||||
'item1'
|
|
||||||
May I present the cycle item again: 'item1'
|
|
||||||
|
|
||||||
'john doe'
|
|
||||||
May I present the cycle item again: 'john doe'
|
|
||||||
|
|
||||||
'42'
|
|
||||||
May I present the cycle item again: '42'
|
|
||||||
|
|
||||||
'item1'
|
|
||||||
May I present the cycle item again: 'item1'
|
|
||||||
|
|
||||||
|
|
||||||
''
|
|
||||||
May I present the cycle item: 'item1'
|
|
||||||
|
|
||||||
''
|
|
||||||
May I present the cycle item: 'john doe'
|
|
||||||
|
|
||||||
''
|
|
||||||
May I present the cycle item: '42'
|
|
||||||
|
|
||||||
''
|
|
||||||
May I present the cycle item: 'item1'
|
|
||||||
|
|
||||||
''
|
|
||||||
May I present the cycle item: 'john doe'
|
|
||||||
|
|
||||||
''
|
|
||||||
May I present the cycle item: '42'
|
|
||||||
|
|
||||||
''
|
|
||||||
May I present the cycle item: 'item1'
|
|
||||||
|
|
||||||
''
|
|
||||||
May I present the cycle item: 'john doe'
|
|
||||||
|
|
||||||
''
|
|
||||||
May I present the cycle item: '42'
|
|
||||||
|
|
||||||
''
|
|
||||||
May I present the cycle item: 'item1'
|
|
||||||
|
|
||||||
|
|
||||||
''
|
|
||||||
May I present the cycle item: 'item1'
|
|
||||||
Included 'item1'.
|
|
||||||
|
|
||||||
''
|
|
||||||
May I present the cycle item: 'john doe'
|
|
||||||
Included 'john doe'.
|
|
||||||
|
|
||||||
''
|
|
||||||
May I present the cycle item: '42'
|
|
||||||
Included '42'.
|
|
||||||
|
|
||||||
''
|
|
||||||
May I present the cycle item: 'item1'
|
|
||||||
Included 'item1'.
|
|
||||||
|
|
||||||
''
|
|
||||||
May I present the cycle item: 'john doe'
|
|
||||||
Included 'john doe'.
|
|
||||||
|
|
||||||
''
|
|
||||||
May I present the cycle item: '42'
|
|
||||||
Included '42'.
|
|
||||||
|
|
||||||
''
|
|
||||||
May I present the cycle item: 'item1'
|
|
||||||
Included 'item1'.
|
|
||||||
|
|
||||||
''
|
|
||||||
May I present the cycle item: 'john doe'
|
|
||||||
Included 'john doe'.
|
|
||||||
|
|
||||||
''
|
|
||||||
May I present the cycle item: '42'
|
|
||||||
Included '42'.
|
|
||||||
|
|
||||||
''
|
|
||||||
May I present the cycle item: 'item1'
|
|
||||||
Included 'item1'.
|
|
||||||
|
|
||||||
'item1'
|
|
||||||
'john doe'
|
|
||||||
''
|
|
||||||
'item1'
|
|
||||||
''
|
|
||||||
'john doe'
|
|
0
vendor/github.com/flosch/pongo2/template_tests/empty.tpl
generated
vendored
0
vendor/github.com/flosch/pongo2/template_tests/empty.tpl
generated
vendored
0
vendor/github.com/flosch/pongo2/template_tests/empty.tpl.out
generated
vendored
0
vendor/github.com/flosch/pongo2/template_tests/empty.tpl.out
generated
vendored
69
vendor/github.com/flosch/pongo2/template_tests/expressions.tpl
generated
vendored
69
vendor/github.com/flosch/pongo2/template_tests/expressions.tpl
generated
vendored
|
@ -1,69 +0,0 @@
|
||||||
integers and complex expressions
|
|
||||||
{{ 10-100 }}
|
|
||||||
{{ -(10-100) }}
|
|
||||||
{{ -(-(10-100)) }}
|
|
||||||
{{ -1 * (-(-(10-100))) }}
|
|
||||||
{{ -1 * (-(-(10-100)) ^ 2) ^ 3 + 3 * (5 - 17) + 1 + 2 }}
|
|
||||||
|
|
||||||
floats
|
|
||||||
{{ 5.5 }}
|
|
||||||
{{ 5.172841 }}
|
|
||||||
{{ 5.5 - 1.5 == 4 }}
|
|
||||||
{{ 5.5 - 1.5 == 4.0 }}
|
|
||||||
|
|
||||||
mul/div
|
|
||||||
{{ 2 * 5 }}
|
|
||||||
{{ 2 * 5.0 }}
|
|
||||||
{{ 2 * 0 }}
|
|
||||||
{{ 2.5 * 5.3 }}
|
|
||||||
{{ 1/2 }}
|
|
||||||
{{ 1/2.0 }}
|
|
||||||
{{ 1/0.000001 }}
|
|
||||||
|
|
||||||
logic expressions
|
|
||||||
{{ !true }}
|
|
||||||
{{ !(true || false) }}
|
|
||||||
{{ true || false }}
|
|
||||||
{{ true or false }}
|
|
||||||
{{ false or false }}
|
|
||||||
{{ false || false }}
|
|
||||||
{{ true && (true && (true && (true && (1 == 1 || false)))) }}
|
|
||||||
|
|
||||||
float comparison
|
|
||||||
{{ 5.5 <= 5.5 }}
|
|
||||||
{{ 5.5 < 5.5 }}
|
|
||||||
{{ 5.5 > 5.5 }}
|
|
||||||
{{ 5.5 >= 5.5 }}
|
|
||||||
|
|
||||||
remainders
|
|
||||||
{{ (simple.number+7)%7 }}
|
|
||||||
{{ (simple.number+7)%7 == 0 }}
|
|
||||||
{{ (simple.number+7)%6 }}
|
|
||||||
|
|
||||||
in/not in
|
|
||||||
{{ 5 in simple.intmap }}
|
|
||||||
{{ 2 in simple.intmap }}
|
|
||||||
{{ 7 in simple.intmap }}
|
|
||||||
{{ !(5 in simple.intmap) }}
|
|
||||||
{{ not(7 in simple.intmap) }}
|
|
||||||
{{ 1 in simple.multiple_item_list }}
|
|
||||||
{{ 4 in simple.multiple_item_list }}
|
|
||||||
{{ !(4 in simple.multiple_item_list) }}
|
|
||||||
{{ "Hello" in simple.misc_list }}
|
|
||||||
{{ "Hello2" in simple.misc_list }}
|
|
||||||
{{ 99 in simple.misc_list }}
|
|
||||||
{{ False in simple.misc_list }}
|
|
||||||
|
|
||||||
issue #48 (associativity for infix operators)
|
|
||||||
{{ 34/3*3 }}
|
|
||||||
{{ 10 + 24 / 6 / 2 }}
|
|
||||||
{{ 6 - 4 - 2 }}
|
|
||||||
|
|
||||||
issue #64 (uint comparison with int const)
|
|
||||||
{{ simple.uint }}
|
|
||||||
{{ simple.uint == 8 }}
|
|
||||||
{{ simple.uint == 9 }}
|
|
||||||
{{ simple.uint >= 8 }}
|
|
||||||
{{ simple.uint <= 8 }}
|
|
||||||
{{ simple.uint < 8 }}
|
|
||||||
{{ simple.uint > 8 }}
|
|
69
vendor/github.com/flosch/pongo2/template_tests/expressions.tpl.out
generated
vendored
69
vendor/github.com/flosch/pongo2/template_tests/expressions.tpl.out
generated
vendored
|
@ -1,69 +0,0 @@
|
||||||
integers and complex expressions
|
|
||||||
-90
|
|
||||||
90
|
|
||||||
-90
|
|
||||||
90
|
|
||||||
531440999967.000000
|
|
||||||
|
|
||||||
floats
|
|
||||||
5.500000
|
|
||||||
5.172841
|
|
||||||
False
|
|
||||||
True
|
|
||||||
|
|
||||||
mul/div
|
|
||||||
10
|
|
||||||
10.000000
|
|
||||||
0
|
|
||||||
13.250000
|
|
||||||
0
|
|
||||||
0.500000
|
|
||||||
1000000.000000
|
|
||||||
|
|
||||||
logic expressions
|
|
||||||
False
|
|
||||||
False
|
|
||||||
True
|
|
||||||
True
|
|
||||||
False
|
|
||||||
False
|
|
||||||
True
|
|
||||||
|
|
||||||
float comparison
|
|
||||||
True
|
|
||||||
False
|
|
||||||
False
|
|
||||||
True
|
|
||||||
|
|
||||||
remainders
|
|
||||||
0
|
|
||||||
True
|
|
||||||
1
|
|
||||||
|
|
||||||
in/not in
|
|
||||||
True
|
|
||||||
True
|
|
||||||
False
|
|
||||||
False
|
|
||||||
True
|
|
||||||
True
|
|
||||||
False
|
|
||||||
True
|
|
||||||
True
|
|
||||||
False
|
|
||||||
True
|
|
||||||
False
|
|
||||||
|
|
||||||
issue #48 (associativity for infix operators)
|
|
||||||
33
|
|
||||||
12
|
|
||||||
0
|
|
||||||
|
|
||||||
issue #64 (uint comparison with int const)
|
|
||||||
8
|
|
||||||
True
|
|
||||||
False
|
|
||||||
True
|
|
||||||
True
|
|
||||||
False
|
|
||||||
False
|
|
3
vendor/github.com/flosch/pongo2/template_tests/extends.tpl
generated
vendored
3
vendor/github.com/flosch/pongo2/template_tests/extends.tpl
generated
vendored
|
@ -1,3 +0,0 @@
|
||||||
{% extends "inheritance/base.tpl" %}
|
|
||||||
|
|
||||||
{% block content %}Extends' content{% endblock %}
|
|
1
vendor/github.com/flosch/pongo2/template_tests/extends.tpl.out
generated
vendored
1
vendor/github.com/flosch/pongo2/template_tests/extends.tpl.out
generated
vendored
|
@ -1 +0,0 @@
|
||||||
Start#This is base's bodyExtends' content#End
|
|
3
vendor/github.com/flosch/pongo2/template_tests/extends_super.tpl
generated
vendored
3
vendor/github.com/flosch/pongo2/template_tests/extends_super.tpl
generated
vendored
|
@ -1,3 +0,0 @@
|
||||||
{% extends "inheritance/base.tpl" %}
|
|
||||||
|
|
||||||
{% block content %}{{ block.Super }}extends-level-1{% endblock %}
|
|
1
vendor/github.com/flosch/pongo2/template_tests/extends_super.tpl.out
generated
vendored
1
vendor/github.com/flosch/pongo2/template_tests/extends_super.tpl.out
generated
vendored
|
@ -1 +0,0 @@
|
||||||
Start#This is base's bodyDefault contentextends-level-1#End
|
|
3
vendor/github.com/flosch/pongo2/template_tests/extends_super2.tpl
generated
vendored
3
vendor/github.com/flosch/pongo2/template_tests/extends_super2.tpl
generated
vendored
|
@ -1,3 +0,0 @@
|
||||||
{% extends "extends_super.tpl" %}
|
|
||||||
|
|
||||||
{% block content %}{{ block.Super }}extends-level-2{% endblock %}
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue