diff --git a/.travis.yml b/.travis.yml index 9240617..8639971 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,16 @@ matrix: include: + - os: osx + osx_image: xcode9.2 + env: SWIFT_VERSION=4.0.3 - os: osx osx_image: xcode9.4 env: SWIFT_VERSION=4.1 - os: osx osx_image: xcode10 env: SWIFT_VERSION=4.2 + - os: linux + env: SWIFT_VERSION=4.0.3 - os: linux env: SWIFT_VERSION=4.1 - os: linux diff --git a/Package.swift b/Package.swift index 2dd6977..b5fb304 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:4.1 +// swift-tools-version:4.0 import PackageDescription let package = Package( diff --git a/Sources/Errors.swift b/Sources/Errors.swift index a6191f9..e885ab3 100644 --- a/Sources/Errors.swift +++ b/Sources/Errors.swift @@ -37,6 +37,15 @@ public struct TemplateSyntaxError : Error, Equatable, CustomStringConvertible { public init(_ description: String) { self.init(reason: description) } + + public static func ==(lhs: TemplateSyntaxError, rhs: TemplateSyntaxError) -> Bool { + return lhs.reason == rhs.reason && + lhs.description == rhs.description && + lhs.token == rhs.token && + lhs.stackTrace == rhs.stackTrace && + lhs.templateName == rhs.templateName && + lhs.allTokens == rhs.allTokens + } } extension Error { diff --git a/Sources/IfTag.swift b/Sources/IfTag.swift index 125f55f..4fd6974 100644 --- a/Sources/IfTag.swift +++ b/Sources/IfTag.swift @@ -118,7 +118,12 @@ final class IfExpressionParser { private init(components: ArraySlice, tokenParser: TokenParser, token: Token) throws { var parsedComponents = Set() var bracketsBalance = 0 - self.tokens = try zip(components.indices, components).compactMap { (index, component) in + #if swift(>=4.1) + self.tokens = try zip(components.indices, components).compactMap { try parseComponent(index: $0.0, component: $0.1) } + #else + self.tokens = try zip(components.indices, components).flatMap { try parseComponent(index: $0.0, component: $0.1) } + #endif + func parseComponent(index: Int, component: String) throws -> IfToken? { guard !parsedComponents.contains(index) else { return nil } if component == "(" { diff --git a/Sources/Inheritence.swift b/Sources/Inheritence.swift index e512bfb..1507f1f 100644 --- a/Sources/Inheritence.swift +++ b/Sources/Inheritence.swift @@ -63,9 +63,11 @@ class ExtendsNode : NodeType { guard (parsedNodes.any { $0 is ExtendsNode }) == nil else { throw TemplateSyntaxError("'extends' cannot appear more than once in the same template") } - - let blockNodes = parsedNodes.compactMap { $0 as? BlockNode } - + #if swift(>=4.1) + let blockNodes = parsedNodes.compactMap { $0 as? BlockNode } + #else + let blockNodes = parsedNodes.flatMap { $0 as? BlockNode } + #endif let nodes = blockNodes.reduce([String: BlockNode]()) { (accumulator, node) -> [String: BlockNode] in var dict = accumulator dict[node.name] = node diff --git a/Sources/Lexer.swift b/Sources/Lexer.swift index f6fc426..77e956a 100644 --- a/Sources/Lexer.swift +++ b/Sources/Lexer.swift @@ -22,11 +22,17 @@ struct Lexer { init(templateName: String? = nil, templateString: String) { self.templateName = templateName self.templateString = templateString - - self.lines = templateString.components(separatedBy: .newlines).enumerated().compactMap { - guard !$0.element.isEmpty else { return nil } - return (content: $0.element, number: UInt($0.offset + 1), templateString.range(of: $0.element)!) - } + #if swift(>=4.1) + self.lines = templateString.components(separatedBy: .newlines).enumerated().compactMap { + guard !$0.element.isEmpty else { return nil } + return (content: $0.element, number: UInt($0.offset + 1), templateString.range(of: $0.element)!) + } + #else + self.lines = templateString.components(separatedBy: .newlines).enumerated().flatMap { + guard !$0.element.isEmpty else { return nil } + return (content: $0.element, number: UInt($0.offset + 1), templateString.range(of: $0.element)!) + } + #endif } /// Create a token that will be passed on to the parser, with the given diff --git a/Sources/Variable.swift b/Sources/Variable.swift index eb30060..203ecc8 100644 --- a/Sources/Variable.swift +++ b/Sources/Variable.swift @@ -116,9 +116,32 @@ public struct Variable : Equatable, Resolvable { return normalize(current) } + + public static func ==(lhs: Variable, rhs: Variable) -> Bool { + return lhs.variable == rhs.variable + } } +#if swift(>=4.1) private func resolveCollection(_ collection: T, bit: String) -> Any? { + if let index = Int(bit) { + if index >= 0 && index < collection.count { + return collection[collection.index(collection.startIndex, offsetBy: index)] + } else { + return nil + } + } else if bit == "first" { + return collection.first + } else if bit == "last" { + return collection[collection.index(collection.endIndex, offsetBy: -1)] + } else if bit == "count" { + return collection.count + } else { + return nil + } +} +#else +private func resolveCollection(_ collection: T, bit: String) -> Any? where T.IndexDistance == Int { if let index = Int(bit) { if index >= 0 && index < collection.count { return collection[collection.index(collection.startIndex, offsetBy: index)] @@ -135,6 +158,7 @@ private func resolveCollection(_ collection: T, bit: String) -> A return nil } } +#endif /// A structure used to represet range of two integer values expressed as `from...to`. /// Values should be numbers (they will be converted to integers).