Comparing version 0.4.0 to 0.5.0
61
goji.js
'use strict'; | ||
var Compiler = require('./lib/Compiler'); | ||
var compiler = new Compiler(); | ||
var compiler; | ||
/** | ||
* Goji is a template engine inspired by | ||
* <a href="http://thymeleaf.org/">Thymeleaf</a>. It uses regular HTML | ||
* as the template "language". | ||
* | ||
* @param {Complier~Options} options Defines the options Goji will use during | ||
* compilation and rendering | ||
* @returns {Gogi} | ||
* @constructor | ||
*/ | ||
function Gogi(options) { | ||
if (! (this instanceof Gogi)) { | ||
return new Gogi(options); | ||
} | ||
exports = module.exports = { | ||
compile: function(template, options) { | ||
return compiler.compile(template, options); | ||
} | ||
}; | ||
compiler = new Compiler(options); | ||
} | ||
/** | ||
* Takes a string template and parses it for includes. | ||
* | ||
* @param {string} template An HTML document or snippet | ||
* @param {Compiler~Options} options Defines the options Goji will use during | ||
* compilation and rendering. Note: this will overwrite whatever | ||
* options were specified in the initial constructor. | ||
* @returns {Compiler~RenderFunction} | ||
*/ | ||
Gogi.prototype.compile = function gojiCompile(template, options) { | ||
return compiler.compile(template, options); | ||
}; | ||
/** | ||
* Clears Goji's internal cache of templates. Does nothing if you disabled | ||
* caching. | ||
*/ | ||
Gogi.prototype.emptyCache = function gojiEmptyCache() { | ||
compiler.emptyCache(); | ||
}; | ||
/** | ||
* Looks for a template with the given name in the templates directory | ||
* (as specified by the {@link Compiler~Options}). Once found, the template | ||
* is read in and returned as a string. This string can then be used | ||
* with the {@link Goji#compile} method. | ||
* | ||
* @param {string} name The name of a template. E.g. if you have a template | ||
* file "foo.html", you would simply provide "foo" as the name | ||
* @returns {string|null} The template as a string or null if the template | ||
* could not be found | ||
*/ | ||
Gogi.prototype.loadTemplateNamed = function gogiLoadTemplate(name) { | ||
return compiler.loadTemplateNamed(name); | ||
}; | ||
exports = module.exports = Gogi; |
'use strict'; | ||
var NodeCache = require('node-cache'); | ||
var sha256 = require('js-sha256').sha256; | ||
var cheerio = require('cheerio'); | ||
@@ -10,2 +12,3 @@ var exprjs = new (require('exprjs'))(); | ||
* Returns the first directory where a node_modules directory exists. | ||
* @private | ||
*/ | ||
@@ -29,2 +32,6 @@ function basePath() { | ||
function extendObj(a, b) { | ||
if (!b) { | ||
return; | ||
} | ||
Object.keys(b).forEach(function keyIterator(val) { | ||
@@ -37,7 +44,2 @@ if (a.hasOwnProperty(val)) { | ||
function loadTemplateNamed(name) { | ||
// TODO: cache these? | ||
return fs.readFileSync(path.resolve(name)).toString(); | ||
} | ||
/** | ||
@@ -52,16 +54,53 @@ * Provides methods for parsing, compiling, and rendering templates. | ||
if (! (this instanceof Compiler)) { | ||
return new Compiler(); | ||
return new Compiler(options); | ||
} | ||
var self = Object.getPrototypeOf(this); | ||
if (options) { | ||
var self = Object.getPrototypeOf(this); | ||
extendObj(self.options, options); | ||
} | ||
if (self.options.cache) { | ||
self._cache = new NodeCache({ | ||
stdTTL: self.options.cacheTTL, | ||
checkperiod: 0 // Needs to be 0 to prevent node-cache from | ||
// causing Goji to hang indefinitely | ||
}); | ||
} | ||
} | ||
/** | ||
* <p>An object literal that has the following properties:</p> | ||
* <ul> | ||
* <li> | ||
* <code>cache</code>: Set to <code>true</code> (default) to enable | ||
* caching of compiled templates. Set to <code>false</code> to compile | ||
* templates every load. | ||
* </li> | ||
* <li> | ||
* <code>cacheTTL</code>: Time, in seconds, to keep templates in the cache. | ||
* Default value is 300 (5 minutes). | ||
* </li> | ||
* <li> | ||
* <code>templatesDir</code>: The location where templates are stored. | ||
* This should be the full path (use `path.resolve`). If it is not present, | ||
* then it will be set to an "html" directory that is in the same | ||
* directory as a node_modules directory. | ||
* </li> | ||
* <li> | ||
* <code>templatesExt</code>: The file extension used on template files. | ||
* This defaults to ".html". Note that it should include the leading dot. | ||
* </li> | ||
* </ul> | ||
* @typedef {object} Compiler~Options | ||
*/ | ||
Compiler.prototype = { | ||
options: { | ||
cache: true, | ||
cacheTTL: 300, | ||
templatesDir: path.resolve(basePath() + '/html'), | ||
templatesExt: '.html' | ||
} | ||
}, | ||
_cache: {} | ||
}; | ||
@@ -234,2 +273,13 @@ | ||
/** | ||
* If caching is enabled, this method can be used to clear the cache. | ||
* | ||
* @since 0.5.0 | ||
*/ | ||
Compiler.prototype.emptyCache = function emptyCache() { | ||
if (this.options.cache) { | ||
this._cache.flushAll(); | ||
} | ||
}; | ||
/** | ||
* Parses for <code>g-if</code> conditional blocks. If the expression | ||
@@ -329,5 +379,3 @@ * evalutates to true, then the block will be rendered. Otherwise, the block | ||
var child = loadTemplateNamed( | ||
self.options.templatesDir + '/' + parts[0] + self.options.templatesExt | ||
); | ||
var child = self.loadTemplateNamed(parts[0]); | ||
@@ -344,2 +392,35 @@ var parsedChild = self._parse(child); | ||
/** | ||
* Looks for a file in the templates direcory with the given name. If the | ||
* file exists, it will be loaded and returned as a string. | ||
* | ||
* @param {string} name The name of the template to load | ||
* @returns {string | null} The template or <code>null</code> (wasn't found) | ||
* @since 0.5.0 | ||
*/ | ||
Compiler.prototype.loadTemplateNamed = function loadTemplateNamed(name) { | ||
var result; | ||
var fullPath = path.resolve( | ||
this.options.templatesDir + '/' + name + this.options.templatesExt | ||
); | ||
if (!fs.existsSync(fullPath)) { | ||
return null; | ||
} | ||
if (this.options.cache) { | ||
result = this._cache.get(fullPath); | ||
if (result.hasOwnProperty(fullPath)) { | ||
result = result[fullPath]; | ||
} else { | ||
result = fs.readFileSync(fullPath).toString(); | ||
this._cache.set(fullPath, result); | ||
} | ||
} else { | ||
result = fs.readFileSync(fullPath).toString(); | ||
} | ||
return result; | ||
}; | ||
/** | ||
* Used to perform all parsing operations necessary to compile a template. | ||
@@ -414,19 +495,2 @@ * | ||
/** | ||
* <p>An object literal that has the following properties:</p> | ||
* <ul> | ||
* <li> | ||
* <code>templatesDir</code>: The location where templates are stored. | ||
* This should be the full path (use `path.resolve`). If it is not present, | ||
* then it will be set to an "html" directory that is in the same | ||
* directory as a node_modules directory. | ||
* </li> | ||
* <li> | ||
* <code>templatesExt</code>: The file extension used on template files. | ||
* This defaults to ".html". Note that it should include the leading dot. | ||
* </li> | ||
* </ul> | ||
* @typedef {object} Compiler~Options | ||
*/ | ||
/** | ||
* Parses a given <code>template</code> for <code>g-include</code> and | ||
@@ -449,4 +513,17 @@ * <code>g-replace</code> blocks. Said blocks are dealt with appropriately. | ||
var compiledTemplate = self._parse(template); | ||
var compiledTemplate; | ||
if (self.options.cache) { | ||
var hash = sha256(template.toString()); | ||
var result = self._cache.get(hash); | ||
if (result.hasOwnProperty(hash)) { | ||
compiledTemplate = result[hash]; | ||
} else { | ||
compiledTemplate = self._parse(template); | ||
self._cache.set(hash, compiledTemplate); | ||
} | ||
} else { | ||
compiledTemplate = self._parse(template); | ||
} | ||
return function(context, options) { | ||
@@ -453,0 +530,0 @@ return self._render(compiledTemplate, context); |
{ | ||
"name": "goji", | ||
"version": "0.4.0", | ||
"version": "0.5.0", | ||
"description": "An HTML templating engine inspired by Thymeleaf", | ||
@@ -29,3 +29,5 @@ "main": "goji.js", | ||
"cheerio": "^0.18.0", | ||
"exprjs": "0.0.3" | ||
"exprjs": "0.0.3", | ||
"js-sha256": "^0.1.1", | ||
"node-cache": "^1.0.3" | ||
}, | ||
@@ -32,0 +34,0 @@ "devDependencies": { |
# Goji | ||
*Goji* is a template engine for [Node.js](https://nodejs.org/) that conforms | ||
to the [Hapi](https://hapijs.com/) view engine requirements. | ||
to the [Hapi](https://hapijs.com/) view engine | ||
[requirements](http://hapijs.com/api/8.0.0#serverviewsoptions). | ||
@@ -13,2 +14,5 @@ *Goji* was inspired by [Thymeleaf](https://www.thymeleaf.org/). The name was | ||
For the API documentation see -- | ||
[http://jsumners.github.io/goji/Goji.html](http://jsumners.github.io/goji/Goji.html) | ||
# Install | ||
@@ -42,5 +46,5 @@ | ||
```javascript | ||
var goji = require('goji'); | ||
var fs = require('fs'); | ||
var template = fs.readFileSync('./template.html'); | ||
var Goji = require('goji'); | ||
var goji = new Goji(); | ||
var template = goji.loadTemplateNamed('template'); | ||
@@ -63,9 +67,37 @@ var renderer = goji.compile(template); | ||
*Goji's* compiler will load templates based on name when parsing | ||
`g-include` or `g-replace` attributes, and when using the | ||
`loadTemplateNamed(name)` method. | ||
By default, the compiler will look for templates with a file extension of | ||
".html" in an "html" directory that is in the same directory as your | ||
project's `node_modules` directory. If you need to change this behavior, you | ||
project's `node_modules` directory. Said templates will be cached for | ||
five minutes. If you need to change this behavior, you | ||
can use the | ||
[Compiler Options](http://jsumners.github.io/goji/Compiler.html#Options) | ||
object. | ||
object: | ||
* `cache`: Set to `true` (default) to enable caching of compiled templates. | ||
Set to `false` to compile templates every load. | ||
* `cacheTTL`: Time, in seconds, to keep templates in the cache. | ||
Default value is 300 (5 minutes). | ||
* `templatesDir`: The location where templates are stored. This should be | ||
the full path (use `path.resolve`). If it is not present, then it will | ||
be set to an "html" directory that is in the same directory as a | ||
`node_modules` directory. | ||
* `templatesExt`: The file extension used on template files. This defaults | ||
to ".html". Note that it should include the leading dot. | ||
```javascript | ||
{ | ||
cache: true, | ||
cacheTTL: 300, | ||
templatesDir: '/path/to/your/templates/directory', | ||
templatesExt: '.html' | ||
} | ||
``` | ||
The compiler options can be passed to the *Goji* constructor, or to the | ||
`compile` method. | ||
# Template Language | ||
@@ -72,0 +104,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
1172077
54
1122
371
4
+ Addedjs-sha256@^0.1.1
+ Addednode-cache@^1.0.3
+ Addedjs-sha256@0.1.4(transitive)
+ Addednode-cache@1.1.0(transitive)
+ Addedunderscore@1.13.7(transitive)