These changes allows the internal template cache to be customised, either by disabling it complete or providing a custom implementation of how templates are cached.tags/v4.0.0
| @@ -486,14 +486,27 @@ | |||||
| * avoid the need to parse the same template twice. | * avoid the need to parse the same template twice. | ||||
| */ | */ | ||||
| function Writer () { | function Writer () { | ||||
| this.cache = {}; | |||||
| this.templateCache = { | |||||
| _cache: {}, | |||||
| set: function set (key, value) { | |||||
| this._cache[key] = value; | |||||
| }, | |||||
| get: function get (key) { | |||||
| return this._cache[key]; | |||||
| }, | |||||
| clear: function clear () { | |||||
| this._cache = {}; | |||||
| } | |||||
| }; | |||||
| } | } | ||||
| /** | /** | ||||
| * Clears all cached templates in this writer. | * Clears all cached templates in this writer. | ||||
| */ | */ | ||||
| Writer.prototype.clearCache = function clearCache () { | Writer.prototype.clearCache = function clearCache () { | ||||
| this.cache = {}; | |||||
| if (typeof this.templateCache !== 'undefined') { | |||||
| this.templateCache.clear(); | |||||
| } | |||||
| }; | }; | ||||
| /** | /** | ||||
| @@ -502,13 +515,15 @@ | |||||
| * that is generated from the parse. | * that is generated from the parse. | ||||
| */ | */ | ||||
| Writer.prototype.parse = function parse (template, tags) { | Writer.prototype.parse = function parse (template, tags) { | ||||
| var cache = this.cache; | |||||
| var cache = this.templateCache; | |||||
| var cacheKey = template + ':' + (tags || mustache.tags).join(':'); | var cacheKey = template + ':' + (tags || mustache.tags).join(':'); | ||||
| var tokens = cache[cacheKey]; | |||||
| if (tokens == null) | |||||
| tokens = cache[cacheKey] = parseTemplate(template, tags); | |||||
| var isCacheEnabled = typeof cache !== 'undefined'; | |||||
| var tokens = isCacheEnabled ? cache.get(cacheKey) : undefined; | |||||
| if (tokens == undefined) { | |||||
| tokens = parseTemplate(template, tags); | |||||
| isCacheEnabled && cache.set(cacheKey, tokens); | |||||
| } | |||||
| return tokens; | return tokens; | ||||
| }; | }; | ||||
| @@ -660,7 +675,21 @@ | |||||
| to_html: undefined, | to_html: undefined, | ||||
| Scanner: undefined, | Scanner: undefined, | ||||
| Context: undefined, | Context: undefined, | ||||
| Writer: undefined | |||||
| Writer: undefined, | |||||
| /** | |||||
| * Allows a user to override the default caching strategy, by providing an | |||||
| * object with set, get and clear methods. This can also be used to disable | |||||
| * the cache by setting it to the literal `undefined`. | |||||
| */ | |||||
| set templateCache (cache) { | |||||
| defaultWriter.templateCache = cache; | |||||
| }, | |||||
| /** | |||||
| * Gets the default or overridden caching object from the default writer. | |||||
| */ | |||||
| get templateCache () { | |||||
| return defaultWriter.templateCache; | |||||
| } | |||||
| }; | }; | ||||
| // All high-level mustache.* functions use this writer. | // All high-level mustache.* functions use this writer. | ||||
| @@ -479,14 +479,27 @@ Context.prototype.lookup = function lookup (name) { | |||||
| * avoid the need to parse the same template twice. | * avoid the need to parse the same template twice. | ||||
| */ | */ | ||||
| function Writer () { | function Writer () { | ||||
| this.cache = {}; | |||||
| this.templateCache = { | |||||
| _cache: {}, | |||||
| set: function set (key, value) { | |||||
| this._cache[key] = value; | |||||
| }, | |||||
| get: function get (key) { | |||||
| return this._cache[key]; | |||||
| }, | |||||
| clear: function clear () { | |||||
| this._cache = {}; | |||||
| } | |||||
| }; | |||||
| } | } | ||||
| /** | /** | ||||
| * Clears all cached templates in this writer. | * Clears all cached templates in this writer. | ||||
| */ | */ | ||||
| Writer.prototype.clearCache = function clearCache () { | Writer.prototype.clearCache = function clearCache () { | ||||
| this.cache = {}; | |||||
| if (typeof this.templateCache !== 'undefined') { | |||||
| this.templateCache.clear(); | |||||
| } | |||||
| }; | }; | ||||
| /** | /** | ||||
| @@ -495,13 +508,15 @@ Writer.prototype.clearCache = function clearCache () { | |||||
| * that is generated from the parse. | * that is generated from the parse. | ||||
| */ | */ | ||||
| Writer.prototype.parse = function parse (template, tags) { | Writer.prototype.parse = function parse (template, tags) { | ||||
| var cache = this.cache; | |||||
| var cache = this.templateCache; | |||||
| var cacheKey = template + ':' + (tags || mustache.tags).join(':'); | var cacheKey = template + ':' + (tags || mustache.tags).join(':'); | ||||
| var tokens = cache[cacheKey]; | |||||
| if (tokens == null) | |||||
| tokens = cache[cacheKey] = parseTemplate(template, tags); | |||||
| var isCacheEnabled = typeof cache !== 'undefined'; | |||||
| var tokens = isCacheEnabled ? cache.get(cacheKey) : undefined; | |||||
| if (tokens == undefined) { | |||||
| tokens = parseTemplate(template, tags); | |||||
| isCacheEnabled && cache.set(cacheKey, tokens); | |||||
| } | |||||
| return tokens; | return tokens; | ||||
| }; | }; | ||||
| @@ -653,7 +668,21 @@ var mustache = { | |||||
| to_html: undefined, | to_html: undefined, | ||||
| Scanner: undefined, | Scanner: undefined, | ||||
| Context: undefined, | Context: undefined, | ||||
| Writer: undefined | |||||
| Writer: undefined, | |||||
| /** | |||||
| * Allows a user to override the default caching strategy, by providing an | |||||
| * object with set, get and clear methods. This can also be used to disable | |||||
| * the cache by setting it to the literal `undefined`. | |||||
| */ | |||||
| set templateCache (cache) { | |||||
| defaultWriter.templateCache = cache; | |||||
| }, | |||||
| /** | |||||
| * Gets the default or overridden caching object from the default writer. | |||||
| */ | |||||
| get templateCache () { | |||||
| return defaultWriter.templateCache; | |||||
| } | |||||
| }; | }; | ||||
| // All high-level mustache.* functions use this writer. | // All high-level mustache.* functions use this writer. | ||||
| @@ -56,8 +56,14 @@ var expectations = { | |||||
| : [ [ '#', 'foo', 0, 8, [ [ '#', 'a', 11, 17, [ [ 'text', ' ', 18, 22 ], [ 'name', 'b', 22, 27 ], [ 'text', '\n', 27, 28 ] ], 30 ] ], 37 ] ] | : [ [ '#', 'foo', 0, 8, [ [ '#', 'a', 11, 17, [ [ 'text', ' ', 18, 22 ], [ 'name', 'b', 22, 27 ], [ 'text', '\n', 27, 28 ] ], 30 ] ], 37 ] ] | ||||
| }; | }; | ||||
| var originalTemplateCache; | |||||
| before(function () { | |||||
| originalTemplateCache = Mustache.templateCache; | |||||
| }); | |||||
| beforeEach(function (){ | beforeEach(function (){ | ||||
| Mustache.clearCache(); | Mustache.clearCache(); | ||||
| Mustache.templateCache = originalTemplateCache; | |||||
| }); | }); | ||||
| describe('Mustache.parse', function () { | describe('Mustache.parse', function () { | ||||
| @@ -153,4 +159,47 @@ describe('Mustache.parse', function () { | |||||
| }); | }); | ||||
| }); | }); | ||||
| describe('when parsing a template with caching disabled and the same tags second time, do not return the cached tokens', function () { | |||||
| it('returns different tokens for the latter parse', function () { | |||||
| Mustache.templateCache = undefined; | |||||
| var template = '{{foo}}[bar]'; | |||||
| var parsedResult1 = Mustache.parse(template); | |||||
| var parsedResult2 = Mustache.parse(template); | |||||
| assert.deepEqual(parsedResult1, parsedResult2); | |||||
| assert.ok(parsedResult1 !== parsedResult2); | |||||
| }); | |||||
| }); | |||||
| describe('when parsing a template with custom caching and the same tags second time, do not return the cached tokens', function () { | |||||
| it('returns the same tokens for the latter parse', function () { | |||||
| Mustache.templateCache = { | |||||
| _cache: [], | |||||
| set: function set (key, value) { | |||||
| this._cache.push([key, value]); | |||||
| }, | |||||
| get: function get (key) { | |||||
| var cacheLength = this._cache.length; | |||||
| for (var i = 0; i < cacheLength; i++) { | |||||
| var entry = this._cache[i]; | |||||
| if (entry[0] === key) { | |||||
| return entry[1]; | |||||
| } | |||||
| } | |||||
| return undefined; | |||||
| }, | |||||
| clear: function clear () { | |||||
| this._cache = []; | |||||
| } | |||||
| }; | |||||
| var template = '{{foo}}[bar]'; | |||||
| var parsedResult1 = Mustache.parse(template); | |||||
| var parsedResult2 = Mustache.parse(template); | |||||
| assert.deepEqual(parsedResult1, parsedResult2); | |||||
| assert.ok(parsedResult1 === parsedResult2); | |||||
| }); | |||||
| }); | |||||
| }); | }); | ||||