Add architecture document and docs
This commit is contained in:
@@ -13,6 +13,7 @@ public class Context : Equatable {
|
||||
}
|
||||
|
||||
public subscript(key: String) -> AnyObject? {
|
||||
/// Retrieves a variable's value, starting at the current context and going upwards
|
||||
get {
|
||||
for dictionary in reverse(dictionaries) {
|
||||
if let value:AnyObject = dictionary[key] {
|
||||
@@ -23,6 +24,7 @@ public class Context : Equatable {
|
||||
return nil
|
||||
}
|
||||
|
||||
/// Set a variable in the current context, deleting the variable if it's nil
|
||||
set(value) {
|
||||
if dictionaries.count > 0 {
|
||||
var dictionary = dictionaries.removeLast()
|
||||
|
||||
@@ -24,6 +24,7 @@ public struct Lexer {
|
||||
return Token.Text(value: string)
|
||||
}
|
||||
|
||||
/// Returns an array of tokens from a given template string.
|
||||
public func tokenize() -> [Token] {
|
||||
// Unfortunately NSRegularExpression doesn't have a split.
|
||||
// So here's a really terrible implementation
|
||||
|
||||
@@ -15,6 +15,7 @@ struct NodeError : Error {
|
||||
}
|
||||
|
||||
public protocol Node {
|
||||
/// Return the node rendered as a string, or returns a failure
|
||||
func render(context:Context) -> Result
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ public func until(tags:[String])(parser:TokenParser, token:Token) -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
/// 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) -> Result
|
||||
public typealias NodeList = [Node]
|
||||
@@ -37,16 +38,19 @@ public class TokenParser {
|
||||
registerTag("now", NowNode.parse)
|
||||
}
|
||||
|
||||
/// Registers a new template tag
|
||||
public func registerTag(name:String, parser:TagParser) {
|
||||
tags[name] = parser
|
||||
}
|
||||
|
||||
/// Registers a simple template tag with a name and a handler
|
||||
public func registerSimpleTag(name:String, handler:((Context) -> (Stencil.Result))) {
|
||||
registerTag(name, parser: { (parser, token) -> TokenParser.Result in
|
||||
return .Success(node:SimpleNode(handler: handler))
|
||||
})
|
||||
}
|
||||
|
||||
/// Parse the given tokens into nodes
|
||||
public func parse() -> Results {
|
||||
return parse(nil)
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import Foundation
|
||||
|
||||
/// A class representing a template
|
||||
public class Template {
|
||||
public let parser:TokenParser
|
||||
|
||||
/// Create a template with the given name inside the main bundle
|
||||
public convenience init?(named:String) {
|
||||
self.init(named:named, inBundle:nil)
|
||||
}
|
||||
|
||||
/// Create a template with the given name inside the given bundle
|
||||
public convenience init?(named:String, inBundle bundle:NSBundle?) {
|
||||
var url:NSURL?
|
||||
|
||||
@@ -19,6 +22,7 @@ public class Template {
|
||||
self.init(URL:url!)
|
||||
}
|
||||
|
||||
/// Create a template with a file found at the given URL
|
||||
public convenience init?(URL:NSURL) {
|
||||
var error:NSError?
|
||||
let maybeTemplateString = NSString(contentsOfURL: URL, encoding: NSUTF8StringEncoding, error: &error)
|
||||
@@ -30,12 +34,14 @@ public class Template {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a template with a template string
|
||||
public init(templateString:String) {
|
||||
let lexer = Lexer(templateString: templateString)
|
||||
let tokens = lexer.tokenize()
|
||||
parser = TokenParser(tokens: tokens)
|
||||
}
|
||||
|
||||
/// Render the given template in a context
|
||||
public func render(context:Context) -> Result {
|
||||
switch parser.parse() {
|
||||
case .Success(let nodes):
|
||||
@@ -46,6 +52,7 @@ public class Template {
|
||||
}
|
||||
}
|
||||
|
||||
/// Render the given template without a context
|
||||
public func render() -> Result {
|
||||
let context = Context()
|
||||
return render(context)
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
public enum Token : Equatable {
|
||||
/// A token representing a piece of text.
|
||||
case Text(value:String)
|
||||
|
||||
/// A token representing a variable.
|
||||
case Variable(value:String)
|
||||
|
||||
/// A token representing a comment.
|
||||
case Comment(value:String)
|
||||
|
||||
/// A token representing a template block.
|
||||
case Block(value:String)
|
||||
|
||||
/// Returns the underlying value as an array seperated by spaces
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
/// A structure used to represent a template variable, and to resolve it in a given context.
|
||||
public struct Variable : Equatable {
|
||||
public let variable:String
|
||||
|
||||
/// Create a variable with a string representing the variable
|
||||
public init(_ variable:String) {
|
||||
self.variable = variable
|
||||
}
|
||||
@@ -11,6 +14,7 @@ public struct Variable : Equatable {
|
||||
return variable.componentsSeparatedByString(".")
|
||||
}
|
||||
|
||||
/// Resolve the variable in the given context
|
||||
public func resolve(context:Context) -> AnyObject? {
|
||||
var current:AnyObject? = context
|
||||
|
||||
|
||||
Reference in New Issue
Block a user