Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove HB prefix, make Parser private #26

Merged
merged 3 commits into from Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 }
}
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] }
}