Skip to content

Commit

Permalink
Add support for using relative paths as the name of a partial - parti…
Browse files Browse the repository at this point in the history
…ally closes #2
  • Loading branch information
steveukx committed Oct 15, 2016
1 parent 5122896 commit 6b39a24
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 23 deletions.
27 changes: 26 additions & 1 deletion README.md
Expand Up @@ -29,6 +29,28 @@ In this case there is a file named `home.mustache` in the `views` directory that
<h1>{{SiteName}}</h1>
</body>
</html>

Configuration
=============

Optional functionality in the middleware can be set before passing it into express:

```
var hoganMiddleware = require('hogan-middleware');
hoganMiddleware({
filter: ['**.mustache'], // override the default file extension searched for
// default is just the mustache file extension
flatten: true, // make all partials available with just their file name
// rather than the slash delimited path. default is enabled
watch: true // set to false to remove the live updating watchers -
// can be useful for running in production where files
// will not be regularly changing.
});
app.engine('mustache', hoganMiddleware.__express);
```

Partial Templates
=================
Expand All @@ -43,7 +65,10 @@ to it for use as partials, so could in turn have `{{>b}}` to include a nested pa
To allow for a tidy source tree, templates can be in any number of sub-directories under the main views directory,
they are all made available for use as partials without any path identifier.

Note - multiple templates with the same name but in different directories will overwrite each other.
Note - multiple templates with the same name but in different directories will overwrite each other. Set the
`flatten` configuration option to false to always use the relative path as the name of the partials
(ie: `{{>app/header}}` instead of just `{{>header}}`). Whether the `flatten` option is enabled or not, the relative
path name will always be available.

Note - don't include the same template as a partial inside itself.

Expand Down
75 changes: 53 additions & 22 deletions src/template-engine.js
Expand Up @@ -20,7 +20,9 @@ function TemplateEngine(settings) {
}

TemplateEngine.__settings = {
filter: ['**.mustache']
filter: ['**.mustache'],
flatten: true,
watch: true
};

/**
Expand Down Expand Up @@ -58,19 +60,6 @@ TemplateEngine.__express = function(templatePath, templateData, next) {
}
};

/**
* Stores an individual template based on the supplied path, the name of the template is the file's basename without
* the extension.
*
* @param {String} templatePath
*/
TemplateEngine._storeTemplate = function(templatePath) {
var templateName = Path.basename(templatePath, Path.extname(templatePath));
TemplateEngine.__templates[templateName] = Hogan.compile(FS.readFileSync(templatePath, 'utf-8'));

debug('Stored template %s', templateName);
};

/**
* Gets all templates, when the template path hasn't yet been scanned it will be read synchronously to ensure there are
* always templates available, the template directory is then watched to allow templates to be changed while the server
Expand All @@ -81,7 +70,15 @@ TemplateEngine._storeTemplate = function(templatePath) {
TemplateEngine._getTemplates = function(templatesPath) {
if(!TemplateEngine.__templates) {
TemplateEngine._refreshTemplates(templatesPath);
FS.watch(templatesPath, {persistent: false}, TemplateEngine._refreshTemplates.bind(TemplateEngine, templatesPath));
FS.watch(
templatesPath,
{
persistent: false
},
function refreshTemplates (a,b,c) {
return TemplateEngine._refreshTemplates(templatesPath);
}
);
}
return TemplateEngine.__templates;
};
Expand All @@ -91,6 +88,11 @@ TemplateEngine._getTemplates = function(templatesPath) {
* @param {String} templatesPath
*/
TemplateEngine._refreshWatches = function(templatesPath) {
if (TemplateEngine.__settings.watch === false) {
debug('Refreshing watched directories has been disabled.');
return;
}

debug('Refreshing watched directories');

// Remove any existing watches
Expand All @@ -111,17 +113,46 @@ TemplateEngine._refreshWatches = function(templatesPath) {
* Reads all templates in the supplied path (synchronously). Can be called at any time, and is used as the handler for
* the file system watch of the templates directory.
*
* @param {String} templatesPath
* @param {String} templateRootPath
*/
TemplateEngine._refreshTemplates = function(templatesPath) {
debug('Refreshing templates for %s', templatesPath);
TemplateEngine._refreshTemplates = function(templateRootPath) {
debug('Refreshing templates for %s', templateRootPath);

TemplateEngine._refreshWatches(templateRootPath);

TemplateEngine._refreshWatches(templatesPath);
var settings = TemplateEngine.__settings;

findTemplates(templateRootPath, settings.filter)
.map(readTemplate)
.reduce(function (templates, template) {

if (settings.flatten) {
templates[template.name] = template.content;
}

templates[template.relative] = template.content;

return templates;

}, TemplateEngine.__templates = {});

TemplateEngine.__templates = {};
ReadDir.readSync(templatesPath, TemplateEngine.__settings.filter, ReadDir.ABSOLUTE_PATHS)
.forEach(TemplateEngine._storeTemplate, TemplateEngine);
debug('Refreshing templates complete');
};

function findTemplates (rootPath, filter) {
return ReadDir.readSync(rootPath, filter, ReadDir.ABSOLUTE_PATHS);
}

function readTemplate (absolutePath) {
return {
content: Hogan.compile(FS.readFileSync(absolutePath, 'utf-8')),
name: stripFileExtension(absolutePath)
};
}

function stripFileExtension (input) {
return input.replace(/(.+)\.[a-z]+/, '$1');
}


module.exports = TemplateEngine;

0 comments on commit 6b39a24

Please sign in to comment.