0001 // The MIT License 0002 // 0003 // Copyright (c) 2015 Gwendal Roué 0004 // 0005 // Permission is hereby granted, free of charge, to any person obtaining a copy 0006 // of this software and associated documentation files (the "Software"), to deal 0007 // in the Software without restriction, including without limitation the rights 0008 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 0009 // copies of the Software, and to permit persons to whom the Software is 0010 // furnished to do so, subject to the following conditions: 0011 // 0012 // The above copyright notice and this permission notice shall be included in 0013 // all copies or substantial portions of the Software. 0014 // 0015 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 0016 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 0017 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 0018 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 0019 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 0020 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 0021 // THE SOFTWARE. 0022 0023 /// See the documentation of the `TemplateRepositoryDataSource` protocol. 0024 public typealias TemplateID= String 0025 0026 /** 0027 The protocol for a TemplateRepository's dataSource. 0028 0029 The dataSource's responsability is to provide Mustache template strings for 0030 template and partial names. 0031 */ 0032 public protocol TemplateRepositoryDataSource
Common.swift:85 public init(kind: Kind, message: String? = nil, templateID: TemplateID? = nil, lineNumber: Int? = nil, underlyingError: ErrorType? = nil) {Common.swift:93 func errorWith(message message: String? = nil, templateID: TemplateID? = nil, lineNumber: Int? = nil, underlyingError: ErrorType? = nil) -> MustacheError {TemplateCompiler.swift:26 private let templateID: TemplateID?TemplateCompiler.swift:28 init(contentType: ContentType, repository: TemplateRepository, templateID: TemplateID?) {TemplateParser.swift:52 func parse(templateString:String, templateID: TemplateID?) {TemplateToken.swift:65 let templateID: TemplateID?TemplateRepository.swift:71 func templateIDForName(name: String, relativeToTemplateID baseTemplateID: TemplateID?) -> TemplateID?TemplateRepository.swift:71 func templateIDForName(name: String, relativeToTemplateID baseTemplateID: TemplateID?) -> TemplateID?TemplateRepository.swift:81 func templateStringForTemplateID(templateID: TemplateID) throws -> StringTemplateRepository.swift:237 func templateAST(named name: String, relativeToTemplateID baseTemplateID: TemplateID? = nil) throws -> TemplateAST {TemplateRepository.swift:274 func templateAST(string string: String, templateID: TemplateID? = nil) throws -> TemplateAST {TemplateRepository.swift:304 private var templateASTCache: [TemplateID: TemplateAST]TemplateRepository.swift:317 func templateIDForName(name: String, relativeToTemplateID baseTemplateID: TemplateID?) -> TemplateID? {TemplateRepository.swift:317 func templateIDForName(name: String, relativeToTemplateID baseTemplateID: TemplateID?) -> TemplateID? {TemplateRepository.swift:321 func templateStringForTemplateID(templateID: TemplateID) throws -> String {LocatedTag.swift:10 var templateID: TemplateID? { get }SectionTag.swift:54 var templateID: TemplateID? { return openingToken.templateID }VariableTag.swift:52 var templateID: TemplateID? { return token.templateID }{ 0033 0034 /** 0035 Returns a template ID, that is to say a string that uniquely identifies a 0036 template or a template partial. 0037 0038 The meaning of this String is opaque: your implementation of a 0039 `TemplateRepositoryDataSource` would define, for itself, how strings would 0040 identity a template or a partial. For example, a file-based data source may 0041 use paths to the templates. 0042 0043 The return value of this method can be nil: the library user will then 0044 eventually catch a missing template error. 0045 0046 ### Template hierarchies 0047 0048 Whenever relevant, template and partial hierarchies are supported via the 0049 baseTemplateID parameter: it contains the template ID of the enclosing 0050 template, or nil when the data source is asked for a template ID from a raw 0051 template string (see TemplateRepository.template(string:error:)). 0052 0053 Not all data sources have to implement hierarchies: they can simply ignore 0054 this parameter. 0055 0056 *Well-behaved* data sources that support hierarchies should support 0057 "absolute paths to partials". For example, the built-in directory-based data 0058 source lets users write both `{{> relative/path/to/partial}}` and 0059 `{{> /absolute/path/tp/partial}}`tags. 0060 0061 ### Unique IDs 0062 0063 Each template must be identified by a single template ID. For example, a 0064 file-based data source which uses path IDs must normalize paths. Not 0065 following this rule yields undefined behavior. 0066 0067 - parameter name: The name of the template or template partial. 0068 - parameter baseTemplateID: The template ID of the enclosing template. 0069 - returns: A template ID. 0070 */ 0071 func templateIDForName
TemplateRepository.swift:115 public init(dataSource: TemplateRepositoryDataSource? = nil) {TemplateRepository.swift:173 public let dataSource: TemplateRepositoryDataSource?TemplateRepository.swift:310 private class DictionaryDataSource: TemplateRepositoryDataSource {(name: String, relativeToTemplateID baseTemplateID: TemplateID?) -> TemplateID? 0072 0073 /** 0074 Returns the Mustache template string that matches the template ID. 0075 0076 - parameter templateID: The template ID of the template. 0077 - parameter error: If there is an error returning a template string, 0078 throws an error that describes the problem. 0079 - returns: A Mustache template string. 0080 */ 0081 func templateStringForTemplateID
TemplateRepository.swift:242 guard let templateID = dataSource.templateIDForName(name, relativeToTemplateID: baseTemplateID) else {(templateID: TemplateID) throws -> String 0082 } 0083 0084 /** 0085 A template repository represents a set of sibling templates and partials. 0086 0087 You don't have to instanciate template repositories, because GRMustache provides 0088 implicit ones whenever you load templates with methods like 0089 `Template(named:error:)`, for example. 0090 0091 However, you may like to use one for your profit. Template repositories provide: 0092 0093 - custom template data source 0094 - custom `Configuration` 0095 - a cache of template parsings 0096 - absolute paths to ease loading of partial templates in a hierarchy of 0097 directories and template files 0098 */ 0099 final public class TemplateRepository
TemplateRepository.swift:255 let templateString = try dataSource.templateStringForTemplateID(templateID){ 0100 0101 // ========================================================================= 0102 // MARK: - Creating Template Repositories 0103 0104 /** 0105 Returns a TemplateRepository which loads template through the provided 0106 dataSource. 0107 0108 The dataSource is optional, but repositories without dataSource can not load 0109 templates by name, and can only parse template strings that do not contain 0110 any `{{> partial }}` tag. 0111 0112 let repository = TemplateRepository() 0113 let template = try! repository.template(string: "Hello {{name}}") 0114 */ 0115 public init
TemplateCompiler.swift:25 private let repository: TemplateRepositoryTemplateCompiler.swift:28 init(contentType: ContentType, repository: TemplateRepository, templateID: TemplateID?) {CoreFunctions.swift:511 let templateRepository = TemplateRepository()CoreFunctions.swift:627 let templateRepository = TemplateRepository()Template.swift:40 let repository = TemplateRepository()Template.swift:199 public let repository: TemplateRepositoryTemplate.swift:207 init(repository: TemplateRepository, templateAST: TemplateAST, baseContext: Context) {(dataSource: TemplateRepositoryDataSource? = nil) { 0116 configuration = DefaultConfiguration 0117 templateASTCache = [:] 0118 self.dataSource = dataSource 0119 } 0120 0121 /** 0122 Returns a TemplateRepository that loads templates from a dictionary. 0123 0124 let templates = ["template": "Hulk Hogan has a Mustache."] 0125 let repository = TemplateRepository(templates: templates) 0126 0127 // Renders "Hulk Hogan has a Mustache." twice 0128 try! repository.template(named: "template").render() 0129 try! repository.template(string: "{{>template}}").render() 0130 0131 - parameter templates: A dictionary whose keys are template names and values 0132 template strings. 0133 - returns: A new TemplateRepository. 0134 */ 0135 convenience public init(templates: [String: String]) { 0136 self.init(dataSource: DictionaryDataSource(templates: templates)) 0137 } 0138 0139 // ========================================================================= 0140 // MARK: - Configuring Template Repositories 0141 0142 /** 0143 The configuration for all templates and partials built by the repository. 0144 0145 It is initialized with `Mustache.DefaultConfiguration`. 0146 0147 You can alter the repository's configuration, or set it to another value, 0148 before you load templates: 0149 0150 // Reset the configuration to a factory configuration and change tag delimiters: 0151 let repository = TemplateRepository() 0152 repository.configuration = Configuration() 0153 repository.configuration.tagDelimiterPair = ("<%", "%>") 0154 0155 // Renders "Hello Luigi" 0156 let template = try! repository.template(string: "Hello <%name%>") 0157 try! template.render(Box(["name": "Luigi"])) 0158 0159 **Warning**: changing the configuration has no effect after the repository 0160 has loaded one template. 0161 */ 0162 public var configuration
CoreFunctions.swift:511 let templateRepository = TemplateRepository()CoreFunctions.swift:627 let templateRepository = TemplateRepository()Template.swift:40 let repository = TemplateRepository()TemplateRepository.swift:136 self.init(dataSource: DictionaryDataSource(templates: templates)): Configuration 0163 0164 0165 // ========================================================================= 0166 // MARK: - Loading Templates from a Repository 0167 0168 0169 /** 0170 The template repository data source, responsible for loading template 0171 strings. 0172 */ 0173 public let dataSource
CoreFunctions.swift:512 templateRepository.configuration.tagDelimiterPair = info.tag.tagDelimiterPairCoreFunctions.swift:628 templateRepository.configuration.contentType = .TextTemplate.swift:42 self.init(repository: repository, templateAST: templateAST, baseContext: repository.configuration.baseContext)TemplateRepository.swift:116 configuration = DefaultConfigurationTemplateRepository.swift:299 _lockedConfiguration = configuration: TemplateRepositoryDataSource? 0174 0175 /** 0176 Returns a template. 0177 0178 Depending on the way the repository has been created, partial tags such as 0179 `{{>partial}}` load partial templates from URLs, file paths, keys in a 0180 dictionary, or whatever is relevant to the repository's data source. 0181 0182 - parameter templateString: A Mustache template string. 0183 - parameter error: If there is an error loading or parsing template 0184 and partials, throws an error that describes the 0185 problem. 0186 - returns: A Mustache Template. 0187 */ 0188 public func template
TemplateRepository.swift:118 self.dataSource = dataSourceTemplateRepository.swift:238 guard let dataSource = self.dataSource else {(string string: String) throws -> Template { 0189 let templateAST = try self.templateAST(string: string) 0190 return Template(repository: self, templateAST: templateAST, baseContext: lockedConfiguration.baseContext) 0191 } 0192 0193 /** 0194 Returns a template identified by its name. 0195 0196 Depending on the repository's data source, the name identifies a bundle 0197 resource, a URL, a file path, a key in a dictionary, etc. 0198 0199 Template repositories cache the parsing of their templates. However this 0200 method always return new Template instances, which you can further configure 0201 independently. 0202 0203 - parameter name: The template name. 0204 - parameter error: If there is an error loading or parsing template and 0205 partials, throws an error that describes the problem. 0206 - returns: A Mustache Template. 0207 0208 See also: 0209 0210 - reloadTemplates 0211 */ 0212 public func template(named name: String) throws -> Template { 0213 let templateAST = try self.templateAST(named: name, relativeToTemplateID: nil) 0214 return Template(repository: self, templateAST: templateAST, baseContext: lockedConfiguration.baseContext) 0215 } 0216 0217 /** 0218 Clears the cache of parsed template strings. 0219 0220 // May reuse a cached parsing: 0221 let template = try! repository.template(named:"profile") 0222 0223 // Forces the reloading of the template: 0224 repository.reloadTemplates(); 0225 let template = try! repository.template(named:"profile") 0226 0227 **Warning**: previously created Template instances are not reloaded. 0228 */ 0229 public func reloadTemplates() { 0230 templateASTCache.removeAll() 0231 } 0232 0233 0234 // ========================================================================= 0235 // MARK: - Not public 0236 0237 func templateAST
CoreFunctions.swift:515 let template = try templateRepository.template(string: templateString)CoreFunctions.swift:631 let template = try templateRepository.template(string: templateString)(named name: String, relativeToTemplateID baseTemplateID: TemplateID? = nil) throws -> TemplateAST { 0238 guard let dataSource = self.dataSource else { 0239 throw MustacheError(kind: .TemplateNotFound, message: "Missing dataSource", templateID: baseTemplateID) 0240 } 0241 0242 guard let templateID = dataSource.templateIDForName(name, relativeToTemplateID: baseTemplateID) else { 0243 if let baseTemplateID = baseTemplateID { 0244 throw MustacheError(kind: .TemplateNotFound, message: "Template not found: \"\(name)\" from \(baseTemplateID)", templateID: baseTemplateID) 0245 } else { 0246 throw MustacheError(kind: .TemplateNotFound, message: "Template not found: \"\(name)\"") 0247 } 0248 } 0249 0250 if let templateAST = templateASTCache[templateID] { 0251 // Return cached AST 0252 return templateAST 0253 } 0254 0255 let templateString = try dataSource.templateStringForTemplateID(templateID) 0256 0257 // Cache an empty AST for that name so that we support recursive 0258 // partials. 0259 let templateAST = TemplateAST() 0260 templateASTCache[templateID] = templateAST 0261 0262 do { 0263 let compiledAST = try self.templateAST(string: templateString, templateID: templateID) 0264 // Success: update the empty AST 0265 templateAST.updateFromTemplateAST(compiledAST) 0266 return templateAST 0267 } catch { 0268 // Failure: remove the empty AST 0269 templateASTCache.removeValueForKey(templateID) 0270 throw error 0271 } 0272 } 0273 0274 func templateAST
TemplateCompiler.swift:273 let parentTemplateAST = try repository.templateAST(named: parentPartialName, relativeToTemplateID:templateID)TemplateCompiler.swift:313 let partialTemplateAST = try repository.templateAST(named: partialName, relativeToTemplateID: templateID)TemplateRepository.swift:213 let templateAST = try self.templateAST(named: name, relativeToTemplateID: nil)(string string: String, templateID: TemplateID? = nil) throws -> TemplateAST { 0275 // A Compiler 0276 let compiler = TemplateCompiler( 0277 contentType: lockedConfiguration.contentType, 0278 repository: self, 0279 templateID: templateID) 0280 0281 // A Parser that feeds the compiler 0282 let parser = TemplateParser( 0283 tokenConsumer: compiler, 0284 tagDelimiterPair: lockedConfiguration.tagDelimiterPair) 0285 0286 // Parse... 0287 parser.parse(string, templateID: templateID) 0288 0289 // ...and extract the result from the Compiler 0290 return try compiler.templateAST() 0291 } 0292 0293 0294 private var _lockedConfiguration
Template.swift:41 let templateAST = try repository.templateAST(string: string)TemplateRepository.swift:189 let templateAST = try self.templateAST(string: string)TemplateRepository.swift:263 let compiledAST = try self.templateAST(string: templateString, templateID: templateID): Configuration? 0295 private var lockedConfiguration
TemplateRepository.swift:298 if _lockedConfiguration == nil {TemplateRepository.swift:299 _lockedConfiguration = configurationTemplateRepository.swift:301 return _lockedConfiguration!: Configuration { 0296 // Changing mutable values within the repository's configuration no 0297 // longer has any effect. 0298 if _lockedConfiguration == nil { 0299 _lockedConfiguration = configuration 0300 } 0301 return _lockedConfiguration! 0302 } 0303 0304 private var templateASTCache
TemplateRepository.swift:190 return Template(repository: self, templateAST: templateAST, baseContext: lockedConfiguration.baseContext)TemplateRepository.swift:214 return Template(repository: self, templateAST: templateAST, baseContext: lockedConfiguration.baseContext)TemplateRepository.swift:277 contentType: lockedConfiguration.contentType,TemplateRepository.swift:284 tagDelimiterPair: lockedConfiguration.tagDelimiterPair): [TemplateID: TemplateAST] 0305 0306 0307 // ------------------------------------------------------------------------- 0308 // MARK: DictionaryDataSource 0309 0310 private class DictionaryDataSource
TemplateRepository.swift:117 templateASTCache = [:]TemplateRepository.swift:230 templateASTCache.removeAll()TemplateRepository.swift:250 if let templateAST = templateASTCache[templateID] {TemplateRepository.swift:260 templateASTCache[templateID] = templateASTTemplateRepository.swift:269 templateASTCache.removeValueForKey(templateID): TemplateRepositoryDataSource { 0311 let templates
TemplateRepository.swift:136 self.init(dataSource: DictionaryDataSource(templates: templates)): [String: String] 0312 0313 init
TemplateRepository.swift:314 self.templates = templatesTemplateRepository.swift:322 if let string = templates[templateID] {(templates: [String: String]) { 0314 self.templates = templates 0315 } 0316 0317 func templateIDForName(name: String, relativeToTemplateID baseTemplateID: TemplateID?) -> TemplateID? { 0318 return name 0319 } 0320 0321 func templateStringForTemplateID(templateID: TemplateID) throws -> String { 0322 if let string = templates[templateID] { 0323 return string 0324 } else { 0325 throw MustacheError(kind: .TemplateNotFound, templateID: templateID) 0326 } 0327 } 0328 } 0329 } 0330
TemplateRepository.swift:136 self.init(dataSource: DictionaryDataSource(templates: templates))