diff --git a/Sources/Filters+Strings.swift b/Sources/Filters+Strings.swift index 2b7d5e5f..4bbbb86f 100644 --- a/Sources/Filters+Strings.swift +++ b/Sources/Filters+Strings.swift @@ -7,6 +7,10 @@ import Foundation import Stencil +enum RemoveNewlinesModes: String { + case all, leading +} + extension Filters { enum Strings { fileprivate static let reservedKeywords = [ @@ -119,28 +123,40 @@ extension Filters { return escapeReservedKeywords(in: string) } + /// Removes newlines and other whitespace from a string. Takes an optional Mode argument: + /// - all (default): remove all newlines and whitespaces + /// - leading: remove newlines and only leading whitespaces + /// + /// - Parameters: + /// - value: the value to be processed + /// - arguments: the arguments to the function; expecting zero or one mode argument + /// - Returns: the trimmed string + /// - Throws: FilterError.invalidInputType if the value parameter isn't a string static func removeNewlines(_ value: Any?, arguments: [Any?]) throws -> Any? { - let mode = arguments.first as? String ?? "all" guard let string = value as? String else { throw Filters.Error.invalidInputType } + let mode = try Filters.parseEnum(from: arguments, default: RemoveNewlinesModes.all) switch mode { - case "all": + case .all: return string .components(separatedBy: .whitespacesAndNewlines) .joined() - case "leading": + case .leading: return string .components(separatedBy: .newlines) - .map { String($0.unicodeScalars.drop(while: { CharacterSet.whitespaces.contains($0) })) } + .map(removeLeadingWhitespaces(from:)) .joined() .trimmingCharacters(in: .whitespaces) - default: - throw Filters.Error.invalidOption(option: mode) } } // MARK: - Private methods + private static func removeLeadingWhitespaces(from string: String) -> String { + let chars = string.unicodeScalars.drop { CharacterSet.whitespaces.contains($0) } + return String(chars) + } + /// This returns the string with its first parameter uppercased. /// - note: This is quite similar to `capitalise` except that this filter doesn't /// lowercase the rest of the string but keeps it untouched. diff --git a/Tests/StencilSwiftKitTests/ParseBoolTests.swift b/Tests/StencilSwiftKitTests/ParseBoolTests.swift index 08bb0279..43c55b69 100644 --- a/Tests/StencilSwiftKitTests/ParseBoolTests.swift +++ b/Tests/StencilSwiftKitTests/ParseBoolTests.swift @@ -9,34 +9,16 @@ import XCTest class ParseBoolTests: XCTestCase { - func testParseBool_WithTrueString() throws { - let value = try Filters.parseBool(from: ["true"]) - XCTAssertTrue(value!) + func testParseBool_TrueWithString() throws { + XCTAssertTrue(try Filters.parseBool(from: ["true"])!) + XCTAssertTrue(try Filters.parseBool(from: ["yes"])!) + XCTAssertTrue(try Filters.parseBool(from: ["1"])!) } - func testParseBool_WithFalseString() throws { - let value = try Filters.parseBool(from: ["false"]) - XCTAssertFalse(value!) - } - - func testParseBool_WithYesString() throws { - let value = try Filters.parseBool(from: ["yes"]) - XCTAssertTrue(value!) - } - - func testParseBool_WithNoString() throws { - let value = try Filters.parseBool(from: ["no"]) - XCTAssertFalse(value!) - } - - func testParseBool_WithOneString() throws { - let value = try Filters.parseBool(from: ["1"]) - XCTAssertTrue(value!) - } - - func testParseBool_WithZeroString() throws { - let value = try Filters.parseBool(from: ["0"]) - XCTAssertFalse(value!) + func testParseBool_FalseWithString() throws { + XCTAssertFalse(try Filters.parseBool(from: ["false"])!) + XCTAssertFalse(try Filters.parseBool(from: ["no"])!) + XCTAssertFalse(try Filters.parseBool(from: ["0"])!) } func testParseBool_WithOptionalInt() throws { @@ -73,4 +55,9 @@ class ParseBoolTests: XCTestCase { func testParseBool_WithEmptyArrayAndRequiredArg() throws { XCTAssertThrowsError(try Filters.parseBool(from: [], required: true)) } + + func testParseBool_WithNonZeroIndex() throws { + XCTAssertTrue(try Filters.parseBool(from: ["test", "true"], at: 1)!) + XCTAssertFalse(try Filters.parseBool(from: ["test", "false"], at: 1)!) + } } diff --git a/Tests/StencilSwiftKitTests/ParseEnumTests.swift b/Tests/StencilSwiftKitTests/ParseEnumTests.swift index da6e7400..3889d114 100644 --- a/Tests/StencilSwiftKitTests/ParseEnumTests.swift +++ b/Tests/StencilSwiftKitTests/ParseEnumTests.swift @@ -34,6 +34,11 @@ class ParseEnumTests: XCTestCase { XCTAssertEqual(value, Test.baz) } + func testParseEnum_WithNonZeroIndex() throws { + let value = try Filters.parseEnum(from: [42, "bar"], at: 1, default: Test.baz) + XCTAssertEqual(value, Test.bar) + } + func testParseEnum_WithUnknownArgument() throws { XCTAssertThrowsError(try Filters.parseEnum(from: ["test"], default: Test.baz)) XCTAssertThrowsError(try Filters.parseEnum(from: [42], default: Test.baz))