factoring out http things
This commit is contained in:
parent
f83944926a
commit
c9612fdd7c
|
@ -1,34 +1,17 @@
|
||||||
// swift-tools-version:4.0
|
// swift-tools-version:4.0
|
||||||
//
|
// Generated automatically by Perfect Assistant
|
||||||
// Package.swift
|
// Date: 2018-05-31 18:31:13 +0000
|
||||||
// PerfectMustache
|
|
||||||
//
|
|
||||||
// Created by Kyle Jessup on 2016-05-02.
|
|
||||||
// Copyright (C) 2016 PerfectlySoft, Inc.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This source file is part of the Perfect.org open source project
|
|
||||||
//
|
|
||||||
// Copyright (c) 2015 - 2018 PerfectlySoft Inc. and the Perfect project authors
|
|
||||||
// Licensed under Apache License v2.0
|
|
||||||
//
|
|
||||||
// See http://perfect.org/licensing.html for license information
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
|
|
||||||
import PackageDescription
|
import PackageDescription
|
||||||
let package = Package(name: "PerfectMustache",
|
|
||||||
products: [.library(name: "PerfectMustache",targets: ["PerfectMustache"]),],
|
let package = Package(
|
||||||
dependencies: [
|
name: "PerfectMustache",
|
||||||
.package(url: "https://github.com/PerfectlySoft/Perfect-HTTP.git", from: "3.0.0"),
|
products: [
|
||||||
|
.library(name: "PerfectMustache", targets: ["PerfectMustache"])
|
||||||
],
|
],
|
||||||
targets: [
|
dependencies: [
|
||||||
.target(
|
],
|
||||||
name: "PerfectMustache",
|
targets: [
|
||||||
dependencies: ["PerfectHTTP"]),
|
.target(name: "PerfectMustache", dependencies: []),
|
||||||
.testTarget(
|
.testTarget(name: "PerfectMustacheTests", dependencies: ["PerfectMustache"])
|
||||||
name: "PerfectMustacheTests",
|
]
|
||||||
dependencies: ["PerfectMustache"]),
|
)
|
||||||
])
|
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
//
|
|
||||||
// HTTPResponseExtension.swift
|
|
||||||
// PerfectMustache
|
|
||||||
//
|
|
||||||
// Created by Jonathan Guthrie on 2017-08-01.
|
|
||||||
// Copyright (C) 2017 PerfectlySoft, Inc.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This source file is part of the Perfect.org open source project
|
|
||||||
//
|
|
||||||
// Copyright (c) 2015 - 2016 PerfectlySoft Inc. and the Perfect project authors
|
|
||||||
// Licensed under Apache License v2.0
|
|
||||||
//
|
|
||||||
// See http://perfect.org/licensing.html for license information
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
|
|
||||||
import PerfectHTTP
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
extension HTTPResponse {
|
|
||||||
public func renderMustache(template: String, context values: [String: Any] = [String: Any]()) {
|
|
||||||
let context = MustacheEvaluationContext(templatePath: template)
|
|
||||||
let collector = MustacheEvaluationOutputCollector()
|
|
||||||
context.extendValues(with: values)
|
|
||||||
do {
|
|
||||||
let d = try context.formulateResponse(withCollector: collector)
|
|
||||||
self.setBody(string: d)
|
|
||||||
.completed()
|
|
||||||
} catch {
|
|
||||||
self.setBody(string: "\(error)")
|
|
||||||
.completed(status: .internalServerError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -19,8 +19,6 @@
|
||||||
|
|
||||||
import PerfectThread
|
import PerfectThread
|
||||||
import PerfectLib
|
import PerfectLib
|
||||||
import PerfectHTTP
|
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
let mustacheExtension = "mustache"
|
let mustacheExtension = "mustache"
|
||||||
|
@ -89,57 +87,25 @@ public enum MustacheError : Error {
|
||||||
case evaluationError(String)
|
case evaluationError(String)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A mustache handler, which should be passed to `mustacheRequest`, generates values to fill a mustache template.
|
|
||||||
/// Call `context.extendValues(with: values)` one or more times and then
|
|
||||||
/// `context.requestCompleted(withCollector collector)` to complete the request and output the resulting content to the client.
|
|
||||||
public protocol MustachePageHandler {
|
|
||||||
/// Called by the system when the handler needs to add values for the template.
|
|
||||||
func extendValuesForResponse(context contxt: MustacheWebEvaluationContext, collector: MustacheEvaluationOutputCollector)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Convenience function to begin a mustache template request
|
|
||||||
|
|
||||||
```swift
|
|
||||||
routes.add(method: .get, uri: "/", handler: {
|
|
||||||
request, response in
|
|
||||||
mustacheRequest(request: request, response: response, handler: UploadHandler(), path: webRoot + "/index.mustache")
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
*/
|
|
||||||
public func mustacheRequest(request req: HTTPRequest, response: HTTPResponse, handler: MustachePageHandler, templatePath: String) {
|
|
||||||
|
|
||||||
let context = MustacheWebEvaluationContext(webResponse: response)
|
|
||||||
context.templatePath = templatePath
|
|
||||||
let collector = MustacheEvaluationOutputCollector()
|
|
||||||
|
|
||||||
handler.extendValuesForResponse(context: context, collector: collector)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This class represents an individual scope for mustache template values.
|
/// This class represents an individual scope for mustache template values.
|
||||||
/// A mustache template handler will return a `MustacheEvaluationContext.MapType` object as a result from its `PageHandler.valuesForResponse` function.
|
/// A mustache template handler will return a `MustacheEvaluationContext.MapType` object as a result from its `PageHandler.valuesForResponse` function.
|
||||||
public class MustacheEvaluationContext {
|
public class MustacheEvaluationContext {
|
||||||
|
var mapValues: MapType
|
||||||
|
|
||||||
public typealias MapType = [String:Any]
|
public typealias MapType = [String:Any]
|
||||||
public typealias SequenceType = [MapType]
|
public typealias SequenceType = [MapType]
|
||||||
|
|
||||||
/// The parent of this context
|
/// The parent of this context
|
||||||
public var parent: MustacheEvaluationContext? = nil
|
public var parent: MustacheEvaluationContext? = nil
|
||||||
|
|
||||||
/// Complete path to the file being processed
|
/// Complete path to the file being processed
|
||||||
public var templatePath: String?
|
public var templatePath: String?
|
||||||
|
|
||||||
/// Mustache content for dynamic generation
|
/// Mustache content for dynamic generation
|
||||||
public var templateContent: String?
|
public var templateContent: String?
|
||||||
|
|
||||||
/// Returns the name of the current template file.
|
/// Returns the name of the current template file.
|
||||||
public var templateName: String? {
|
public var templateName: String? {
|
||||||
let nam = templatePath?.lastFilePathComponent
|
let nam = templatePath?.lastFilePathComponent
|
||||||
return nam
|
return nam
|
||||||
}
|
}
|
||||||
|
|
||||||
var mapValues: MapType
|
|
||||||
|
|
||||||
public init(templatePath: String, map: MapType = MapType()) {
|
public init(templatePath: String, map: MapType = MapType()) {
|
||||||
self.templatePath = templatePath
|
self.templatePath = templatePath
|
||||||
self.mapValues = map
|
self.mapValues = map
|
||||||
|
@ -196,7 +162,6 @@ public class MustacheEvaluationContext {
|
||||||
/// - returns: The value, if found, or nil
|
/// - returns: The value, if found, or nil
|
||||||
public func getValue(named nam: String) -> MapType.Value? {
|
public func getValue(named nam: String) -> MapType.Value? {
|
||||||
let values = nam.components(separatedBy: ".")
|
let values = nam.components(separatedBy: ".")
|
||||||
|
|
||||||
var cntxt: MapType.Value? = mapValues
|
var cntxt: MapType.Value? = mapValues
|
||||||
for val in values {
|
for val in values {
|
||||||
guard let prev = cntxt as? MapType else {
|
guard let prev = cntxt as? MapType else {
|
||||||
|
@ -204,7 +169,6 @@ public class MustacheEvaluationContext {
|
||||||
}
|
}
|
||||||
cntxt = prev[val]
|
cntxt = prev[val]
|
||||||
}
|
}
|
||||||
|
|
||||||
let v = cntxt
|
let v = cntxt
|
||||||
if v == nil && parent != nil {
|
if v == nil && parent != nil {
|
||||||
return parent?.getValue(named: nam)
|
return parent?.getValue(named: nam)
|
||||||
|
@ -231,48 +195,6 @@ public class MustacheEvaluationContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This class represents an individual scope for mustache template values.
|
|
||||||
/// A mustache template handler will return a `MustacheWebEvaluationContext.MapType` object as a result from its `PageHandler.valuesForResponse` function.
|
|
||||||
public class MustacheWebEvaluationContext: MustacheEvaluationContext {
|
|
||||||
|
|
||||||
/// Provides access to the current HTTPResponse object.
|
|
||||||
public var webResponse: HTTPResponse
|
|
||||||
|
|
||||||
/// Provides access to the current HTTPRequest object.
|
|
||||||
public var webRequest: HTTPRequest {
|
|
||||||
return webResponse.request
|
|
||||||
}
|
|
||||||
|
|
||||||
init(webResponse: HTTPResponse, templatePath: String, map: MapType = MapType()) {
|
|
||||||
self.webResponse = webResponse
|
|
||||||
super.init(templatePath: templatePath, map: map)
|
|
||||||
}
|
|
||||||
|
|
||||||
init(webResponse: HTTPResponse, map: MapType = MapType()) {
|
|
||||||
self.webResponse = webResponse
|
|
||||||
super.init(map: map)
|
|
||||||
}
|
|
||||||
|
|
||||||
override func newChildContext() -> MustacheEvaluationContext {
|
|
||||||
let cc = MustacheWebEvaluationContext(webResponse: webResponse)
|
|
||||||
cc.parent = self
|
|
||||||
return cc
|
|
||||||
}
|
|
||||||
|
|
||||||
override func newChildContext(withMap with: MapType) -> MustacheEvaluationContext {
|
|
||||||
let cc = MustacheWebEvaluationContext(webResponse: webResponse, map: with)
|
|
||||||
cc.parent = self
|
|
||||||
return cc
|
|
||||||
}
|
|
||||||
|
|
||||||
/// All the template values have been completed and resulting content should be
|
|
||||||
/// formulated and returned to the client.
|
|
||||||
public func requestCompleted(withCollector collector: MustacheEvaluationOutputCollector) throws {
|
|
||||||
self.webResponse.appendBody(string: try self.formulateResponse(withCollector: collector))
|
|
||||||
self.webResponse.completed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An instance of this class will collect all output data generated by mustache tags during evaluation.
|
/// An instance of this class will collect all output data generated by mustache tags during evaluation.
|
||||||
/// Call the `asString()` function to retreive the resulting data.
|
/// Call the `asString()` function to retreive the resulting data.
|
||||||
public class MustacheEvaluationOutputCollector {
|
public class MustacheEvaluationOutputCollector {
|
||||||
|
@ -368,11 +290,9 @@ public class MustacheTag {
|
||||||
/// Reconstitutes the tag into its original source string form.
|
/// Reconstitutes the tag into its original source string form.
|
||||||
/// - returns: The resulting string, including the original delimiters and tag-type marker.
|
/// - returns: The resulting string, including the original delimiters and tag-type marker.
|
||||||
public func description() -> String {
|
public func description() -> String {
|
||||||
|
|
||||||
guard type != .plain else {
|
guard type != .plain else {
|
||||||
return tag
|
return tag
|
||||||
}
|
}
|
||||||
|
|
||||||
var s = delimOpen()
|
var s = delimOpen()
|
||||||
switch type {
|
switch type {
|
||||||
case .name:
|
case .name:
|
||||||
|
@ -406,7 +326,6 @@ public class MustacheTag {
|
||||||
|
|
||||||
/// A sub-class of MustacheTag which represents a mustache "partial" tag.
|
/// A sub-class of MustacheTag which represents a mustache "partial" tag.
|
||||||
public class MustachePartialTag : MustacheTag {
|
public class MustachePartialTag : MustacheTag {
|
||||||
|
|
||||||
override func clone() -> MustacheTag {
|
override func clone() -> MustacheTag {
|
||||||
let s = MustachePartialTag()
|
let s = MustachePartialTag()
|
||||||
self.populateClone(s)
|
self.populateClone(s)
|
||||||
|
@ -415,7 +334,6 @@ public class MustachePartialTag : MustacheTag {
|
||||||
|
|
||||||
/// Override for evaluating the partial tag.
|
/// Override for evaluating the partial tag.
|
||||||
public override func evaluate(context contxt: MustacheEvaluationContext, collector: MustacheEvaluationOutputCollector) {
|
public override func evaluate(context contxt: MustacheEvaluationContext, collector: MustacheEvaluationOutputCollector) {
|
||||||
|
|
||||||
guard let page = contxt.getCurrentFilePath(), !page.isEmpty else {
|
guard let page = contxt.getCurrentFilePath(), !page.isEmpty else {
|
||||||
print("Exception while executing partial \(tag): unable to find template root directory")
|
print("Exception while executing partial \(tag): unable to find template root directory")
|
||||||
return
|
return
|
||||||
|
@ -673,21 +591,17 @@ public class MustacheParser {
|
||||||
/// - throws: `MustacheError.SyntaxError`
|
/// - throws: `MustacheError.SyntaxError`
|
||||||
/// - returns: A `MustacheTemplate` object which can be evaluated.
|
/// - returns: A `MustacheTemplate` object which can be evaluated.
|
||||||
public func parse(string strng: String) throws -> MustacheTemplate {
|
public func parse(string strng: String) throws -> MustacheTemplate {
|
||||||
|
|
||||||
let t = MustacheTemplate()
|
let t = MustacheTemplate()
|
||||||
self.activeList = t
|
self.activeList = t
|
||||||
self.g = strng.unicodeScalars.makeIterator()
|
self.g = strng.unicodeScalars.makeIterator()
|
||||||
|
|
||||||
try consumeLoop()
|
try consumeLoop()
|
||||||
|
|
||||||
t.pragmas = pragmas
|
t.pragmas = pragmas
|
||||||
|
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func next() -> UnicodeScalar? {
|
func next() -> UnicodeScalar? {
|
||||||
offset += 1
|
offset += 1
|
||||||
return g!.next()
|
return g?.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
func consumeLoop() throws {
|
func consumeLoop() throws {
|
||||||
|
@ -712,24 +626,19 @@ public class MustacheParser {
|
||||||
func addChild(_ t: MustacheTag) {
|
func addChild(_ t: MustacheTag) {
|
||||||
self.activeList!.children.append(t)
|
self.activeList!.children.append(t)
|
||||||
t.parent = self.activeList!
|
t.parent = self.activeList!
|
||||||
|
|
||||||
t.openD = openDelimiters
|
t.openD = openDelimiters
|
||||||
t.closeD = closeDelimiters
|
t.closeD = closeDelimiters
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read until delimiters are encountered
|
// Read until delimiters are encountered
|
||||||
func consumePlain() -> MustacheTagType {
|
func consumePlain() -> MustacheTagType {
|
||||||
|
|
||||||
let currTag = MustacheTag()
|
let currTag = MustacheTag()
|
||||||
currTag.type = .plain
|
currTag.type = .plain
|
||||||
|
|
||||||
addChild(currTag)
|
addChild(currTag)
|
||||||
|
|
||||||
while true {
|
while true {
|
||||||
guard let e = next() else {
|
guard let e = next() else {
|
||||||
return .none
|
return .none
|
||||||
}
|
}
|
||||||
|
|
||||||
if e == openDelimiters[0] {
|
if e == openDelimiters[0] {
|
||||||
testingPutback = String(e)
|
testingPutback = String(e)
|
||||||
if consumePossibleOpenDelimiter(index: 1) {
|
if consumePossibleOpenDelimiter(index: 1) {
|
||||||
|
@ -770,12 +679,10 @@ public class MustacheParser {
|
||||||
|
|
||||||
// Read until delimiters are encountered
|
// Read until delimiters are encountered
|
||||||
func consumeTag() throws -> MustacheTagType {
|
func consumeTag() throws -> MustacheTagType {
|
||||||
|
|
||||||
if let e = skipWhiteSpace() {
|
if let e = skipWhiteSpace() {
|
||||||
// e is first non-white character
|
// e is first non-white character
|
||||||
// # ^ ! >
|
// # ^ ! >
|
||||||
switch e {
|
switch e {
|
||||||
|
|
||||||
case "%": // pragma
|
case "%": // pragma
|
||||||
let tagName = consumeTagName(firstChar: skipWhiteSpace())
|
let tagName = consumeTagName(firstChar: skipWhiteSpace())
|
||||||
let newTag = MustachePragmaTag()
|
let newTag = MustachePragmaTag()
|
||||||
|
@ -862,11 +769,9 @@ public class MustacheParser {
|
||||||
// reads until closing delimiters
|
// reads until closing delimiters
|
||||||
// firstChar was read as part of previous step and should be added to the result
|
// firstChar was read as part of previous step and should be added to the result
|
||||||
func consumeTagName(firstChar first: UnicodeScalar?) -> String {
|
func consumeTagName(firstChar first: UnicodeScalar?) -> String {
|
||||||
|
|
||||||
guard let f = first else {
|
guard let f = first else {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
var s = String(f)
|
var s = String(f)
|
||||||
return consumeTagName(into: &s)
|
return consumeTagName(into: &s)
|
||||||
}
|
}
|
||||||
|
@ -970,4 +875,3 @@ public class MustacheParser {
|
||||||
closeDelimiters = close
|
closeDelimiters = close
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,51 +1,7 @@
|
||||||
import XCTest
|
import XCTest
|
||||||
import PerfectHTTP
|
|
||||||
import PerfectNet
|
|
||||||
import PerfectLib
|
import PerfectLib
|
||||||
@testable import PerfectMustache
|
@testable import PerfectMustache
|
||||||
|
|
||||||
class ShimHTTPRequest: HTTPRequest {
|
|
||||||
var pathComponents: [String] = []
|
|
||||||
|
|
||||||
var method = HTTPMethod.get
|
|
||||||
var path = "/"
|
|
||||||
var queryParams = [(String, String)]()
|
|
||||||
var protocolVersion = (1, 1)
|
|
||||||
var remoteAddress = (host: "127.0.0.1", port: 8000 as UInt16)
|
|
||||||
var serverAddress = (host: "127.0.0.1", port: 8282 as UInt16)
|
|
||||||
var serverName = "my_server"
|
|
||||||
var documentRoot = "./webroot"
|
|
||||||
var connection = NetTCP()
|
|
||||||
var urlVariables = [String:String]()
|
|
||||||
func header(_ named: HTTPRequestHeader.Name) -> String? { return nil }
|
|
||||||
func addHeader(_ named: HTTPRequestHeader.Name, value: String) {}
|
|
||||||
func setHeader(_ named: HTTPRequestHeader.Name, value: String) {}
|
|
||||||
var headers = AnyIterator<(HTTPRequestHeader.Name, String)> { return nil }
|
|
||||||
var postParams = [(String, String)]()
|
|
||||||
var postBodyBytes: [UInt8]? = nil
|
|
||||||
var postBodyString: String? = nil
|
|
||||||
var postFileUploads: [MimeReader.BodySpec]? = nil
|
|
||||||
var scratchPad = [String:Any]()
|
|
||||||
}
|
|
||||||
|
|
||||||
class ShimHTTPResponse: HTTPResponse {
|
|
||||||
func next() {}
|
|
||||||
var request: HTTPRequest = ShimHTTPRequest()
|
|
||||||
var status: HTTPResponseStatus = .ok
|
|
||||||
var isStreaming = false
|
|
||||||
var bodyBytes = [UInt8]()
|
|
||||||
func header(_ named: HTTPResponseHeader.Name) -> String? { return nil }
|
|
||||||
func addHeader(_ named: HTTPResponseHeader.Name, value: String) -> Self { return self }
|
|
||||||
func setHeader(_ named: HTTPResponseHeader.Name, value: String) -> Self { return self }
|
|
||||||
var headers = AnyIterator<(HTTPResponseHeader.Name, String)> { return nil }
|
|
||||||
func addCookie(_: PerfectHTTP.HTTPCookie) {}
|
|
||||||
func appendBody(bytes: [UInt8]) {}
|
|
||||||
func appendBody(string: String) {}
|
|
||||||
func setBody(json: [String:Any]) throws {}
|
|
||||||
func push(callback: @escaping (Bool) -> ()) {}
|
|
||||||
func completed() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
class PerfectMustacheTests: XCTestCase {
|
class PerfectMustacheTests: XCTestCase {
|
||||||
|
|
||||||
func testMustacheParser1() {
|
func testMustacheParser1() {
|
||||||
|
@ -54,9 +10,7 @@ class PerfectMustacheTests: XCTestCase {
|
||||||
let template = try MustacheParser().parse(string: usingTemplate)
|
let template = try MustacheParser().parse(string: usingTemplate)
|
||||||
let d = ["name":"The name"] as [String:Any]
|
let d = ["name":"The name"] as [String:Any]
|
||||||
|
|
||||||
let response = ShimHTTPResponse()
|
let context = MustacheEvaluationContext(map: d)
|
||||||
|
|
||||||
let context = MustacheWebEvaluationContext(webResponse: response, map: d)
|
|
||||||
let collector = MustacheEvaluationOutputCollector()
|
let collector = MustacheEvaluationOutputCollector()
|
||||||
template.evaluate(context: context, collector: collector)
|
template.evaluate(context: context, collector: collector)
|
||||||
|
|
||||||
|
@ -73,9 +27,7 @@ class PerfectMustacheTests: XCTestCase {
|
||||||
let template = try MustacheParser().parse(string: usingTemplate)
|
let template = try MustacheParser().parse(string: usingTemplate)
|
||||||
let d = ["name":{ (tag:String, context:MustacheEvaluationContext) -> String in return nameVal }] as [String:Any]
|
let d = ["name":{ (tag:String, context:MustacheEvaluationContext) -> String in return nameVal }] as [String:Any]
|
||||||
|
|
||||||
let response = ShimHTTPResponse()
|
let context = MustacheEvaluationContext(map: d)
|
||||||
|
|
||||||
let context = MustacheWebEvaluationContext(webResponse: response, map: d)
|
|
||||||
let collector = MustacheEvaluationOutputCollector()
|
let collector = MustacheEvaluationOutputCollector()
|
||||||
template.evaluate(context: context, collector: collector)
|
template.evaluate(context: context, collector: collector)
|
||||||
|
|
||||||
|
@ -174,9 +126,7 @@ class PerfectMustacheTests: XCTestCase {
|
||||||
let template = try MustacheParser().parse(string: usingTemplate)
|
let template = try MustacheParser().parse(string: usingTemplate)
|
||||||
let d = ["name": ["first": "The", "last": "name"]] as [String:Any]
|
let d = ["name": ["first": "The", "last": "name"]] as [String:Any]
|
||||||
|
|
||||||
let response = ShimHTTPResponse()
|
let context = MustacheEvaluationContext(map: d)
|
||||||
|
|
||||||
let context = MustacheWebEvaluationContext(webResponse: response, map: d)
|
|
||||||
let collector = MustacheEvaluationOutputCollector()
|
let collector = MustacheEvaluationOutputCollector()
|
||||||
template.evaluate(context: context, collector: collector)
|
template.evaluate(context: context, collector: collector)
|
||||||
|
|
||||||
|
@ -192,9 +142,7 @@ class PerfectMustacheTests: XCTestCase {
|
||||||
let template = try MustacheParser().parse(string: usingTemplate)
|
let template = try MustacheParser().parse(string: usingTemplate)
|
||||||
let d = ["foo": ["data": ["name": ["first": "The", "last": "name"]]]] as [String:Any]
|
let d = ["foo": ["data": ["name": ["first": "The", "last": "name"]]]] as [String:Any]
|
||||||
|
|
||||||
let response = ShimHTTPResponse()
|
let context = MustacheEvaluationContext(map: d)
|
||||||
|
|
||||||
let context = MustacheWebEvaluationContext(webResponse: response, map: d)
|
|
||||||
let collector = MustacheEvaluationOutputCollector()
|
let collector = MustacheEvaluationOutputCollector()
|
||||||
template.evaluate(context: context, collector: collector)
|
template.evaluate(context: context, collector: collector)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue