Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accept relative paths in import/include #349

Merged
merged 9 commits into from
Feb 20, 2015
14 changes: 8 additions & 6 deletions src/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ function quotedArray(arr) {
}

var Compiler = Object.extend({
init: function() {
init: function(name) {
this.name = name;
this.codebuf = [];
this.lastId = 0;
this.buffer = null;
Expand All @@ -60,6 +61,7 @@ var Compiler = Object.extend({
},

emit: function(code) {
//console.log("emit", code);
this.codebuf.push(code);
},

Expand Down Expand Up @@ -891,7 +893,7 @@ var Compiler = Object.extend({

this.emit('env.getTemplate(');
this._compileExpression(node.template, frame);
this.emitLine(', ' + this.makeCallback(id));
this.emitLine(', false, "'+this.name+'", ' + this.makeCallback(id));
this.addScopeLevel();

this.emitLine(id + '.getExported(' +
Expand All @@ -914,7 +916,7 @@ var Compiler = Object.extend({

this.emit('env.getTemplate(');
this._compileExpression(node.template, frame);
this.emitLine(', ' + this.makeCallback(importedId));
this.emitLine(', false, "'+this.name+'", ' + this.makeCallback(importedId));
this.addScopeLevel();

this.emitLine(importedId + '.getExported(' +
Expand Down Expand Up @@ -989,7 +991,7 @@ var Compiler = Object.extend({

this.emit('env.getTemplate(');
this._compileExpression(node.template, frame);
this.emitLine(', true, ' + this.makeCallback('parentTemplate'));
this.emitLine(', true, "'+this.name+'", ' + this.makeCallback('parentTemplate'));

this.emitLine('for(var ' + k + ' in parentTemplate.blocks) {');
this.emitLine('context.addBlock(' + k +
Expand All @@ -1006,7 +1008,7 @@ var Compiler = Object.extend({

this.emit('env.getTemplate(');
this._compileExpression(node.template, frame);
this.emitLine(', ' + this.makeCallback(id));
this.emitLine(', false, "'+this.name+'", '+ this.makeCallback(id));
this.addScopeLevel();

this.emitLine(id + '.render(' +
Expand Down Expand Up @@ -1104,7 +1106,7 @@ var Compiler = Object.extend({

module.exports = {
compile: function(src, asyncFilters, extensions, name, opts) {
var c = new Compiler();
var c = new Compiler(name);

// Run the extension preprocessors against the source.
if(extensions && extensions.length) {
Expand Down
23 changes: 20 additions & 3 deletions src/environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,18 @@ var Environment = Obj.extend({
return this.filters[name];
},

getTemplate: function(name, eagerCompile, cb) {
getTemplate: function(name, eagerCompile, parentName, cb) {
if(name && name.raw) {
// this fixes autoescape for templates referenced in symbols
name = name.raw;
}

if(lib.isFunction(parentName)) {
cb = parentName;
parentName = null;
eagerCompile = eagerCompile || false;
}

if(lib.isFunction(eagerCompile)) {
cb = eagerCompile;
eagerCompile = false;
Expand Down Expand Up @@ -140,6 +146,11 @@ var Environment = Obj.extend({
}
}

// Resolve name relative to parentName
if (parentName && (name.indexOf("./") == 0 || name.indexOf("../") == 0)) {
name = loader.resolve(parentName, name);
}

if(loader.async) {
loader.getSource(name, function(err, src) {
if(err) { throw err; }
Expand Down Expand Up @@ -229,8 +240,14 @@ var Environment = Obj.extend({
return syncResult;
},

renderString: function(src, ctx, cb) {
var tmpl = new Template(src, this);
renderString: function(src, ctx, opts, cb) {
if(lib.isFunction(opts)) {
cb = opts;
opts = {};
}
opts = opts || {};

var tmpl = new Template(src, this, opts.path);
return tmpl.render(ctx, cb);
}
});
Expand Down
5 changes: 5 additions & 0 deletions src/loader.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
var path = require('path');
var Obj = require('./object');
var lib = require('./lib');

Expand All @@ -16,6 +17,10 @@ var Loader = Obj.extend({
listener.apply(null, args);
});
}
},

resolve: function(from, to) {
return path.resolve(path.dirname(from), to);
}
});

Expand Down
6 changes: 3 additions & 3 deletions src/node-loaders.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ var FileSystemLoader = Loader.extend({
var paths = this.searchPaths;

for(var i=0; i<paths.length; i++) {
var p = path.join(paths[i], name);
var basePath = path.resolve(paths[i]);
var p = path.resolve(paths[i], name);

// Only allow the current directory and anything
// underneath it to be searched
if((paths[i] == '.' || p.indexOf(paths[i]) === 0) &&
existsSync(p)) {
if(p.indexOf(basePath) === 0 && existsSync(p)) {
fullpath = p;
break;
}
Expand Down
18 changes: 18 additions & 0 deletions tests/api.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
(function() {
var expect, Environment, Loader, templatesPath;
var path = require('path');

if(typeof require != 'undefined') {
expect = require('expect.js');
Expand All @@ -22,5 +23,22 @@
var child = env.getTemplate('base-inherit.html');
expect(child.render()).to.be('Foo*Bar*BazFizzle');
});

it('should handle correctly relative paths', function() {
var env = new Environment(new Loader(templatesPath));

var child1 = env.getTemplate('relative/test1.html');
var child2 = env.getTemplate('relative/test2.html');

expect(child1.render()).to.be('FooTest1BazFizzle');
expect(child2.render()).to.be('FooTest2BazFizzle');
});

it('should handle correctly relative paths in renderString', function() {
var env = new Environment(new Loader(templatesPath));
expect(env.renderString('{% extends "./relative/test1.html" %}{% block block1 %}Test3{% endblock %}', {}, {
path: path.resolve(templatesPath, "string.html")
})).to.be('FooTest3BazFizzle');
});
});
})();
3 changes: 3 additions & 0 deletions tests/templates/relative/test1.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{% extends "../base.html" %}

{% block block1 %}Test1{% endblock %}
3 changes: 3 additions & 0 deletions tests/templates/relative/test2.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{% extends "./test1.html" %}

{% block block1 %}Test2{% endblock %}