Remove HB prefix, make Parser private (#26)
This commit is contained in:
@@ -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 let line: String
|
||||
public let lineNumber: Int
|
||||
public let columnNumber: Int
|
||||
}
|
||||
/// context used in parser error
|
||||
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 {}
|
||||
|
||||
Reference in New Issue
Block a user