Add architecture document and docs

This commit is contained in:
Kyle Fuller
2014-11-30 00:04:17 +00:00
parent 017692a0dc
commit 5d61043f8c
9 changed files with 209 additions and 0 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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