Fix issues in Sources
Sources sources
This commit is contained in:
@@ -1,10 +1,8 @@
|
||||
public func until(_ tags: [String]) -> ((TokenParser, Token) -> Bool) {
|
||||
return { parser, token in
|
||||
if let name = token.components.first {
|
||||
for tag in tags {
|
||||
if name == tag {
|
||||
return true
|
||||
}
|
||||
for tag in tags where name == tag {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +10,6 @@ public func until(_ tags: [String]) -> ((TokenParser, Token) -> Bool) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// A class for parsing an array of tokens and converts them into a collection of Node's
|
||||
public class TokenParser {
|
||||
public typealias TagParser = (TokenParser, Token) throws -> NodeType
|
||||
@@ -30,11 +27,11 @@ public class TokenParser {
|
||||
return try parse(nil)
|
||||
}
|
||||
|
||||
public func parse(_ parse_until:((_ parser:TokenParser, _ token:Token) -> (Bool))?) throws -> [NodeType] {
|
||||
public func parse(_ parseUntil: ((_ parser: TokenParser, _ token: Token) -> (Bool))?) throws -> [NodeType] {
|
||||
var nodes = [NodeType]()
|
||||
|
||||
while tokens.count > 0 {
|
||||
let token = nextToken()!
|
||||
while !tokens.isEmpty {
|
||||
guard let token = nextToken() else { break }
|
||||
|
||||
switch token.kind {
|
||||
case .text:
|
||||
@@ -42,7 +39,7 @@ public class TokenParser {
|
||||
case .variable:
|
||||
try nodes.append(VariableNode.parse(self, token: token))
|
||||
case .block:
|
||||
if let parse_until = parse_until , parse_until(self, token) {
|
||||
if let parseUntil = parseUntil, parseUntil(self, token) {
|
||||
prependToken(token)
|
||||
return nodes
|
||||
}
|
||||
@@ -65,14 +62,14 @@ public class TokenParser {
|
||||
}
|
||||
|
||||
public func nextToken() -> Token? {
|
||||
if tokens.count > 0 {
|
||||
if !tokens.isEmpty {
|
||||
return tokens.remove(at: 0)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
public func prependToken(_ token:Token) {
|
||||
public func prependToken(_ token: Token) {
|
||||
tokens.insert(token, at: 0)
|
||||
}
|
||||
|
||||
@@ -94,7 +91,6 @@ public class TokenParser {
|
||||
}
|
||||
|
||||
extension Environment {
|
||||
|
||||
func findTag(name: String) throws -> Extension.TagParser {
|
||||
for ext in extensions {
|
||||
if let filter = ext.tags[name] {
|
||||
@@ -118,23 +114,23 @@ extension Environment {
|
||||
} else {
|
||||
throw TemplateSyntaxError("""
|
||||
Unknown filter '\(name)'. \
|
||||
Found similar filters: \(suggestedFilters.map({ "'\($0)'" }).joined(separator: ", ")).
|
||||
Found similar filters: \(suggestedFilters.map { "'\($0)'" }.joined(separator: ", ")).
|
||||
""")
|
||||
}
|
||||
}
|
||||
|
||||
private func suggestedFilters(for name: String) -> [String] {
|
||||
let allFilters = extensions.flatMap({ $0.filters.keys })
|
||||
let allFilters = extensions.flatMap { $0.filters.keys }
|
||||
|
||||
let filtersWithDistance = allFilters
|
||||
.map({ (filterName: $0, distance: $0.levenshteinDistance(name)) })
|
||||
.map { (filterName: $0, distance: $0.levenshteinDistance(name)) }
|
||||
// do not suggest filters which names are shorter than the distance
|
||||
.filter({ $0.filterName.count > $0.distance })
|
||||
.filter { $0.filterName.count > $0.distance }
|
||||
guard let minDistance = filtersWithDistance.min(by: { $0.distance < $1.distance })?.distance else {
|
||||
return []
|
||||
}
|
||||
// suggest all filters with the same distance
|
||||
return filtersWithDistance.filter({ $0.distance == minDistance }).map({ $0.filterName })
|
||||
return filtersWithDistance.filter { $0.distance == minDistance }.map { $0.filterName }
|
||||
}
|
||||
|
||||
/// Create filter expression from a string
|
||||
@@ -153,8 +149,14 @@ extension Environment {
|
||||
// find offset of filter in the containing token so that only filter is highligted, not the whole token
|
||||
if let filterTokenRange = containingToken.contents.range(of: filterToken) {
|
||||
var location = containingToken.sourceMap.location
|
||||
location.lineOffset += containingToken.contents.distance(from: containingToken.contents.startIndex, to: filterTokenRange.lowerBound)
|
||||
syntaxError.token = .variable(value: filterToken, at: SourceMap(filename: containingToken.sourceMap.filename, location: location))
|
||||
location.lineOffset += containingToken.contents.distance(
|
||||
from: containingToken.contents.startIndex,
|
||||
to: filterTokenRange.lowerBound
|
||||
)
|
||||
syntaxError.token = .variable(
|
||||
value: filterToken,
|
||||
at: SourceMap(filename: containingToken.sourceMap.filename, location: location)
|
||||
)
|
||||
} else {
|
||||
syntaxError.token = containingToken
|
||||
}
|
||||
@@ -183,9 +185,8 @@ extension Environment {
|
||||
|
||||
// https://en.wikipedia.org/wiki/Levenshtein_distance#Iterative_with_two_matrix_rows
|
||||
extension String {
|
||||
|
||||
subscript(_ i: Int) -> Character {
|
||||
return self[self.index(self.startIndex, offsetBy: i)]
|
||||
subscript(_ index: Int) -> Character {
|
||||
return self[self.index(self.startIndex, offsetBy: index)]
|
||||
}
|
||||
|
||||
func levenshteinDistance(_ target: String) -> Int {
|
||||
@@ -198,19 +199,19 @@ extension String {
|
||||
last = [Int](0...target.count)
|
||||
current = [Int](repeating: 0, count: target.count + 1)
|
||||
|
||||
for i in 0..<self.count {
|
||||
for selfIndex in 0..<self.count {
|
||||
// calculate v1 (current row distances) from the previous row v0
|
||||
|
||||
// first element of v1 is A[i+1][0]
|
||||
// edit distance is delete (i+1) chars from s to match empty t
|
||||
current[0] = i + 1
|
||||
current[0] = selfIndex + 1
|
||||
|
||||
// use formula to fill in the rest of the row
|
||||
for j in 0..<target.count {
|
||||
current[j+1] = Swift.min(
|
||||
last[j+1] + 1,
|
||||
current[j] + 1,
|
||||
last[j] + (self[i] == target[j] ? 0 : 1)
|
||||
for targetIndex in 0..<target.count {
|
||||
current[targetIndex + 1] = Swift.min(
|
||||
last[targetIndex + 1] + 1,
|
||||
current[targetIndex] + 1,
|
||||
last[targetIndex] + (self[selfIndex] == target[targetIndex] ? 0 : 1)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -220,5 +221,4 @@ extension String {
|
||||
|
||||
return current[target.count]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user