From 4a78d44712c511c070e43971abd732b40d6dc94a Mon Sep 17 00:00:00 2001 From: Adam Fowler Date: Mon, 3 May 2021 15:33:28 +0100 Subject: [PATCH] Add HBMustacheCustomRenderable Support custom rendering of swift types Fixes tests that rely on NSNull --- .dockerignore | 2 ++ .../CustomRenderable.swift | 29 +++++++++++++++++++ .../HummingbirdMustache/Template+Render.swift | 13 ++++++++- .../HummingbirdMustacheTests/SpecTests.swift | 8 ++--- 4 files changed, 45 insertions(+), 7 deletions(-) create mode 100644 .dockerignore create mode 100644 Sources/HummingbirdMustache/CustomRenderable.swift diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..2fb3343 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +.build +.git \ No newline at end of file diff --git a/Sources/HummingbirdMustache/CustomRenderable.swift b/Sources/HummingbirdMustache/CustomRenderable.swift new file mode 100644 index 0000000..dfdb0fb --- /dev/null +++ b/Sources/HummingbirdMustache/CustomRenderable.swift @@ -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 } +} diff --git a/Sources/HummingbirdMustache/Template+Render.swift b/Sources/HummingbirdMustache/Template+Render.swift index 3df4c69..d85f7ad 100644 --- a/Sources/HummingbirdMustache/Template+Render.swift +++ b/Sources/HummingbirdMustache/Template+Render.swift @@ -11,6 +11,7 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// +import Foundation extension HBMustacheTemplate { /// Render template using object @@ -46,13 +47,19 @@ extension HBMustacheTemplate { if let child = getChild(named: variable, transform: transform, context: context) { if let template = child as? HBMustacheTemplate { return template.render(context: context) + } else if let renderable = child as? HBMustacheCustomRenderable { + return context.contentType.escapeText(renderable.renderText) } else { return context.contentType.escapeText(String(describing: child)) } } case .unescapedVariable(let variable, let transform): if let child = getChild(named: variable, transform: transform, context: context) { - return String(describing: child) + if let renderable = child as? HBMustacheCustomRenderable { + return renderable.renderText + } else { + return String(describing: child) + } } case .section(let variable, let transform, let template): let child = self.getChild(named: variable, transform: transform, context: context) @@ -94,6 +101,8 @@ extension HBMustacheTemplate { return bool ? template.render(context: context) : "" case let lambda as HBMustacheLambda: return lambda.run(context.stack.last!, template) + case let null as HBMustacheCustomRenderable where null.isNull == true: + return "" case .some(let value): return template.render(context: context.withObject(value)) case .none: @@ -113,6 +122,8 @@ extension HBMustacheTemplate { return array.renderInvertedSection(with: template, context: context) case let bool as Bool: return bool ? "" : template.render(context: context) + case let null as HBMustacheCustomRenderable where null.isNull == true: + return template.render(context: context) case .some: return "" case .none: diff --git a/Tests/HummingbirdMustacheTests/SpecTests.swift b/Tests/HummingbirdMustacheTests/SpecTests.swift index 9fc5258..9954da0 100644 --- a/Tests/HummingbirdMustacheTests/SpecTests.swift +++ b/Tests/HummingbirdMustacheTests/SpecTests.swift @@ -22,8 +22,8 @@ import XCTest public struct AnyDecodable: Decodable { public let value: Any - public init(_ value: T?) { - self.value = value ?? () + public init(_ value: T) { + self.value = value } } @@ -32,11 +32,7 @@ public extension AnyDecodable { let container = try decoder.singleValueContainer() if container.decodeNil() { - #if canImport(Foundation) self.init(NSNull()) - #else - self.init(Self?.none) - #endif } else if let bool = try? container.decode(Bool.self) { self.init(bool) } else if let int = try? container.decode(Int.self) {