chore: Lock down APIs
This commit is contained in:
@@ -2,6 +2,13 @@
|
||||
|
||||
## Master
|
||||
|
||||
### Breaking
|
||||
|
||||
- Many internal classes are no longer private. Some APIs were previously
|
||||
accessible due to earlier versions of Swift requiring the types to be public
|
||||
to be able to test. Now we have access to `@testable` these can correctly be
|
||||
private.
|
||||
|
||||
### Enhancements
|
||||
|
||||
- You may now register custom template filters which make use of arguments.
|
||||
|
||||
@@ -14,7 +14,7 @@ public class Context {
|
||||
self.namespace = namespace
|
||||
}
|
||||
|
||||
open subscript(key: String) -> Any? {
|
||||
public subscript(key: String) -> Any? {
|
||||
/// Retrieves a variable's value, starting at the current context and going upwards
|
||||
get {
|
||||
for dictionary in Array(dictionaries.reversed()) {
|
||||
@@ -47,7 +47,7 @@ public class Context {
|
||||
}
|
||||
|
||||
/// Push a new level onto the context for the duration of the execution of the given closure
|
||||
open func push<Result>(dictionary: [String: Any]? = nil, closure: (() throws -> Result)) rethrows -> Result {
|
||||
public func push<Result>(dictionary: [String: Any]? = nil, closure: (() throws -> Result)) rethrows -> Result {
|
||||
push(dictionary)
|
||||
defer { _ = pop() }
|
||||
return try closure()
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
open class ForNode : NodeType {
|
||||
class ForNode : NodeType {
|
||||
let variable:Variable
|
||||
let loopVariable:String
|
||||
let nodes:[NodeType]
|
||||
let emptyNodes: [NodeType]
|
||||
|
||||
open class func parse(_ parser:TokenParser, token:Token) throws -> NodeType {
|
||||
class func parse(_ parser:TokenParser, token:Token) throws -> NodeType {
|
||||
let components = token.components()
|
||||
|
||||
guard components.count == 4 && components[2] == "in" else {
|
||||
@@ -30,14 +30,14 @@ open class ForNode : NodeType {
|
||||
return ForNode(variable: variable, loopVariable: loopVariable, nodes: forNodes, emptyNodes:emptyNodes)
|
||||
}
|
||||
|
||||
public init(variable:String, loopVariable:String, nodes:[NodeType], emptyNodes:[NodeType]) {
|
||||
init(variable:String, loopVariable:String, nodes:[NodeType], emptyNodes:[NodeType]) {
|
||||
self.variable = Variable(variable)
|
||||
self.loopVariable = loopVariable
|
||||
self.nodes = nodes
|
||||
self.emptyNodes = emptyNodes
|
||||
}
|
||||
|
||||
open func render(_ context: Context) throws -> String {
|
||||
func render(_ context: Context) throws -> String {
|
||||
let values = try variable.resolve(context)
|
||||
|
||||
if let values = values as? [Any] , values.count > 0 {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
open class IfNode : NodeType {
|
||||
open let variable:Variable
|
||||
open let trueNodes:[NodeType]
|
||||
open let falseNodes:[NodeType]
|
||||
class IfNode : NodeType {
|
||||
let variable:Variable
|
||||
let trueNodes:[NodeType]
|
||||
let falseNodes:[NodeType]
|
||||
|
||||
open class func parse(_ parser:TokenParser, token:Token) throws -> NodeType {
|
||||
class func parse(_ parser:TokenParser, token:Token) throws -> NodeType {
|
||||
let components = token.components()
|
||||
guard components.count == 2 else {
|
||||
throw TemplateSyntaxError("'if' statements should use the following 'if condition' `\(token.contents)`.")
|
||||
@@ -26,7 +26,7 @@ open class IfNode : NodeType {
|
||||
return IfNode(variable: variable, trueNodes: trueNodes, falseNodes: falseNodes)
|
||||
}
|
||||
|
||||
open class func parse_ifnot(_ parser:TokenParser, token:Token) throws -> NodeType {
|
||||
class func parse_ifnot(_ parser:TokenParser, token:Token) throws -> NodeType {
|
||||
let components = token.components()
|
||||
guard components.count == 2 else {
|
||||
throw TemplateSyntaxError("'ifnot' statements should use the following 'ifnot condition' `\(token.contents)`.")
|
||||
@@ -49,13 +49,13 @@ open class IfNode : NodeType {
|
||||
return IfNode(variable: variable, trueNodes: trueNodes, falseNodes: falseNodes)
|
||||
}
|
||||
|
||||
public init(variable:String, trueNodes:[NodeType], falseNodes:[NodeType]) {
|
||||
init(variable:String, trueNodes:[NodeType], falseNodes:[NodeType]) {
|
||||
self.variable = Variable(variable)
|
||||
self.trueNodes = trueNodes
|
||||
self.falseNodes = falseNodes
|
||||
}
|
||||
|
||||
open func render(_ context: Context) throws -> String {
|
||||
func render(_ context: Context) throws -> String {
|
||||
let result = try variable.resolve(context)
|
||||
var truthy = false
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import PathKit
|
||||
|
||||
|
||||
open class IncludeNode : NodeType {
|
||||
open let templateName: Variable
|
||||
class IncludeNode : NodeType {
|
||||
let templateName: Variable
|
||||
|
||||
open class func parse(_ parser: TokenParser, token: Token) throws -> NodeType {
|
||||
class func parse(_ parser: TokenParser, token: Token) throws -> NodeType {
|
||||
let bits = token.components()
|
||||
|
||||
guard bits.count == 2 else {
|
||||
@@ -14,11 +14,11 @@ open class IncludeNode : NodeType {
|
||||
return IncludeNode(templateName: Variable(bits[1]))
|
||||
}
|
||||
|
||||
public init(templateName: Variable) {
|
||||
init(templateName: Variable) {
|
||||
self.templateName = templateName
|
||||
}
|
||||
|
||||
open func render(_ context: Context) throws -> String {
|
||||
func render(_ context: Context) throws -> String {
|
||||
guard let loader = context["loader"] as? TemplateLoader else {
|
||||
throw TemplateSyntaxError("Template loader not in context")
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
public struct Lexer {
|
||||
public let templateString: String
|
||||
struct Lexer {
|
||||
let templateString: String
|
||||
|
||||
public init(templateString: String) {
|
||||
init(templateString: String) {
|
||||
self.templateString = templateString
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ public struct Lexer {
|
||||
}
|
||||
|
||||
/// Returns an array of tokens from a given template string.
|
||||
public func tokenize() -> [Token] {
|
||||
func tokenize() -> [Token] {
|
||||
var tokens: [Token] = []
|
||||
|
||||
let scanner = Scanner(templateString)
|
||||
|
||||
@@ -21,7 +21,7 @@ enum Filter: FilterType {
|
||||
}
|
||||
|
||||
|
||||
open class Namespace {
|
||||
public class Namespace {
|
||||
public typealias TagParser = (TokenParser, Token) throws -> NodeType
|
||||
|
||||
var tags = [String: TagParser]()
|
||||
@@ -51,24 +51,24 @@ open class Namespace {
|
||||
}
|
||||
|
||||
/// Registers a new template tag
|
||||
open func registerTag(_ name: String, parser: @escaping TagParser) {
|
||||
public func registerTag(_ name: String, parser: @escaping TagParser) {
|
||||
tags[name] = parser
|
||||
}
|
||||
|
||||
/// Registers a simple template tag with a name and a handler
|
||||
open func registerSimpleTag(_ name: String, handler: @escaping (Context) throws -> String) {
|
||||
public func registerSimpleTag(_ name: String, handler: @escaping (Context) throws -> String) {
|
||||
registerTag(name, parser: { parser, token in
|
||||
return SimpleNode(handler: handler)
|
||||
})
|
||||
}
|
||||
|
||||
/// Registers a template filter with the given name
|
||||
open func registerFilter(_ name: String, filter: @escaping (Any?) throws -> Any?) {
|
||||
public func registerFilter(_ name: String, filter: @escaping (Any?) throws -> Any?) {
|
||||
filters[name] = .simple(filter)
|
||||
}
|
||||
|
||||
/// Registers a template filter with the given name
|
||||
open func registerFilter(_ name: String, filter: @escaping (Any?, [Any?]) throws -> Any?) {
|
||||
public func registerFilter(_ name: String, filter: @escaping (Any?, [Any?]) throws -> Any?) {
|
||||
filters[name] = .arguments(filter)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,27 +26,27 @@ public func renderNodes(_ nodes:[NodeType], _ context:Context) throws -> String
|
||||
return try nodes.map { try $0.render(context) }.joined(separator: "")
|
||||
}
|
||||
|
||||
open class SimpleNode : NodeType {
|
||||
let handler:(Context) throws -> String
|
||||
public class SimpleNode : NodeType {
|
||||
public let handler:(Context) throws -> String
|
||||
|
||||
public init(handler: @escaping (Context) throws -> String) {
|
||||
self.handler = handler
|
||||
}
|
||||
|
||||
open func render(_ context: Context) throws -> String {
|
||||
public func render(_ context: Context) throws -> String {
|
||||
return try handler(context)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
open class TextNode : NodeType {
|
||||
open let text:String
|
||||
public class TextNode : NodeType {
|
||||
public let text:String
|
||||
|
||||
public init(text:String) {
|
||||
self.text = text
|
||||
}
|
||||
|
||||
open func render(_ context:Context) throws -> String {
|
||||
public func render(_ context:Context) throws -> String {
|
||||
return self.text
|
||||
}
|
||||
}
|
||||
@@ -57,8 +57,8 @@ public protocol Resolvable {
|
||||
}
|
||||
|
||||
|
||||
open class VariableNode : NodeType {
|
||||
open let variable: Resolvable
|
||||
public class VariableNode : NodeType {
|
||||
public let variable: Resolvable
|
||||
|
||||
public init(variable: Resolvable) {
|
||||
self.variable = variable
|
||||
@@ -68,7 +68,7 @@ open class VariableNode : NodeType {
|
||||
self.variable = Variable(variable)
|
||||
}
|
||||
|
||||
open func render(_ context: Context) throws -> String {
|
||||
public func render(_ context: Context) throws -> String {
|
||||
let result = try variable.resolve(context)
|
||||
|
||||
if let result = result as? String {
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
open class NowNode : NodeType {
|
||||
open let format:Variable
|
||||
class NowNode : NodeType {
|
||||
let format:Variable
|
||||
|
||||
open class func parse(_ parser:TokenParser, token:Token) throws -> NodeType {
|
||||
class func parse(_ parser:TokenParser, token:Token) throws -> NodeType {
|
||||
var format:Variable?
|
||||
|
||||
let components = token.components()
|
||||
@@ -19,11 +19,11 @@ open class NowNode : NodeType {
|
||||
return NowNode(format:format)
|
||||
}
|
||||
|
||||
public init(format:Variable?) {
|
||||
init(format:Variable?) {
|
||||
self.format = format ?? Variable("\"yyyy-MM-dd 'at' HH:mm\"")
|
||||
}
|
||||
|
||||
open func render(_ context: Context) throws -> String {
|
||||
func render(_ context: Context) throws -> String {
|
||||
let date = Date()
|
||||
let format = try self.format.resolve(context)
|
||||
var formatter:DateFormatter?
|
||||
|
||||
@@ -14,7 +14,7 @@ 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
|
||||
open class TokenParser {
|
||||
public class TokenParser {
|
||||
public typealias TagParser = (TokenParser, Token) throws -> NodeType
|
||||
|
||||
fileprivate var tokens: [Token]
|
||||
@@ -26,11 +26,11 @@ open class TokenParser {
|
||||
}
|
||||
|
||||
/// Parse the given tokens into nodes
|
||||
open func parse() throws -> [NodeType] {
|
||||
public func parse() throws -> [NodeType] {
|
||||
return try parse(nil)
|
||||
}
|
||||
|
||||
open func parse(_ parse_until:((_ parser:TokenParser, _ token:Token) -> (Bool))?) throws -> [NodeType] {
|
||||
public func parse(_ parse_until:((_ parser:TokenParser, _ token:Token) -> (Bool))?) throws -> [NodeType] {
|
||||
var nodes = [NodeType]()
|
||||
|
||||
while tokens.count > 0 {
|
||||
@@ -64,7 +64,7 @@ open class TokenParser {
|
||||
return nodes
|
||||
}
|
||||
|
||||
open func nextToken() -> Token? {
|
||||
public func nextToken() -> Token? {
|
||||
if tokens.count > 0 {
|
||||
return tokens.remove(at: 0)
|
||||
}
|
||||
@@ -72,11 +72,11 @@ open class TokenParser {
|
||||
return nil
|
||||
}
|
||||
|
||||
open func prependToken(_ token:Token) {
|
||||
public func prependToken(_ token:Token) {
|
||||
tokens.insert(token, at: 0)
|
||||
}
|
||||
|
||||
open func findFilter(_ name: String) throws -> FilterType {
|
||||
public func findFilter(_ name: String) throws -> FilterType {
|
||||
if let filter = namespace.filters[name] {
|
||||
return filter
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ let NSFileNoSuchFileError = 4
|
||||
#endif
|
||||
|
||||
/// A class representing a template
|
||||
open class Template: ExpressibleByStringLiteral {
|
||||
public class Template: ExpressibleByStringLiteral {
|
||||
let tokens: [Token]
|
||||
|
||||
/// Create a template with the given name inside the given bundle
|
||||
@@ -51,7 +51,7 @@ open class Template: ExpressibleByStringLiteral {
|
||||
}
|
||||
|
||||
/// Render the given template
|
||||
open func render(_ context: Context? = nil) throws -> String {
|
||||
public func render(_ context: Context? = nil) throws -> String {
|
||||
let context = context ?? Context()
|
||||
let parser = TokenParser(tokens: tokens, namespace: context.namespace)
|
||||
let nodes = try parser.parse()
|
||||
|
||||
@@ -3,8 +3,8 @@ import PathKit
|
||||
|
||||
|
||||
// A class for loading a template from disk
|
||||
open class TemplateLoader {
|
||||
open let paths: [Path]
|
||||
public class TemplateLoader {
|
||||
public let paths: [Path]
|
||||
|
||||
public init(paths: [Path]) {
|
||||
self.paths = paths
|
||||
@@ -16,11 +16,11 @@ open class TemplateLoader {
|
||||
}
|
||||
}
|
||||
|
||||
open func loadTemplate(_ templateName: String) -> Template? {
|
||||
public func loadTemplate(_ templateName: String) -> Template? {
|
||||
return loadTemplate([templateName])
|
||||
}
|
||||
|
||||
open func loadTemplate(_ templateNames: [String]) -> Template? {
|
||||
public func loadTemplate(_ templateNames: [String]) -> Template? {
|
||||
for path in paths {
|
||||
for templateName in templateNames {
|
||||
let templatePath = path + Path(templateName)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Spectre
|
||||
import Stencil
|
||||
@testable import Stencil
|
||||
import Foundation
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Spectre
|
||||
import Stencil
|
||||
@testable import Stencil
|
||||
|
||||
|
||||
func testIfNode() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Spectre
|
||||
import Stencil
|
||||
@testable import Stencil
|
||||
import PathKit
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Spectre
|
||||
import Stencil
|
||||
@testable import Stencil
|
||||
|
||||
|
||||
func testLexer() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
import Spectre
|
||||
import Stencil
|
||||
@testable import Stencil
|
||||
|
||||
|
||||
func testNowNode() {
|
||||
|
||||
Reference in New Issue
Block a user