removed trailing witespaces
This commit is contained in:
@@ -9,7 +9,7 @@ public struct Environment {
|
|||||||
extensions: [Extension]? = nil,
|
extensions: [Extension]? = nil,
|
||||||
templateClass: Template.Type = Template.self,
|
templateClass: Template.Type = Template.self,
|
||||||
errorReporter: ErrorReporter = SimpleErrorReporter()) {
|
errorReporter: ErrorReporter = SimpleErrorReporter()) {
|
||||||
|
|
||||||
self.templateClass = templateClass
|
self.templateClass = templateClass
|
||||||
self.errorReporter = errorReporter
|
self.errorReporter = errorReporter
|
||||||
self.loader = loader
|
self.loader = loader
|
||||||
@@ -41,11 +41,11 @@ public struct Environment {
|
|||||||
let template = templateClass.init(templateString: string, environment: self)
|
let template = templateClass.init(templateString: string, environment: self)
|
||||||
return try render(template: template, context: context)
|
return try render(template: template, context: context)
|
||||||
}
|
}
|
||||||
|
|
||||||
func render(template: Template, context: [String: Any]?) throws -> String {
|
func render(template: Template, context: [String: Any]?) throws -> String {
|
||||||
// update template environment as it can be created from string literal with default environment
|
// update template environment as it can be created from string literal with default environment
|
||||||
template.environment = self
|
template.environment = self
|
||||||
return try template.render(context)
|
return try template.render(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,21 +27,21 @@ public struct TemplateSyntaxError : Error, Equatable, CustomStringConvertible {
|
|||||||
var allTokens: [Token] {
|
var allTokens: [Token] {
|
||||||
return stackTrace + (token.map({ [$0] }) ?? [])
|
return stackTrace + (token.map({ [$0] }) ?? [])
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(reason: String, token: Token? = nil, stackTrace: [Token] = []) {
|
public init(reason: String, token: Token? = nil, stackTrace: [Token] = []) {
|
||||||
self.reason = reason
|
self.reason = reason
|
||||||
self.stackTrace = stackTrace
|
self.stackTrace = stackTrace
|
||||||
self.token = token
|
self.token = token
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(_ description: String) {
|
public init(_ description: String) {
|
||||||
self.init(reason: description)
|
self.init(reason: description)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func ==(lhs:TemplateSyntaxError, rhs:TemplateSyntaxError) -> Bool {
|
public static func ==(lhs:TemplateSyntaxError, rhs:TemplateSyntaxError) -> Bool {
|
||||||
return lhs.description == rhs.description && lhs.token == rhs.token && lhs.stackTrace == rhs.stackTrace
|
return lhs.description == rhs.description && lhs.token == rhs.token && lhs.stackTrace == rhs.stackTrace
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public protocol ErrorReporter: class {
|
public protocol ErrorReporter: class {
|
||||||
@@ -49,24 +49,24 @@ public protocol ErrorReporter: class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
open class SimpleErrorReporter: ErrorReporter {
|
open class SimpleErrorReporter: ErrorReporter {
|
||||||
|
|
||||||
open func renderError(_ error: Error) -> String {
|
open func renderError(_ error: Error) -> String {
|
||||||
guard let templateError = error as? TemplateSyntaxError else { return error.localizedDescription }
|
guard let templateError = error as? TemplateSyntaxError else { return error.localizedDescription }
|
||||||
|
|
||||||
func describe(token: Token) -> String {
|
func describe(token: Token) -> String {
|
||||||
let templateName = token.sourceMap.filename ?? ""
|
let templateName = token.sourceMap.filename ?? ""
|
||||||
let line = token.sourceMap.line
|
let line = token.sourceMap.line
|
||||||
let highlight = "\(String(Array(repeating: " ", count: line.offset)))^\(String(Array(repeating: "~", count: max(token.contents.characters.count - 1, 0))))"
|
let highlight = "\(String(Array(repeating: " ", count: line.offset)))^\(String(Array(repeating: "~", count: max(token.contents.characters.count - 1, 0))))"
|
||||||
|
|
||||||
return "\(templateName)\(line.number):\(line.offset): error: \(templateError.reason)\n"
|
return "\(templateName)\(line.number):\(line.offset): error: \(templateError.reason)\n"
|
||||||
+ "\(line.content)\n"
|
+ "\(line.content)\n"
|
||||||
+ "\(highlight)\n"
|
+ "\(highlight)\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
var descriptions = templateError.stackTrace.reduce([]) { $0 + [describe(token: $1)] }
|
var descriptions = templateError.stackTrace.reduce([]) { $0 + [describe(token: $1)] }
|
||||||
let description = templateError.token.map(describe(token:)) ?? templateError.reason
|
let description = templateError.token.map(describe(token:)) ?? templateError.reason
|
||||||
descriptions.append(description)
|
descriptions.append(description)
|
||||||
return descriptions.joined(separator: "\n")
|
return descriptions.joined(separator: "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,21 +88,21 @@ final class NotExpression: Expression, PrefixOperator, CustomStringConvertible {
|
|||||||
final class InExpression: Expression, InfixOperator, CustomStringConvertible {
|
final class InExpression: Expression, InfixOperator, CustomStringConvertible {
|
||||||
let lhs: Expression
|
let lhs: Expression
|
||||||
let rhs: Expression
|
let rhs: Expression
|
||||||
|
|
||||||
init(lhs: Expression, rhs: Expression) {
|
init(lhs: Expression, rhs: Expression) {
|
||||||
self.lhs = lhs
|
self.lhs = lhs
|
||||||
self.rhs = rhs
|
self.rhs = rhs
|
||||||
}
|
}
|
||||||
|
|
||||||
var description: String {
|
var description: String {
|
||||||
return "(\(lhs) in \(rhs))"
|
return "(\(lhs) in \(rhs))"
|
||||||
}
|
}
|
||||||
|
|
||||||
func evaluate(context: Context) throws -> Bool {
|
func evaluate(context: Context) throws -> Bool {
|
||||||
if let lhs = lhs as? VariableExpression, let rhs = rhs as? VariableExpression {
|
if let lhs = lhs as? VariableExpression, let rhs = rhs as? VariableExpression {
|
||||||
let lhsValue = try lhs.variable.resolve(context)
|
let lhsValue = try lhs.variable.resolve(context)
|
||||||
let rhsValue = try rhs.variable.resolve(context)
|
let rhsValue = try rhs.variable.resolve(context)
|
||||||
|
|
||||||
if let lhs = lhsValue as? AnyHashable, let rhs = rhsValue as? [AnyHashable] {
|
if let lhs = lhsValue as? AnyHashable, let rhs = rhsValue as? [AnyHashable] {
|
||||||
return rhs.contains(lhs)
|
return rhs.contains(lhs)
|
||||||
} else if let lhs = lhsValue as? String, let rhs = rhsValue as? String {
|
} else if let lhs = lhsValue as? String, let rhs = rhsValue as? String {
|
||||||
@@ -111,10 +111,10 @@ final class InExpression: Expression, InfixOperator, CustomStringConvertible {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final class OrExpression: Expression, InfixOperator, CustomStringConvertible {
|
final class OrExpression: Expression, InfixOperator, CustomStringConvertible {
|
||||||
|
|||||||
@@ -42,9 +42,9 @@ class DefaultExtension: Extension {
|
|||||||
registerTag("for", parser: ForNode.parse)
|
registerTag("for", parser: ForNode.parse)
|
||||||
registerTag("if", parser: IfNode.parse)
|
registerTag("if", parser: IfNode.parse)
|
||||||
registerTag("ifnot", parser: IfNode.parse_ifnot)
|
registerTag("ifnot", parser: IfNode.parse_ifnot)
|
||||||
#if !os(Linux)
|
#if !os(Linux)
|
||||||
registerTag("now", parser: NowNode.parse)
|
registerTag("now", parser: NowNode.parse)
|
||||||
#endif
|
#endif
|
||||||
registerTag("include", parser: IncludeNode.parse)
|
registerTag("include", parser: IncludeNode.parse)
|
||||||
registerTag("extends", parser: ExtendsNode.parse)
|
registerTag("extends", parser: ExtendsNode.parse)
|
||||||
registerTag("block", parser: BlockNode.parse)
|
registerTag("block", parser: BlockNode.parse)
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ class ForNode : NodeType {
|
|||||||
let components = token.components()
|
let components = token.components()
|
||||||
|
|
||||||
guard components.count >= 3 && components[2] == "in" &&
|
guard components.count >= 3 && components[2] == "in" &&
|
||||||
(components.count == 4 || (components.count >= 6 && components[4] == "where")) else {
|
(components.count == 4 || (components.count >= 6 && components[4] == "where")) else {
|
||||||
throw TemplateSyntaxError("'for' statements should use the following syntax 'for x in y where condition'.")
|
throw TemplateSyntaxError("'for' statements should use the following syntax 'for x in y where condition'.")
|
||||||
}
|
}
|
||||||
|
|
||||||
let loopVariables = components[1].characters
|
let loopVariables = components[1].characters
|
||||||
@@ -38,7 +38,7 @@ class ForNode : NodeType {
|
|||||||
guard let token = parser.nextToken() else {
|
guard let token = parser.nextToken() else {
|
||||||
throw TemplateSyntaxError("`endfor` was not found.")
|
throw TemplateSyntaxError("`endfor` was not found.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if token.contents == "empty" {
|
if token.contents == "empty" {
|
||||||
emptyNodes = try parser.parse(until(["endfor"]))
|
emptyNodes = try parser.parse(until(["endfor"]))
|
||||||
_ = parser.nextToken()
|
_ = parser.nextToken()
|
||||||
@@ -134,14 +134,14 @@ class ForNode : NodeType {
|
|||||||
"last": index == (count - 1),
|
"last": index == (count - 1),
|
||||||
"counter": index + 1,
|
"counter": index + 1,
|
||||||
"counter0": index,
|
"counter0": index,
|
||||||
]
|
]
|
||||||
|
|
||||||
return try context.push(dictionary: ["forloop": forContext]) {
|
return try context.push(dictionary: ["forloop": forContext]) {
|
||||||
return try push(value: item, context: context) {
|
return try push(value: item, context: context) {
|
||||||
try renderNodes(nodes, context)
|
try renderNodes(nodes, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.joined(separator: "")
|
}.joined(separator: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
return try context.push {
|
return try context.push {
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ enum IfToken {
|
|||||||
case .variable(_):
|
case .variable(_):
|
||||||
return 0
|
return 0
|
||||||
case .end:
|
case .end:
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class BlockContext {
|
|||||||
self.blocks[blockName] = [block]
|
self.blocks[blockName] = [block]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func popBlock(named blockName: String) -> BlockNode? {
|
func popBlock(named blockName: String) -> BlockNode? {
|
||||||
if var blocks = blocks[blockName] {
|
if var blocks = blocks[blockName] {
|
||||||
let block = blocks.removeFirst()
|
let block = blocks.removeFirst()
|
||||||
@@ -86,7 +86,7 @@ class ExtendsNode : NodeType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let baseTemplate = try context.environment.loadTemplate(name: templateName)
|
let baseTemplate = try context.environment.loadTemplate(name: templateName)
|
||||||
|
|
||||||
let blockContext: BlockContext
|
let blockContext: BlockContext
|
||||||
if let _blockContext = context[BlockContext.contextKey] as? BlockContext {
|
if let _blockContext = context[BlockContext.contextKey] as? BlockContext {
|
||||||
blockContext = _blockContext
|
blockContext = _blockContext
|
||||||
@@ -148,7 +148,7 @@ class BlockNode : NodeType {
|
|||||||
// child node is a block node from child template that extends this node (has the same name)
|
// child node is a block node from child template that extends this node (has the same name)
|
||||||
|
|
||||||
var newContext: [String: Any] = [BlockContext.contextKey: blockContext]
|
var newContext: [String: Any] = [BlockContext.contextKey: blockContext]
|
||||||
|
|
||||||
if let blockSuperNode = child.nodes.first(where: {
|
if let blockSuperNode = child.nodes.first(where: {
|
||||||
if case .variable(let variable, _)? = $0.token, variable == "block.super" { return true }
|
if case .variable(let variable, _)? = $0.token, variable == "block.super" { return true }
|
||||||
else { return false}
|
else { return false}
|
||||||
@@ -170,7 +170,7 @@ class BlockNode : NodeType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// render extension node
|
// render extension node
|
||||||
do {
|
do {
|
||||||
return try context.push(dictionary: newContext) {
|
return try context.push(dictionary: newContext) {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ struct Lexer {
|
|||||||
"{{": "}}",
|
"{{": "}}",
|
||||||
"{%": "%}",
|
"{%": "%}",
|
||||||
"{#": "#}",
|
"{#": "#}",
|
||||||
]
|
]
|
||||||
|
|
||||||
while !scanner.isEmpty {
|
while !scanner.isEmpty {
|
||||||
if let text = scanner.scan(until: ["{{", "{%", "{#"]) {
|
if let text = scanner.scan(until: ["{{", "{%", "{#"]) {
|
||||||
@@ -66,14 +66,14 @@ struct Lexer {
|
|||||||
|
|
||||||
return tokens
|
return tokens
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Scanner {
|
class Scanner {
|
||||||
let originalContent: String
|
let originalContent: String
|
||||||
var content: String
|
var content: String
|
||||||
var range: Range<String.Index>
|
var range: Range<String.Index>
|
||||||
|
|
||||||
init(_ content: String) {
|
init(_ content: String) {
|
||||||
self.originalContent = content
|
self.originalContent = content
|
||||||
self.content = content
|
self.content = content
|
||||||
@@ -83,7 +83,7 @@ class Scanner {
|
|||||||
var isEmpty: Bool {
|
var isEmpty: Bool {
|
||||||
return content.isEmpty
|
return content.isEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
func scan(until: String, returnUntil: Bool = false) -> String {
|
func scan(until: String, returnUntil: Bool = false) -> String {
|
||||||
var index = content.startIndex
|
var index = content.startIndex
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ class Scanner {
|
|||||||
range = range.upperBound..<range.upperBound
|
range = range.upperBound..<range.upperBound
|
||||||
while index != content.endIndex {
|
while index != content.endIndex {
|
||||||
let substring = content.substring(from: index)
|
let substring = content.substring(from: index)
|
||||||
|
|
||||||
if substring.hasPrefix(until) {
|
if substring.hasPrefix(until) {
|
||||||
let result = content.substring(to: index)
|
let result = content.substring(to: index)
|
||||||
|
|
||||||
@@ -174,12 +174,12 @@ extension String {
|
|||||||
let last = findLastNot(character: character) ?? endIndex
|
let last = findLastNot(character: character) ?? endIndex
|
||||||
return String(self[first..<last])
|
return String(self[first..<last])
|
||||||
}
|
}
|
||||||
|
|
||||||
public func rangeLine(_ range: Range<String.Index>) -> RangeLine {
|
public func rangeLine(_ range: Range<String.Index>) -> RangeLine {
|
||||||
var lineNumber: UInt = 0
|
var lineNumber: UInt = 0
|
||||||
var offset: Int = 0
|
var offset: Int = 0
|
||||||
var lineContent = ""
|
var lineContent = ""
|
||||||
|
|
||||||
for line in components(separatedBy: CharacterSet.newlines) {
|
for line in components(separatedBy: CharacterSet.newlines) {
|
||||||
lineNumber += 1
|
lineNumber += 1
|
||||||
lineContent = line
|
lineContent = line
|
||||||
@@ -189,7 +189,7 @@ extension String {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (lineContent, lineNumber, offset)
|
return (lineContent, lineNumber, offset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import Foundation
|
|||||||
public protocol NodeType {
|
public protocol NodeType {
|
||||||
/// Render the node in the given context
|
/// Render the node in the given context
|
||||||
func render(_ context:Context) throws -> String
|
func render(_ context:Context) throws -> String
|
||||||
|
|
||||||
/// Reference to this node's token
|
/// Reference to this node's token
|
||||||
var token: Token? { get }
|
var token: Token? { get }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ public class TokenParser {
|
|||||||
|
|
||||||
throw TemplateSyntaxError("Unknown filter '\(name)'")
|
throw TemplateSyntaxError("Unknown filter '\(name)'")
|
||||||
}
|
}
|
||||||
|
|
||||||
public func compileFilter(_ filterToken: String, containedIn containingToken: Token) throws -> Resolvable {
|
public func compileFilter(_ filterToken: String, containedIn containingToken: Token) throws -> Resolvable {
|
||||||
do {
|
do {
|
||||||
return try FilterExpression(token: filterToken, parser: self)
|
return try FilterExpression(token: filterToken, parser: self)
|
||||||
@@ -121,7 +121,7 @@ public class TokenParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(*, deprecated, message: "Use compileFilter(_:containedIn:)")
|
@available(*, deprecated, message: "Use compileFilter(_:containedIn:)")
|
||||||
public func compileFilter(_ token: String) throws -> Resolvable {
|
public func compileFilter(_ token: String) throws -> Resolvable {
|
||||||
return try FilterExpression(token: token, parser: self)
|
return try FilterExpression(token: token, parser: self)
|
||||||
|
|||||||
@@ -43,14 +43,14 @@ extension String {
|
|||||||
public struct SourceMap: Equatable {
|
public struct SourceMap: Equatable {
|
||||||
public let filename: String?
|
public let filename: String?
|
||||||
public let line: RangeLine
|
public let line: RangeLine
|
||||||
|
|
||||||
init(filename: String? = nil, line: RangeLine = ("", 0, 0)) {
|
init(filename: String? = nil, line: RangeLine = ("", 0, 0)) {
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
self.line = line
|
self.line = line
|
||||||
}
|
}
|
||||||
|
|
||||||
static let unknown = SourceMap()
|
static let unknown = SourceMap()
|
||||||
|
|
||||||
public static func ==(lhs: SourceMap, rhs: SourceMap) -> Bool {
|
public static func ==(lhs: SourceMap, rhs: SourceMap) -> Bool {
|
||||||
return lhs.filename == rhs.filename && lhs.line == rhs.line
|
return lhs.filename == rhs.filename && lhs.line == rhs.line
|
||||||
}
|
}
|
||||||
@@ -89,7 +89,7 @@ public enum Token : Equatable {
|
|||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public var sourceMap: SourceMap {
|
public var sourceMap: SourceMap {
|
||||||
switch self {
|
switch self {
|
||||||
case .block(_, let sourceMap),
|
case .block(_, let sourceMap),
|
||||||
|
|||||||
@@ -95,11 +95,11 @@ public struct Variable : Equatable, Resolvable {
|
|||||||
current = array.count
|
current = array.count
|
||||||
}
|
}
|
||||||
} else if let object = current as? NSObject { // NSKeyValueCoding
|
} else if let object = current as? NSObject { // NSKeyValueCoding
|
||||||
#if os(Linux)
|
#if os(Linux)
|
||||||
return nil
|
return nil
|
||||||
#else
|
#else
|
||||||
current = object.value(forKey: bit)
|
current = object.value(forKey: bit)
|
||||||
#endif
|
#endif
|
||||||
} else if let value = current {
|
} else if let value = current {
|
||||||
current = Mirror(reflecting: value).getValue(for: bit)
|
current = Mirror(reflecting: value).getValue(for: bit)
|
||||||
if current == nil {
|
if current == nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user