-
-
Notifications
You must be signed in to change notification settings - Fork 270
/
context.go
108 lines (94 loc) · 2.84 KB
/
context.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package pongo2
import (
"errors"
"fmt"
"regexp"
)
var reIdentifiers = regexp.MustCompile("^[a-zA-Z0-9_]+$")
// 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.
// Currently, context["pongo2"] contains the following keys:
// 1. version: returns the version string
//
// Template examples for accessing items from your context:
// {{ myconstant }}
// {{ myfunc("test", 42) }}
// {{ user.name }}
// {{ pongo2.version }}
type Context map[string]interface{}
func (c Context) checkForValidIdentifiers() error {
for k, v := range c {
if !reIdentifiers.MatchString(k) {
return fmt.Errorf("Context-key '%s' (value: '%+v') is not a valid identifier.", k, v)
}
}
return nil
}
func (c Context) Update(other Context) Context {
for k, v := range other {
c[k] = v
}
return c
}
// If you're writing a custom tag, your tag's Execute()-function will
// have access to the ExecutionContext. This struct stores anything
// about the current rendering process's Context including
// the Context provided by the user (field Public).
// You can safely use the Private context to provide data to the user's
// template (like a 'forloop'-information). The Shared-context is used
// to share data between tags. All ExecutionContexts share this context.
//
// Please be careful when accessing the Public data.
// PLEASE DO NOT MODIFY THE PUBLIC CONTEXT (read-only).
//
// To create your own execution context within tags, use the
// NewExecutionContext(parent) function.
type ExecutionContext struct {
template *Template
Autoescape bool
Public Context
Private Context
Shared Context
}
var pongo2MetaContext = Context{
"version": Version,
}
func newExecutionContext(tpl *Template, ctx Context) *ExecutionContext {
privateCtx := make(Context)
// Make the pongo2-related funcs/vars available to the context
privateCtx["pongo2"] = pongo2MetaContext
return &ExecutionContext{
template: tpl,
Public: ctx,
Private: privateCtx,
Autoescape: true,
}
}
func NewChildExecutionContext(parent *ExecutionContext) *ExecutionContext {
newctx := &ExecutionContext{
template: parent.template,
Public: parent.Public,
Private: make(Context),
Autoescape: parent.Autoescape,
}
newctx.Shared = parent.Shared
// Copy all existing private items
newctx.Private.Update(parent.Private)
return newctx
}
func (ctx *ExecutionContext) Error(msg string, token *Token) error {
pos := ""
filename := ctx.template.name
if token != nil {
// No tokens available
// TODO: Add location (from where?)
filename = token.Filename
pos = fmt.Sprintf(" | Line %d Col %d (%s)",
token.Line, token.Col, token.String())
}
return errors.New(
fmt.Sprintf("[Execution Error in %s%s] %s",
filename, pos, msg,
))
}