chore: Lock down APIs

This commit is contained in:
Kyle Fuller
2016-11-27 02:20:46 +00:00
parent 60b378d482
commit a13401b046
17 changed files with 67 additions and 60 deletions

View File

@@ -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.

View File

@@ -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()

View File

@@ -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 {

View File

@@ -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

View File

@@ -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")
}

View File

@@ -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)

View File

@@ -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)
}
}

View File

@@ -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 {

View File

@@ -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?

View File

@@ -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
}

View File

@@ -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()

View File

@@ -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)

View File

@@ -1,5 +1,5 @@
import Spectre
import Stencil
@testable import Stencil
import Foundation

View File

@@ -1,5 +1,5 @@
import Spectre
import Stencil
@testable import Stencil
func testIfNode() {

View File

@@ -1,5 +1,5 @@
import Spectre
import Stencil
@testable import Stencil
import PathKit

View File

@@ -1,5 +1,5 @@
import Spectre
import Stencil
@testable import Stencil
func testLexer() {

View File

@@ -1,6 +1,6 @@
import Foundation
import Spectre
import Stencil
@testable import Stencil
func testNowNode() {