Reputation: 1242
I am writing a small CMS application using NodeJS and Jade. For various reasons I want to store my Jade template files in a database (e.g. MongoDB), not on disk.
This works fine for a simple, self-contained Jade template: I can simply fetch the Jade string from the database, and jade.compile
it.
However, if the template extends
another template, I seem to be forced into storing my templates on disk. From jade.js
:
parseExtends: function(){
var fs = _dereq_('fs');
var path = this.resolvePath(this.expect('extends').val.trim(), 'extends');
if ('.jade' != path.substr(-5)) path += '.jade';
var str = fs.readFileSync(path, 'utf8');
...
So the extends
keyword explicitly assumes the extended template is stored on disk.
What is the easiest way to let my Jade templates extend other templates that are stored in a database - or any other repository?
Upvotes: 1
Views: 317
Reputation: 1242
It seems that this can be accomplished by overriding parseExtends
and parseImports
.
However, you will need some kind of synchronous storage, as Jade does all compilation synchronously. That is, no callbacks.
I eventually "solved" this by prefetching all templates and storing them in a templateMap
object:
{
"path": "/templates/frontpage.jade",
"content": "<html><body>Here's some Jade</body></html>"
},
...
Then overriding parseExtends
and parseImports
so that they look for the template path in templateMap
, not on disk:
jade.Parser.prototype.parseExtends = function () {
var path = this.expect('extends').val.trim();
path = Path.normalize(path).replace("\\", "/"); // Necessary on Windows
var self = this;
var str = templatesMap[path];
if (!str) {
return callback(new RendererError("Could not find template " + path));
}
var parser = new this.constructor(str, path, this.options);
parser.blocks = this.blocks;
parser.contexts = this.contexts;
self.extending = parser;
return new Nodes.Literal('');
}
Upvotes: 3