Skip to content

Commit d41b2bd

Browse files
authored
Merge pull request #3 from vapor/optional-cache
add ability to remove caching
2 parents c2cb7b7 + ea1d68f commit d41b2bd

18 files changed

+126
-64
lines changed
File renamed without changes.

Resources/embed-base.leaf

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Leaf embedded: #embed("embed-addition")

Resources/include-base.leaf

-1
This file was deleted.

Sources/Leaf/Constants.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,6 @@ public var defaultTags: [String: Tag] = [
1616
"else": Else(),
1717
"loop": Loop(),
1818
"uppercased": Uppercased(),
19-
"include": Include()
19+
"embed": Embed(),
20+
"index": Index(),
2021
]

Sources/Leaf/Context.swift

+6-9
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,13 @@ public final class Context {
3636

3737
// TODO: Subscripts
3838

39-
subscript(path: String) -> Node? {
40-
let components = path.components(separatedBy: ".")
41-
return self[components]
42-
}
39+
func get<T: PathIndex>(path: [T]) -> Node? {
40+
var next = queue.tip
41+
repeat {
42+
if let value = next?.value[path] { return value }
43+
next = next?.child
44+
} while next != nil
4345

44-
subscript(path: [String]) -> Node? {
45-
for node in queue {
46-
guard let value = node[path] else { continue }
47-
return value
48-
}
4946
return nil
5047
}
5148

Sources/Leaf/Link.swift

+14-11
Original file line numberDiff line numberDiff line change
@@ -28,29 +28,32 @@ public final class Link<Value> { // TODO: Rename Context
2828
Add a new Link to the end of the chain.
2929
*/
3030
public func extend(_ output: Value) {
31-
if let child = child {
32-
child.extend(output)
33-
} else {
34-
let new = Link(output)
35-
new.parent = self
36-
self.child = new
37-
}
31+
let tail = self.tail()
32+
let new = Link(output)
33+
new.parent = tail
34+
tail.child = new
3835
}
3936

4037
/**
4138
The tip of the chain associated with this link
4239
*/
4340
public func tip() -> Link {
44-
guard let parent = parent else { return self }
45-
return parent.tip()
41+
var tip = self
42+
while let next = tip.parent {
43+
tip = next
44+
}
45+
return tip
4646
}
4747

4848
/**
4949
The tail of the chain associated with this link
5050
*/
5151
public func tail() -> Link {
52-
guard let child = child else { return self }
53-
return child.tail()
52+
var tail = self
53+
while let next = tail.child {
54+
tail = next
55+
}
56+
return tail
5457
}
5558

5659
/**

Sources/Leaf/Stem+Spawn.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ extension Stem {
1212
}
1313

1414
public func spawnLeaf(named name: String) throws -> Leaf {
15-
if let existing = cache[name] { return existing }
15+
if let existing = cache?[name] { return existing }
1616

1717
var subpath = name.finished(with: SUFFIX)
1818
if subpath.hasPrefix("/") {

Sources/Leaf/Stem.swift

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
public final class Stem {
22
public let workingDirectory: String
33
public fileprivate(set) var tags: [String: Tag] = defaultTags
4-
public fileprivate(set) var cache: [String: Leaf] = [:]
4+
public fileprivate(set) var cache: [String: Leaf]?
55

6-
public init(workingDirectory: String) {
6+
public init(workingDirectory: String, cache: [String: Leaf]? = [:]) {
77
self.workingDirectory = workingDirectory.finished(with: "/")
8+
self.cache = cache
89
}
910
}
1011

1112
extension Stem {
1213
public func cache(_ leaf: Leaf, named name: String) {
13-
cache[name] = leaf
14+
cache?[name] = leaf
1415
}
1516
}
1617

Sources/Leaf/Tag/BasicTag.swift

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
public protocol BasicTag: Tag {
2+
func run(arguments: [Argument]) throws -> Node?
3+
}
4+
5+
extension BasicTag {
6+
public func run(
7+
stem: Stem,
8+
context: Context,
9+
tagTemplate: TagTemplate,
10+
arguments: [Argument]
11+
) throws -> Node? {
12+
return try run(arguments: arguments)
13+
}
14+
}

Sources/Leaf/Tag/Models/Include.swift Sources/Leaf/Tag/Models/Embed.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
public final class Include: Tag {
1+
public final class Embed: Tag {
22
public enum Error: LeafError {
33
case expectedSingleConstant(have: [Parameter])
44
}
55

6-
public let name = "include"
6+
public let name = "embed"
77

88
public func postCompile(
99
stem: Stem,

Sources/Leaf/Tag/Models/Index.swift

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
public class Index: BasicTag {
2+
public let name = "index"
3+
4+
public func run(arguments: [Argument]) throws -> Node? {
5+
guard
6+
arguments.count == 2,
7+
let array = arguments[0].value?.nodeArray,
8+
let index = arguments[1].value?.int,
9+
index < array.count
10+
else { return nil }
11+
return array[index]
12+
}
13+
}

Sources/Leaf/Tag/TagTemplate.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ extension TagTemplate {
3333
return parameters.map { arg in
3434
switch arg {
3535
case let .variable(path: path):
36-
let value = context[path]
36+
let value = context.get(path: path)
3737
return .variable(path: path, value: value)
3838
case let .constant(c):
3939
return .constant(value: c)

Tests/LeafTests/EmbedTests.swift

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import Foundation
2+
import XCTest
3+
@testable import Leaf
4+
5+
class EmbedTests: XCTestCase {
6+
static let allTests = [
7+
("testBasicEmbed", testBasicEmbed),
8+
("testEmbedThrow", testEmbedThrow),
9+
]
10+
11+
func testBasicEmbed() throws {
12+
let template = try stem.spawnLeaf(named: "/embed-base")
13+
let context = Context(["name": "World"])
14+
let rendered = try stem.render(template, with: context).string
15+
let expectation = "Leaf embedded: Hello, World!"
16+
XCTAssert(rendered == expectation, "have: \(rendered) want: \(expectation)")
17+
}
18+
19+
func testEmbedThrow() throws {
20+
do {
21+
_ = try stem.spawnLeaf(raw: "#embed(invalid-variable)")
22+
XCTFail("Expected throw")
23+
} catch Embed.Error.expectedSingleConstant { }
24+
}
25+
}

Tests/LeafTests/IncludeTests.swift

-26
This file was deleted.

Tests/LeafTests/IndexTests.swift

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import Foundation
2+
import XCTest
3+
@testable import Leaf
4+
5+
class IndexTests: XCTestCase {
6+
static let allTests = [
7+
("testBasicIndex", testBasicIndex),
8+
("testOutOfBounds", testOutOfBounds)
9+
]
10+
11+
func testBasicIndex() throws {
12+
let template = try stem.spawnLeaf(raw: "Hello, #index(friends, idx)!")
13+
let context = Context(["friends": ["Joe", "Jan", "Jay", "Jen"], "idx": 3])
14+
let rendered = try stem.render(template, with: context).string
15+
let expectation = "Hello, Jen!"
16+
XCTAssertEqual(rendered, expectation)
17+
}
18+
19+
func testOutOfBounds() throws {
20+
let template = try stem.spawnLeaf(raw: "Hello, #index(friends, idx)!")
21+
let context = Context(["friends": [], "idx": 3])
22+
let rendered = try stem.render(template, with: context).string
23+
let expectation = "Hello, !"
24+
XCTAssertEqual(rendered, expectation)
25+
}
26+
}

Tests/LeafTests/PerformanceTests.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class PerformanceTests: XCTestCase {
2727
let ctxt = Context(["name": "World"])
2828
measure {
2929
(1...500).forEach { _ in
30-
_ = ctxt["name"]
30+
_ = ctxt.get(path: ["name"])
3131
}
3232
}
3333
}

Tests/LeafTests/TagTemplateTests.swift

+7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ class TagTemplateTests: XCTestCase {
88
("testEquatable", testEquatable),
99
("testChainFail", testChainFail),
1010
("testMissingOpenParens", testMissingOpenParens),
11+
("testEquatableComponents", testEquatableComponents),
1112
]
1213

1314
func testBasic() throws {
@@ -45,6 +46,12 @@ class TagTemplateTests: XCTestCase {
4546
XCTAssertFalse(other == rhs)
4647
}
4748

49+
func testEquatableComponents() throws {
50+
let lhs = Leaf.Component.raw("raw".bytes)
51+
let rhs = Leaf.Component.chain([])
52+
XCTAssertNotEqual(lhs, rhs)
53+
}
54+
4855
func testChainFail() throws {
4956
do {
5057
_ = try stem.spawnLeaf(raw: "##else() {}")

Tests/LinuxMain.swift

+9-8
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,18 @@ import XCTest
22
@testable import LeafTests
33

44
XCTMain([
5-
testCase(PerformanceTests.allTests),
5+
testCase(BufferTests.allTests),
66
testCase(ContextTests.allTests),
7+
testCase(EmbedTests.allTests),
8+
testCase(IfTests.allTests),
9+
testCase(IndexTests.allTests),
710
testCase(LinkTests.allTests),
8-
testCase(TagTemplateTests.allTests),
11+
testCase(LoopTests.allTests),
912
testCase(NodeRenderTests.allTests),
10-
testCase(BufferTests.allTests),
11-
testCase(IncludeTests.allTests),
12-
testCase(RenderTests.allTests),
1313
testCase(ParameterTests.allTests),
14-
testCase(LoopTests.allTests),
15-
testCase(IfTests.allTests),
16-
testCase(VariableTests.allTests),
14+
testCase(PerformanceTests.allTests),
15+
testCase(RenderTests.allTests),
16+
testCase(TagTemplateTests.allTests),
1717
testCase(UppercasedTests.allTests),
18+
testCase(VariableTests.allTests),
1819
])

0 commit comments

Comments
 (0)