Update from Hummingbird Project Template (#58)
* Update from hummingbird-project-template 572d468b2cabeca286314c5a35196bd42445c8ef * run swift-format * Remove .swiftformat --------- Co-authored-by: adam-fowler <adam-fowler@users.noreply.github.com> Co-authored-by: Adam Fowler <adamfowler71@gmail.com>
This commit is contained in:
committed by
GitHub
parent
8c5c8ead74
commit
ec4ef9aa04
6
.github/workflows/validate.yml
vendored
6
.github/workflows/validate.yml
vendored
@@ -8,16 +8,12 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
runs-on: macOS-latest
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
brew install mint
|
||||
mint install NickLockwood/SwiftFormat@0.53.10 --no-link
|
||||
- name: run script
|
||||
run: ./scripts/validate.sh
|
||||
|
||||
63
.swift-format
Normal file
63
.swift-format
Normal file
@@ -0,0 +1,63 @@
|
||||
{
|
||||
"version" : 1,
|
||||
"indentation" : {
|
||||
"spaces" : 4
|
||||
},
|
||||
"tabWidth" : 4,
|
||||
"fileScopedDeclarationPrivacy" : {
|
||||
"accessLevel" : "private"
|
||||
},
|
||||
"spacesAroundRangeFormationOperators" : false,
|
||||
"indentConditionalCompilationBlocks" : false,
|
||||
"indentSwitchCaseLabels" : false,
|
||||
"lineBreakAroundMultilineExpressionChainComponents" : false,
|
||||
"lineBreakBeforeControlFlowKeywords" : false,
|
||||
"lineBreakBeforeEachArgument" : true,
|
||||
"lineBreakBeforeEachGenericRequirement" : true,
|
||||
"lineLength" : 150,
|
||||
"maximumBlankLines" : 1,
|
||||
"respectsExistingLineBreaks" : true,
|
||||
"prioritizeKeepingFunctionOutputTogether" : true,
|
||||
"multiElementCollectionTrailingCommas" : true,
|
||||
"rules" : {
|
||||
"AllPublicDeclarationsHaveDocumentation" : false,
|
||||
"AlwaysUseLiteralForEmptyCollectionInit" : false,
|
||||
"AlwaysUseLowerCamelCase" : false,
|
||||
"AmbiguousTrailingClosureOverload" : true,
|
||||
"BeginDocumentationCommentWithOneLineSummary" : false,
|
||||
"DoNotUseSemicolons" : true,
|
||||
"DontRepeatTypeInStaticProperties" : true,
|
||||
"FileScopedDeclarationPrivacy" : true,
|
||||
"FullyIndirectEnum" : true,
|
||||
"GroupNumericLiterals" : true,
|
||||
"IdentifiersMustBeASCII" : true,
|
||||
"NeverForceUnwrap" : false,
|
||||
"NeverUseForceTry" : false,
|
||||
"NeverUseImplicitlyUnwrappedOptionals" : false,
|
||||
"NoAccessLevelOnExtensionDeclaration" : true,
|
||||
"NoAssignmentInExpressions" : true,
|
||||
"NoBlockComments" : true,
|
||||
"NoCasesWithOnlyFallthrough" : true,
|
||||
"NoEmptyTrailingClosureParentheses" : true,
|
||||
"NoLabelsInCasePatterns" : true,
|
||||
"NoLeadingUnderscores" : false,
|
||||
"NoParensAroundConditions" : true,
|
||||
"NoVoidReturnOnFunctionSignature" : true,
|
||||
"OmitExplicitReturns" : true,
|
||||
"OneCasePerLine" : true,
|
||||
"OneVariableDeclarationPerLine" : true,
|
||||
"OnlyOneTrailingClosureArgument" : true,
|
||||
"OrderedImports" : true,
|
||||
"ReplaceForEachWithForLoop" : true,
|
||||
"ReturnVoidInsteadOfEmptyTuple" : true,
|
||||
"UseEarlyExits" : false,
|
||||
"UseExplicitNilCheckInConditions" : false,
|
||||
"UseLetInEveryBoundCaseVariable" : false,
|
||||
"UseShorthandTypeNames" : true,
|
||||
"UseSingleLinePropertyGetter" : false,
|
||||
"UseSynthesizedInitializer" : false,
|
||||
"UseTripleSlashForDocumentationComments" : true,
|
||||
"UseWhereClausesInForLoops" : false,
|
||||
"ValidateDocumentationComments" : false
|
||||
}
|
||||
}
|
||||
26
.swiftformat
26
.swiftformat
@@ -1,26 +0,0 @@
|
||||
# Minimum swiftformat version
|
||||
--minversion 0.53.10
|
||||
|
||||
# Swift version
|
||||
--swiftversion 5.9
|
||||
|
||||
# file options
|
||||
--exclude .build
|
||||
|
||||
# rules
|
||||
--disable redundantReturn, extensionAccessControl, typeSugar, conditionalAssignment, preferForLoop, redundantInternal, redundantStaticSelf
|
||||
|
||||
# format options
|
||||
--ifdef no-indent
|
||||
--nospaceoperators ...,..<
|
||||
--patternlet inline
|
||||
--self insert
|
||||
--stripunusedargs unnamed-only
|
||||
|
||||
#--maxwidth 150
|
||||
--wraparguments before-first
|
||||
--wrapparameters before-first
|
||||
--wrapcollections before-first
|
||||
|
||||
#file header
|
||||
# --header "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the Hummingbird server framework project\n//\n// Copyright (c) {created.year}-{year} the Hummingbird authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See hummingbird/CONTRIBUTORS.txt for the list of Hummingbird authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//"
|
||||
@@ -28,4 +28,4 @@ The main development branch of the repository is `main`.
|
||||
|
||||
### Formatting
|
||||
|
||||
We use Nick Lockwood's SwiftFormat for formatting code. PRs will not be accepted if they haven't be formatted. The current version of SwiftFormat we are using is v0.53.10.
|
||||
We use Apple's swift-format for formatting code. PRs will not be accepted if they haven't be formatted.
|
||||
@@ -7,7 +7,7 @@ let package = Package(
|
||||
name: "swift-mustache",
|
||||
platforms: [.macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6)],
|
||||
products: [
|
||||
.library(name: "Mustache", targets: ["Mustache"]),
|
||||
.library(name: "Mustache", targets: ["Mustache"])
|
||||
],
|
||||
dependencies: [],
|
||||
targets: [
|
||||
|
||||
@@ -21,14 +21,14 @@ public protocol MustacheContentType: Sendable {
|
||||
/// Text content type where no character is escaped
|
||||
struct TextContentType: MustacheContentType {
|
||||
func escapeText(_ text: String) -> String {
|
||||
return text
|
||||
text
|
||||
}
|
||||
}
|
||||
|
||||
/// HTML content where text is escaped for HTML output
|
||||
struct HTMLContentType: MustacheContentType {
|
||||
func escapeText(_ text: String) -> String {
|
||||
return text.htmlEscape()
|
||||
text.htmlEscape()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ struct HTMLContentType: MustacheContentType {
|
||||
/// with `MustacheContentTypes.register`.
|
||||
public enum MustacheContentTypes {
|
||||
static func get(_ name: String) -> MustacheContentType? {
|
||||
return self.types[name]
|
||||
self.types[name]
|
||||
}
|
||||
|
||||
/// Register new content type
|
||||
|
||||
@@ -131,7 +131,7 @@ struct MustacheContext {
|
||||
|
||||
/// return context with sequence info and sequence element added to stack
|
||||
func withContentType(_ contentType: MustacheContentType) -> MustacheContext {
|
||||
return .init(
|
||||
.init(
|
||||
stack: self.stack,
|
||||
sequenceContext: self.sequenceContext,
|
||||
indentation: self.indentation,
|
||||
|
||||
@@ -50,6 +50,6 @@ public struct MustacheLambda {
|
||||
}
|
||||
|
||||
internal func callAsFunction(_ s: String) -> Any? {
|
||||
return self.callback(s)
|
||||
self.callback(s)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,5 +21,5 @@ public protocol MustacheParent {
|
||||
/// Extend dictionary where the key is a string so that it uses the key values to access
|
||||
/// it values
|
||||
extension Dictionary: MustacheParent where Key == String {
|
||||
public func child(named: String) -> Any? { return self[named] }
|
||||
public func child(named: String) -> Any? { self[named] }
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ struct Parser {
|
||||
self.position = string.startIndex
|
||||
}
|
||||
|
||||
var buffer: String { return self._storage.buffer }
|
||||
var buffer: String { self._storage.buffer }
|
||||
private(set) var position: String.Index
|
||||
}
|
||||
|
||||
@@ -59,7 +59,10 @@ extension Parser {
|
||||
/// - Returns: If current character was the one we expected
|
||||
mutating func read(_ char: Character) throws -> Bool {
|
||||
let c = try character()
|
||||
guard c == char else { unsafeRetreat(); return false }
|
||||
guard c == char else {
|
||||
unsafeRetreat()
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -84,7 +87,10 @@ extension Parser {
|
||||
/// - Returns: If current character is in character set
|
||||
mutating func read(_ characterSet: Set<Character>) throws -> Bool {
|
||||
let c = try character()
|
||||
guard characterSet.contains(c) else { unsafeRetreat(); return false }
|
||||
guard characterSet.contains(c) else {
|
||||
unsafeRetreat()
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -286,13 +292,13 @@ extension Parser {
|
||||
/// Return whether we have reached the end of the buffer
|
||||
/// - Returns: Have we reached the end
|
||||
func reachedEnd() -> Bool {
|
||||
return self.position == self.buffer.endIndex
|
||||
self.position == self.buffer.endIndex
|
||||
}
|
||||
|
||||
/// Return whether we are at the start of the buffer
|
||||
/// - Returns: Are we are the start
|
||||
func atStart() -> Bool {
|
||||
return self.position == self.buffer.startIndex
|
||||
self.position == self.buffer.startIndex
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,7 +384,7 @@ extension Parser {
|
||||
// unsafe versions without checks
|
||||
extension Parser {
|
||||
func unsafeCurrent() -> Character {
|
||||
return self.buffer[self.position]
|
||||
self.buffer[self.position]
|
||||
}
|
||||
|
||||
mutating func unsafeAdvance() {
|
||||
|
||||
@@ -327,7 +327,8 @@ extension MustacheTemplate {
|
||||
}
|
||||
if self.isStandalone(&parser, state: state) {
|
||||
setNewLine = true
|
||||
} else if whiteSpaceBefore.count > 0 {}
|
||||
} else if whiteSpaceBefore.count > 0 {
|
||||
}
|
||||
let sectionTemplate = try parse(&parser, state: state.withSectionName(name, newLine: setNewLine))
|
||||
tokens.append(.blockExpansion(name: name, default: sectionTemplate, indentation: String(whiteSpaceBefore)))
|
||||
whiteSpaceBefore = ""
|
||||
@@ -512,7 +513,7 @@ extension MustacheTemplate {
|
||||
}
|
||||
|
||||
static func isStandalone(_ parser: inout Parser, state: ParserState) -> Bool {
|
||||
return state.newLine && self.hasLineFinished(&parser)
|
||||
state.newLine && self.hasLineFinished(&parser)
|
||||
}
|
||||
|
||||
private static let sectionNameCharsWithoutBrackets = Set<Character>("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_?*")
|
||||
|
||||
@@ -31,13 +31,13 @@ public protocol MustacheTransformable {
|
||||
func transform(_ name: String) -> Any?
|
||||
}
|
||||
|
||||
public extension StringProtocol {
|
||||
extension StringProtocol {
|
||||
/// Transform String/Substring
|
||||
///
|
||||
/// Transforms available are `capitalized`, `lowercased`, `uppercased` and `reversed`
|
||||
/// - Parameter name: transform name
|
||||
/// - Returns: Result
|
||||
func transform(_ name: String) -> Any? {
|
||||
public func transform(_ name: String) -> Any? {
|
||||
switch name {
|
||||
case "empty":
|
||||
return isEmpty
|
||||
@@ -209,13 +209,13 @@ extension Dictionary: ComparableSequence where Key: Comparable {
|
||||
}
|
||||
}
|
||||
|
||||
public extension FixedWidthInteger {
|
||||
extension FixedWidthInteger {
|
||||
/// Transform FixedWidthInteger
|
||||
///
|
||||
/// Transforms available are `plusone`, `minusone`, `odd`, `even`
|
||||
/// - Parameter name: transform name
|
||||
/// - Returns: Result
|
||||
func transform(_ name: String) -> Any? {
|
||||
public func transform(_ name: String) -> Any? {
|
||||
switch name {
|
||||
case "equalzero":
|
||||
return self == 0
|
||||
|
||||
@@ -17,11 +17,15 @@ import XCTest
|
||||
|
||||
final class ErrorTests: XCTestCase {
|
||||
func testSectionCloseNameIncorrect() {
|
||||
XCTAssertThrowsError(try MustacheTemplate(string: """
|
||||
XCTAssertThrowsError(
|
||||
try MustacheTemplate(
|
||||
string: """
|
||||
{{#test}}
|
||||
{{.}}
|
||||
{{/test2}}
|
||||
""")) { error in
|
||||
"""
|
||||
)
|
||||
) { error in
|
||||
switch error {
|
||||
case let error as MustacheTemplate.ParserError:
|
||||
XCTAssertEqual(error.error as? MustacheTemplate.Error, .sectionCloseNameIncorrect)
|
||||
@@ -36,11 +40,15 @@ final class ErrorTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testUnfinishedName() {
|
||||
XCTAssertThrowsError(try MustacheTemplate(string: """
|
||||
XCTAssertThrowsError(
|
||||
try MustacheTemplate(
|
||||
string: """
|
||||
{{#test}}
|
||||
{{name}
|
||||
{{/test2}}
|
||||
""")) { error in
|
||||
"""
|
||||
)
|
||||
) { error in
|
||||
switch error {
|
||||
case let error as MustacheTemplate.ParserError:
|
||||
XCTAssertEqual(error.error as? MustacheTemplate.Error, .unfinishedName)
|
||||
@@ -55,10 +63,14 @@ final class ErrorTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testExpectedSectionEnd() {
|
||||
XCTAssertThrowsError(try MustacheTemplate(string: """
|
||||
XCTAssertThrowsError(
|
||||
try MustacheTemplate(
|
||||
string: """
|
||||
{{#test}}
|
||||
{{.}}
|
||||
""")) { error in
|
||||
"""
|
||||
)
|
||||
) { error in
|
||||
switch error {
|
||||
case let error as MustacheTemplate.ParserError:
|
||||
XCTAssertEqual(error.error as? MustacheTemplate.Error, .expectedSectionEnd)
|
||||
@@ -73,11 +85,15 @@ final class ErrorTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testInvalidSetDelimiter() {
|
||||
XCTAssertThrowsError(try MustacheTemplate(string: """
|
||||
XCTAssertThrowsError(
|
||||
try MustacheTemplate(
|
||||
string: """
|
||||
{{=<% %>=}}
|
||||
<%.%>
|
||||
<%={{}}=%>
|
||||
""")) { error in
|
||||
"""
|
||||
)
|
||||
) { error in
|
||||
switch error {
|
||||
case let error as MustacheTemplate.ParserError:
|
||||
XCTAssertEqual(error.error as? MustacheTemplate.Error, .invalidSetDelimiter)
|
||||
|
||||
@@ -12,9 +12,10 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@testable import Mustache
|
||||
import XCTest
|
||||
|
||||
@testable import Mustache
|
||||
|
||||
final class LibraryTests: XCTestCase {
|
||||
func testDirectoryLoad() async throws {
|
||||
let fs = FileManager()
|
||||
@@ -54,11 +55,13 @@ final class LibraryTests: XCTestCase {
|
||||
let mustache = Data("<test>{{#value}}<value>{{.}}</value>{{/value}}</test>".utf8)
|
||||
try mustache.write(to: URL(fileURLWithPath: "templates/test.mustache"))
|
||||
defer { XCTAssertNoThrow(try fs.removeItem(atPath: "templates/test.mustache")) }
|
||||
let mustache2 = Data("""
|
||||
let mustache2 = Data(
|
||||
"""
|
||||
{{#test}}
|
||||
{{{name}}
|
||||
{{/test2}}
|
||||
""".utf8)
|
||||
""".utf8
|
||||
)
|
||||
try mustache2.write(to: URL(fileURLWithPath: "templates/error.mustache"))
|
||||
defer { XCTAssertNoThrow(try fs.removeItem(atPath: "templates/error.mustache")) }
|
||||
|
||||
|
||||
@@ -12,46 +12,57 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@testable import Mustache
|
||||
import XCTest
|
||||
|
||||
@testable import Mustache
|
||||
|
||||
final class PartialTests: XCTestCase {
|
||||
/// Testing partials
|
||||
func testMustacheManualExample9() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
<h2>Names</h2>
|
||||
{{#names}}
|
||||
{{> user}}
|
||||
{{/names}}
|
||||
""")
|
||||
let template2 = try MustacheTemplate(string: """
|
||||
"""
|
||||
)
|
||||
let template2 = try MustacheTemplate(
|
||||
string: """
|
||||
<strong>{{.}}</strong>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let library = MustacheLibrary(templates: ["base": template, "user": template2])
|
||||
|
||||
let object: [String: Any] = ["names": ["john", "adam", "claire"]]
|
||||
XCTAssertEqual(library.render(object, withTemplate: "base"), """
|
||||
XCTAssertEqual(
|
||||
library.render(object, withTemplate: "base"),
|
||||
"""
|
||||
<h2>Names</h2>
|
||||
<strong>john</strong>
|
||||
<strong>adam</strong>
|
||||
<strong>claire</strong>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// Test where last line of partial generates no content. It should not add a
|
||||
/// tab either
|
||||
func testPartialEmptyLineTabbing() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
<h2>Names</h2>
|
||||
{{#names}}
|
||||
{{> user}}
|
||||
{{/names}}
|
||||
Text after
|
||||
|
||||
""")
|
||||
let template2 = try MustacheTemplate(string: """
|
||||
"""
|
||||
)
|
||||
let template2 = try MustacheTemplate(
|
||||
string: """
|
||||
{{^empty(.)}}
|
||||
<strong>{{.}}</strong>
|
||||
{{/empty(.)}}
|
||||
@@ -59,73 +70,98 @@ final class PartialTests: XCTestCase {
|
||||
<strong>empty</strong>
|
||||
{{/empty(.)}}
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
var library = MustacheLibrary()
|
||||
library.register(template, named: "base")
|
||||
library.register(template2, named: "user")
|
||||
let object: [String: Any] = ["names": ["john", "adam", "claire"]]
|
||||
XCTAssertEqual(library.render(object, withTemplate: "base"), """
|
||||
XCTAssertEqual(
|
||||
library.render(object, withTemplate: "base"),
|
||||
"""
|
||||
<h2>Names</h2>
|
||||
<strong>john</strong>
|
||||
<strong>adam</strong>
|
||||
<strong>claire</strong>
|
||||
Text after
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testTrailingNewLines() throws {
|
||||
let template1 = try MustacheTemplate(string: """
|
||||
let template1 = try MustacheTemplate(
|
||||
string: """
|
||||
{{> withNewLine }}
|
||||
>> {{> withNewLine }}
|
||||
[ {{> withNewLine }} ]
|
||||
""")
|
||||
let template2 = try MustacheTemplate(string: """
|
||||
"""
|
||||
)
|
||||
let template2 = try MustacheTemplate(
|
||||
string: """
|
||||
{{> withoutNewLine }}
|
||||
>> {{> withoutNewLine }}
|
||||
[ {{> withoutNewLine }} ]
|
||||
""")
|
||||
let withNewLine = try MustacheTemplate(string: """
|
||||
"""
|
||||
)
|
||||
let withNewLine = try MustacheTemplate(
|
||||
string: """
|
||||
{{#things}}{{.}}, {{/things}}
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let withoutNewLine = try MustacheTemplate(string: "{{#things}}{{.}}, {{/things}}")
|
||||
let library = MustacheLibrary(templates: ["base1": template1, "base2": template2, "withNewLine": withNewLine, "withoutNewLine": withoutNewLine])
|
||||
let library = MustacheLibrary(templates: [
|
||||
"base1": template1, "base2": template2, "withNewLine": withNewLine, "withoutNewLine": withoutNewLine,
|
||||
])
|
||||
let object = ["things": [1, 2, 3, 4, 5]]
|
||||
XCTAssertEqual(library.render(object, withTemplate: "base1"), """
|
||||
XCTAssertEqual(
|
||||
library.render(object, withTemplate: "base1"),
|
||||
"""
|
||||
1, 2, 3, 4, 5,
|
||||
>> 1, 2, 3, 4, 5,
|
||||
|
||||
[ 1, 2, 3, 4, 5,
|
||||
]
|
||||
""")
|
||||
XCTAssertEqual(library.render(object, withTemplate: "base2"), """
|
||||
"""
|
||||
)
|
||||
XCTAssertEqual(
|
||||
library.render(object, withTemplate: "base2"),
|
||||
"""
|
||||
1, 2, 3, 4, 5, >> 1, 2, 3, 4, 5,
|
||||
[ 1, 2, 3, 4, 5, ]
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// Testing dynamic partials
|
||||
func testDynamicPartials() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
<h2>Names</h2>
|
||||
{{partial}}
|
||||
""")
|
||||
let template2 = try MustacheTemplate(string: """
|
||||
"""
|
||||
)
|
||||
let template2 = try MustacheTemplate(
|
||||
string: """
|
||||
{{#names}}
|
||||
<strong>{{.}}</strong>
|
||||
{{/names}}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let library = MustacheLibrary(templates: ["base": template])
|
||||
|
||||
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>
|
||||
<strong>john</strong>
|
||||
<strong>adam</strong>
|
||||
<strong>claire</strong>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test inheritance
|
||||
@@ -163,7 +199,9 @@ final class PartialTests: XCTestCase {
|
||||
""",
|
||||
named: "mypage"
|
||||
)
|
||||
XCTAssertEqual(library.render({}, withTemplate: "mypage")!, """
|
||||
XCTAssertEqual(
|
||||
library.render({}, withTemplate: "mypage")!,
|
||||
"""
|
||||
<html>
|
||||
<head>
|
||||
<title>My page title</title>
|
||||
@@ -171,7 +209,8 @@ final class PartialTests: XCTestCase {
|
||||
<h1>Hello world</h1>
|
||||
</html>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testInheritanceIndentation() throws {
|
||||
@@ -194,11 +233,14 @@ final class PartialTests: XCTestCase {
|
||||
""",
|
||||
named: "template"
|
||||
)
|
||||
XCTAssertEqual(library.render({}, withTemplate: "template"), """
|
||||
XCTAssertEqual(
|
||||
library.render({}, withTemplate: "template"),
|
||||
"""
|
||||
Hi,
|
||||
one
|
||||
two
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,8 @@ extension AnyDecodable {
|
||||
self.init(dictionary.mapValues { $0.value })
|
||||
} else {
|
||||
throw DecodingError.dataCorruptedError(
|
||||
in: container, debugDescription: "AnyDecodable value cannot be decoded"
|
||||
in: container,
|
||||
debugDescription: "AnyDecodable value cannot be decoded"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -102,7 +103,8 @@ final class MustacheSpecTests: XCTestCase {
|
||||
\(result ?? "nil")
|
||||
expected:
|
||||
\(test.expected)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,7 +115,8 @@ final class MustacheSpecTests: XCTestCase {
|
||||
|
||||
func testSpec(name: String, ignoring: [String] = []) async throws {
|
||||
let url = URL(
|
||||
string: "https://raw.githubusercontent.com/mustache/spec/master/specs/\(name).json")!
|
||||
string: "https://raw.githubusercontent.com/mustache/spec/master/specs/\(name).json"
|
||||
)!
|
||||
try await testSpec(url: url, ignoring: ignoring)
|
||||
}
|
||||
|
||||
@@ -135,7 +138,8 @@ final class MustacheSpecTests: XCTestCase {
|
||||
|
||||
func testSpec(name: String, only: [String]) async throws {
|
||||
let url = URL(
|
||||
string: "https://raw.githubusercontent.com/mustache/spec/master/specs/\(name).json")!
|
||||
string: "https://raw.githubusercontent.com/mustache/spec/master/specs/\(name).json"
|
||||
)!
|
||||
try await testSpec(url: url, only: only)
|
||||
}
|
||||
|
||||
@@ -161,7 +165,12 @@ final class MustacheSpecTests: XCTestCase {
|
||||
"Interpolation": MustacheLambda { "world" },
|
||||
"Interpolation - Expansion": MustacheLambda { "{{planet}}" },
|
||||
"Interpolation - Alternate Delimiters": MustacheLambda { "|planet| => {{planet}}" },
|
||||
"Interpolation - Multiple Calls": MustacheLambda { return MustacheLambda { g += 1; return g }},
|
||||
"Interpolation - Multiple Calls": MustacheLambda {
|
||||
return MustacheLambda {
|
||||
g += 1
|
||||
return g
|
||||
}
|
||||
},
|
||||
"Escaping": MustacheLambda { ">" },
|
||||
"Section": MustacheLambda { text in text == "{{x}}" ? "yes" : "no" },
|
||||
"Section - Expansion": MustacheLambda { text in text + "{{planet}}" + text },
|
||||
|
||||
@@ -12,9 +12,10 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@testable import Mustache
|
||||
import XCTest
|
||||
|
||||
@testable import Mustache
|
||||
|
||||
final class TemplateParserTests: XCTestCase {
|
||||
func testText() throws {
|
||||
let template = try MustacheTemplate(string: "test template")
|
||||
|
||||
@@ -141,81 +141,103 @@ final class TemplateRendererTests: XCTestCase {
|
||||
|
||||
/// variables
|
||||
func testMustacheManualVariables() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
Hello {{name}}
|
||||
You have just won {{value}} dollars!
|
||||
{{#in_ca}}
|
||||
Well, {{taxed_value}} dollars, after taxes.
|
||||
{{/in_ca}}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
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
|
||||
You have just won 10000 dollars!
|
||||
Well, 6000.0 dollars, after taxes.
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test escaped and unescaped text
|
||||
func testMustacheManualEscapedText() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
*{{name}}
|
||||
*{{age}}
|
||||
*{{company}}
|
||||
*{{{company}}}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["name": "Chris", "company": "<b>GitHub</b>"]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
*Chris
|
||||
*
|
||||
*<b>GitHub</b>
|
||||
*<b>GitHub</b>
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test dotted names
|
||||
func test_MustacheManualDottedNames() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
* {{client.name}}
|
||||
* {{age}}
|
||||
* {{client.company.name}}
|
||||
* {{{company.name}}}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = [
|
||||
"client": (
|
||||
name: "Chris & Friends",
|
||||
age: 50
|
||||
),
|
||||
"company": [
|
||||
"name": "<b>GitHub</b>",
|
||||
"name": "<b>GitHub</b>"
|
||||
],
|
||||
]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
* Chris & Friends
|
||||
*
|
||||
*
|
||||
* <b>GitHub</b>
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test implicit operator
|
||||
func testMustacheManualImplicitOperator() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
* {{.}}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object = "Hello!"
|
||||
XCTAssertEqual(template.render(object), """
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
* Hello!
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test lambda
|
||||
func test_MustacheManualLambda() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
* {{time.hour}}
|
||||
* {{today}}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = [
|
||||
"year": 1970,
|
||||
"month": 1,
|
||||
@@ -231,113 +253,151 @@ final class TemplateRendererTests: XCTestCase {
|
||||
return "{{year}}-{{month}}-{{day}}"
|
||||
},
|
||||
]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
* 0
|
||||
* 1970-1-1
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test boolean
|
||||
func testMustacheManualSectionFalse() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
Shown.
|
||||
{{#person}}
|
||||
Never shown!
|
||||
{{/person}}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["person": false]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
Shown.
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test non-empty lists
|
||||
func testMustacheManualSectionList() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
<b>{{name}}</b>
|
||||
{{/repo}}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
<b>resque</b>
|
||||
<b>hub</b>
|
||||
<b>rip</b>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test non-empty lists
|
||||
func testMustacheManualSectionList2() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
<b>{{.}}</b>
|
||||
{{/repo}}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": ["resque", "hub", "rip"]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
<b>resque</b>
|
||||
<b>hub</b>
|
||||
<b>rip</b>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test lambdas
|
||||
func testMustacheManualSectionLambda() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#wrapped}}{{name}} is awesome.{{/wrapped}}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
func wrapped(_ s: String) -> Any? {
|
||||
return "<b>\(s)</b>"
|
||||
"<b>\(s)</b>"
|
||||
}
|
||||
let object: [String: Any] = ["name": "Willy", "wrapped": MustacheLambda(wrapped)]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
<b>Willy is awesome.</b>
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test setting context object
|
||||
func testMustacheManualContextObject() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#person?}}
|
||||
Hi {{name}}!
|
||||
{{/person?}}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["person?": ["name": "Jon"]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
Hi Jon!
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test inverted sections
|
||||
func testMustacheManualInvertedSection() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
<b>{{name}}</b>
|
||||
{{/repo}}
|
||||
{{^repo}}
|
||||
No repos :(
|
||||
{{/repo}}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": []]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
No repos :(
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test comments
|
||||
func testMustacheManualComment() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
<h1>Today{{! ignore me }}.</h1>
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": []]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
<h1>Today.</h1>
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test dynamic names
|
||||
@@ -357,18 +417,23 @@ final class TemplateRendererTests: XCTestCase {
|
||||
|
||||
/// test block with defaults
|
||||
func testMustacheManualBlocksWithDefaults() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
<h1>{{$title}}The News of Today{{/title}}</h1>
|
||||
{{$body}}
|
||||
<p>Nothing special happened.</p>
|
||||
{{/body}}
|
||||
|
||||
""")
|
||||
XCTAssertEqual(template.render([]), """
|
||||
"""
|
||||
)
|
||||
XCTAssertEqual(
|
||||
template.render([]),
|
||||
"""
|
||||
<h1>The News of Today</h1>
|
||||
<p>Nothing special happened.</p>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testMustacheManualParents() throws {
|
||||
@@ -405,7 +470,7 @@ final class TemplateRendererTests: XCTestCase {
|
||||
"headlines": [
|
||||
"A pug's handler grew mustaches.",
|
||||
"What an exciting day!",
|
||||
],
|
||||
]
|
||||
]
|
||||
XCTAssertEqual(
|
||||
library.render(object, withTemplate: "main"),
|
||||
@@ -474,11 +539,13 @@ final class TemplateRendererTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testPerformance() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
<b>{{name}}</b>
|
||||
{{/repo}}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
||||
let date = Date()
|
||||
for _ in 1...10000 {
|
||||
|
||||
@@ -17,177 +17,233 @@ import XCTest
|
||||
|
||||
final class TransformTests: XCTestCase {
|
||||
func testLowercased() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{ lowercased(name) }}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["name": "Test"]
|
||||
XCTAssertEqual(template.render(object), "test")
|
||||
}
|
||||
|
||||
func testUppercased() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{ uppercased(name) }}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["name": "Test"]
|
||||
XCTAssertEqual(template.render(object), "TEST")
|
||||
}
|
||||
|
||||
func testNewline() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
<b>{{name}}</b>
|
||||
{{/repo}}
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
<b>resque</b>
|
||||
<b>hub</b>
|
||||
<b>rip</b>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testFirstLast() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
<b>{{#first()}}first: {{/first()}}{{#last()}}last: {{/last()}}{{ name }}</b>
|
||||
{{/repo}}
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
<b>first: resque</b>
|
||||
<b>hub</b>
|
||||
<b>last: rip</b>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testIndex() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
<b>{{#index()}}{{plusone(.)}}{{/index()}}) {{ name }}</b>
|
||||
{{/repo}}
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
<b>1) resque</b>
|
||||
<b>2) hub</b>
|
||||
<b>3) rip</b>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testDoubleSequenceTransformWorks() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
{{count(reversed(numbers))}}
|
||||
{{/repo}}
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": ["numbers": [1, 2, 3]]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
3
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testMultipleTransformWorks() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
{{minusone(plusone(last(reversed(numbers))))}}
|
||||
{{/repo}}
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": ["numbers": [5, 4, 3]]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
5
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testNestedTransformWorks() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
{{#uppercased(string)}}{{reversed(.)}}{{/uppercased(string)}}
|
||||
{{/repo}}
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": ["string": "a123a"]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
A321A
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testEvenOdd() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
<b>{{index()}}) {{#even()}}even {{/even()}}{{#odd()}}odd {{/odd()}}{{ name }}</b>
|
||||
{{/repo}}
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
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>1) odd hub</b>
|
||||
<b>2) even rip</b>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testReversed() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#reversed(repo)}}
|
||||
<b>{{ name }}</b>
|
||||
{{/reversed(repo)}}
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
<b>rip</b>
|
||||
<b>hub</b>
|
||||
<b>resque</b>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testArrayIndex() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
<b>{{ index() }}) {{ name }}</b>
|
||||
{{/repo}}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
<b>0) resque</b>
|
||||
<b>1) hub</b>
|
||||
<b>2) rip</b>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testArraySorted() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#sorted(repo)}}
|
||||
<b>{{ index() }}) {{ . }}</b>
|
||||
{{/sorted(repo)}}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": ["resque", "hub", "rip"]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
<b>0) hub</b>
|
||||
<b>1) resque</b>
|
||||
<b>2) rip</b>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testDictionaryEmpty() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#empty(array)}}Array{{/empty(array)}}{{#empty(dictionary)}}Dictionary{{/empty(dictionary)}}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["array": [], "dictionary": [:]]
|
||||
XCTAssertEqual(template.render(object), "ArrayDictionary")
|
||||
}
|
||||
@@ -199,18 +255,22 @@ final class TransformTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testDictionaryEnumerated() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#enumerated(.)}}<b>{{ key }} = {{ value }}</b>{{/enumerated(.)}}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["one": 1, "two": 2]
|
||||
let result = template.render(object)
|
||||
XCTAssertTrue(result == "<b>one = 1</b><b>two = 2</b>" || result == "<b>two = 2</b><b>one = 1</b>")
|
||||
}
|
||||
|
||||
func testDictionarySortedByKey() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#sorted(.)}}<b>{{ key }} = {{ value }}</b>{{/sorted(.)}}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["one": 1, "two": 2, "three": 3]
|
||||
let result = template.render(object)
|
||||
XCTAssertEqual(result, "<b>one = 1</b><b>three = 3</b><b>two = 2</b>")
|
||||
|
||||
@@ -31,8 +31,6 @@ SWIFT_FORMAT_VERSION=0.53.10
|
||||
set -eu
|
||||
here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
which swiftformat > /dev/null 2>&1 || (echo "swiftformat not installed. You can install it using 'brew install swiftformat'" ; exit -1)
|
||||
|
||||
function replace_acceptable_years() {
|
||||
# this needs to replace all acceptable forms with 'YEARS'
|
||||
sed -e 's/20[12][0-9]-20[12][0-9]/YEARS/' -e 's/20[12][0-9]/YEARS/' -e '/^#!/ d'
|
||||
@@ -40,13 +38,9 @@ function replace_acceptable_years() {
|
||||
|
||||
printf "=> Checking format... "
|
||||
FIRST_OUT="$(git status --porcelain)"
|
||||
if [[ -n "${CI-""}" ]]; then
|
||||
printf "(using v$(mint run NickLockwood/SwiftFormat@"$SWIFT_FORMAT_VERSION" --version)) "
|
||||
mint run NickLockwood/SwiftFormat@"$SWIFT_FORMAT_VERSION" . > /dev/null 2>&1
|
||||
else
|
||||
printf "(using v$(swiftformat --version)) "
|
||||
swiftformat . > /dev/null 2>&1
|
||||
fi
|
||||
git ls-files -z '*.swift' | xargs -0 swift format format --parallel --in-place
|
||||
git diff --exit-code '*.swift'
|
||||
|
||||
SECOND_OUT="$(git status --porcelain)"
|
||||
if [[ "$FIRST_OUT" != "$SECOND_OUT" ]]; then
|
||||
printf "\033[0;31mformatting issues!\033[0m\n"
|
||||
@@ -55,10 +49,11 @@ if [[ "$FIRST_OUT" != "$SECOND_OUT" ]]; then
|
||||
else
|
||||
printf "\033[0;32mokay.\033[0m\n"
|
||||
fi
|
||||
exit
|
||||
printf "=> Checking license headers... "
|
||||
tmp=$(mktemp /tmp/.soto-core-sanity_XXXXXX)
|
||||
|
||||
exit 0
|
||||
|
||||
for language in swift-or-c; do
|
||||
declare -a matching_files
|
||||
declare -a exceptions
|
||||
@@ -66,18 +61,18 @@ for language in swift-or-c; do
|
||||
matching_files=( -name '*' )
|
||||
case "$language" in
|
||||
swift-or-c)
|
||||
exceptions=( -path '*Sources/INIParser/*' -o -path '*Sources/CSotoExpat/*' -o -path '*Benchmark/.build/*' -o -name Package.swift)
|
||||
exceptions=( -path '*/Benchmarks/.build/*' -o -name Package.swift)
|
||||
matching_files=( -name '*.swift' -o -name '*.c' -o -name '*.h' )
|
||||
cat > "$tmp" <<"EOF"
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Hummingbird open source project
|
||||
// This source file is part of the Hummingbird server framework project
|
||||
//
|
||||
// Copyright (c) YEARS the Hummingbird authors
|
||||
// Licensed under Apache License v2.0
|
||||
//
|
||||
// See LICENSE.txt for license information
|
||||
// See CONTRIBUTORS.txt for the list of Hummingbird authors
|
||||
// See hummingbird/CONTRIBUTORS.txt for the list of Hummingbird authors
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
@@ -89,13 +84,13 @@ EOF
|
||||
cat > "$tmp" <<"EOF"
|
||||
##===----------------------------------------------------------------------===##
|
||||
##
|
||||
## This source file is part of the Hummingbird open source project
|
||||
## This source file is part of the Hummingbird server framework project
|
||||
##
|
||||
## Copyright (c) YEARS the Hummingbird authors
|
||||
## Licensed under Apache License v2.0
|
||||
##
|
||||
## See LICENSE.txt for license information
|
||||
## See CONTRIBUTORS.txt for the list of Hummingbird authors
|
||||
## See hummingbird/CONTRIBUTORS.txt for the list of Hummingbird authors
|
||||
##
|
||||
## SPDX-License-Identifier: Apache-2.0
|
||||
##
|
||||
|
||||
Reference in New Issue
Block a user