swift format
This commit is contained in:
@@ -8,7 +8,7 @@ struct HBMustacheContext: HBMustacheMethods {
|
|||||||
init(first: Bool = false, last: Bool = false) {
|
init(first: Bool = false, last: Bool = false) {
|
||||||
self.first = first
|
self.first = first
|
||||||
self.last = last
|
self.last = last
|
||||||
self.index = 0
|
index = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apply method to `HBMustacheContext`. These are available when processing elements
|
/// Apply method to `HBMustacheContext`. These are available when processing elements
|
||||||
@@ -25,18 +25,17 @@ struct HBMustacheContext: HBMustacheMethods {
|
|||||||
func runMethod(_ name: String) -> Any? {
|
func runMethod(_ name: String) -> Any? {
|
||||||
switch name {
|
switch name {
|
||||||
case "first":
|
case "first":
|
||||||
return self.first
|
return first
|
||||||
case "last":
|
case "last":
|
||||||
return self.last
|
return last
|
||||||
case "index":
|
case "index":
|
||||||
return self.index
|
return index
|
||||||
case "even":
|
case "even":
|
||||||
return (self.index & 1) == 0
|
return (index & 1) == 0
|
||||||
case "odd":
|
case "odd":
|
||||||
return (self.index & 1) == 1
|
return (index & 1) == 1
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public struct HBMustacheLambda {
|
|||||||
/// Initialize `HBMustacheLambda`
|
/// Initialize `HBMustacheLambda`
|
||||||
/// - Parameter cb: function to be called by lambda
|
/// - Parameter cb: function to be called by lambda
|
||||||
public init(_ cb: @escaping Callback) {
|
public init(_ cb: @escaping Callback) {
|
||||||
self.callback = cb
|
callback = cb
|
||||||
}
|
}
|
||||||
|
|
||||||
internal func run(_ object: Any, _ template: HBMustacheTemplate) -> String {
|
internal func run(_ object: Any, _ template: HBMustacheTemplate) -> String {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ extension HBMustacheLibrary {
|
|||||||
guard let enumerator = fs.enumerator(atPath: directory) else { return }
|
guard let enumerator = fs.enumerator(atPath: directory) else { return }
|
||||||
for case let path as String in enumerator {
|
for case let path as String in enumerator {
|
||||||
guard path.hasSuffix(extWithDot) else { continue }
|
guard path.hasSuffix(extWithDot) else { continue }
|
||||||
guard let data = fs.contents(atPath: directory + path) else { continue}
|
guard let data = fs.contents(atPath: directory + path) else { continue }
|
||||||
let string = String(decoding: data, as: Unicode.UTF8.self)
|
let string = String(decoding: data, as: Unicode.UTF8.self)
|
||||||
guard let template = try? HBMustacheTemplate(string: string) else {
|
guard let template = try? HBMustacheTemplate(string: string) else {
|
||||||
logger?.error("Failed to load \(path)")
|
logger?.error("Failed to load \(path)")
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import Logging
|
|||||||
public class HBMustacheLibrary {
|
public class HBMustacheLibrary {
|
||||||
/// Initialize empty library
|
/// Initialize empty library
|
||||||
public init() {
|
public init() {
|
||||||
self.templates = [:]
|
templates = [:]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize library with contents of folder.
|
/// Initialize library with contents of folder.
|
||||||
@@ -19,8 +19,8 @@ public class HBMustacheLibrary {
|
|||||||
/// - Parameter directory: Directory to look for mustache templates
|
/// - Parameter directory: Directory to look for mustache templates
|
||||||
/// - Parameter extension: Extension of files to look for
|
/// - Parameter extension: Extension of files to look for
|
||||||
public init(directory: String, withExtension extension: String = "mustache", logger: Logger? = nil) {
|
public init(directory: String, withExtension extension: String = "mustache", logger: Logger? = nil) {
|
||||||
self.templates = [:]
|
templates = [:]
|
||||||
self.loadTemplates(from: directory, withExtension: `extension`, logger: logger)
|
loadTemplates(from: directory, withExtension: `extension`, logger: logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register template under name
|
/// Register template under name
|
||||||
|
|||||||
@@ -17,22 +17,22 @@ public protocol HBMustacheMethods {
|
|||||||
func runMethod(_ name: String) -> Any?
|
func runMethod(_ name: String) -> Any?
|
||||||
}
|
}
|
||||||
|
|
||||||
extension StringProtocol {
|
public extension StringProtocol {
|
||||||
/// Apply method to String/Substring
|
/// Apply method to String/Substring
|
||||||
///
|
///
|
||||||
/// Methods available are `capitalized`, `lowercased`, `uppercased` and `reversed`
|
/// Methods available are `capitalized`, `lowercased`, `uppercased` and `reversed`
|
||||||
/// - Parameter name: Method name
|
/// - Parameter name: Method name
|
||||||
/// - Returns: Result
|
/// - Returns: Result
|
||||||
public func runMethod(_ name: String) -> Any? {
|
func runMethod(_ name: String) -> Any? {
|
||||||
switch name {
|
switch name {
|
||||||
case "capitalized":
|
case "capitalized":
|
||||||
return self.capitalized
|
return capitalized
|
||||||
case "lowercased":
|
case "lowercased":
|
||||||
return self.lowercased()
|
return lowercased()
|
||||||
case "uppercased":
|
case "uppercased":
|
||||||
return self.uppercased()
|
return uppercased()
|
||||||
case "reversed":
|
case "reversed":
|
||||||
return self.reversed()
|
return reversed()
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -57,13 +57,13 @@ extension Array: HBMustacheMethods {
|
|||||||
public func runMethod(_ name: String) -> Any? {
|
public func runMethod(_ name: String) -> Any? {
|
||||||
switch name {
|
switch name {
|
||||||
case "first":
|
case "first":
|
||||||
return self.first
|
return first
|
||||||
case "last":
|
case "last":
|
||||||
return self.last
|
return last
|
||||||
case "reversed":
|
case "reversed":
|
||||||
return self.reversed()
|
return reversed()
|
||||||
case "count":
|
case "count":
|
||||||
return self.count
|
return count
|
||||||
default:
|
default:
|
||||||
if let comparableSeq = self as? HBComparableSequence {
|
if let comparableSeq = self as? HBComparableSequence {
|
||||||
return comparableSeq.runComparableMethod(name)
|
return comparableSeq.runComparableMethod(name)
|
||||||
@@ -77,7 +77,7 @@ extension Array: HBComparableSequence where Element: Comparable {
|
|||||||
func runComparableMethod(_ name: String) -> Any? {
|
func runComparableMethod(_ name: String) -> Any? {
|
||||||
switch name {
|
switch name {
|
||||||
case "sorted":
|
case "sorted":
|
||||||
return self.sorted()
|
return sorted()
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -94,9 +94,9 @@ extension Dictionary: HBMustacheMethods {
|
|||||||
public func runMethod(_ name: String) -> Any? {
|
public func runMethod(_ name: String) -> Any? {
|
||||||
switch name {
|
switch name {
|
||||||
case "count":
|
case "count":
|
||||||
return self.count
|
return count
|
||||||
case "enumerated":
|
case "enumerated":
|
||||||
return self.map { (key: $0.key, value: $0.value) }
|
return map { (key: $0.key, value: $0.value) }
|
||||||
default:
|
default:
|
||||||
if let comparableSeq = self as? HBComparableSequence {
|
if let comparableSeq = self as? HBComparableSequence {
|
||||||
return comparableSeq.runComparableMethod(name)
|
return comparableSeq.runComparableMethod(name)
|
||||||
@@ -110,20 +110,20 @@ extension Dictionary: HBComparableSequence where Key: Comparable {
|
|||||||
func runComparableMethod(_ name: String) -> Any? {
|
func runComparableMethod(_ name: String) -> Any? {
|
||||||
switch name {
|
switch name {
|
||||||
case "sorted":
|
case "sorted":
|
||||||
return self.map { (key: $0.key, value: $0.value) }.sorted { $0.key < $1.key }
|
return map { (key: $0.key, value: $0.value) }.sorted { $0.key < $1.key }
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension FixedWidthInteger {
|
public extension FixedWidthInteger {
|
||||||
/// Apply method to FixedWidthInteger
|
/// Apply method to FixedWidthInteger
|
||||||
///
|
///
|
||||||
/// Methods available are `plusone`, `minusone`, `odd`, `even`
|
/// Methods available are `plusone`, `minusone`, `odd`, `even`
|
||||||
/// - Parameter name: method name
|
/// - Parameter name: method name
|
||||||
/// - Returns: Result
|
/// - Returns: Result
|
||||||
public func runMethod(_ name: String) -> Any? {
|
func runMethod(_ name: String) -> Any? {
|
||||||
switch name {
|
switch name {
|
||||||
case "plusone":
|
case "plusone":
|
||||||
return self + 1
|
return self + 1
|
||||||
|
|||||||
@@ -17,4 +17,3 @@ private func unwrapOptional(_ object: Any) -> Any? {
|
|||||||
guard let first = mirror.children.first else { return nil }
|
guard let first = mirror.children.first else { return nil }
|
||||||
return first.value
|
return first.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,4 +10,3 @@ protocol HBMustacheParent {
|
|||||||
extension Dictionary: HBMustacheParent where Key == String {
|
extension Dictionary: HBMustacheParent where Key == String {
|
||||||
func child(named: String) -> Any? { return self[named] }
|
func child(named: String) -> Any? { return self[named] }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,10 +23,10 @@ struct HBParser {
|
|||||||
if let buffer = utf8Data as? [UInt8] {
|
if let buffer = utf8Data as? [UInt8] {
|
||||||
self.buffer = buffer
|
self.buffer = buffer
|
||||||
} else {
|
} else {
|
||||||
self.buffer = Array(utf8Data)
|
buffer = Array(utf8Data)
|
||||||
}
|
}
|
||||||
self.index = 0
|
index = 0
|
||||||
self.range = 0..<self.buffer.endIndex
|
range = 0 ..< buffer.endIndex
|
||||||
|
|
||||||
// should check that the data is valid utf8
|
// should check that the data is valid utf8
|
||||||
if validateUTF8 == true, self.validateUTF8() == false {
|
if validateUTF8 == true, self.validateUTF8() == false {
|
||||||
@@ -35,19 +35,19 @@ struct HBParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init(_ string: String) {
|
init(_ string: String) {
|
||||||
self.buffer = Array(string.utf8)
|
buffer = Array(string.utf8)
|
||||||
self.index = 0
|
index = 0
|
||||||
self.range = 0..<self.buffer.endIndex
|
range = 0 ..< buffer.endIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return contents of parser as a string
|
/// Return contents of parser as a string
|
||||||
var count: Int {
|
var count: Int {
|
||||||
return self.range.count
|
return range.count
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return contents of parser as a string
|
/// Return contents of parser as a string
|
||||||
var string: String {
|
var string: String {
|
||||||
return makeString(self.buffer[self.range])
|
return makeString(buffer[range])
|
||||||
}
|
}
|
||||||
|
|
||||||
private var buffer: [UInt8]
|
private var buffer: [UInt8]
|
||||||
@@ -60,12 +60,12 @@ struct HBParser {
|
|||||||
extension HBParser {
|
extension HBParser {
|
||||||
/// initialise a parser that parses a section of the buffer attached to another parser
|
/// initialise a parser that parses a section of the buffer attached to another parser
|
||||||
init(_ parser: HBParser, range: Range<Int>) {
|
init(_ parser: HBParser, range: Range<Int>) {
|
||||||
self.buffer = parser.buffer
|
buffer = parser.buffer
|
||||||
self.index = range.startIndex
|
index = range.startIndex
|
||||||
self.range = range
|
self.range = range
|
||||||
|
|
||||||
precondition(range.startIndex >= 0 && range.endIndex <= self.buffer.endIndex)
|
precondition(range.startIndex >= 0 && range.endIndex <= buffer.endIndex)
|
||||||
precondition(self.buffer[range.startIndex] & 0xC0 != 0x80) // check we arent in the middle of a UTF8 character
|
precondition(buffer[range.startIndex] & 0xC0 != 0x80) // check we arent in the middle of a UTF8 character
|
||||||
}
|
}
|
||||||
|
|
||||||
/// initialise a parser that parses a section of the buffer attached to this parser
|
/// initialise a parser that parses a section of the buffer attached to this parser
|
||||||
@@ -79,7 +79,7 @@ extension HBParser {
|
|||||||
/// - Throws: .overflow
|
/// - Throws: .overflow
|
||||||
/// - Returns: Current character
|
/// - Returns: Current character
|
||||||
mutating func character() throws -> Unicode.Scalar {
|
mutating func character() throws -> Unicode.Scalar {
|
||||||
guard !self.reachedEnd() else { throw Error.overflow }
|
guard !reachedEnd() else { throw Error.overflow }
|
||||||
return unsafeCurrentAndAdvance()
|
return unsafeCurrentAndAdvance()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,9 +88,9 @@ extension HBParser {
|
|||||||
/// - Throws: .overflow
|
/// - Throws: .overflow
|
||||||
/// - Returns: If current character was the one we expected
|
/// - Returns: If current character was the one we expected
|
||||||
mutating func read(_ char: Unicode.Scalar) throws -> Bool {
|
mutating func read(_ char: Unicode.Scalar) throws -> Bool {
|
||||||
let initialIndex = self.index
|
let initialIndex = index
|
||||||
let c = try character()
|
let c = try character()
|
||||||
guard c == char else { self.index = initialIndex; return false }
|
guard c == char else { index = initialIndex; return false }
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,9 +99,9 @@ extension HBParser {
|
|||||||
/// - Throws: .overflow
|
/// - Throws: .overflow
|
||||||
/// - Returns: If current character is in character set
|
/// - Returns: If current character is in character set
|
||||||
mutating func read(_ characterSet: Set<Unicode.Scalar>) throws -> Bool {
|
mutating func read(_ characterSet: Set<Unicode.Scalar>) throws -> Bool {
|
||||||
let initialIndex = self.index
|
let initialIndex = index
|
||||||
let c = try character()
|
let c = try character()
|
||||||
guard characterSet.contains(c) else { self.index = initialIndex; return false }
|
guard characterSet.contains(c) else { index = initialIndex; return false }
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,10 +110,10 @@ extension HBParser {
|
|||||||
/// - Throws: .overflow, .emptyString
|
/// - Throws: .overflow, .emptyString
|
||||||
/// - Returns: If characters at current position equal string
|
/// - Returns: If characters at current position equal string
|
||||||
mutating func read(_ string: String) throws -> Bool {
|
mutating func read(_ string: String) throws -> Bool {
|
||||||
let initialIndex = self.index
|
let initialIndex = index
|
||||||
guard string.count > 0 else { throw Error.emptyString }
|
guard string.count > 0 else { throw Error.emptyString }
|
||||||
let subString = try read(count: string.count)
|
let subString = try read(count: string.count)
|
||||||
guard subString.string == string else { self.index = initialIndex; return false }
|
guard subString.string == string else { index = initialIndex; return false }
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,14 +123,14 @@ extension HBParser {
|
|||||||
/// - Returns: The string read from the buffer
|
/// - Returns: The string read from the buffer
|
||||||
mutating func read(count: Int) throws -> HBParser {
|
mutating func read(count: Int) throws -> HBParser {
|
||||||
var count = count
|
var count = count
|
||||||
var readEndIndex = self.index
|
var readEndIndex = index
|
||||||
while count > 0 {
|
while count > 0 {
|
||||||
guard readEndIndex != self.range.endIndex else { throw Error.overflow }
|
guard readEndIndex != range.endIndex else { throw Error.overflow }
|
||||||
readEndIndex = skipUTF8Character(at: readEndIndex)
|
readEndIndex = skipUTF8Character(at: readEndIndex)
|
||||||
count -= 1
|
count -= 1
|
||||||
}
|
}
|
||||||
let result = self.subParser(self.index..<readEndIndex)
|
let result = subParser(index ..< readEndIndex)
|
||||||
self.index = readEndIndex
|
index = readEndIndex
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,10 +139,10 @@ extension HBParser {
|
|||||||
/// - Throws: .overflow if we hit the end of the buffer before reading character
|
/// - Throws: .overflow if we hit the end of the buffer before reading character
|
||||||
/// - Returns: String read from buffer
|
/// - Returns: String read from buffer
|
||||||
@discardableResult mutating func read(until: Unicode.Scalar, throwOnOverflow: Bool = true) throws -> HBParser {
|
@discardableResult mutating func read(until: Unicode.Scalar, throwOnOverflow: Bool = true) throws -> HBParser {
|
||||||
let startIndex = self.index
|
let startIndex = index
|
||||||
while !self.reachedEnd() {
|
while !reachedEnd() {
|
||||||
if unsafeCurrent() == until {
|
if unsafeCurrent() == until {
|
||||||
return self.subParser(startIndex..<self.index)
|
return subParser(startIndex ..< index)
|
||||||
}
|
}
|
||||||
unsafeAdvance()
|
unsafeAdvance()
|
||||||
}
|
}
|
||||||
@@ -150,7 +150,7 @@ extension HBParser {
|
|||||||
_setPosition(startIndex)
|
_setPosition(startIndex)
|
||||||
throw Error.overflow
|
throw Error.overflow
|
||||||
}
|
}
|
||||||
return self.subParser(startIndex..<self.index)
|
return subParser(startIndex ..< index)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read from buffer until we hit a character in supplied set. Position after this is of the character we were checking for
|
/// Read from buffer until we hit a character in supplied set. Position after this is of the character we were checking for
|
||||||
@@ -158,10 +158,10 @@ extension HBParser {
|
|||||||
/// - Throws: .overflow
|
/// - Throws: .overflow
|
||||||
/// - Returns: String read from buffer
|
/// - Returns: String read from buffer
|
||||||
@discardableResult mutating func read(until characterSet: Set<Unicode.Scalar>, throwOnOverflow: Bool = true) throws -> HBParser {
|
@discardableResult mutating func read(until characterSet: Set<Unicode.Scalar>, throwOnOverflow: Bool = true) throws -> HBParser {
|
||||||
let startIndex = self.index
|
let startIndex = index
|
||||||
while !self.reachedEnd() {
|
while !reachedEnd() {
|
||||||
if characterSet.contains(unsafeCurrent()) {
|
if characterSet.contains(unsafeCurrent()) {
|
||||||
return self.subParser(startIndex..<self.index)
|
return subParser(startIndex ..< index)
|
||||||
}
|
}
|
||||||
unsafeAdvance()
|
unsafeAdvance()
|
||||||
}
|
}
|
||||||
@@ -169,7 +169,7 @@ extension HBParser {
|
|||||||
_setPosition(startIndex)
|
_setPosition(startIndex)
|
||||||
throw Error.overflow
|
throw Error.overflow
|
||||||
}
|
}
|
||||||
return self.subParser(startIndex..<self.index)
|
return subParser(startIndex ..< index)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read from buffer until we hit a character that returns true for supplied closure. Position after this is of the character we were checking for
|
/// Read from buffer until we hit a character that returns true for supplied closure. Position after this is of the character we were checking for
|
||||||
@@ -177,10 +177,10 @@ extension HBParser {
|
|||||||
/// - Throws: .overflow
|
/// - Throws: .overflow
|
||||||
/// - Returns: String read from buffer
|
/// - Returns: String read from buffer
|
||||||
@discardableResult mutating func read(until: (Unicode.Scalar) -> Bool, throwOnOverflow: Bool = true) throws -> HBParser {
|
@discardableResult mutating func read(until: (Unicode.Scalar) -> Bool, throwOnOverflow: Bool = true) throws -> HBParser {
|
||||||
let startIndex = self.index
|
let startIndex = index
|
||||||
while !self.reachedEnd() {
|
while !reachedEnd() {
|
||||||
if until(unsafeCurrent()) {
|
if until(unsafeCurrent()) {
|
||||||
return self.subParser(startIndex..<self.index)
|
return subParser(startIndex ..< index)
|
||||||
}
|
}
|
||||||
unsafeAdvance()
|
unsafeAdvance()
|
||||||
}
|
}
|
||||||
@@ -188,7 +188,7 @@ extension HBParser {
|
|||||||
_setPosition(startIndex)
|
_setPosition(startIndex)
|
||||||
throw Error.overflow
|
throw Error.overflow
|
||||||
}
|
}
|
||||||
return self.subParser(startIndex..<self.index)
|
return subParser(startIndex ..< index)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read from buffer until we hit a character where supplied KeyPath is true. Position after this is of the character we were checking for
|
/// Read from buffer until we hit a character where supplied KeyPath is true. Position after this is of the character we were checking for
|
||||||
@@ -196,10 +196,10 @@ extension HBParser {
|
|||||||
/// - Throws: .overflow
|
/// - Throws: .overflow
|
||||||
/// - Returns: String read from buffer
|
/// - Returns: String read from buffer
|
||||||
@discardableResult mutating func read(until keyPath: KeyPath<Unicode.Scalar, Bool>, throwOnOverflow: Bool = true) throws -> HBParser {
|
@discardableResult mutating func read(until keyPath: KeyPath<Unicode.Scalar, Bool>, throwOnOverflow: Bool = true) throws -> HBParser {
|
||||||
let startIndex = self.index
|
let startIndex = index
|
||||||
while !self.reachedEnd() {
|
while !reachedEnd() {
|
||||||
if unsafeCurrent()[keyPath: keyPath] {
|
if unsafeCurrent()[keyPath: keyPath] {
|
||||||
return self.subParser(startIndex..<self.index)
|
return subParser(startIndex ..< index)
|
||||||
}
|
}
|
||||||
unsafeAdvance()
|
unsafeAdvance()
|
||||||
}
|
}
|
||||||
@@ -207,7 +207,7 @@ extension HBParser {
|
|||||||
_setPosition(startIndex)
|
_setPosition(startIndex)
|
||||||
throw Error.overflow
|
throw Error.overflow
|
||||||
}
|
}
|
||||||
return self.subParser(startIndex..<self.index)
|
return subParser(startIndex ..< index)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read from buffer until we hit a string. By default the position after this is of the beginning of the string we were checking for
|
/// Read from buffer until we hit a string. By default the position after this is of the beginning of the string we were checking for
|
||||||
@@ -234,7 +234,7 @@ extension HBParser {
|
|||||||
if skipToEnd == false {
|
if skipToEnd == false {
|
||||||
index = foundIndex
|
index = foundIndex
|
||||||
}
|
}
|
||||||
let result = subParser(startIndex..<foundIndex)
|
let result = subParser(startIndex ..< foundIndex)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -246,16 +246,16 @@ extension HBParser {
|
|||||||
_setPosition(startIndex)
|
_setPosition(startIndex)
|
||||||
throw Error.overflow
|
throw Error.overflow
|
||||||
}
|
}
|
||||||
return subParser(startIndex..<index)
|
return subParser(startIndex ..< index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read from buffer from current position until the end of the buffer
|
/// Read from buffer from current position until the end of the buffer
|
||||||
/// - Returns: String read from buffer
|
/// - Returns: String read from buffer
|
||||||
@discardableResult mutating func readUntilTheEnd() -> HBParser {
|
@discardableResult mutating func readUntilTheEnd() -> HBParser {
|
||||||
let startIndex = self.index
|
let startIndex = index
|
||||||
self.index = self.range.endIndex
|
index = range.endIndex
|
||||||
return self.subParser(startIndex..<self.index)
|
return subParser(startIndex ..< index)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read while character at current position is the one supplied
|
/// Read while character at current position is the one supplied
|
||||||
@@ -263,7 +263,7 @@ extension HBParser {
|
|||||||
/// - Returns: String read from buffer
|
/// - Returns: String read from buffer
|
||||||
@discardableResult mutating func read(while: Unicode.Scalar) -> Int {
|
@discardableResult mutating func read(while: Unicode.Scalar) -> Int {
|
||||||
var count = 0
|
var count = 0
|
||||||
while !self.reachedEnd(),
|
while !reachedEnd(),
|
||||||
unsafeCurrent() == `while`
|
unsafeCurrent() == `while`
|
||||||
{
|
{
|
||||||
unsafeAdvance()
|
unsafeAdvance()
|
||||||
@@ -276,39 +276,39 @@ extension HBParser {
|
|||||||
/// - Parameter while: character set to check
|
/// - Parameter while: character set to check
|
||||||
/// - Returns: String read from buffer
|
/// - Returns: String read from buffer
|
||||||
@discardableResult mutating func read(while characterSet: Set<Unicode.Scalar>) -> HBParser {
|
@discardableResult mutating func read(while characterSet: Set<Unicode.Scalar>) -> HBParser {
|
||||||
let startIndex = self.index
|
let startIndex = index
|
||||||
while !self.reachedEnd(),
|
while !reachedEnd(),
|
||||||
characterSet.contains(unsafeCurrent())
|
characterSet.contains(unsafeCurrent())
|
||||||
{
|
{
|
||||||
unsafeAdvance()
|
unsafeAdvance()
|
||||||
}
|
}
|
||||||
return self.subParser(startIndex..<self.index)
|
return subParser(startIndex ..< index)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read while character returns true for supplied closure
|
/// Read while character returns true for supplied closure
|
||||||
/// - Parameter while: character set to check
|
/// - Parameter while: character set to check
|
||||||
/// - Returns: String read from buffer
|
/// - Returns: String read from buffer
|
||||||
@discardableResult mutating func read(while: (Unicode.Scalar) -> Bool) -> HBParser {
|
@discardableResult mutating func read(while: (Unicode.Scalar) -> Bool) -> HBParser {
|
||||||
let startIndex = self.index
|
let startIndex = index
|
||||||
while !self.reachedEnd(),
|
while !reachedEnd(),
|
||||||
`while`(unsafeCurrent())
|
`while`(unsafeCurrent())
|
||||||
{
|
{
|
||||||
unsafeAdvance()
|
unsafeAdvance()
|
||||||
}
|
}
|
||||||
return self.subParser(startIndex..<self.index)
|
return subParser(startIndex ..< index)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read while character returns true for supplied KeyPath
|
/// Read while character returns true for supplied KeyPath
|
||||||
/// - Parameter while: character set to check
|
/// - Parameter while: character set to check
|
||||||
/// - Returns: String read from buffer
|
/// - Returns: String read from buffer
|
||||||
@discardableResult mutating func read(while keyPath: KeyPath<Unicode.Scalar, Bool>) -> HBParser {
|
@discardableResult mutating func read(while keyPath: KeyPath<Unicode.Scalar, Bool>) -> HBParser {
|
||||||
let startIndex = self.index
|
let startIndex = index
|
||||||
while !self.reachedEnd(),
|
while !reachedEnd(),
|
||||||
unsafeCurrent()[keyPath: keyPath]
|
unsafeCurrent()[keyPath: keyPath]
|
||||||
{
|
{
|
||||||
unsafeAdvance()
|
unsafeAdvance()
|
||||||
}
|
}
|
||||||
return self.subParser(startIndex..<self.index)
|
return subParser(startIndex ..< index)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Split parser into sections separated by character
|
/// Split parser into sections separated by character
|
||||||
@@ -316,14 +316,14 @@ extension HBParser {
|
|||||||
/// - Returns: arrays of sub parsers
|
/// - Returns: arrays of sub parsers
|
||||||
mutating func split(separator: Unicode.Scalar) -> [HBParser] {
|
mutating func split(separator: Unicode.Scalar) -> [HBParser] {
|
||||||
var subParsers: [HBParser] = []
|
var subParsers: [HBParser] = []
|
||||||
while !self.reachedEnd() {
|
while !reachedEnd() {
|
||||||
do {
|
do {
|
||||||
let section = try read(until: separator)
|
let section = try read(until: separator)
|
||||||
subParsers.append(section)
|
subParsers.append(section)
|
||||||
unsafeAdvance()
|
unsafeAdvance()
|
||||||
} catch {
|
} catch {
|
||||||
if !self.reachedEnd() {
|
if !reachedEnd() {
|
||||||
subParsers.append(self.readUntilTheEnd())
|
subParsers.append(readUntilTheEnd())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -333,7 +333,7 @@ extension HBParser {
|
|||||||
/// Return whether we have reached the end of the buffer
|
/// Return whether we have reached the end of the buffer
|
||||||
/// - Returns: Have we reached the end
|
/// - Returns: Have we reached the end
|
||||||
func reachedEnd() -> Bool {
|
func reachedEnd() -> Bool {
|
||||||
return self.index == self.range.endIndex
|
return index == range.endIndex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,15 +343,15 @@ extension HBParser {
|
|||||||
/// - Throws: .overflow
|
/// - Throws: .overflow
|
||||||
/// - Returns: Unicode.Scalar
|
/// - Returns: Unicode.Scalar
|
||||||
func current() -> Unicode.Scalar {
|
func current() -> Unicode.Scalar {
|
||||||
guard !self.reachedEnd() else { return Unicode.Scalar(0) }
|
guard !reachedEnd() else { return Unicode.Scalar(0) }
|
||||||
return unsafeCurrent()
|
return unsafeCurrent()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move forward one character
|
/// Move forward one character
|
||||||
/// - Throws: .overflow
|
/// - Throws: .overflow
|
||||||
mutating func advance() throws {
|
mutating func advance() throws {
|
||||||
guard !self.reachedEnd() else { throw Error.overflow }
|
guard !reachedEnd() else { throw Error.overflow }
|
||||||
return self.unsafeAdvance()
|
return unsafeAdvance()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move forward so many character
|
/// Move forward so many character
|
||||||
@@ -360,8 +360,8 @@ extension HBParser {
|
|||||||
mutating func advance(by amount: Int) throws {
|
mutating func advance(by amount: Int) throws {
|
||||||
var amount = amount
|
var amount = amount
|
||||||
while amount > 0 {
|
while amount > 0 {
|
||||||
guard !self.reachedEnd() else { throw Error.overflow }
|
guard !reachedEnd() else { throw Error.overflow }
|
||||||
self.index = skipUTF8Character(at: self.index)
|
index = skipUTF8Character(at: index)
|
||||||
amount -= 1
|
amount -= 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -369,8 +369,8 @@ extension HBParser {
|
|||||||
/// Move backwards one character
|
/// Move backwards one character
|
||||||
/// - Throws: .overflow
|
/// - Throws: .overflow
|
||||||
mutating func retreat() throws {
|
mutating func retreat() throws {
|
||||||
guard self.index > self.range.startIndex else { throw Error.overflow }
|
guard index > range.startIndex else { throw Error.overflow }
|
||||||
self.index = backOneUTF8Character(at: self.index)
|
index = backOneUTF8Character(at: index)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move back so many characters
|
/// Move back so many characters
|
||||||
@@ -379,20 +379,20 @@ extension HBParser {
|
|||||||
mutating func retreat(by amount: Int) throws {
|
mutating func retreat(by amount: Int) throws {
|
||||||
var amount = amount
|
var amount = amount
|
||||||
while amount > 0 {
|
while amount > 0 {
|
||||||
guard self.index > self.range.startIndex else { throw Error.overflow }
|
guard index > range.startIndex else { throw Error.overflow }
|
||||||
self.index = backOneUTF8Character(at: self.index)
|
index = backOneUTF8Character(at: index)
|
||||||
amount -= 1
|
amount -= 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func unsafeAdvance() {
|
mutating func unsafeAdvance() {
|
||||||
self.index = skipUTF8Character(at: self.index)
|
index = skipUTF8Character(at: index)
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func unsafeAdvance(by amount: Int) {
|
mutating func unsafeAdvance(by amount: Int) {
|
||||||
var amount = amount
|
var amount = amount
|
||||||
while amount > 0 {
|
while amount > 0 {
|
||||||
self.index = skipUTF8Character(at: self.index)
|
index = skipUTF8Character(at: index)
|
||||||
amount -= 1
|
amount -= 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -416,8 +416,8 @@ extension HBParser: Sequence {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mutating func next() -> Unicode.Scalar? {
|
mutating func next() -> Unicode.Scalar? {
|
||||||
guard !self.parser.reachedEnd() else { return nil }
|
guard !parser.reachedEnd() else { return nil }
|
||||||
return self.parser.unsafeCurrentAndAdvance()
|
return parser.unsafeCurrentAndAdvance()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -425,7 +425,7 @@ extension HBParser: Sequence {
|
|||||||
// internal versions without checks
|
// internal versions without checks
|
||||||
private extension HBParser {
|
private extension HBParser {
|
||||||
func unsafeCurrent() -> Unicode.Scalar {
|
func unsafeCurrent() -> Unicode.Scalar {
|
||||||
return decodeUTF8Character(at: self.index).0
|
return decodeUTF8Character(at: index).0
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func unsafeCurrentAndAdvance() -> Unicode.Scalar {
|
mutating func unsafeCurrentAndAdvance() -> Unicode.Scalar {
|
||||||
@@ -477,16 +477,16 @@ extension HBParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func skipUTF8Character(at index: Int) -> Int {
|
func skipUTF8Character(at index: Int) -> Int {
|
||||||
if self.buffer[index] & 0x80 != 0x80 { return index + 1 }
|
if buffer[index] & 0x80 != 0x80 { return index + 1 }
|
||||||
if self.buffer[index + 1] & 0xC0 == 0x80 { return index + 2 }
|
if buffer[index + 1] & 0xC0 == 0x80 { return index + 2 }
|
||||||
if self.buffer[index + 2] & 0xC0 == 0x80 { return index + 3 }
|
if buffer[index + 2] & 0xC0 == 0x80 { return index + 3 }
|
||||||
return index + 4
|
return index + 4
|
||||||
}
|
}
|
||||||
|
|
||||||
func backOneUTF8Character(at index: Int) -> Int {
|
func backOneUTF8Character(at index: Int) -> Int {
|
||||||
if self.buffer[index - 1] & 0xC0 != 0x80 { return index - 1 }
|
if buffer[index - 1] & 0xC0 != 0x80 { return index - 1 }
|
||||||
if self.buffer[index - 2] & 0xC0 != 0x80 { return index - 2 }
|
if buffer[index - 2] & 0xC0 != 0x80 { return index - 2 }
|
||||||
if self.buffer[index - 3] & 0xC0 != 0x80 { return index - 3 }
|
if buffer[index - 3] & 0xC0 != 0x80 { return index - 3 }
|
||||||
return index - 4
|
return index - 4
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -526,9 +526,9 @@ extension HBParser {
|
|||||||
|
|
||||||
/// return if the buffer is valid UTF8
|
/// return if the buffer is valid UTF8
|
||||||
func validateUTF8() -> Bool {
|
func validateUTF8() -> Bool {
|
||||||
var index = self.range.startIndex
|
var index = range.startIndex
|
||||||
while index < self.range.endIndex {
|
while index < range.endIndex {
|
||||||
let (scalar, newIndex) = self.validateUTF8Character(at: index)
|
let (scalar, newIndex) = validateUTF8Character(at: index)
|
||||||
guard scalar != nil else { return false }
|
guard scalar != nil else { return false }
|
||||||
index = newIndex
|
index = newIndex
|
||||||
}
|
}
|
||||||
@@ -598,17 +598,17 @@ extension HBParser {
|
|||||||
return newIndex
|
return newIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
guard self.index != self.range.endIndex else { return "" }
|
guard index != range.endIndex else { return "" }
|
||||||
do {
|
do {
|
||||||
if #available(macOS 11, *) {
|
if #available(macOS 11, *) {
|
||||||
return try String(unsafeUninitializedCapacity: range.endIndex - index) { bytes -> Int in
|
return try String(unsafeUninitializedCapacity: range.endIndex - index) { bytes -> Int in
|
||||||
return try _percentDecode(self.buffer[self.index..<range.endIndex], bytes)
|
try _percentDecode(self.buffer[self.index ..< range.endIndex], bytes)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let newBuffer = try [UInt8].init(unsafeUninitializedCapacity: self.range.endIndex - self.index) { bytes, count in
|
let newBuffer = try [UInt8].init(unsafeUninitializedCapacity: range.endIndex - index) { bytes, count in
|
||||||
try count = _percentDecode(self.buffer[self.index..<range.endIndex], bytes)
|
try count = _percentDecode(self.buffer[self.index ..< range.endIndex], bytes)
|
||||||
}
|
}
|
||||||
return self.makeString(newBuffer)
|
return makeString(newBuffer)
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
return nil
|
return nil
|
||||||
@@ -622,8 +622,8 @@ extension Unicode.Scalar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var isNewline: Bool {
|
var isNewline: Bool {
|
||||||
switch self.value {
|
switch value {
|
||||||
case 0x000A...0x000D /* LF ... CR */: return true
|
case 0x000A ... 0x000D /* LF ... CR */: return true
|
||||||
case 0x0085 /* NEXT LINE (NEL) */: return true
|
case 0x0085 /* NEXT LINE (NEL) */: return true
|
||||||
case 0x2028 /* LINE SEPARATOR */: return true
|
case 0x2028 /* LINE SEPARATOR */: return true
|
||||||
case 0x2029 /* PARAGRAPH SEPARATOR */: return true
|
case 0x2029 /* PARAGRAPH SEPARATOR */: return true
|
||||||
@@ -640,7 +640,7 @@ extension Unicode.Scalar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var isLetterOrNumber: Bool {
|
var isLetterOrNumber: Bool {
|
||||||
return self.isLetter || self.isNumber
|
return isLetter || isNumber
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ public protocol HBMustacheSequence {
|
|||||||
func renderInvertedSection(with template: HBMustacheTemplate) -> String
|
func renderInvertedSection(with template: HBMustacheTemplate) -> String
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Sequence {
|
public extension Sequence {
|
||||||
/// Render section using template
|
/// Render section using template
|
||||||
public func renderSection(with template: HBMustacheTemplate) -> String {
|
func renderSection(with template: HBMustacheTemplate) -> String {
|
||||||
var string = ""
|
var string = ""
|
||||||
var context = HBMustacheContext(first: true)
|
var context = HBMustacheContext(first: true)
|
||||||
var iterator = self.makeIterator()
|
var iterator = makeIterator()
|
||||||
guard var currentObject = iterator.next() else { return "" }
|
guard var currentObject = iterator.next() else { return "" }
|
||||||
|
|
||||||
while let object = iterator.next() {
|
while let object = iterator.next() {
|
||||||
@@ -29,14 +29,13 @@ extension Sequence {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Render inverted section using template
|
/// Render inverted section using template
|
||||||
public func renderInvertedSection(with template: HBMustacheTemplate) -> String {
|
func renderInvertedSection(with template: HBMustacheTemplate) -> String {
|
||||||
var iterator = makeIterator()
|
var iterator = makeIterator()
|
||||||
if iterator.next() == nil {
|
if iterator.next() == nil {
|
||||||
return template.render(self)
|
return template.render(self)
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Array: HBMustacheSequence {}
|
extension Array: HBMustacheSequence {}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ extension String {
|
|||||||
/// HTML escape string. Replace '<', '>' and '&' with HTML escaped versions
|
/// HTML escape string. Replace '<', '>' and '&' with HTML escaped versions
|
||||||
func htmlEscape() -> String {
|
func htmlEscape() -> String {
|
||||||
var newString = ""
|
var newString = ""
|
||||||
newString.reserveCapacity(self.count)
|
newString.reserveCapacity(count)
|
||||||
// currently doing this by going through each character could speed
|
// currently doing this by going through each character could speed
|
||||||
// this us by treating as an array of UInt8's
|
// this us by treating as an array of UInt8's
|
||||||
for c in self {
|
for c in self {
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ extension HBMustacheTemplate {
|
|||||||
/// parse variable name
|
/// parse variable name
|
||||||
static func parseName(_ parser: inout HBParser) throws -> (String, String?) {
|
static func parseName(_ parser: inout HBParser) throws -> (String, String?) {
|
||||||
parser.read(while: \.isWhitespace)
|
parser.read(while: \.isWhitespace)
|
||||||
var text = parser.read(while: sectionNameChars )
|
var text = parser.read(while: sectionNameChars)
|
||||||
parser.read(while: \.isWhitespace)
|
parser.read(while: \.isWhitespace)
|
||||||
guard try parser.read("}"), try parser.read("}") else { throw Error.unfinishedName }
|
guard try parser.read("}"), try parser.read("}") else { throw Error.unfinishedName }
|
||||||
// does the name include brackets. If so this is a method call
|
// does the name include brackets. If so this is a method call
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ extension HBMustacheTemplate {
|
|||||||
var string = ""
|
var string = ""
|
||||||
for token in tokens {
|
for token in tokens {
|
||||||
switch token {
|
switch token {
|
||||||
case .text(let text):
|
case let .text(text):
|
||||||
string += text
|
string += text
|
||||||
case .variable(let variable, let method):
|
case let .variable(variable, method):
|
||||||
if let child = getChild(named: variable, from: object, method: method, context: context) {
|
if let child = getChild(named: variable, from: object, method: method, context: context) {
|
||||||
if let template = child as? HBMustacheTemplate {
|
if let template = child as? HBMustacheTemplate {
|
||||||
string += template.render(object)
|
string += template.render(object)
|
||||||
@@ -19,19 +19,19 @@ extension HBMustacheTemplate {
|
|||||||
string += String(describing: child).htmlEscape()
|
string += String(describing: child).htmlEscape()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case .unescapedVariable(let variable, let method):
|
case let .unescapedVariable(variable, method):
|
||||||
if let child = getChild(named: variable, from: object, method: method, context: context) {
|
if let child = getChild(named: variable, from: object, method: method, context: context) {
|
||||||
string += String(describing: child)
|
string += String(describing: child)
|
||||||
}
|
}
|
||||||
case .section(let variable, let method, let template):
|
case let .section(variable, method, template):
|
||||||
let child = getChild(named: variable, from: object, method: method, context: context)
|
let child = getChild(named: variable, from: object, method: method, context: context)
|
||||||
string += renderSection(child, parent: object, with: template)
|
string += renderSection(child, parent: object, with: template)
|
||||||
|
|
||||||
case .invertedSection(let variable, let method, let template):
|
case let .invertedSection(variable, method, template):
|
||||||
let child = getChild(named: variable, from: object, method: method, context: context)
|
let child = getChild(named: variable, from: object, method: method, context: context)
|
||||||
string += renderInvertedSection(child, parent: object, with: template)
|
string += renderInvertedSection(child, parent: object, with: template)
|
||||||
|
|
||||||
case .partial(let name):
|
case let .partial(name):
|
||||||
if let text = library?.render(object, withTemplate: name) {
|
if let text = library?.render(object, withTemplate: name) {
|
||||||
string += text
|
string += text
|
||||||
}
|
}
|
||||||
@@ -54,7 +54,7 @@ extension HBMustacheTemplate {
|
|||||||
return bool ? template.render(parent) : ""
|
return bool ? template.render(parent) : ""
|
||||||
case let lambda as HBMustacheLambda:
|
case let lambda as HBMustacheLambda:
|
||||||
return lambda.run(parent, template)
|
return lambda.run(parent, template)
|
||||||
case .some(let value):
|
case let .some(value):
|
||||||
return template.render(value)
|
return template.render(value)
|
||||||
case .none:
|
case .none:
|
||||||
return ""
|
return ""
|
||||||
@@ -111,7 +111,8 @@ extension HBMustacheTemplate {
|
|||||||
// if we want to run a method and the current child can have methods applied to it then
|
// if we want to run a method and the current child can have methods applied to it then
|
||||||
// run method on the current child
|
// run method on the current child
|
||||||
if let method = method,
|
if let method = method,
|
||||||
let runnable = child as? HBMustacheMethods {
|
let runnable = child as? HBMustacheMethods
|
||||||
|
{
|
||||||
if let result = runnable.runMethod(method) {
|
if let result = runnable.runMethod(method) {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -119,4 +120,3 @@ extension HBMustacheTemplate {
|
|||||||
return child
|
return child
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ public class HBMustacheTemplate {
|
|||||||
/// - Parameter string: Template text
|
/// - Parameter string: Template text
|
||||||
/// - Throws: HBMustacheTemplate.Error
|
/// - Throws: HBMustacheTemplate.Error
|
||||||
public init(string: String) throws {
|
public init(string: String) throws {
|
||||||
self.tokens = try Self.parse(string)
|
tokens = try Self.parse(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Render object using this template
|
/// Render object using this template
|
||||||
/// - Parameter object: Object to render
|
/// - Parameter object: Object to render
|
||||||
/// - Returns: Rendered text
|
/// - Returns: Rendered text
|
||||||
public func render(_ object: Any) -> String {
|
public func render(_ object: Any) -> String {
|
||||||
self.render(object, context: nil)
|
render(object, context: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal init(_ tokens: [Token]) {
|
internal init(_ tokens: [Token]) {
|
||||||
@@ -22,7 +22,7 @@ public class HBMustacheTemplate {
|
|||||||
self.library = library
|
self.library = library
|
||||||
for token in tokens {
|
for token in tokens {
|
||||||
switch token {
|
switch token {
|
||||||
case .section(_, _, let template), .invertedSection(_, _, let template):
|
case let .section(_, _, template), let .invertedSection(_, _, template):
|
||||||
template.setLibrary(library)
|
template.setLibrary(library)
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
@@ -42,4 +42,3 @@ public class HBMustacheTemplate {
|
|||||||
let tokens: [Token]
|
let tokens: [Token]
|
||||||
var library: HBMustacheLibrary?
|
var library: HBMustacheLibrary?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import XCTest
|
|
||||||
@testable import HummingbirdMustache
|
@testable import HummingbirdMustache
|
||||||
|
import XCTest
|
||||||
|
|
||||||
final class LibraryTests: XCTestCase {
|
final class LibraryTests: XCTestCase {
|
||||||
func testDirectoryLoad() throws {
|
func testDirectoryLoad() throws {
|
||||||
|
|||||||
@@ -1,117 +1,117 @@
|
|||||||
import XCTest
|
|
||||||
import HummingbirdMustache
|
import HummingbirdMustache
|
||||||
|
import XCTest
|
||||||
|
|
||||||
final class MethodTests: XCTestCase {
|
final class MethodTests: XCTestCase {
|
||||||
func testLowercased() throws {
|
func testLowercased() throws {
|
||||||
let template = try HBMustacheTemplate(string: """
|
let template = try HBMustacheTemplate(string: """
|
||||||
{{ lowercased(name) }}
|
{{ lowercased(name) }}
|
||||||
""")
|
""")
|
||||||
let object: [String: Any] = ["name": "Test"]
|
let object: [String: Any] = ["name": "Test"]
|
||||||
XCTAssertEqual(template.render(object), "test")
|
XCTAssertEqual(template.render(object), "test")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testUppercased() throws {
|
func testUppercased() throws {
|
||||||
let template = try HBMustacheTemplate(string: """
|
let template = try HBMustacheTemplate(string: """
|
||||||
{{ uppercased(name) }}
|
{{ uppercased(name) }}
|
||||||
""")
|
""")
|
||||||
let object: [String: Any] = ["name": "Test"]
|
let object: [String: Any] = ["name": "Test"]
|
||||||
XCTAssertEqual(template.render(object), "TEST")
|
XCTAssertEqual(template.render(object), "TEST")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testFirstLast() throws {
|
func testFirstLast() throws {
|
||||||
let template = try HBMustacheTemplate(string: """
|
let template = try HBMustacheTemplate(string: """
|
||||||
{{#repo}}
|
{{#repo}}
|
||||||
<b>{{#first()}}first: {{/}}{{#last()}}last: {{/}}{{ name }}</b>
|
<b>{{#first()}}first: {{/}}{{#last()}}last: {{/}}{{ name }}</b>
|
||||||
{{/repo}}
|
{{/repo}}
|
||||||
""")
|
""")
|
||||||
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
||||||
XCTAssertEqual(template.render(object), """
|
XCTAssertEqual(template.render(object), """
|
||||||
<b>first: resque</b>
|
<b>first: resque</b>
|
||||||
<b>hub</b>
|
<b>hub</b>
|
||||||
<b>last: rip</b>
|
<b>last: rip</b>
|
||||||
|
|
||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testIndex() throws {
|
func testIndex() throws {
|
||||||
let template = try HBMustacheTemplate(string: """
|
let template = try HBMustacheTemplate(string: """
|
||||||
{{#repo}}
|
{{#repo}}
|
||||||
<b>{{#index()}}{{plusone(.)}}{{/}}) {{ name }}</b>
|
<b>{{#index()}}{{plusone(.)}}{{/}}) {{ name }}</b>
|
||||||
{{/repo}}
|
{{/repo}}
|
||||||
""")
|
""")
|
||||||
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
||||||
XCTAssertEqual(template.render(object), """
|
XCTAssertEqual(template.render(object), """
|
||||||
<b>1) resque</b>
|
<b>1) resque</b>
|
||||||
<b>2) hub</b>
|
<b>2) hub</b>
|
||||||
<b>3) rip</b>
|
<b>3) rip</b>
|
||||||
|
|
||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testEvenOdd() throws {
|
func testEvenOdd() throws {
|
||||||
let template = try HBMustacheTemplate(string: """
|
let template = try HBMustacheTemplate(string: """
|
||||||
{{#repo}}
|
{{#repo}}
|
||||||
<b>{{index()}}) {{#even()}}even {{/}}{{#odd()}}odd {{/}}{{ name }}</b>
|
<b>{{index()}}) {{#even()}}even {{/}}{{#odd()}}odd {{/}}{{ name }}</b>
|
||||||
{{/repo}}
|
{{/repo}}
|
||||||
""")
|
""")
|
||||||
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
||||||
XCTAssertEqual(template.render(object), """
|
XCTAssertEqual(template.render(object), """
|
||||||
<b>0) even resque</b>
|
<b>0) even resque</b>
|
||||||
<b>1) odd hub</b>
|
<b>1) odd hub</b>
|
||||||
<b>2) even rip</b>
|
<b>2) even rip</b>
|
||||||
|
|
||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testReversed() throws {
|
func testReversed() throws {
|
||||||
let template = try HBMustacheTemplate(string: """
|
let template = try HBMustacheTemplate(string: """
|
||||||
{{#reversed(repo)}}
|
{{#reversed(repo)}}
|
||||||
<b>{{ name }}</b>
|
<b>{{ name }}</b>
|
||||||
{{/repo}}
|
{{/repo}}
|
||||||
""")
|
""")
|
||||||
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
||||||
XCTAssertEqual(template.render(object), """
|
XCTAssertEqual(template.render(object), """
|
||||||
<b>rip</b>
|
<b>rip</b>
|
||||||
<b>hub</b>
|
<b>hub</b>
|
||||||
<b>resque</b>
|
<b>resque</b>
|
||||||
|
|
||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testArrayIndex() throws {
|
func testArrayIndex() throws {
|
||||||
let template = try HBMustacheTemplate(string: """
|
let template = try HBMustacheTemplate(string: """
|
||||||
{{#repo}}
|
{{#repo}}
|
||||||
<b>{{ index() }}) {{ name }}</b>
|
<b>{{ index() }}) {{ name }}</b>
|
||||||
{{/repo}}
|
{{/repo}}
|
||||||
""")
|
""")
|
||||||
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
||||||
XCTAssertEqual(template.render(object), """
|
XCTAssertEqual(template.render(object), """
|
||||||
<b>0) resque</b>
|
<b>0) resque</b>
|
||||||
<b>1) hub</b>
|
<b>1) hub</b>
|
||||||
<b>2) rip</b>
|
<b>2) rip</b>
|
||||||
|
|
||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testArraySorted() throws {
|
func testArraySorted() throws {
|
||||||
let template = try HBMustacheTemplate(string: """
|
let template = try HBMustacheTemplate(string: """
|
||||||
{{#sorted(repo)}}
|
{{#sorted(repo)}}
|
||||||
<b>{{ index() }}) {{ . }}</b>
|
<b>{{ index() }}) {{ . }}</b>
|
||||||
{{/repo}}
|
{{/repo}}
|
||||||
""")
|
""")
|
||||||
let object: [String: Any] = ["repo": ["resque", "hub", "rip"]]
|
let object: [String: Any] = ["repo": ["resque", "hub", "rip"]]
|
||||||
XCTAssertEqual(template.render(object), """
|
XCTAssertEqual(template.render(object), """
|
||||||
<b>0) hub</b>
|
<b>0) hub</b>
|
||||||
<b>1) resque</b>
|
<b>1) resque</b>
|
||||||
<b>2) rip</b>
|
<b>2) rip</b>
|
||||||
|
|
||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testDictionaryEnumerated() throws {
|
func testDictionaryEnumerated() throws {
|
||||||
let template = try HBMustacheTemplate(string: """
|
let template = try HBMustacheTemplate(string: """
|
||||||
{{#enumerated(.)}}<b>{{ key }} = {{ value }}</b>{{/.}}
|
{{#enumerated(.)}}<b>{{ key }} = {{ value }}</b>{{/.}}
|
||||||
""")
|
""")
|
||||||
let object: [String: Any] = ["one": 1, "two": 2]
|
let object: [String: Any] = ["one": 1, "two": 2]
|
||||||
let result = template.render(object)
|
let result = template.render(object)
|
||||||
XCTAssertTrue(result == "<b>one = 1</b><b>two = 2</b>" || result == "<b>two = 2</b><b>one = 1</b>")
|
XCTAssertTrue(result == "<b>one = 1</b><b>two = 2</b>" || result == "<b>two = 2</b><b>one = 1</b>")
|
||||||
@@ -119,11 +119,10 @@ final class MethodTests: XCTestCase {
|
|||||||
|
|
||||||
func testDictionarySortedByKey() throws {
|
func testDictionarySortedByKey() throws {
|
||||||
let template = try HBMustacheTemplate(string: """
|
let template = try HBMustacheTemplate(string: """
|
||||||
{{#sorted(.)}}<b>{{ key }} = {{ value }}</b>{{/.}}
|
{{#sorted(.)}}<b>{{ key }} = {{ value }}</b>{{/.}}
|
||||||
""")
|
""")
|
||||||
let object: [String: Any] = ["one": 1, "two": 2, "three": 3]
|
let object: [String: Any] = ["one": 1, "two": 2, "three": 3]
|
||||||
let result = template.render(object)
|
let result = template.render(object)
|
||||||
XCTAssertEqual(result, "<b>one = 1</b><b>three = 3</b><b>two = 2</b>")
|
XCTAssertEqual(result, "<b>one = 1</b><b>three = 3</b><b>two = 2</b>")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,54 +1,53 @@
|
|||||||
import XCTest
|
|
||||||
@testable import HummingbirdMustache
|
@testable import HummingbirdMustache
|
||||||
|
import XCTest
|
||||||
|
|
||||||
final class PartialTests: XCTestCase {
|
final class PartialTests: XCTestCase {
|
||||||
|
|
||||||
/// Testing partials
|
/// Testing partials
|
||||||
func testMustacheManualExample9() throws {
|
func testMustacheManualExample9() throws {
|
||||||
let library = HBMustacheLibrary()
|
let library = HBMustacheLibrary()
|
||||||
let template = try HBMustacheTemplate(string: """
|
let template = try HBMustacheTemplate(string: """
|
||||||
<h2>Names</h2>
|
<h2>Names</h2>
|
||||||
{{#names}}
|
{{#names}}
|
||||||
{{> user}}
|
{{> user}}
|
||||||
{{/names}}
|
{{/names}}
|
||||||
""")
|
""")
|
||||||
let template2 = try HBMustacheTemplate(string: """
|
let template2 = try HBMustacheTemplate(string: """
|
||||||
<strong>{{.}}</strong>
|
<strong>{{.}}</strong>
|
||||||
""")
|
""")
|
||||||
library.register(template, named: "base")
|
library.register(template, named: "base")
|
||||||
library.register(template2, named: "user")
|
library.register(template2, named: "user")
|
||||||
|
|
||||||
let object: [String: Any] = ["names": ["john", "adam", "claire"]]
|
let object: [String: Any] = ["names": ["john", "adam", "claire"]]
|
||||||
XCTAssertEqual(library.render(object, withTemplate: "base"), """
|
XCTAssertEqual(library.render(object, withTemplate: "base"), """
|
||||||
<h2>Names</h2>
|
<h2>Names</h2>
|
||||||
<strong>john</strong>
|
<strong>john</strong>
|
||||||
<strong>adam</strong>
|
<strong>adam</strong>
|
||||||
<strong>claire</strong>
|
<strong>claire</strong>
|
||||||
|
|
||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Testing dynamic partials
|
/// Testing dynamic partials
|
||||||
func testDynamicPartials() throws {
|
func testDynamicPartials() throws {
|
||||||
let library = HBMustacheLibrary()
|
let library = HBMustacheLibrary()
|
||||||
let template = try HBMustacheTemplate(string: """
|
let template = try HBMustacheTemplate(string: """
|
||||||
<h2>Names</h2>
|
<h2>Names</h2>
|
||||||
{{partial}}
|
{{partial}}
|
||||||
""")
|
""")
|
||||||
let template2 = try HBMustacheTemplate(string: """
|
let template2 = try HBMustacheTemplate(string: """
|
||||||
{{#names}}
|
{{#names}}
|
||||||
<strong>{{.}}</strong>
|
<strong>{{.}}</strong>
|
||||||
{{/names}}
|
{{/names}}
|
||||||
""")
|
""")
|
||||||
library.register(template, named: "base")
|
library.register(template, named: "base")
|
||||||
|
|
||||||
let object: [String: Any] = ["names": ["john", "adam", "claire"], "partial": template2]
|
let object: [String: Any] = ["names": ["john", "adam", "claire"], "partial": template2]
|
||||||
XCTAssertEqual(library.render(object, withTemplate: "base"), """
|
XCTAssertEqual(library.render(object, withTemplate: "base"), """
|
||||||
<h2>Names</h2>
|
<h2>Names</h2>
|
||||||
<strong>john</strong>
|
<strong>john</strong>
|
||||||
<strong>adam</strong>
|
<strong>adam</strong>
|
||||||
<strong>claire</strong>
|
<strong>claire</strong>
|
||||||
|
|
||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import XCTest
|
|
||||||
@testable import HummingbirdMustache
|
@testable import HummingbirdMustache
|
||||||
|
import XCTest
|
||||||
|
|
||||||
final class TemplateParserTests: XCTestCase {
|
final class TemplateParserTests: XCTestCase {
|
||||||
func testText() throws {
|
func testText() throws {
|
||||||
@@ -75,15 +75,15 @@ extension HBMustacheTemplate: Equatable {
|
|||||||
extension HBMustacheTemplate.Token: Equatable {
|
extension HBMustacheTemplate.Token: Equatable {
|
||||||
public static func == (lhs: HBMustacheTemplate.Token, rhs: HBMustacheTemplate.Token) -> Bool {
|
public static func == (lhs: HBMustacheTemplate.Token, rhs: HBMustacheTemplate.Token) -> Bool {
|
||||||
switch (lhs, rhs) {
|
switch (lhs, rhs) {
|
||||||
case (.text(let lhs), .text(let rhs)):
|
case let (.text(lhs), .text(rhs)):
|
||||||
return lhs == rhs
|
return lhs == rhs
|
||||||
case (.variable(let lhs, let lhs2), .variable(let rhs, let rhs2)):
|
case let (.variable(lhs, lhs2), .variable(rhs, rhs2)):
|
||||||
return lhs == rhs && lhs2 == rhs2
|
return lhs == rhs && lhs2 == rhs2
|
||||||
case (.section(let lhs1, let lhs2, let lhs3), .section(let rhs1, let rhs2, let rhs3)):
|
case let (.section(lhs1, lhs2, lhs3), .section(rhs1, rhs2, rhs3)):
|
||||||
return lhs1 == rhs1 && lhs2 == rhs2 && lhs3 == rhs3
|
return lhs1 == rhs1 && lhs2 == rhs2 && lhs3 == rhs3
|
||||||
case (.invertedSection(let lhs1, let lhs2, let lhs3), .invertedSection(let rhs1, let rhs2, let rhs3)):
|
case let (.invertedSection(lhs1, lhs2, lhs3), .invertedSection(rhs1, rhs2, rhs3)):
|
||||||
return lhs1 == rhs1 && lhs2 == rhs2 && lhs3 == rhs3
|
return lhs1 == rhs1 && lhs2 == rhs2 && lhs3 == rhs3
|
||||||
case (.partial(let name1), .partial(let name2)):
|
case let (.partial(name1), .partial(name2)):
|
||||||
return name1 == name2
|
return name1 == name2
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import XCTest
|
|
||||||
@testable import HummingbirdMustache
|
@testable import HummingbirdMustache
|
||||||
|
import XCTest
|
||||||
|
|
||||||
final class TemplateRendererTests: XCTestCase {
|
final class TemplateRendererTests: XCTestCase {
|
||||||
func testText() throws {
|
func testText() throws {
|
||||||
@@ -95,134 +95,134 @@ final class TemplateRendererTests: XCTestCase {
|
|||||||
/// variables
|
/// variables
|
||||||
func testMustacheManualExample1() throws {
|
func testMustacheManualExample1() throws {
|
||||||
let template = try HBMustacheTemplate(string: """
|
let template = try HBMustacheTemplate(string: """
|
||||||
Hello {{name}}
|
Hello {{name}}
|
||||||
You have just won {{value}} dollars!
|
You have just won {{value}} dollars!
|
||||||
{{#in_ca}}
|
{{#in_ca}}
|
||||||
Well, {{taxed_value}} dollars, after taxes.
|
Well, {{taxed_value}} dollars, after taxes.
|
||||||
{{/in_ca}}
|
{{/in_ca}}
|
||||||
""")
|
""")
|
||||||
let object: [String: Any] = ["name": "Chris", "value": 10000, "taxed_value": 10000 - (10000 * 0.4), "in_ca": true]
|
let object: [String: Any] = ["name": "Chris", "value": 10000, "taxed_value": 10000 - (10000 * 0.4), "in_ca": true]
|
||||||
XCTAssertEqual(template.render(object), """
|
XCTAssertEqual(template.render(object), """
|
||||||
Hello Chris
|
Hello Chris
|
||||||
You have just won 10000 dollars!
|
You have just won 10000 dollars!
|
||||||
Well, 6000.0 dollars, after taxes.
|
Well, 6000.0 dollars, after taxes.
|
||||||
|
|
||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// test esacped and unescaped text
|
/// test esacped and unescaped text
|
||||||
func testMustacheManualExample2() throws {
|
func testMustacheManualExample2() throws {
|
||||||
let template = try HBMustacheTemplate(string: """
|
let template = try HBMustacheTemplate(string: """
|
||||||
*{{name}}
|
*{{name}}
|
||||||
*{{age}}
|
*{{age}}
|
||||||
*{{company}}
|
*{{company}}
|
||||||
*{{{company}}}
|
*{{{company}}}
|
||||||
""")
|
""")
|
||||||
let object: [String: Any] = ["name": "Chris", "company": "<b>GitHub</b>"]
|
let object: [String: Any] = ["name": "Chris", "company": "<b>GitHub</b>"]
|
||||||
XCTAssertEqual(template.render(object), """
|
XCTAssertEqual(template.render(object), """
|
||||||
*Chris
|
*Chris
|
||||||
*
|
*
|
||||||
*<b>GitHub</b>
|
*<b>GitHub</b>
|
||||||
*<b>GitHub</b>
|
*<b>GitHub</b>
|
||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// test boolean
|
/// test boolean
|
||||||
func testMustacheManualExample3() throws {
|
func testMustacheManualExample3() throws {
|
||||||
let template = try HBMustacheTemplate(string: """
|
let template = try HBMustacheTemplate(string: """
|
||||||
Shown.
|
Shown.
|
||||||
{{#person}}
|
{{#person}}
|
||||||
Never shown!
|
Never shown!
|
||||||
{{/person}}
|
{{/person}}
|
||||||
""")
|
""")
|
||||||
let object: [String: Any] = ["person": false]
|
let object: [String: Any] = ["person": false]
|
||||||
XCTAssertEqual(template.render(object), """
|
XCTAssertEqual(template.render(object), """
|
||||||
Shown.
|
Shown.
|
||||||
|
|
||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// test non-empty lists
|
/// test non-empty lists
|
||||||
func testMustacheManualExample4() throws {
|
func testMustacheManualExample4() throws {
|
||||||
let template = try HBMustacheTemplate(string: """
|
let template = try HBMustacheTemplate(string: """
|
||||||
{{#repo}}
|
{{#repo}}
|
||||||
<b>{{name}}</b>
|
<b>{{name}}</b>
|
||||||
{{/repo}}
|
{{/repo}}
|
||||||
""")
|
""")
|
||||||
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
||||||
XCTAssertEqual(template.render(object), """
|
XCTAssertEqual(template.render(object), """
|
||||||
<b>resque</b>
|
<b>resque</b>
|
||||||
<b>hub</b>
|
<b>hub</b>
|
||||||
<b>rip</b>
|
<b>rip</b>
|
||||||
|
|
||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// test lambdas
|
/// test lambdas
|
||||||
func testMustacheManualExample5() throws {
|
func testMustacheManualExample5() throws {
|
||||||
let template = try HBMustacheTemplate(string: """
|
let template = try HBMustacheTemplate(string: """
|
||||||
{{#wrapped}}{{name}} is awesome.{{/wrapped}}
|
{{#wrapped}}{{name}} is awesome.{{/wrapped}}
|
||||||
""")
|
""")
|
||||||
func wrapped(object: Any, template: HBMustacheTemplate) -> String {
|
func wrapped(object: Any, template: HBMustacheTemplate) -> String {
|
||||||
return "<b>\(template.render(object))</b>"
|
return "<b>\(template.render(object))</b>"
|
||||||
}
|
}
|
||||||
let object: [String: Any] = ["name": "Willy", "wrapped": HBMustacheLambda(wrapped)]
|
let object: [String: Any] = ["name": "Willy", "wrapped": HBMustacheLambda(wrapped)]
|
||||||
XCTAssertEqual(template.render(object), """
|
XCTAssertEqual(template.render(object), """
|
||||||
<b>Willy is awesome.</b>
|
<b>Willy is awesome.</b>
|
||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// test setting context object
|
/// test setting context object
|
||||||
func testMustacheManualExample6() throws {
|
func testMustacheManualExample6() throws {
|
||||||
let template = try HBMustacheTemplate(string: """
|
let template = try HBMustacheTemplate(string: """
|
||||||
{{#person?}}
|
{{#person?}}
|
||||||
Hi {{name}}!
|
Hi {{name}}!
|
||||||
{{/person?}}
|
{{/person?}}
|
||||||
""")
|
""")
|
||||||
let object: [String: Any] = ["person?": ["name": "Jon"]]
|
let object: [String: Any] = ["person?": ["name": "Jon"]]
|
||||||
XCTAssertEqual(template.render(object), """
|
XCTAssertEqual(template.render(object), """
|
||||||
Hi Jon!
|
Hi Jon!
|
||||||
|
|
||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// test inverted sections
|
/// test inverted sections
|
||||||
func testMustacheManualExample7() throws {
|
func testMustacheManualExample7() throws {
|
||||||
let template = try HBMustacheTemplate(string: """
|
let template = try HBMustacheTemplate(string: """
|
||||||
{{#repo}}
|
{{#repo}}
|
||||||
<b>{{name}}</b>
|
<b>{{name}}</b>
|
||||||
{{/repo}}
|
{{/repo}}
|
||||||
{{^repo}}
|
{{^repo}}
|
||||||
No repos :(
|
No repos :(
|
||||||
{{/repo}}
|
{{/repo}}
|
||||||
""")
|
""")
|
||||||
let object: [String: Any] = ["repo": []]
|
let object: [String: Any] = ["repo": []]
|
||||||
XCTAssertEqual(template.render(object), """
|
XCTAssertEqual(template.render(object), """
|
||||||
No repos :(
|
No repos :(
|
||||||
|
|
||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// test comments
|
/// test comments
|
||||||
func testMustacheManualExample8() throws {
|
func testMustacheManualExample8() throws {
|
||||||
let template = try HBMustacheTemplate(string: """
|
let template = try HBMustacheTemplate(string: """
|
||||||
<h1>Today{{! ignore me }}.</h1>
|
<h1>Today{{! ignore me }}.</h1>
|
||||||
""")
|
""")
|
||||||
let object: [String: Any] = ["repo": []]
|
let object: [String: Any] = ["repo": []]
|
||||||
XCTAssertEqual(template.render(object), """
|
XCTAssertEqual(template.render(object), """
|
||||||
<h1>Today.</h1>
|
<h1>Today.</h1>
|
||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testPerformance() throws {
|
func testPerformance() throws {
|
||||||
let template = try HBMustacheTemplate(string: """
|
let template = try HBMustacheTemplate(string: """
|
||||||
{{#repo}}
|
{{#repo}}
|
||||||
<b>{{name}}</b>
|
<b>{{name}}</b>
|
||||||
{{/repo}}
|
{{/repo}}
|
||||||
""")
|
""")
|
||||||
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
||||||
let date = Date()
|
let date = Date()
|
||||||
for _ in 1...10000 {
|
for _ in 1 ... 10000 {
|
||||||
_ = template.render(object)
|
_ = template.render(object)
|
||||||
}
|
}
|
||||||
print(-date.timeIntervalSinceNow)
|
print(-date.timeIntervalSinceNow)
|
||||||
|
|||||||
Reference in New Issue
Block a user