Add HBMustacheCustomRenderable
Support custom rendering of swift types Fixes tests that rely on NSNull
This commit is contained in:
2
.dockerignore
Normal file
2
.dockerignore
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
.build
|
||||||
|
.git
|
||||||
29
Sources/HummingbirdMustache/CustomRenderable.swift
Normal file
29
Sources/HummingbirdMustache/CustomRenderable.swift
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This source file is part of the Hummingbird server framework project
|
||||||
|
//
|
||||||
|
// Copyright (c) 2021-2021 the Hummingbird authors
|
||||||
|
// Licensed under Apache License v2.0
|
||||||
|
//
|
||||||
|
// See LICENSE.txt for license information
|
||||||
|
// See hummingbird/CONTRIBUTORS.txt for the list of Hummingbird authors
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
protocol HBMustacheCustomRenderable {
|
||||||
|
var renderText: String { get }
|
||||||
|
var isNull: Bool { get }
|
||||||
|
}
|
||||||
|
|
||||||
|
extension HBMustacheCustomRenderable {
|
||||||
|
var renderText: String { String(describing: self) }
|
||||||
|
var isNull: Bool { false }
|
||||||
|
}
|
||||||
|
|
||||||
|
extension NSNull: HBMustacheCustomRenderable {
|
||||||
|
public var renderText: String { "" }
|
||||||
|
public var isNull: Bool { true }
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
import Foundation
|
||||||
|
|
||||||
extension HBMustacheTemplate {
|
extension HBMustacheTemplate {
|
||||||
/// Render template using object
|
/// Render template using object
|
||||||
@@ -46,14 +47,20 @@ extension HBMustacheTemplate {
|
|||||||
if let child = getChild(named: variable, transform: transform, context: context) {
|
if let child = getChild(named: variable, transform: transform, context: context) {
|
||||||
if let template = child as? HBMustacheTemplate {
|
if let template = child as? HBMustacheTemplate {
|
||||||
return template.render(context: context)
|
return template.render(context: context)
|
||||||
|
} else if let renderable = child as? HBMustacheCustomRenderable {
|
||||||
|
return context.contentType.escapeText(renderable.renderText)
|
||||||
} else {
|
} else {
|
||||||
return context.contentType.escapeText(String(describing: child))
|
return context.contentType.escapeText(String(describing: child))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case .unescapedVariable(let variable, let transform):
|
case .unescapedVariable(let variable, let transform):
|
||||||
if let child = getChild(named: variable, transform: transform, context: context) {
|
if let child = getChild(named: variable, transform: transform, context: context) {
|
||||||
|
if let renderable = child as? HBMustacheCustomRenderable {
|
||||||
|
return renderable.renderText
|
||||||
|
} else {
|
||||||
return String(describing: child)
|
return String(describing: child)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
case .section(let variable, let transform, let template):
|
case .section(let variable, let transform, let template):
|
||||||
let child = self.getChild(named: variable, transform: transform, context: context)
|
let child = self.getChild(named: variable, transform: transform, context: context)
|
||||||
return self.renderSection(child, with: template, context: context)
|
return self.renderSection(child, with: template, context: context)
|
||||||
@@ -94,6 +101,8 @@ extension HBMustacheTemplate {
|
|||||||
return bool ? template.render(context: context) : ""
|
return bool ? template.render(context: context) : ""
|
||||||
case let lambda as HBMustacheLambda:
|
case let lambda as HBMustacheLambda:
|
||||||
return lambda.run(context.stack.last!, template)
|
return lambda.run(context.stack.last!, template)
|
||||||
|
case let null as HBMustacheCustomRenderable where null.isNull == true:
|
||||||
|
return ""
|
||||||
case .some(let value):
|
case .some(let value):
|
||||||
return template.render(context: context.withObject(value))
|
return template.render(context: context.withObject(value))
|
||||||
case .none:
|
case .none:
|
||||||
@@ -113,6 +122,8 @@ extension HBMustacheTemplate {
|
|||||||
return array.renderInvertedSection(with: template, context: context)
|
return array.renderInvertedSection(with: template, context: context)
|
||||||
case let bool as Bool:
|
case let bool as Bool:
|
||||||
return bool ? "" : template.render(context: context)
|
return bool ? "" : template.render(context: context)
|
||||||
|
case let null as HBMustacheCustomRenderable where null.isNull == true:
|
||||||
|
return template.render(context: context)
|
||||||
case .some:
|
case .some:
|
||||||
return ""
|
return ""
|
||||||
case .none:
|
case .none:
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ import XCTest
|
|||||||
public struct AnyDecodable: Decodable {
|
public struct AnyDecodable: Decodable {
|
||||||
public let value: Any
|
public let value: Any
|
||||||
|
|
||||||
public init<T>(_ value: T?) {
|
public init<T>(_ value: T) {
|
||||||
self.value = value ?? ()
|
self.value = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,11 +32,7 @@ public extension AnyDecodable {
|
|||||||
let container = try decoder.singleValueContainer()
|
let container = try decoder.singleValueContainer()
|
||||||
|
|
||||||
if container.decodeNil() {
|
if container.decodeNil() {
|
||||||
#if canImport(Foundation)
|
|
||||||
self.init(NSNull())
|
self.init(NSNull())
|
||||||
#else
|
|
||||||
self.init(Self?.none)
|
|
||||||
#endif
|
|
||||||
} else if let bool = try? container.decode(Bool.self) {
|
} else if let bool = try? container.decode(Bool.self) {
|
||||||
self.init(bool)
|
self.init(bool)
|
||||||
} else if let int = try? container.decode(Int.self) {
|
} else if let int = try? container.decode(Int.self) {
|
||||||
|
|||||||
Reference in New Issue
Block a user