Remove HB prefix, make Parser private (#26)
This commit is contained in:
14
README.md
14
README.md
@@ -8,7 +8,7 @@ While Hummingbird Mustache has been designed to be used with the Hummingbird ser
|
||||
|
||||
Load your templates from the filesystem
|
||||
```swift
|
||||
let library = HBMustacheLibrary("folder/my/templates/are/in")
|
||||
let library = MustacheLibrary("folder/my/templates/are/in")
|
||||
```
|
||||
This will look for all the files with the extension ".mustache" in the specified folder and subfolders and attempt to load them. Each file is registed with the name of the file (with subfolder, if inside a subfolder) minus the "mustache" extension.
|
||||
|
||||
@@ -20,23 +20,23 @@ let output = library.render(object, withTemplate: "myTemplate")
|
||||
|
||||
### Using with Hummingbird
|
||||
|
||||
HummingbirdMustache doesn't have any integration with Hummingbird as I wanted to keep the library dependency free. But if you are going to use the library with Hummingbird it is recommended you extend `HBApplication` to store an instance of your library.
|
||||
HummingbirdMustache doesn't have any integration with Hummingbird as I wanted to keep the library dependency free. But if you are going to use the library with Hummingbird it is recommended you extend `Application` to store an instance of your library.
|
||||
|
||||
```swift
|
||||
extension HBApplication {
|
||||
var mustache: HBMustacheLibrary {
|
||||
extension Application {
|
||||
var mustache: MustacheLibrary {
|
||||
get { self.extensions.get(\.mustache) }
|
||||
set { self.extensions.set(\.mustache, value: newValue) }
|
||||
}
|
||||
}
|
||||
|
||||
extension HBRequest {
|
||||
var mustache: HBMustacheLibrary { self.application.mustache }
|
||||
extension Request {
|
||||
var mustache: MustacheLibrary { self.application.mustache }
|
||||
}
|
||||
// load mustache templates from templates folder
|
||||
application.mustache = try .init(directory: "templates")
|
||||
```
|
||||
You can now access your mustache templates via `HBRequest` eg `HBRequest.mustache.render(obj, withTemplate: "myTemplate")`
|
||||
You can now access your mustache templates via `Request` eg `Request.mustache.render(obj, withTemplate: "myTemplate")`
|
||||
|
||||
## Support
|
||||
|
||||
|
||||
@@ -13,20 +13,20 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Protocol for content types
|
||||
public protocol HBMustacheContentType: Sendable {
|
||||
public protocol MustacheContentType: Sendable {
|
||||
/// escape text for this content type eg for HTML replace "<" with "<"
|
||||
func escapeText(_ text: String) -> String
|
||||
}
|
||||
|
||||
/// Text content type where no character is escaped
|
||||
struct HBTextContentType: HBMustacheContentType {
|
||||
struct TextContentType: MustacheContentType {
|
||||
func escapeText(_ text: String) -> String {
|
||||
return text
|
||||
}
|
||||
}
|
||||
|
||||
/// HTML content where text is escaped for HTML output
|
||||
struct HBHTMLContentType: HBMustacheContentType {
|
||||
struct HTMLContentType: MustacheContentType {
|
||||
func escapeText(_ text: String) -> String {
|
||||
return text.htmlEscape()
|
||||
}
|
||||
@@ -36,9 +36,9 @@ struct HBHTMLContentType: HBMustacheContentType {
|
||||
///
|
||||
/// The string is read from the "CONTENT_TYPE" pragma `{{% CONTENT_TYPE: type}}`. Replace type with
|
||||
/// the content type required. The default available types are `TEXT` and `HTML`. You can register your own
|
||||
/// with `HBMustacheContentTypes.register`.
|
||||
public enum HBMustacheContentTypes {
|
||||
static func get(_ name: String) -> HBMustacheContentType? {
|
||||
/// with `MustacheContentTypes.register`.
|
||||
public enum MustacheContentTypes {
|
||||
static func get(_ name: String) -> MustacheContentType? {
|
||||
return self.types[name]
|
||||
}
|
||||
|
||||
@@ -46,12 +46,12 @@ public enum HBMustacheContentTypes {
|
||||
/// - Parameters:
|
||||
/// - contentType: Content type
|
||||
/// - name: String to identify it
|
||||
public static func register(_ contentType: HBMustacheContentType, named name: String) {
|
||||
public static func register(_ contentType: MustacheContentType, named name: String) {
|
||||
self.types[name] = contentType
|
||||
}
|
||||
|
||||
static var types: [String: HBMustacheContentType] = [
|
||||
"HTML": HBHTMLContentType(),
|
||||
"TEXT": HBTextContentType(),
|
||||
static var types: [String: MustacheContentType] = [
|
||||
"HTML": HTMLContentType(),
|
||||
"TEXT": TextContentType(),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -13,31 +13,31 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Context while rendering mustache tokens
|
||||
struct HBMustacheContext {
|
||||
struct MustacheContext {
|
||||
let stack: [Any]
|
||||
let sequenceContext: HBMustacheSequenceContext?
|
||||
let sequenceContext: MustacheSequenceContext?
|
||||
let indentation: String?
|
||||
let inherited: [String: HBMustacheTemplate]?
|
||||
let contentType: HBMustacheContentType
|
||||
let library: HBMustacheLibrary?
|
||||
let inherited: [String: MustacheTemplate]?
|
||||
let contentType: MustacheContentType
|
||||
let library: MustacheLibrary?
|
||||
|
||||
/// initialize context with a single objectt
|
||||
init(_ object: Any, library: HBMustacheLibrary? = nil) {
|
||||
init(_ object: Any, library: MustacheLibrary? = nil) {
|
||||
self.stack = [object]
|
||||
self.sequenceContext = nil
|
||||
self.indentation = nil
|
||||
self.inherited = nil
|
||||
self.contentType = HBHTMLContentType()
|
||||
self.contentType = HTMLContentType()
|
||||
self.library = library
|
||||
}
|
||||
|
||||
private init(
|
||||
stack: [Any],
|
||||
sequenceContext: HBMustacheSequenceContext?,
|
||||
sequenceContext: MustacheSequenceContext?,
|
||||
indentation: String?,
|
||||
inherited: [String: HBMustacheTemplate]?,
|
||||
contentType: HBMustacheContentType,
|
||||
library: HBMustacheLibrary? = nil
|
||||
inherited: [String: MustacheTemplate]?,
|
||||
contentType: MustacheContentType,
|
||||
library: MustacheLibrary? = nil
|
||||
) {
|
||||
self.stack = stack
|
||||
self.sequenceContext = sequenceContext
|
||||
@@ -48,7 +48,7 @@ struct HBMustacheContext {
|
||||
}
|
||||
|
||||
/// return context with object add to stack
|
||||
func withObject(_ object: Any) -> HBMustacheContext {
|
||||
func withObject(_ object: Any) -> MustacheContext {
|
||||
var stack = self.stack
|
||||
stack.append(object)
|
||||
return .init(
|
||||
@@ -62,13 +62,13 @@ struct HBMustacheContext {
|
||||
}
|
||||
|
||||
/// return context with indent and parameter information for invoking a partial
|
||||
func withPartial(indented: String?, inheriting: [String: HBMustacheTemplate]?) -> HBMustacheContext {
|
||||
func withPartial(indented: String?, inheriting: [String: MustacheTemplate]?) -> MustacheContext {
|
||||
let indentation: String? = if let indented {
|
||||
(self.indentation ?? "") + indented
|
||||
} else {
|
||||
self.indentation
|
||||
}
|
||||
let inherits: [String: HBMustacheTemplate]? = if let inheriting {
|
||||
let inherits: [String: MustacheTemplate]? = if let inheriting {
|
||||
if let originalInherits = self.inherited {
|
||||
originalInherits.merging(inheriting) { value, _ in value }
|
||||
} else {
|
||||
@@ -82,13 +82,13 @@ struct HBMustacheContext {
|
||||
sequenceContext: nil,
|
||||
indentation: indentation,
|
||||
inherited: inherits,
|
||||
contentType: HBHTMLContentType(),
|
||||
contentType: HTMLContentType(),
|
||||
library: self.library
|
||||
)
|
||||
}
|
||||
|
||||
/// return context with sequence info and sequence element added to stack
|
||||
func withSequence(_ object: Any, sequenceContext: HBMustacheSequenceContext) -> HBMustacheContext {
|
||||
func withSequence(_ object: Any, sequenceContext: MustacheSequenceContext) -> MustacheContext {
|
||||
var stack = self.stack
|
||||
stack.append(object)
|
||||
return .init(
|
||||
@@ -102,7 +102,7 @@ struct HBMustacheContext {
|
||||
}
|
||||
|
||||
/// return context with sequence info and sequence element added to stack
|
||||
func withContentType(_ contentType: HBMustacheContentType) -> HBMustacheContext {
|
||||
func withContentType(_ contentType: MustacheContentType) -> MustacheContext {
|
||||
return .init(
|
||||
stack: self.stack,
|
||||
sequenceContext: self.sequenceContext,
|
||||
|
||||
@@ -16,23 +16,23 @@ import Foundation
|
||||
|
||||
/// Allow object to override standard hummingbird type rendering which uses
|
||||
/// `String(describing)`.
|
||||
public protocol HBMustacheCustomRenderable {
|
||||
public protocol MustacheCustomRenderable {
|
||||
/// Custom rendered version of object
|
||||
var renderText: String { get }
|
||||
/// Whether the object is a null object. Used when scoping sections
|
||||
var isNull: Bool { get }
|
||||
}
|
||||
|
||||
extension HBMustacheCustomRenderable {
|
||||
extension MustacheCustomRenderable {
|
||||
/// default version returning the standard rendering
|
||||
var renderText: String { String(describing: self) }
|
||||
/// default version returning false
|
||||
var isNull: Bool { false }
|
||||
}
|
||||
|
||||
/// Extend NSNull to conform to `HBMustacheCustomRenderable` to avoid outputting `<null>` and returning
|
||||
/// Extend NSNull to conform to `MustacheCustomRenderable` to avoid outputting `<null>` and returning
|
||||
/// a valid response for `isNull`
|
||||
extension NSNull: HBMustacheCustomRenderable {
|
||||
extension NSNull: MustacheCustomRenderable {
|
||||
public var renderText: String { "" }
|
||||
public var isNull: Bool { true }
|
||||
}
|
||||
|
||||
38
Sources/HummingbirdMustache/Deprecations.swift
Normal file
38
Sources/HummingbirdMustache/Deprecations.swift
Normal file
@@ -0,0 +1,38 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Hummingbird server framework project
|
||||
//
|
||||
// Copyright (c) 2024 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Below is a list of deprecated symbols with the "HB" prefix. These are available
|
||||
// temporarily to ease transition from the old symbols that included the "HB"
|
||||
// prefix to the new ones.
|
||||
//
|
||||
// This file will be removed before we do a 2.0 release
|
||||
|
||||
@_documentation(visibility: internal) @available(*, deprecated, renamed: "MustacheContentType")
|
||||
public typealias HBMustacheContentType = MustacheContentType
|
||||
@_documentation(visibility: internal) @available(*, deprecated, renamed: "MustacheContentTypes")
|
||||
public typealias HBMustacheContentTypes = MustacheContentTypes
|
||||
@_documentation(visibility: internal) @available(*, deprecated, renamed: "MustacheCustomRenderable")
|
||||
public typealias HBMustacheCustomRenderable = MustacheCustomRenderable
|
||||
@_documentation(visibility: internal) @available(*, deprecated, renamed: "MustacheLambda")
|
||||
public typealias HBMustacheLambda = MustacheLambda
|
||||
@_documentation(visibility: internal) @available(*, deprecated, renamed: "MustacheLibrary")
|
||||
public typealias HBMustacheLibrary = MustacheLibrary
|
||||
@_documentation(visibility: internal) @available(*, deprecated, renamed: "MustacheParent")
|
||||
public typealias HBMustacheParent = MustacheParent
|
||||
@_documentation(visibility: internal) @available(*, deprecated, renamed: "MustacheParserContext")
|
||||
public typealias HBMustacheParserContext = MustacheParserContext
|
||||
@_documentation(visibility: internal) @available(*, deprecated, renamed: "MustacheTemplate")
|
||||
public typealias HBMustacheTemplate = MustacheTemplate
|
||||
@_documentation(visibility: internal) @available(*, deprecated, renamed: "MustacheTransformable")
|
||||
public typealias HBMustacheTransformable = MustacheTransformable
|
||||
@@ -21,30 +21,30 @@
|
||||
/// ```
|
||||
/// struct Object {
|
||||
/// let name: String
|
||||
/// let wrapped: HBMustacheLambda
|
||||
/// let wrapped: MustacheLambda
|
||||
/// }
|
||||
/// let willy = Object(name: "Willy", wrapped: .init({ object, template in
|
||||
/// return "<b>\(template.render(object))</b>"
|
||||
/// }))
|
||||
/// let mustache = "{{#wrapped}}{{name}} is awesome.{{/wrapped}}"
|
||||
/// let template = try HBMustacheTemplate(string: mustache)
|
||||
/// let template = try MustacheTemplate(string: mustache)
|
||||
/// let output = template.render(willy)
|
||||
/// print(output) // <b>Willy is awesome</b>
|
||||
/// ```
|
||||
///
|
||||
public struct HBMustacheLambda {
|
||||
public struct MustacheLambda {
|
||||
/// lambda callback
|
||||
public typealias Callback = (Any, HBMustacheTemplate) -> String
|
||||
public typealias Callback = (Any, MustacheTemplate) -> String
|
||||
|
||||
let callback: Callback
|
||||
|
||||
/// Initialize `HBMustacheLambda`
|
||||
/// Initialize `MustacheLambda`
|
||||
/// - Parameter cb: function to be called by lambda
|
||||
public init(_ cb: @escaping Callback) {
|
||||
self.callback = cb
|
||||
}
|
||||
|
||||
internal func run(_ object: Any, _ template: HBMustacheTemplate) -> String {
|
||||
internal func run(_ object: Any, _ template: MustacheTemplate) -> String {
|
||||
return self.callback(object, template)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
extension HBMustacheLibrary {
|
||||
extension MustacheLibrary {
|
||||
/// Load templates from a folder
|
||||
static func loadTemplates(from directory: String, withExtension extension: String = "mustache") async throws -> [String: HBMustacheTemplate] {
|
||||
static func loadTemplates(from directory: String, withExtension extension: String = "mustache") async throws -> [String: MustacheTemplate] {
|
||||
var directory = directory
|
||||
if !directory.hasSuffix("/") {
|
||||
directory += "/"
|
||||
@@ -24,15 +24,15 @@ extension HBMustacheLibrary {
|
||||
let extWithDot = ".\(`extension`)"
|
||||
let fs = FileManager()
|
||||
guard let enumerator = fs.enumerator(atPath: directory) else { return [:] }
|
||||
var templates: [String: HBMustacheTemplate] = [:]
|
||||
var templates: [String: MustacheTemplate] = [:]
|
||||
for case let path as String in enumerator {
|
||||
guard path.hasSuffix(extWithDot) else { continue }
|
||||
guard let data = fs.contents(atPath: directory + path) else { continue }
|
||||
let string = String(decoding: data, as: Unicode.UTF8.self)
|
||||
var template: HBMustacheTemplate
|
||||
var template: MustacheTemplate
|
||||
do {
|
||||
template = try HBMustacheTemplate(string: string)
|
||||
} catch let error as HBMustacheTemplate.ParserError {
|
||||
template = try MustacheTemplate(string: string)
|
||||
} catch let error as MustacheTemplate.ParserError {
|
||||
throw ParserError(filename: path, context: error.context, error: error.error)
|
||||
}
|
||||
// drop ".mustache" from path to get name
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
/// ```
|
||||
/// {{#sequence}}{{>entry}}{{/sequence}}
|
||||
/// ```
|
||||
public struct HBMustacheLibrary: Sendable {
|
||||
public struct MustacheLibrary: Sendable {
|
||||
/// Initialize empty library
|
||||
public init() {
|
||||
self.templates = [:]
|
||||
@@ -30,7 +30,7 @@ public struct HBMustacheLibrary: Sendable {
|
||||
/// the folder is recursive and templates in subfolders will be registered with the name `subfolder/template`.
|
||||
/// - Parameter directory: Directory to look for mustache templates
|
||||
/// - Parameter extension: Extension of files to look for
|
||||
public init(templates: [String: HBMustacheTemplate]) {
|
||||
public init(templates: [String: MustacheTemplate]) {
|
||||
self.templates = templates
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public struct HBMustacheLibrary: Sendable {
|
||||
/// - Parameters:
|
||||
/// - template: Template
|
||||
/// - name: Name of template
|
||||
public mutating func register(_ template: HBMustacheTemplate, named name: String) {
|
||||
public mutating func register(_ template: MustacheTemplate, named name: String) {
|
||||
self.templates[name] = template
|
||||
}
|
||||
|
||||
@@ -57,14 +57,14 @@ public struct HBMustacheLibrary: Sendable {
|
||||
/// - mustache: Mustache text
|
||||
/// - name: Name of template
|
||||
public mutating func register(_ mustache: String, named name: String) throws {
|
||||
let template = try HBMustacheTemplate(string: mustache)
|
||||
let template = try MustacheTemplate(string: mustache)
|
||||
self.templates[name] = template
|
||||
}
|
||||
|
||||
/// Return template registed with name
|
||||
/// - Parameter name: name to search for
|
||||
/// - Returns: Template
|
||||
public func getTemplate(named name: String) -> HBMustacheTemplate? {
|
||||
public func getTemplate(named name: String) -> MustacheTemplate? {
|
||||
self.templates[name]
|
||||
}
|
||||
|
||||
@@ -83,10 +83,10 @@ public struct HBMustacheLibrary: Sendable {
|
||||
/// File error occurred in
|
||||
public let filename: String
|
||||
/// Context (line, linenumber and column number)
|
||||
public let context: HBParser.Context
|
||||
public let context: MustacheParserContext
|
||||
/// Actual error that occurred
|
||||
public let error: Error
|
||||
}
|
||||
|
||||
private var templates: [String: HBMustacheTemplate]
|
||||
private var templates: [String: MustacheTemplate]
|
||||
}
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
|
||||
/// Protocol for object that has a custom method for accessing their children, instead
|
||||
/// of using Mirror
|
||||
public protocol HBMustacheParent {
|
||||
public protocol MustacheParent {
|
||||
func child(named: String) -> Any?
|
||||
}
|
||||
|
||||
/// Extend dictionary where the key is a string so that it uses the key values to access
|
||||
/// it values
|
||||
extension Dictionary: HBMustacheParent where Key == String {
|
||||
extension Dictionary: MustacheParent where Key == String {
|
||||
public func child(named: String) -> Any? { return self[named] }
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
import Foundation
|
||||
|
||||
/// Reader object for parsing String buffers
|
||||
public struct HBParser {
|
||||
struct Parser {
|
||||
enum Error: Swift.Error {
|
||||
case overflow
|
||||
}
|
||||
@@ -42,12 +42,12 @@ public struct HBParser {
|
||||
private(set) var position: String.Index
|
||||
}
|
||||
|
||||
extension HBParser {
|
||||
extension Parser {
|
||||
/// Return current character
|
||||
/// - Throws: .overflow
|
||||
/// - Returns: Current character
|
||||
mutating func character() throws -> Character {
|
||||
guard !self.reachedEnd() else { throw HBParser.Error.overflow }
|
||||
guard !self.reachedEnd() else { throw Parser.Error.overflow }
|
||||
let c = unsafeCurrent()
|
||||
unsafeAdvance()
|
||||
return c
|
||||
@@ -93,7 +93,7 @@ extension HBParser {
|
||||
/// - Throws: .overflow
|
||||
/// - Returns: The string read from the buffer
|
||||
mutating func read(count: Int) throws -> Substring {
|
||||
guard self.buffer.distance(from: self.position, to: self.buffer.endIndex) >= count else { throw HBParser.Error.overflow }
|
||||
guard self.buffer.distance(from: self.position, to: self.buffer.endIndex) >= count else { throw Parser.Error.overflow }
|
||||
let end = self.buffer.index(self.position, offsetBy: count)
|
||||
let subString = self.buffer[self.position..<end]
|
||||
unsafeAdvance(by: count)
|
||||
@@ -114,7 +114,7 @@ extension HBParser {
|
||||
}
|
||||
if throwOnOverflow {
|
||||
unsafeSetPosition(startIndex)
|
||||
throw HBParser.Error.overflow
|
||||
throw Parser.Error.overflow
|
||||
}
|
||||
return self.buffer[startIndex..<self.position]
|
||||
}
|
||||
@@ -170,7 +170,7 @@ extension HBParser {
|
||||
}
|
||||
if throwOnOverflow {
|
||||
unsafeSetPosition(startIndex)
|
||||
throw HBParser.Error.overflow
|
||||
throw Parser.Error.overflow
|
||||
}
|
||||
return self.buffer[startIndex..<self.position]
|
||||
}
|
||||
@@ -287,16 +287,16 @@ extension HBParser {
|
||||
}
|
||||
}
|
||||
|
||||
extension HBParser {
|
||||
/// context used in parser error
|
||||
public struct Context {
|
||||
public struct MustacheParserContext {
|
||||
public let line: String
|
||||
public let lineNumber: Int
|
||||
public let columnNumber: Int
|
||||
}
|
||||
|
||||
extension Parser {
|
||||
/// Return context of current position (line, lineNumber, columnNumber)
|
||||
func getContext() -> Context {
|
||||
func getContext() -> MustacheParserContext {
|
||||
var parser = self
|
||||
var columnNumber = 0
|
||||
while !parser.atStart() {
|
||||
@@ -316,12 +316,12 @@ extension HBParser {
|
||||
let textBefore = buffer[buffer.startIndex..<self.position]
|
||||
let lineNumber = textBefore.filter(\.isNewline).count
|
||||
|
||||
return Context(line: String(line), lineNumber: lineNumber + 1, columnNumber: columnNumber + 1)
|
||||
return MustacheParserContext(line: String(line), lineNumber: lineNumber + 1, columnNumber: columnNumber + 1)
|
||||
}
|
||||
}
|
||||
|
||||
/// Public versions of internal functions which include tests for overflow
|
||||
extension HBParser {
|
||||
/// versions of internal functions which include tests for overflow
|
||||
extension Parser {
|
||||
/// Return the character at the current position
|
||||
/// - Throws: .overflow
|
||||
/// - Returns: Character
|
||||
@@ -333,14 +333,14 @@ extension HBParser {
|
||||
/// Move forward one character
|
||||
/// - Throws: .overflow
|
||||
mutating func advance() throws {
|
||||
guard !self.reachedEnd() else { throw HBParser.Error.overflow }
|
||||
guard !self.reachedEnd() else { throw Parser.Error.overflow }
|
||||
return unsafeAdvance()
|
||||
}
|
||||
|
||||
/// Move back one character
|
||||
/// - Throws: .overflow
|
||||
mutating func retreat() throws {
|
||||
guard self.position != self.buffer.startIndex else { throw HBParser.Error.overflow }
|
||||
guard self.position != self.buffer.startIndex else { throw Parser.Error.overflow }
|
||||
return unsafeRetreat()
|
||||
}
|
||||
|
||||
@@ -348,7 +348,7 @@ extension HBParser {
|
||||
/// - Parameter amount: number of characters to move forward
|
||||
/// - Throws: .overflow
|
||||
mutating func advance(by amount: Int) throws {
|
||||
guard self.buffer.distance(from: self.position, to: self.buffer.endIndex) >= amount else { throw HBParser.Error.overflow }
|
||||
guard self.buffer.distance(from: self.position, to: self.buffer.endIndex) >= amount else { throw Parser.Error.overflow }
|
||||
return unsafeAdvance(by: amount)
|
||||
}
|
||||
|
||||
@@ -356,18 +356,18 @@ extension HBParser {
|
||||
/// - Parameter amount: number of characters to move back
|
||||
/// - Throws: .overflow
|
||||
mutating func retreat(by amount: Int) throws {
|
||||
guard self.buffer.distance(from: self.buffer.startIndex, to: self.position) >= amount else { throw HBParser.Error.overflow }
|
||||
guard self.buffer.distance(from: self.buffer.startIndex, to: self.position) >= amount else { throw Parser.Error.overflow }
|
||||
return unsafeRetreat(by: amount)
|
||||
}
|
||||
|
||||
mutating func setPosition(_ position: String.Index) throws {
|
||||
guard position <= self.buffer.endIndex else { throw HBParser.Error.overflow }
|
||||
guard position <= self.buffer.endIndex else { throw Parser.Error.overflow }
|
||||
unsafeSetPosition(position)
|
||||
}
|
||||
}
|
||||
|
||||
// unsafe versions without checks
|
||||
extension HBParser {
|
||||
extension Parser {
|
||||
func unsafeCurrent() -> Character {
|
||||
return self.buffer[self.position]
|
||||
}
|
||||
|
||||
@@ -13,18 +13,18 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Protocol for objects that can be rendered as a sequence in Mustache
|
||||
protocol HBMustacheSequence {
|
||||
protocol MustacheSequence {
|
||||
/// Render section using template
|
||||
func renderSection(with template: HBMustacheTemplate, context: HBMustacheContext) -> String
|
||||
func renderSection(with template: MustacheTemplate, context: MustacheContext) -> String
|
||||
/// Render inverted section using template
|
||||
func renderInvertedSection(with template: HBMustacheTemplate, context: HBMustacheContext) -> String
|
||||
func renderInvertedSection(with template: MustacheTemplate, context: MustacheContext) -> String
|
||||
}
|
||||
|
||||
extension Sequence {
|
||||
/// Render section using template
|
||||
func renderSection(with template: HBMustacheTemplate, context: HBMustacheContext) -> String {
|
||||
func renderSection(with template: MustacheTemplate, context: MustacheContext) -> String {
|
||||
var string = ""
|
||||
var sequenceContext = HBMustacheSequenceContext(first: true)
|
||||
var sequenceContext = MustacheSequenceContext(first: true)
|
||||
|
||||
var iterator = makeIterator()
|
||||
guard var currentObject = iterator.next() else { return "" }
|
||||
@@ -43,7 +43,7 @@ extension Sequence {
|
||||
}
|
||||
|
||||
/// Render inverted section using template
|
||||
func renderInvertedSection(with template: HBMustacheTemplate, context: HBMustacheContext) -> String {
|
||||
func renderInvertedSection(with template: MustacheTemplate, context: MustacheContext) -> String {
|
||||
var iterator = makeIterator()
|
||||
if iterator.next() == nil {
|
||||
return template.render(context: context.withObject(self))
|
||||
@@ -52,6 +52,6 @@ extension Sequence {
|
||||
}
|
||||
}
|
||||
|
||||
extension Array: HBMustacheSequence {}
|
||||
extension Set: HBMustacheSequence {}
|
||||
extension ReversedCollection: HBMustacheSequence {}
|
||||
extension Array: MustacheSequence {}
|
||||
extension Set: MustacheSequence {}
|
||||
extension ReversedCollection: MustacheSequence {}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Context that current object inside a sequence is being rendered in. Only relevant when rendering a sequence
|
||||
struct HBMustacheSequenceContext: HBMustacheTransformable {
|
||||
struct MustacheSequenceContext: MustacheTransformable {
|
||||
var first: Bool
|
||||
var last: Bool
|
||||
var index: Int
|
||||
@@ -24,7 +24,7 @@ struct HBMustacheSequenceContext: HBMustacheTransformable {
|
||||
self.index = 0
|
||||
}
|
||||
|
||||
/// Transform `HBMustacheContext`. These are available when processing elements
|
||||
/// Transform `MustacheContext`. These are available when processing elements
|
||||
/// of a sequence.
|
||||
///
|
||||
/// Format your mustache as follows to accept them. They look like a function without any arguments
|
||||
|
||||
@@ -12,14 +12,14 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
extension HBMustacheTemplate {
|
||||
/// Error return by `HBMustacheTemplate.parse`. Includes information about where error occurred
|
||||
extension MustacheTemplate {
|
||||
/// Error return by `MustacheTemplate.parse`. Includes information about where error occurred
|
||||
public struct ParserError: Swift.Error {
|
||||
public let context: HBParser.Context
|
||||
public let context: MustacheParserContext
|
||||
public let error: Swift.Error
|
||||
}
|
||||
|
||||
/// Error generated by `HBMustacheTemplate.parse`
|
||||
/// Error generated by `MustacheTemplate.parse`
|
||||
public enum Error: Swift.Error {
|
||||
/// the end section does not match the name of the start section
|
||||
case sectionCloseNameIncorrect
|
||||
@@ -72,7 +72,7 @@ extension HBMustacheTemplate {
|
||||
|
||||
/// parse mustache text to generate a list of tokens
|
||||
static func parse(_ string: String) throws -> [Token] {
|
||||
var parser = HBParser(string)
|
||||
var parser = Parser(string)
|
||||
do {
|
||||
return try self.parse(&parser, state: .init())
|
||||
} catch {
|
||||
@@ -81,7 +81,7 @@ extension HBMustacheTemplate {
|
||||
}
|
||||
|
||||
/// parse section in mustache text
|
||||
static func parse(_ parser: inout HBParser, state: ParserState) throws -> [Token] {
|
||||
static func parse(_ parser: inout Parser, state: ParserState) throws -> [Token] {
|
||||
var tokens: [Token] = []
|
||||
var state = state
|
||||
var whiteSpaceBefore: Substring = ""
|
||||
@@ -122,7 +122,7 @@ extension HBMustacheTemplate {
|
||||
whiteSpaceBefore = ""
|
||||
}
|
||||
let sectionTokens = try parse(&parser, state: state.withSectionName(name, transform: transform))
|
||||
tokens.append(.section(name: name, transform: transform, template: HBMustacheTemplate(sectionTokens)))
|
||||
tokens.append(.section(name: name, transform: transform, template: MustacheTemplate(sectionTokens)))
|
||||
|
||||
case "^":
|
||||
// inverted section
|
||||
@@ -135,7 +135,7 @@ extension HBMustacheTemplate {
|
||||
whiteSpaceBefore = ""
|
||||
}
|
||||
let sectionTokens = try parse(&parser, state: state.withSectionName(name, transform: transform))
|
||||
tokens.append(.invertedSection(name: name, transform: transform, template: HBMustacheTemplate(sectionTokens)))
|
||||
tokens.append(.invertedSection(name: name, transform: transform, template: MustacheTemplate(sectionTokens)))
|
||||
|
||||
case "$":
|
||||
// inherited section
|
||||
@@ -150,7 +150,7 @@ extension HBMustacheTemplate {
|
||||
whiteSpaceBefore = ""
|
||||
}
|
||||
let sectionTokens = try parse(&parser, state: state.withSectionName(name, transform: transform))
|
||||
tokens.append(.inheritedSection(name: name, template: HBMustacheTemplate(sectionTokens)))
|
||||
tokens.append(.inheritedSection(name: name, template: MustacheTemplate(sectionTokens)))
|
||||
|
||||
case "/":
|
||||
// end of section
|
||||
@@ -224,7 +224,7 @@ extension HBMustacheTemplate {
|
||||
whiteSpaceBefore = ""
|
||||
}
|
||||
let sectionTokens = try parse(&parser, state: state.withSectionName(name))
|
||||
var inherit: [String: HBMustacheTemplate] = [:]
|
||||
var inherit: [String: MustacheTemplate] = [:]
|
||||
// parse tokens in section to extract inherited sections
|
||||
for token in sectionTokens {
|
||||
switch token {
|
||||
@@ -271,7 +271,7 @@ extension HBMustacheTemplate {
|
||||
}
|
||||
|
||||
/// read until we hit either the start delimiter of a tag or a newline
|
||||
static func readUntilDelimiterOrNewline(_ parser: inout HBParser, state: ParserState) throws -> String {
|
||||
static func readUntilDelimiterOrNewline(_ parser: inout Parser, state: ParserState) throws -> String {
|
||||
var untilSet: Set<Character> = ["\n", "\r\n"]
|
||||
guard let delimiterFirstChar = state.startDelimiter.first else { return "" }
|
||||
var totalText = ""
|
||||
@@ -296,14 +296,14 @@ extension HBMustacheTemplate {
|
||||
}
|
||||
|
||||
/// parse variable name
|
||||
static func parseName(_ parser: inout HBParser, state: ParserState) throws -> (String, String?) {
|
||||
static func parseName(_ parser: inout Parser, state: ParserState) throws -> (String, String?) {
|
||||
parser.read(while: \.isWhitespace)
|
||||
let text = String(parser.read(while: self.sectionNameChars))
|
||||
parser.read(while: \.isWhitespace)
|
||||
guard try parser.read(string: state.endDelimiter) else { throw Error.unfinishedName }
|
||||
|
||||
// does the name include brackets. If so this is a transform call
|
||||
var nameParser = HBParser(String(text))
|
||||
var nameParser = Parser(String(text))
|
||||
let string = nameParser.read(while: self.sectionNameCharsWithoutBrackets)
|
||||
if nameParser.reachedEnd() {
|
||||
return (text, nil)
|
||||
@@ -320,7 +320,7 @@ extension HBMustacheTemplate {
|
||||
}
|
||||
|
||||
/// parse partial name
|
||||
static func parsePartialName(_ parser: inout HBParser, state: ParserState) throws -> String {
|
||||
static func parsePartialName(_ parser: inout Parser, state: ParserState) throws -> String {
|
||||
parser.read(while: \.isWhitespace)
|
||||
let text = String(parser.read(while: self.sectionNameChars))
|
||||
parser.read(while: \.isWhitespace)
|
||||
@@ -328,12 +328,12 @@ extension HBMustacheTemplate {
|
||||
return text
|
||||
}
|
||||
|
||||
static func parseComment(_ parser: inout HBParser, state: ParserState) throws -> String {
|
||||
static func parseComment(_ parser: inout Parser, state: ParserState) throws -> String {
|
||||
let text = try parser.read(untilString: state.endDelimiter, throwOnOverflow: true, skipToEnd: true)
|
||||
return String(text)
|
||||
}
|
||||
|
||||
static func parserSetDelimiter(_ parser: inout HBParser, state: ParserState) throws -> ParserState {
|
||||
static func parserSetDelimiter(_ parser: inout Parser, state: ParserState) throws -> ParserState {
|
||||
let startDelimiter: Substring
|
||||
let endDelimiter: Substring
|
||||
|
||||
@@ -352,7 +352,7 @@ extension HBMustacheTemplate {
|
||||
return state.withDelimiters(start: String(startDelimiter), end: String(endDelimiter))
|
||||
}
|
||||
|
||||
static func readConfigVariable(_ parser: inout HBParser, state: ParserState) throws -> Token? {
|
||||
static func readConfigVariable(_ parser: inout Parser, state: ParserState) throws -> Token? {
|
||||
let variable: Substring
|
||||
let value: Substring
|
||||
|
||||
@@ -374,14 +374,14 @@ extension HBMustacheTemplate {
|
||||
|
||||
switch variable {
|
||||
case "CONTENT_TYPE":
|
||||
guard let contentType = HBMustacheContentTypes.get(String(value)) else { throw Error.unrecognisedConfigVariable }
|
||||
guard let contentType = MustacheContentTypes.get(String(value)) else { throw Error.unrecognisedConfigVariable }
|
||||
return .contentType(contentType)
|
||||
default:
|
||||
throw Error.unrecognisedConfigVariable
|
||||
}
|
||||
}
|
||||
|
||||
static func hasLineFinished(_ parser: inout HBParser) -> Bool {
|
||||
static func hasLineFinished(_ parser: inout Parser) -> Bool {
|
||||
var parser2 = parser
|
||||
if parser.reachedEnd() { return true }
|
||||
parser2.read(while: Set(" \t"))
|
||||
@@ -393,7 +393,7 @@ extension HBMustacheTemplate {
|
||||
return false
|
||||
}
|
||||
|
||||
static func isStandalone(_ parser: inout HBParser, state: ParserState) -> Bool {
|
||||
static func isStandalone(_ parser: inout Parser, state: ParserState) -> Bool {
|
||||
return state.newLine && self.hasLineFinished(&parser)
|
||||
}
|
||||
|
||||
|
||||
@@ -14,14 +14,14 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
extension HBMustacheTemplate {
|
||||
extension MustacheTemplate {
|
||||
/// Render template using object
|
||||
/// - Parameters:
|
||||
/// - stack: Object
|
||||
/// - context: Context that render is occurring in. Contains information about position in sequence
|
||||
/// - indentation: indentation of partial
|
||||
/// - Returns: Rendered text
|
||||
func render(context: HBMustacheContext) -> String {
|
||||
func render(context: MustacheContext) -> String {
|
||||
var string = ""
|
||||
var context = context
|
||||
|
||||
@@ -42,15 +42,15 @@ extension HBMustacheTemplate {
|
||||
return string
|
||||
}
|
||||
|
||||
func renderToken(_ token: Token, context: inout HBMustacheContext) -> String {
|
||||
func renderToken(_ token: Token, context: inout MustacheContext) -> String {
|
||||
switch token {
|
||||
case .text(let text):
|
||||
return text
|
||||
case .variable(let variable, let transform):
|
||||
if let child = getChild(named: variable, transform: transform, context: context) {
|
||||
if let template = child as? HBMustacheTemplate {
|
||||
if let template = child as? MustacheTemplate {
|
||||
return template.render(context: context)
|
||||
} else if let renderable = child as? HBMustacheCustomRenderable {
|
||||
} else if let renderable = child as? MustacheCustomRenderable {
|
||||
return context.contentType.escapeText(renderable.renderText)
|
||||
} else {
|
||||
return context.contentType.escapeText(String(describing: child))
|
||||
@@ -58,7 +58,7 @@ extension HBMustacheTemplate {
|
||||
}
|
||||
case .unescapedVariable(let variable, let transform):
|
||||
if let child = getChild(named: variable, transform: transform, context: context) {
|
||||
if let renderable = child as? HBMustacheCustomRenderable {
|
||||
if let renderable = child as? MustacheCustomRenderable {
|
||||
return renderable.renderText
|
||||
} else {
|
||||
return String(describing: child)
|
||||
@@ -96,15 +96,15 @@ extension HBMustacheTemplate {
|
||||
/// - parent: Current object being rendered
|
||||
/// - template: Template to render with
|
||||
/// - Returns: Rendered text
|
||||
func renderSection(_ child: Any?, with template: HBMustacheTemplate, context: HBMustacheContext) -> String {
|
||||
func renderSection(_ child: Any?, with template: MustacheTemplate, context: MustacheContext) -> String {
|
||||
switch child {
|
||||
case let array as HBMustacheSequence:
|
||||
case let array as MustacheSequence:
|
||||
return array.renderSection(with: template, context: context)
|
||||
case let bool as Bool:
|
||||
return bool ? template.render(context: context) : ""
|
||||
case let lambda as HBMustacheLambda:
|
||||
case let lambda as MustacheLambda:
|
||||
return lambda.run(context.stack.last!, template)
|
||||
case let null as HBMustacheCustomRenderable where null.isNull == true:
|
||||
case let null as MustacheCustomRenderable where null.isNull == true:
|
||||
return ""
|
||||
case .some(let value):
|
||||
return template.render(context: context.withObject(value))
|
||||
@@ -119,13 +119,13 @@ extension HBMustacheTemplate {
|
||||
/// - parent: Current object being rendered
|
||||
/// - template: Template to render with
|
||||
/// - Returns: Rendered text
|
||||
func renderInvertedSection(_ child: Any?, with template: HBMustacheTemplate, context: HBMustacheContext) -> String {
|
||||
func renderInvertedSection(_ child: Any?, with template: MustacheTemplate, context: MustacheContext) -> String {
|
||||
switch child {
|
||||
case let array as HBMustacheSequence:
|
||||
case let array as MustacheSequence:
|
||||
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:
|
||||
case let null as MustacheCustomRenderable where null.isNull == true:
|
||||
return template.render(context: context)
|
||||
case .some:
|
||||
return ""
|
||||
@@ -135,9 +135,9 @@ extension HBMustacheTemplate {
|
||||
}
|
||||
|
||||
/// Get child object from variable name
|
||||
func getChild(named name: String, transform: String?, context: HBMustacheContext) -> Any? {
|
||||
func getChild(named name: String, transform: String?, context: MustacheContext) -> Any? {
|
||||
func _getImmediateChild(named name: String, from object: Any) -> Any? {
|
||||
if let customBox = object as? HBMustacheParent {
|
||||
if let customBox = object as? MustacheParent {
|
||||
return customBox.child(named: name)
|
||||
} else {
|
||||
let mirror = Mirror(reflecting: object)
|
||||
@@ -183,7 +183,7 @@ extension HBMustacheTemplate {
|
||||
// if we want to run a transform and the current child can have transforms applied to it then
|
||||
// run transform on the current child
|
||||
if let transform {
|
||||
if let runnable = child as? HBMustacheTransformable {
|
||||
if let runnable = child as? MustacheTransformable {
|
||||
return runnable.transform(transform)
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Class holding Mustache template
|
||||
public struct HBMustacheTemplate: Sendable {
|
||||
public struct MustacheTemplate: Sendable {
|
||||
/// Initialize template
|
||||
/// - Parameter string: Template text
|
||||
/// - Throws: HBMustacheTemplate.Error
|
||||
/// - Throws: MustacheTemplate.Error
|
||||
public init(string: String) throws {
|
||||
self.tokens = try Self.parse(string)
|
||||
}
|
||||
@@ -24,7 +24,7 @@ public struct HBMustacheTemplate: Sendable {
|
||||
/// Render object using this template
|
||||
/// - Parameter object: Object to render
|
||||
/// - Returns: Rendered text
|
||||
public func render(_ object: Any, library: HBMustacheLibrary? = nil) -> String {
|
||||
public func render(_ object: Any, library: MustacheLibrary? = nil) -> String {
|
||||
self.render(context: .init(object, library: library))
|
||||
}
|
||||
|
||||
@@ -36,11 +36,11 @@ public struct HBMustacheTemplate: Sendable {
|
||||
case text(String)
|
||||
case variable(name: String, transform: String? = nil)
|
||||
case unescapedVariable(name: String, transform: String? = nil)
|
||||
case section(name: String, transform: String? = nil, template: HBMustacheTemplate)
|
||||
case invertedSection(name: String, transform: String? = nil, template: HBMustacheTemplate)
|
||||
case inheritedSection(name: String, template: HBMustacheTemplate)
|
||||
case partial(String, indentation: String?, inherits: [String: HBMustacheTemplate]?)
|
||||
case contentType(HBMustacheContentType)
|
||||
case section(name: String, transform: String? = nil, template: MustacheTemplate)
|
||||
case invertedSection(name: String, transform: String? = nil, template: MustacheTemplate)
|
||||
case inheritedSection(name: String, template: MustacheTemplate)
|
||||
case partial(String, indentation: String?, inherits: [String: MustacheTemplate]?)
|
||||
case contentType(MustacheContentType)
|
||||
}
|
||||
|
||||
var tokens: [Token]
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
/// ```
|
||||
/// {{#reversed(sequence)}}{{.}}{{\reversed(sequence)}}
|
||||
/// ```
|
||||
public protocol HBMustacheTransformable {
|
||||
public protocol MustacheTransformable {
|
||||
func transform(_ name: String) -> Any?
|
||||
}
|
||||
|
||||
@@ -55,15 +55,15 @@ public extension StringProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
extension String: HBMustacheTransformable {}
|
||||
extension Substring: HBMustacheTransformable {}
|
||||
extension String: MustacheTransformable {}
|
||||
extension Substring: MustacheTransformable {}
|
||||
|
||||
/// Protocol for sequence that can be sorted
|
||||
private protocol HBComparableSequence {
|
||||
private protocol ComparableSequence {
|
||||
func comparableTransform(_ name: String) -> Any?
|
||||
}
|
||||
|
||||
extension Array: HBMustacheTransformable {
|
||||
extension Array: MustacheTransformable {
|
||||
/// Transform Array.
|
||||
///
|
||||
/// Transforms available are `first`, `last`, `reversed`, `count` and for arrays
|
||||
@@ -83,7 +83,7 @@ extension Array: HBMustacheTransformable {
|
||||
case "empty":
|
||||
return isEmpty
|
||||
default:
|
||||
if let comparableSeq = self as? HBComparableSequence {
|
||||
if let comparableSeq = self as? ComparableSequence {
|
||||
return comparableSeq.comparableTransform(name)
|
||||
}
|
||||
return nil
|
||||
@@ -91,7 +91,7 @@ extension Array: HBMustacheTransformable {
|
||||
}
|
||||
}
|
||||
|
||||
extension Array: HBComparableSequence where Element: Comparable {
|
||||
extension Array: ComparableSequence where Element: Comparable {
|
||||
func comparableTransform(_ name: String) -> Any? {
|
||||
switch name {
|
||||
case "sorted":
|
||||
@@ -102,7 +102,7 @@ extension Array: HBComparableSequence where Element: Comparable {
|
||||
}
|
||||
}
|
||||
|
||||
extension Dictionary: HBMustacheTransformable {
|
||||
extension Dictionary: MustacheTransformable {
|
||||
/// Transform Dictionary
|
||||
///
|
||||
/// Transforms available are `count`, `enumerated` and for dictionaries
|
||||
@@ -118,7 +118,7 @@ extension Dictionary: HBMustacheTransformable {
|
||||
case "enumerated":
|
||||
return map { (key: $0.key, value: $0.value) }
|
||||
default:
|
||||
if let comparableSeq = self as? HBComparableSequence {
|
||||
if let comparableSeq = self as? ComparableSequence {
|
||||
return comparableSeq.comparableTransform(name)
|
||||
}
|
||||
return nil
|
||||
@@ -126,7 +126,7 @@ extension Dictionary: HBMustacheTransformable {
|
||||
}
|
||||
}
|
||||
|
||||
extension Dictionary: HBComparableSequence where Key: Comparable {
|
||||
extension Dictionary: ComparableSequence where Key: Comparable {
|
||||
func comparableTransform(_ name: String) -> Any? {
|
||||
switch name {
|
||||
case "sorted":
|
||||
@@ -161,13 +161,13 @@ public extension FixedWidthInteger {
|
||||
}
|
||||
}
|
||||
|
||||
extension Int: HBMustacheTransformable {}
|
||||
extension Int8: HBMustacheTransformable {}
|
||||
extension Int16: HBMustacheTransformable {}
|
||||
extension Int32: HBMustacheTransformable {}
|
||||
extension Int64: HBMustacheTransformable {}
|
||||
extension UInt: HBMustacheTransformable {}
|
||||
extension UInt8: HBMustacheTransformable {}
|
||||
extension UInt16: HBMustacheTransformable {}
|
||||
extension UInt32: HBMustacheTransformable {}
|
||||
extension UInt64: HBMustacheTransformable {}
|
||||
extension Int: MustacheTransformable {}
|
||||
extension Int8: MustacheTransformable {}
|
||||
extension Int16: MustacheTransformable {}
|
||||
extension Int32: MustacheTransformable {}
|
||||
extension Int64: MustacheTransformable {}
|
||||
extension UInt: MustacheTransformable {}
|
||||
extension UInt8: MustacheTransformable {}
|
||||
extension UInt16: MustacheTransformable {}
|
||||
extension UInt32: MustacheTransformable {}
|
||||
extension UInt64: MustacheTransformable {}
|
||||
|
||||
@@ -17,14 +17,14 @@ import XCTest
|
||||
|
||||
final class ErrorTests: XCTestCase {
|
||||
func testSectionCloseNameIncorrect() {
|
||||
XCTAssertThrowsError(try HBMustacheTemplate(string: """
|
||||
XCTAssertThrowsError(try MustacheTemplate(string: """
|
||||
{{#test}}
|
||||
{{.}}
|
||||
{{/test2}}
|
||||
""")) { error in
|
||||
switch error {
|
||||
case let error as HBMustacheTemplate.ParserError:
|
||||
XCTAssertEqual(error.error as? HBMustacheTemplate.Error, .sectionCloseNameIncorrect)
|
||||
case let error as MustacheTemplate.ParserError:
|
||||
XCTAssertEqual(error.error as? MustacheTemplate.Error, .sectionCloseNameIncorrect)
|
||||
XCTAssertEqual(error.context.line, "{{/test2}}")
|
||||
XCTAssertEqual(error.context.lineNumber, 3)
|
||||
XCTAssertEqual(error.context.columnNumber, 4)
|
||||
@@ -36,14 +36,14 @@ final class ErrorTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testUnfinishedName() {
|
||||
XCTAssertThrowsError(try HBMustacheTemplate(string: """
|
||||
XCTAssertThrowsError(try MustacheTemplate(string: """
|
||||
{{#test}}
|
||||
{{name}
|
||||
{{/test2}}
|
||||
""")) { error in
|
||||
switch error {
|
||||
case let error as HBMustacheTemplate.ParserError:
|
||||
XCTAssertEqual(error.error as? HBMustacheTemplate.Error, .unfinishedName)
|
||||
case let error as MustacheTemplate.ParserError:
|
||||
XCTAssertEqual(error.error as? MustacheTemplate.Error, .unfinishedName)
|
||||
XCTAssertEqual(error.context.line, "{{name}")
|
||||
XCTAssertEqual(error.context.lineNumber, 2)
|
||||
XCTAssertEqual(error.context.columnNumber, 7)
|
||||
@@ -55,13 +55,13 @@ final class ErrorTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testExpectedSectionEnd() {
|
||||
XCTAssertThrowsError(try HBMustacheTemplate(string: """
|
||||
XCTAssertThrowsError(try MustacheTemplate(string: """
|
||||
{{#test}}
|
||||
{{.}}
|
||||
""")) { error in
|
||||
switch error {
|
||||
case let error as HBMustacheTemplate.ParserError:
|
||||
XCTAssertEqual(error.error as? HBMustacheTemplate.Error, .expectedSectionEnd)
|
||||
case let error as MustacheTemplate.ParserError:
|
||||
XCTAssertEqual(error.error as? MustacheTemplate.Error, .expectedSectionEnd)
|
||||
XCTAssertEqual(error.context.line, "{{.}}")
|
||||
XCTAssertEqual(error.context.lineNumber, 2)
|
||||
XCTAssertEqual(error.context.columnNumber, 6)
|
||||
@@ -73,14 +73,14 @@ final class ErrorTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testInvalidSetDelimiter() {
|
||||
XCTAssertThrowsError(try HBMustacheTemplate(string: """
|
||||
XCTAssertThrowsError(try MustacheTemplate(string: """
|
||||
{{=<% %>=}}
|
||||
<%.%>
|
||||
<%={{}}=%>
|
||||
""")) { error in
|
||||
switch error {
|
||||
case let error as HBMustacheTemplate.ParserError:
|
||||
XCTAssertEqual(error.error as? HBMustacheTemplate.Error, .invalidSetDelimiter)
|
||||
case let error as MustacheTemplate.ParserError:
|
||||
XCTAssertEqual(error.error as? MustacheTemplate.Error, .invalidSetDelimiter)
|
||||
XCTAssertEqual(error.context.line, "<%={{}}=%>")
|
||||
XCTAssertEqual(error.context.lineNumber, 3)
|
||||
XCTAssertEqual(error.context.columnNumber, 4)
|
||||
|
||||
@@ -24,7 +24,7 @@ final class LibraryTests: XCTestCase {
|
||||
try mustache.write(to: URL(fileURLWithPath: "templates/test.mustache"))
|
||||
defer { XCTAssertNoThrow(try fs.removeItem(atPath: "templates/test.mustache")) }
|
||||
|
||||
let library = try await HBMustacheLibrary(directory: "./templates")
|
||||
let library = try await MustacheLibrary(directory: "./templates")
|
||||
let object = ["value": ["value1", "value2"]]
|
||||
XCTAssertEqual(library.render(object, withTemplate: "test"), "<test><value>value1</value><value>value2</value></test>")
|
||||
}
|
||||
@@ -42,7 +42,7 @@ final class LibraryTests: XCTestCase {
|
||||
XCTAssertNoThrow(try fs.removeItem(atPath: "templates"))
|
||||
}
|
||||
|
||||
let library = try await HBMustacheLibrary(directory: "./templates")
|
||||
let library = try await MustacheLibrary(directory: "./templates")
|
||||
let object = ["value": ["value1", "value2"]]
|
||||
XCTAssertEqual(library.render(object, withTemplate: "test"), "<test><value>value1</value><value>value2</value></test>")
|
||||
}
|
||||
@@ -63,8 +63,8 @@ final class LibraryTests: XCTestCase {
|
||||
defer { XCTAssertNoThrow(try fs.removeItem(atPath: "templates/error.mustache")) }
|
||||
|
||||
do {
|
||||
_ = try await HBMustacheLibrary(directory: "./templates")
|
||||
} catch let parserError as HBMustacheLibrary.ParserError {
|
||||
_ = try await MustacheLibrary(directory: "./templates")
|
||||
} catch let parserError as MustacheLibrary.ParserError {
|
||||
XCTAssertEqual(parserError.filename, "error.mustache")
|
||||
XCTAssertEqual(parserError.context.line, "{{{name}}")
|
||||
XCTAssertEqual(parserError.context.lineNumber, 2)
|
||||
|
||||
@@ -18,17 +18,17 @@ import XCTest
|
||||
final class PartialTests: XCTestCase {
|
||||
/// Testing partials
|
||||
func testMustacheManualExample9() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
<h2>Names</h2>
|
||||
{{#names}}
|
||||
{{> user}}
|
||||
{{/names}}
|
||||
""")
|
||||
let template2 = try HBMustacheTemplate(string: """
|
||||
let template2 = try MustacheTemplate(string: """
|
||||
<strong>{{.}}</strong>
|
||||
|
||||
""")
|
||||
let library = HBMustacheLibrary(templates: ["base": template, "user": template2])
|
||||
let library = MustacheLibrary(templates: ["base": template, "user": template2])
|
||||
|
||||
let object: [String: Any] = ["names": ["john", "adam", "claire"]]
|
||||
XCTAssertEqual(library.render(object, withTemplate: "base"), """
|
||||
@@ -43,7 +43,7 @@ final class PartialTests: XCTestCase {
|
||||
/// Test where last line of partial generates no content. It should not add a
|
||||
/// tab either
|
||||
func testPartialEmptyLineTabbing() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
<h2>Names</h2>
|
||||
{{#names}}
|
||||
{{> user}}
|
||||
@@ -51,7 +51,7 @@ final class PartialTests: XCTestCase {
|
||||
Text after
|
||||
|
||||
""")
|
||||
let template2 = try HBMustacheTemplate(string: """
|
||||
let template2 = try MustacheTemplate(string: """
|
||||
{{^empty(.)}}
|
||||
<strong>{{.}}</strong>
|
||||
{{/empty(.)}}
|
||||
@@ -60,9 +60,9 @@ final class PartialTests: XCTestCase {
|
||||
{{/empty(.)}}
|
||||
|
||||
""")
|
||||
var library = HBMustacheLibrary()
|
||||
var library = MustacheLibrary()
|
||||
library.register(template, named: "base")
|
||||
library.register(template2, named: "user") // , withTemplate: String)// = HBMustacheLibrary(templates: ["base": template, "user": template2])
|
||||
library.register(template2, named: "user") // , withTemplate: String)// = MustacheLibrary(templates: ["base": template, "user": template2])
|
||||
|
||||
let object: [String: Any] = ["names": ["john", "adam", "claire"]]
|
||||
XCTAssertEqual(library.render(object, withTemplate: "base"), """
|
||||
@@ -77,16 +77,16 @@ final class PartialTests: XCTestCase {
|
||||
|
||||
/// Testing dynamic partials
|
||||
func testDynamicPartials() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
<h2>Names</h2>
|
||||
{{partial}}
|
||||
""")
|
||||
let template2 = try HBMustacheTemplate(string: """
|
||||
let template2 = try MustacheTemplate(string: """
|
||||
{{#names}}
|
||||
<strong>{{.}}</strong>
|
||||
{{/names}}
|
||||
""")
|
||||
let library = HBMustacheLibrary(templates: ["base": template])
|
||||
let library = MustacheLibrary(templates: ["base": template])
|
||||
|
||||
let object: [String: Any] = ["names": ["john", "adam", "claire"], "partial": template2]
|
||||
XCTAssertEqual(library.render(object, withTemplate: "base"), """
|
||||
@@ -100,7 +100,7 @@ final class PartialTests: XCTestCase {
|
||||
|
||||
/// test inheritance
|
||||
func testInheritance() throws {
|
||||
var library = HBMustacheLibrary()
|
||||
var library = MustacheLibrary()
|
||||
try library.register(
|
||||
"""
|
||||
<head>
|
||||
|
||||
@@ -68,17 +68,17 @@ final class MustacheSpecTests: XCTestCase {
|
||||
func run() throws {
|
||||
// print("Test: \(self.name)")
|
||||
if let partials = self.partials {
|
||||
let template = try HBMustacheTemplate(string: self.template)
|
||||
var templates: [String: HBMustacheTemplate] = ["__test__": template]
|
||||
let template = try MustacheTemplate(string: self.template)
|
||||
var templates: [String: MustacheTemplate] = ["__test__": template]
|
||||
for (key, value) in partials {
|
||||
let template = try HBMustacheTemplate(string: value)
|
||||
let template = try MustacheTemplate(string: value)
|
||||
templates[key] = template
|
||||
}
|
||||
let library = HBMustacheLibrary(templates: templates)
|
||||
let library = MustacheLibrary(templates: templates)
|
||||
let result = library.render(self.data.value, withTemplate: "__test__")
|
||||
self.XCTAssertSpecEqual(result, self)
|
||||
} else {
|
||||
let template = try HBMustacheTemplate(string: self.template)
|
||||
let template = try MustacheTemplate(string: self.template)
|
||||
let result = template.render(self.data.value)
|
||||
self.XCTAssertSpecEqual(result, self)
|
||||
}
|
||||
|
||||
@@ -17,55 +17,55 @@ import XCTest
|
||||
|
||||
final class TemplateParserTests: XCTestCase {
|
||||
func testText() throws {
|
||||
let template = try HBMustacheTemplate(string: "test template")
|
||||
let template = try MustacheTemplate(string: "test template")
|
||||
XCTAssertEqual(template.tokens, [.text("test template")])
|
||||
}
|
||||
|
||||
func testVariable() throws {
|
||||
let template = try HBMustacheTemplate(string: "test {{variable}}")
|
||||
let template = try MustacheTemplate(string: "test {{variable}}")
|
||||
XCTAssertEqual(template.tokens, [.text("test "), .variable(name: "variable")])
|
||||
}
|
||||
|
||||
func testSection() throws {
|
||||
let template = try HBMustacheTemplate(string: "test {{#section}}text{{/section}}")
|
||||
let template = try MustacheTemplate(string: "test {{#section}}text{{/section}}")
|
||||
XCTAssertEqual(template.tokens, [.text("test "), .section(name: "section", template: .init([.text("text")]))])
|
||||
}
|
||||
|
||||
func testInvertedSection() throws {
|
||||
let template = try HBMustacheTemplate(string: "test {{^section}}text{{/section}}")
|
||||
let template = try MustacheTemplate(string: "test {{^section}}text{{/section}}")
|
||||
XCTAssertEqual(template.tokens, [.text("test "), .invertedSection(name: "section", template: .init([.text("text")]))])
|
||||
}
|
||||
|
||||
func testComment() throws {
|
||||
let template = try HBMustacheTemplate(string: "test {{!section}}")
|
||||
let template = try MustacheTemplate(string: "test {{!section}}")
|
||||
XCTAssertEqual(template.tokens, [.text("test ")])
|
||||
}
|
||||
|
||||
func testWhitespace() throws {
|
||||
let template = try HBMustacheTemplate(string: "{{ section }}")
|
||||
let template = try MustacheTemplate(string: "{{ section }}")
|
||||
XCTAssertEqual(template.tokens, [.variable(name: "section")])
|
||||
}
|
||||
|
||||
func testContentType() throws {
|
||||
let template = try HBMustacheTemplate(string: "{{% CONTENT_TYPE:TEXT}}")
|
||||
let template1 = try HBMustacheTemplate(string: "{{% CONTENT_TYPE:TEXT }}")
|
||||
let template2 = try HBMustacheTemplate(string: "{{% CONTENT_TYPE: TEXT}}")
|
||||
let template3 = try HBMustacheTemplate(string: "{{%CONTENT_TYPE:TEXT}}")
|
||||
XCTAssertEqual(template.tokens, [.contentType(HBTextContentType())])
|
||||
XCTAssertEqual(template1.tokens, [.contentType(HBTextContentType())])
|
||||
XCTAssertEqual(template2.tokens, [.contentType(HBTextContentType())])
|
||||
XCTAssertEqual(template3.tokens, [.contentType(HBTextContentType())])
|
||||
let template = try MustacheTemplate(string: "{{% CONTENT_TYPE:TEXT}}")
|
||||
let template1 = try MustacheTemplate(string: "{{% CONTENT_TYPE:TEXT }}")
|
||||
let template2 = try MustacheTemplate(string: "{{% CONTENT_TYPE: TEXT}}")
|
||||
let template3 = try MustacheTemplate(string: "{{%CONTENT_TYPE:TEXT}}")
|
||||
XCTAssertEqual(template.tokens, [.contentType(TextContentType())])
|
||||
XCTAssertEqual(template1.tokens, [.contentType(TextContentType())])
|
||||
XCTAssertEqual(template2.tokens, [.contentType(TextContentType())])
|
||||
XCTAssertEqual(template3.tokens, [.contentType(TextContentType())])
|
||||
}
|
||||
}
|
||||
|
||||
extension HBMustacheTemplate: Equatable {
|
||||
public static func == (lhs: HBMustacheTemplate, rhs: HBMustacheTemplate) -> Bool {
|
||||
extension MustacheTemplate: Equatable {
|
||||
public static func == (lhs: MustacheTemplate, rhs: MustacheTemplate) -> Bool {
|
||||
lhs.tokens == rhs.tokens
|
||||
}
|
||||
}
|
||||
|
||||
extension HBMustacheTemplate.Token: Equatable {
|
||||
public static func == (lhs: HBMustacheTemplate.Token, rhs: HBMustacheTemplate.Token) -> Bool {
|
||||
extension MustacheTemplate.Token: Equatable {
|
||||
public static func == (lhs: MustacheTemplate.Token, rhs: MustacheTemplate.Token) -> Bool {
|
||||
switch (lhs, rhs) {
|
||||
case (.text(let lhs), .text(let rhs)):
|
||||
return lhs == rhs
|
||||
|
||||
@@ -17,50 +17,50 @@ import XCTest
|
||||
|
||||
final class TemplateRendererTests: XCTestCase {
|
||||
func testText() throws {
|
||||
let template = try HBMustacheTemplate(string: "test text")
|
||||
let template = try MustacheTemplate(string: "test text")
|
||||
XCTAssertEqual(template.render("test"), "test text")
|
||||
}
|
||||
|
||||
func testStringVariable() throws {
|
||||
let template = try HBMustacheTemplate(string: "test {{.}}")
|
||||
let template = try MustacheTemplate(string: "test {{.}}")
|
||||
XCTAssertEqual(template.render("text"), "test text")
|
||||
}
|
||||
|
||||
func testIntegerVariable() throws {
|
||||
let template = try HBMustacheTemplate(string: "test {{.}}")
|
||||
let template = try MustacheTemplate(string: "test {{.}}")
|
||||
XCTAssertEqual(template.render(101), "test 101")
|
||||
}
|
||||
|
||||
func testDictionary() throws {
|
||||
let template = try HBMustacheTemplate(string: "test {{value}} {{bool}}")
|
||||
let template = try MustacheTemplate(string: "test {{value}} {{bool}}")
|
||||
XCTAssertEqual(template.render(["value": "test2", "bool": true]), "test test2 true")
|
||||
}
|
||||
|
||||
func testArraySection() throws {
|
||||
let template = try HBMustacheTemplate(string: "test {{#value}}*{{.}}{{/value}}")
|
||||
let template = try MustacheTemplate(string: "test {{#value}}*{{.}}{{/value}}")
|
||||
XCTAssertEqual(template.render(["value": ["test2", "bool"]]), "test *test2*bool")
|
||||
XCTAssertEqual(template.render(["value": ["test2"]]), "test *test2")
|
||||
XCTAssertEqual(template.render(["value": []]), "test ")
|
||||
}
|
||||
|
||||
func testBooleanSection() throws {
|
||||
let template = try HBMustacheTemplate(string: "test {{#.}}Yep{{/.}}")
|
||||
let template = try MustacheTemplate(string: "test {{#.}}Yep{{/.}}")
|
||||
XCTAssertEqual(template.render(true), "test Yep")
|
||||
XCTAssertEqual(template.render(false), "test ")
|
||||
}
|
||||
|
||||
func testIntegerSection() throws {
|
||||
let template = try HBMustacheTemplate(string: "test {{#.}}{{.}}{{/.}}")
|
||||
let template = try MustacheTemplate(string: "test {{#.}}{{.}}{{/.}}")
|
||||
XCTAssertEqual(template.render(23), "test 23")
|
||||
}
|
||||
|
||||
func testStringSection() throws {
|
||||
let template = try HBMustacheTemplate(string: "test {{#.}}{{.}}{{/.}}")
|
||||
let template = try MustacheTemplate(string: "test {{#.}}{{.}}{{/.}}")
|
||||
XCTAssertEqual(template.render("Hello"), "test Hello")
|
||||
}
|
||||
|
||||
func testInvertedSection() throws {
|
||||
let template = try HBMustacheTemplate(string: "test {{^.}}Inverted{{/.}}")
|
||||
let template = try MustacheTemplate(string: "test {{^.}}Inverted{{/.}}")
|
||||
XCTAssertEqual(template.render(true), "test ")
|
||||
XCTAssertEqual(template.render(false), "test Inverted")
|
||||
}
|
||||
@@ -69,7 +69,7 @@ final class TemplateRendererTests: XCTestCase {
|
||||
struct Test {
|
||||
let string: String
|
||||
}
|
||||
let template = try HBMustacheTemplate(string: "test {{string}}")
|
||||
let template = try MustacheTemplate(string: "test {{string}}")
|
||||
XCTAssertEqual(template.render(Test(string: "string")), "test string")
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ final class TemplateRendererTests: XCTestCase {
|
||||
struct Test {
|
||||
let string: String?
|
||||
}
|
||||
let template = try HBMustacheTemplate(string: "test {{string}}")
|
||||
let template = try MustacheTemplate(string: "test {{string}}")
|
||||
XCTAssertEqual(template.render(Test(string: "string")), "test string")
|
||||
XCTAssertEqual(template.render(Test(string: nil)), "test ")
|
||||
}
|
||||
@@ -86,10 +86,10 @@ final class TemplateRendererTests: XCTestCase {
|
||||
struct Test {
|
||||
let string: String?
|
||||
}
|
||||
let template = try HBMustacheTemplate(string: "test {{#string}}*{{.}}{{/string}}")
|
||||
let template = try MustacheTemplate(string: "test {{#string}}*{{.}}{{/string}}")
|
||||
XCTAssertEqual(template.render(Test(string: "string")), "test *string")
|
||||
XCTAssertEqual(template.render(Test(string: nil)), "test ")
|
||||
let template2 = try HBMustacheTemplate(string: "test {{^string}}*{{/string}}")
|
||||
let template2 = try MustacheTemplate(string: "test {{^string}}*{{/string}}")
|
||||
XCTAssertEqual(template2.render(Test(string: "string")), "test ")
|
||||
XCTAssertEqual(template2.render(Test(string: nil)), "test *")
|
||||
}
|
||||
@@ -98,7 +98,7 @@ final class TemplateRendererTests: XCTestCase {
|
||||
struct Test {
|
||||
let string: String?
|
||||
}
|
||||
let template = try HBMustacheTemplate(string: "test {{#.}}{{string}}{{/.}}")
|
||||
let template = try MustacheTemplate(string: "test {{#.}}{{string}}{{/.}}")
|
||||
XCTAssertEqual(template.render([Test(string: "string")]), "test string")
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ final class TemplateRendererTests: XCTestCase {
|
||||
struct Test {
|
||||
let string: String?
|
||||
}
|
||||
let template = try HBMustacheTemplate(string: "test {{#.}}{{#string}}*{{.}}{{/string}}{{/.}}")
|
||||
let template = try MustacheTemplate(string: "test {{#.}}{{#string}}*{{.}}{{/string}}{{/.}}")
|
||||
XCTAssertEqual(template.render([Test(string: "string")]), "test *string")
|
||||
}
|
||||
|
||||
@@ -118,20 +118,20 @@ final class TemplateRendererTests: XCTestCase {
|
||||
let test: SubTest
|
||||
}
|
||||
|
||||
let template = try HBMustacheTemplate(string: "test {{test.string}}")
|
||||
let template = try MustacheTemplate(string: "test {{test.string}}")
|
||||
XCTAssertEqual(template.render(Test(test: .init(string: "sub"))), "test sub")
|
||||
}
|
||||
|
||||
func testTextEscaping() throws {
|
||||
let template1 = try HBMustacheTemplate(string: "{{% CONTENT_TYPE:TEXT}}{{.}}")
|
||||
let template1 = try MustacheTemplate(string: "{{% CONTENT_TYPE:TEXT}}{{.}}")
|
||||
XCTAssertEqual(template1.render("<>"), "<>")
|
||||
let template2 = try HBMustacheTemplate(string: "{{% CONTENT_TYPE:HTML}}{{.}}")
|
||||
let template2 = try MustacheTemplate(string: "{{% CONTENT_TYPE:HTML}}{{.}}")
|
||||
XCTAssertEqual(template2.render("<>"), "<>")
|
||||
}
|
||||
|
||||
func testStopClimbingStack() throws {
|
||||
let template1 = try HBMustacheTemplate(string: "{{#test}}{{name}}{{/test}}")
|
||||
let template2 = try HBMustacheTemplate(string: "{{#test}}{{.name}}{{/test}}")
|
||||
let template1 = try MustacheTemplate(string: "{{#test}}{{name}}{{/test}}")
|
||||
let template2 = try MustacheTemplate(string: "{{#test}}{{.name}}{{/test}}")
|
||||
let object: [String: Any] = ["test": [:], "name": "John"]
|
||||
let object2: [String: Any] = ["test": ["name": "Jane"], "name": "John"]
|
||||
XCTAssertEqual(template1.render(object), "John")
|
||||
@@ -141,7 +141,7 @@ final class TemplateRendererTests: XCTestCase {
|
||||
|
||||
/// variables
|
||||
func testMustacheManualExample1() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
Hello {{name}}
|
||||
You have just won {{value}} dollars!
|
||||
{{#in_ca}}
|
||||
@@ -159,7 +159,7 @@ final class TemplateRendererTests: XCTestCase {
|
||||
|
||||
/// test esacped and unescaped text
|
||||
func testMustacheManualExample2() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
*{{name}}
|
||||
*{{age}}
|
||||
*{{company}}
|
||||
@@ -176,7 +176,7 @@ final class TemplateRendererTests: XCTestCase {
|
||||
|
||||
/// test boolean
|
||||
func testMustacheManualExample3() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
Shown.
|
||||
{{#person}}
|
||||
Never shown!
|
||||
@@ -191,7 +191,7 @@ final class TemplateRendererTests: XCTestCase {
|
||||
|
||||
/// test non-empty lists
|
||||
func testMustacheManualExample4() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#repo}}
|
||||
<b>{{name}}</b>
|
||||
{{/repo}}
|
||||
@@ -207,13 +207,13 @@ final class TemplateRendererTests: XCTestCase {
|
||||
|
||||
/// test lambdas
|
||||
func testMustacheManualExample5() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#wrapped}}{{name}} is awesome.{{/wrapped}}
|
||||
""")
|
||||
func wrapped(object: Any, template: HBMustacheTemplate) -> String {
|
||||
func wrapped(object: Any, template: MustacheTemplate) -> String {
|
||||
return "<b>\(template.render(object))</b>"
|
||||
}
|
||||
let object: [String: Any] = ["name": "Willy", "wrapped": HBMustacheLambda(wrapped)]
|
||||
let object: [String: Any] = ["name": "Willy", "wrapped": MustacheLambda(wrapped)]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
<b>Willy is awesome.</b>
|
||||
""")
|
||||
@@ -221,7 +221,7 @@ final class TemplateRendererTests: XCTestCase {
|
||||
|
||||
/// test setting context object
|
||||
func testMustacheManualExample6() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#person?}}
|
||||
Hi {{name}}!
|
||||
{{/person?}}
|
||||
@@ -235,7 +235,7 @@ final class TemplateRendererTests: XCTestCase {
|
||||
|
||||
/// test inverted sections
|
||||
func testMustacheManualExample7() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#repo}}
|
||||
<b>{{name}}</b>
|
||||
{{/repo}}
|
||||
@@ -252,7 +252,7 @@ final class TemplateRendererTests: XCTestCase {
|
||||
|
||||
/// test comments
|
||||
func testMustacheManualExample8() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
<h1>Today{{! ignore me }}.</h1>
|
||||
""")
|
||||
let object: [String: Any] = ["repo": []]
|
||||
@@ -261,12 +261,12 @@ final class TemplateRendererTests: XCTestCase {
|
||||
""")
|
||||
}
|
||||
|
||||
/// test HBMustacheCustomRenderable
|
||||
/// test MustacheCustomRenderable
|
||||
func testCustomRenderable() throws {
|
||||
let template = try HBMustacheTemplate(string: "{{.}}")
|
||||
let template1 = try HBMustacheTemplate(string: "{{#.}}not null{{/.}}")
|
||||
let template2 = try HBMustacheTemplate(string: "{{^.}}null{{/.}}")
|
||||
struct Object: HBMustacheCustomRenderable {
|
||||
let template = try MustacheTemplate(string: "{{.}}")
|
||||
let template1 = try MustacheTemplate(string: "{{#.}}not null{{/.}}")
|
||||
let template2 = try MustacheTemplate(string: "{{^.}}null{{/.}}")
|
||||
struct Object: MustacheCustomRenderable {
|
||||
let value: String
|
||||
|
||||
var renderText: String { self.value.uppercased() }
|
||||
@@ -282,7 +282,7 @@ final class TemplateRendererTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testPerformance() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#repo}}
|
||||
<b>{{name}}</b>
|
||||
{{/repo}}
|
||||
|
||||
@@ -17,7 +17,7 @@ import XCTest
|
||||
|
||||
final class TransformTests: XCTestCase {
|
||||
func testLowercased() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{ lowercased(name) }}
|
||||
""")
|
||||
let object: [String: Any] = ["name": "Test"]
|
||||
@@ -25,7 +25,7 @@ final class TransformTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testUppercased() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{ uppercased(name) }}
|
||||
""")
|
||||
let object: [String: Any] = ["name": "Test"]
|
||||
@@ -33,7 +33,7 @@ final class TransformTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testNewline() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#repo}}
|
||||
<b>{{name}}</b>
|
||||
{{/repo}}
|
||||
@@ -49,7 +49,7 @@ final class TransformTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testFirstLast() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#repo}}
|
||||
<b>{{#first()}}first: {{/first()}}{{#last()}}last: {{/last()}}{{ name }}</b>
|
||||
{{/repo}}
|
||||
@@ -65,7 +65,7 @@ final class TransformTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testIndex() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#repo}}
|
||||
<b>{{#index()}}{{plusone(.)}}{{/index()}}) {{ name }}</b>
|
||||
{{/repo}}
|
||||
@@ -81,7 +81,7 @@ final class TransformTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testEvenOdd() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#repo}}
|
||||
<b>{{index()}}) {{#even()}}even {{/even()}}{{#odd()}}odd {{/odd()}}{{ name }}</b>
|
||||
{{/repo}}
|
||||
@@ -97,7 +97,7 @@ final class TransformTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testReversed() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#reversed(repo)}}
|
||||
<b>{{ name }}</b>
|
||||
{{/reversed(repo)}}
|
||||
@@ -113,7 +113,7 @@ final class TransformTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testArrayIndex() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#repo}}
|
||||
<b>{{ index() }}) {{ name }}</b>
|
||||
{{/repo}}
|
||||
@@ -128,7 +128,7 @@ final class TransformTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testArraySorted() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#sorted(repo)}}
|
||||
<b>{{ index() }}) {{ . }}</b>
|
||||
{{/sorted(repo)}}
|
||||
@@ -143,7 +143,7 @@ final class TransformTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testDictionaryEmpty() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#empty(array)}}Array{{/empty(array)}}{{#empty(dictionary)}}Dictionary{{/empty(dictionary)}}
|
||||
""")
|
||||
let object: [String: Any] = ["array": [], "dictionary": [:]]
|
||||
@@ -152,12 +152,12 @@ final class TransformTests: XCTestCase {
|
||||
|
||||
func testListOutput() throws {
|
||||
let object = [1, 2, 3, 4]
|
||||
let template = try HBMustacheTemplate(string: "{{#.}}{{.}}{{^last()}}, {{/last()}}{{/.}}")
|
||||
let template = try MustacheTemplate(string: "{{#.}}{{.}}{{^last()}}, {{/last()}}{{/.}}")
|
||||
XCTAssertEqual(template.render(object), "1, 2, 3, 4")
|
||||
}
|
||||
|
||||
func testDictionaryEnumerated() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#enumerated(.)}}<b>{{ key }} = {{ value }}</b>{{/enumerated(.)}}
|
||||
""")
|
||||
let object: [String: Any] = ["one": 1, "two": 2]
|
||||
@@ -166,7 +166,7 @@ final class TransformTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testDictionarySortedByKey() throws {
|
||||
let template = try HBMustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#sorted(.)}}<b>{{ key }} = {{ value }}</b>{{/sorted(.)}}
|
||||
""")
|
||||
let object: [String: Any] = ["one": 1, "two": 2, "three": 3]
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
|
||||
The library doesn't provide a lambda implementation but it does provide something akin to the lambda feature.
|
||||
|
||||
Add a `HBMustacheLambda` to the object you want to be rendered and it can be used in a similar way to lambdas are used in Mustache. When you create a section referencing the lambda the contents of the section are passed as a template along with the current object to the lamdba function. This is slightly different from the standard implementation where the unprocessed text is passed to the lambda.
|
||||
Add a `MustacheLambda` to the object you want to be rendered and it can be used in a similar way to lambdas are used in Mustache. When you create a section referencing the lambda the contents of the section are passed as a template along with the current object to the lamdba function. This is slightly different from the standard implementation where the unprocessed text is passed to the lambda.
|
||||
|
||||
Given the object `person` defined below
|
||||
```swift
|
||||
struct Person {
|
||||
let name: String
|
||||
let wrapped: HBMustacheLambda
|
||||
let wrapped: MustacheLambda
|
||||
}
|
||||
let person = Person(
|
||||
name: "John",
|
||||
wrapped: HBMustacheLambda { object, template in
|
||||
wrapped: MustacheLambda { object, template in
|
||||
return "<b>\(template.render(object))</b>"
|
||||
}
|
||||
)
|
||||
@@ -21,7 +21,7 @@ let person = Person(
|
||||
and the following mustache template
|
||||
```swift
|
||||
let mustache = "{{#wrapped}}{{name}} is awesome.{{/wrapped}}"
|
||||
let template = try HBMustacheTemplate(string: mustache)
|
||||
let template = try MustacheTemplate(string: mustache)
|
||||
```
|
||||
Then `template.render(person)` will output
|
||||
```
|
||||
|
||||
@@ -52,9 +52,9 @@ The following sequence context transforms are available
|
||||
|
||||
## Custom transforms
|
||||
|
||||
You can add transforms to your own objects. Conform the object to `HBMustacheTransformable` and provide an implementation of the function `transform`. eg
|
||||
You can add transforms to your own objects. Conform the object to `MustacheTransformable` and provide an implementation of the function `transform`. eg
|
||||
```swift
|
||||
struct Object: HBMustacheTransformable {
|
||||
struct Object: MustacheTransformable {
|
||||
let either: Bool
|
||||
let or: Bool
|
||||
|
||||
|
||||
Reference in New Issue
Block a user