Skip to content

Commit 1739076

Browse files
committed
Added the option to throw when a variable used in the template is not found in the context
1 parent 5b2d5dc commit 1739076

File tree

4 files changed

+30
-2
lines changed

4 files changed

+30
-2
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ _None_
1212
, i.e. `myfilter = "uppercase"` and then use it to invoke this filter with `{{ string|filter:myfilter }}`.
1313
[Ilya Puchka](https://github.com/ilyapuchka)
1414
[#203](https://github.com/stencilproject/Stencil/pull/203)
15+
- Added option to throw when a variable used in a template could not be resolved.
16+
[Andres Cecilia Luque](https://github.com/acecilia)
17+
[#289](https://github.com/stencilproject/Stencil/pull/289)
1518

1619
### Deprecations
1720

Sources/Environment.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
public struct Environment {
22
public let templateClass: Template.Type
33
public var extensions: [Extension]
4+
public let throwOnUnresolvedVariable: Bool
45

56
public var loader: Loader?
67

78
public init(loader: Loader? = nil,
89
extensions: [Extension] = [],
10+
throwOnUnresolvedVariable: Bool = false,
911
templateClass: Template.Type = Template.self) {
1012

1113
self.templateClass = templateClass
1214
self.loader = loader
1315
self.extensions = extensions + [DefaultExtension()]
16+
self.throwOnUnresolvedVariable = throwOnUnresolvedVariable
1417
}
1518

1619
public func loadTemplate(name: String) throws -> Template {

Sources/Variable.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,16 @@ class FilterExpression: Resolvable {
3030
func resolve(_ context: Context) throws -> Any? {
3131
let result = try variable.resolve(context)
3232

33-
return try filters.reduce(result) { value, filter in
33+
let filteredResult = try filters.reduce(result) { value, filter in
3434
let arguments = try filter.1.map { try $0.resolve(context) }
3535
return try filter.0.invoke(value: value, arguments: arguments, context: context)
3636
}
37+
38+
if filteredResult == nil, context.environment.throwOnUnresolvedVariable {
39+
throw TemplateSyntaxError("Variable could not be resolved")
40+
}
41+
42+
return filteredResult
3743
}
3844
}
3945

Tests/StencilTests/EnvironmentSpec.swift

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,23 @@ final class EnvironmentTests: XCTestCase {
182182
}
183183
}
184184

185+
func testUnresolvedVariable() {
186+
self.template = Template(templateString: "Hello {{ human.name }}")
187+
188+
it("can render a variable not defined in the context and throwing is disabled") {
189+
self.environment = Environment()
190+
let result = try self.environment.render(template: self.template, context: [:])
191+
try expect(result) == "Hello "
192+
}
193+
194+
it("throws when a variable is not defined in the context and throwing is enabled") {
195+
self.environment = Environment(throwOnUnresolvedVariable: true)
196+
try self.expectError(context: [:], reason: "Variable could not be resolved", token: "human.name")
197+
}
198+
}
199+
185200
private func expectError(
201+
context: [String: Any] = ["names": ["Bob", "Alice"], "name": "Bob"],
186202
reason: String,
187203
token: String,
188204
file: String = #file,
@@ -192,7 +208,7 @@ final class EnvironmentTests: XCTestCase {
192208
let expectedError = expectedSyntaxError(token: token, template: template, description: reason)
193209

194210
let error = try expect(
195-
self.environment.render(template: self.template, context: ["names": ["Bob", "Alice"], "name": "Bob"]),
211+
self.environment.render(template: self.template, context: context),
196212
file: file,
197213
line: line,
198214
function: function

0 commit comments

Comments
 (0)