Remove HB prefix, make Parser private (#26)

This commit is contained in:
Adam Fowler
2024-03-11 22:07:05 +00:00
committed by GitHub
parent f029081b61
commit bdfa05391a
25 changed files with 300 additions and 262 deletions

View File

@@ -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()
}
@@ -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(),
]
}

View File

@@ -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,

View File

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

View 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

View File

@@ -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)
}
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 {}

View File

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

View File

@@ -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)
}

View File

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

View File

@@ -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]

View File

@@ -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 {}