feat: Allow subclassing templates (#79)

This commit is contained in:
Kyle Fuller
2016-12-07 21:46:04 +00:00
committed by GitHub
parent d7b152089e
commit 26f30cbd9d
5 changed files with 28 additions and 8 deletions

View File

@@ -56,6 +56,9 @@
- You can now use `{{ block.super }}` to render a super block from another `{% - You can now use `{{ block.super }}` to render a super block from another `{%
block %}`. block %}`.
- `Environment` allows you to provide a custom `Template` subclass, allowing
new template to use a specific subclass.
### Deprecations ### Deprecations
- `Template` initialisers have been deprecated in favour of using a template - `Template` initialisers have been deprecated in favour of using a template

View File

@@ -1,9 +1,11 @@
public struct Environment { public struct Environment {
public let templateClass: Template.Type
public let extensions: [Extension] public let extensions: [Extension]
public var loader: Loader? public var loader: Loader?
public init(loader: Loader? = nil, extensions: [Extension]? = nil) { public init(loader: Loader? = nil, extensions: [Extension]? = nil, templateClass: Template.Type = Template.self) {
self.templateClass = templateClass
self.loader = loader self.loader = loader
self.extensions = [DefaultExtension()] + (extensions ?? []) self.extensions = [DefaultExtension()] + (extensions ?? [])
} }
@@ -30,7 +32,7 @@ public struct Environment {
} }
public func renderTemplate(string: String, context: [String: Any]? = nil) throws -> String { public func renderTemplate(string: String, context: [String: Any]? = nil) throws -> String {
let template = Template(templateString: string, environment: self) let template = templateClass.init(templateString: string, environment: self)
return try template.render(context) return try template.render(context)
} }
} }

View File

@@ -51,7 +51,8 @@ public class FileSystemLoader: Loader, CustomStringConvertible {
continue continue
} }
return try Template(path: templatePath, environment: environment, name: name) let content: String = try templatePath.read()
return try environment.templateClass.init(templateString: content, environment: environment, name: name)
} }
throw TemplateDoesNotExist(templateNames: [name], loader: self) throw TemplateDoesNotExist(templateNames: [name], loader: self)
@@ -63,7 +64,8 @@ public class FileSystemLoader: Loader, CustomStringConvertible {
let templatePath = try path.safeJoin(path: Path(templateName)) let templatePath = try path.safeJoin(path: Path(templateName))
if templatePath.exists { if templatePath.exists {
return try Template(path: templatePath, environment: environment, name: templateName) let content: String = try templatePath.read()
return try environment.templateClass.init(templateString: content, environment: environment, name: templateName)
} }
} }
} }

View File

@@ -6,7 +6,7 @@ let NSFileNoSuchFileError = 4
#endif #endif
/// A class representing a template /// A class representing a template
public class Template: ExpressibleByStringLiteral { open class Template: ExpressibleByStringLiteral {
let environment: Environment let environment: Environment
let tokens: [Token] let tokens: [Token]
@@ -14,7 +14,7 @@ public class Template: ExpressibleByStringLiteral {
public let name: String? public let name: String?
/// Create a template with a template string /// Create a template with a template string
public init(templateString: String, environment: Environment? = nil, name: String? = nil) { public required init(templateString: String, environment: Environment? = nil, name: String? = nil) {
self.environment = environment ?? Environment() self.environment = environment ?? Environment()
self.name = name self.name = name
@@ -71,7 +71,7 @@ public class Template: ExpressibleByStringLiteral {
} }
/// Render the given template /// Render the given template
public func render(_ dictionary: [String: Any]? = nil) throws -> String { open func render(_ dictionary: [String: Any]? = nil) throws -> String {
return try render(Context(dictionary: dictionary, environment: environment)) return try render(Context(dictionary: dictionary, environment: environment))
} }
} }

View File

@@ -25,9 +25,15 @@ func testEnvironment() {
let result = try environment.renderTemplate(name: "example.html") let result = try environment.renderTemplate(name: "example.html")
try expect(result) == "Hello World!" try expect(result) == "Hello World!"
} }
}
}
$0.it("allows you to provide a custom template class") {
let environment = Environment(loader: ExampleLoader(), templateClass: CustomTemplate.self)
let result = try environment.renderTemplate(string: "Hello World")
try expect(result) == "here"
}
}
}
fileprivate class ExampleLoader: Loader { fileprivate class ExampleLoader: Loader {
@@ -39,3 +45,10 @@ fileprivate class ExampleLoader: Loader {
throw TemplateDoesNotExist(templateNames: [name], loader: self) throw TemplateDoesNotExist(templateNames: [name], loader: self)
} }
} }
class CustomTemplate: Template {
override func render(_ dictionary: [String: Any]? = nil) throws -> String {
return "here"
}
}