Skip to content

Commit

Permalink
Remove HB prefix, make Parser private (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
adam-fowler committed Mar 11, 2024
1 parent f029081 commit bdfa053
Show file tree
Hide file tree
Showing 25 changed files with 300 additions and 262 deletions.
14 changes: 7 additions & 7 deletions README.md
Expand Up @@ -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.

Expand All @@ -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

Expand Down
20 changes: 10 additions & 10 deletions Sources/HummingbirdMustache/ContentType.swift
Expand Up @@ -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 "&lt;"
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()
}
Expand All @@ -36,22 +36,22 @@ 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]
}

/// Register new content type
/// - 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(),
]
}
34 changes: 17 additions & 17 deletions Sources/HummingbirdMustache/Context.swift
Expand Up @@ -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
Expand All @@ -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(
Expand All @@ -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 {
Expand All @@ -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(
Expand All @@ -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,
Expand Down
8 changes: 4 additions & 4 deletions Sources/HummingbirdMustache/CustomRenderable.swift
Expand Up @@ -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 changes: 38 additions & 0 deletions Sources/HummingbirdMustache/Deprecations.swift
@@ -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
12 changes: 6 additions & 6 deletions Sources/HummingbirdMustache/Lambda.swift
Expand Up @@ -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)
}
}
12 changes: 6 additions & 6 deletions Sources/HummingbirdMustache/Library+FileSystem.swift
Expand Up @@ -14,25 +14,25 @@

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 += "/"
}
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
Expand Down
14 changes: 7 additions & 7 deletions Sources/HummingbirdMustache/Library.swift
Expand Up @@ -18,7 +18,7 @@
/// ```
/// {{#sequence}}{{>entry}}{{/sequence}}
/// ```
public struct HBMustacheLibrary: Sendable {
public struct MustacheLibrary: Sendable {
/// Initialize empty library
public init() {
self.templates = [:]
Expand All @@ -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
}

Expand All @@ -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
}

Expand All @@ -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]
}

Expand All @@ -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]
}
4 changes: 2 additions & 2 deletions Sources/HummingbirdMustache/Parent.swift
Expand Up @@ -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] }
}

0 comments on commit bdfa053

Please sign in to comment.