From d740ba7cec7b30ce7519e107467cfa0b87ffcdaa Mon Sep 17 00:00:00 2001 From: "Alexandros \"Chorvus\" Tzortzidis" Date: Tue, 16 Oct 2012 08:58:46 +0300 Subject: [PATCH] Enabled 'include' and 'extends' to use paths relative to basedir --- lib/parser.js | 58 ++++++++++++--------- test/cases/auxiliary/extends-from-root.jade | 4 ++ test/cases/auxiliary/include-from-root.jade | 1 + test/cases/include-extends-from-root.html | 8 +++ test/cases/include-extends-from-root.jade | 1 + test/run.js | 2 +- 6 files changed, 47 insertions(+), 27 deletions(-) create mode 100644 test/cases/auxiliary/extends-from-root.jade create mode 100644 test/cases/auxiliary/include-from-root.jade create mode 100644 test/cases/include-extends-from-root.html create mode 100644 test/cases/include-extends-from-root.jade diff --git a/lib/parser.js b/lib/parser.js index 2396d6ced..cada990b8 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -378,24 +378,45 @@ Parser.prototype = { return node; }, + /** + * Resolves a path relative to the template for use in + * includes and extends + * + * @param {String} path + * @param {String} purpose Used in error messages. + * @return {String} + * @api private + */ + + resolvePath: function (path, purpose) { + var p = require('path'); + var dirname = p.dirname; + var basename = p.basename; + var join = p.join; + + if (path[0] !== '/' && !this.filename) + throw new Error('the "filename" option is required to use "' + purpose + '" with "relative" paths'); + + if (path[0] === '/' && !this.options.basedir) + throw new Error('the "basedir" option is required to use "' + purpose + '" with "absolute" paths'); + + path = join(path[0] === '/' ? this.options.basedir : dirname(this.filename), path); + + if (basename(path).indexOf('.') === -1) path += '.jade'; + + return path; + }, + /** * 'extends' name */ parseExtends: function(){ - var path = require('path'); var fs = require('fs'); - var dirname = path.dirname; - var basename = path.basename; - var join = path.join; - if (!this.filename) - throw new Error('the "filename" option is required to extend templates'); + var path = this.resolvePath(this.expect('extends').val.trim(), 'extends'); + if ('.jade' != path.substr(-5)) path += '.jade'; - var path = this.expect('extends').val.trim(); - var dir = dirname(this.filename); - - var path = join(dir, path + '.jade'); var str = fs.readFileSync(path, 'utf8'); var parser = new Parser(str, path, this.options); @@ -444,33 +465,18 @@ Parser.prototype = { */ parseInclude: function(){ - var path = require('path'); var fs = require('fs'); - var dirname = path.dirname; - var basename = path.basename; - var join = path.join; - - var path = this.expect('include').val.trim(); - var dir = dirname(this.filename); - if (!this.filename) - throw new Error('the "filename" option is required to use includes'); - - // no extension - if (!~basename(path).indexOf('.')) { - path += '.jade'; - } + var path = this.resolvePath(this.expect('include').val.trim(), 'include'); // non-jade if ('.jade' != path.substr(-5)) { - var path = join(dir, path); var str = fs.readFileSync(path, 'utf8').replace(/\r/g, ''); var ext = extname(path).slice(1); if (filters.exists(ext)) str = filters(ext, str, { filename: path }); return new nodes.Literal(str); } - var path = join(dir, path); var str = fs.readFileSync(path, 'utf8'); var parser = new Parser(str, path, this.options); parser.blocks = utils.merge({}, this.blocks); diff --git a/test/cases/auxiliary/extends-from-root.jade b/test/cases/auxiliary/extends-from-root.jade new file mode 100644 index 000000000..0271858b5 --- /dev/null +++ b/test/cases/auxiliary/extends-from-root.jade @@ -0,0 +1,4 @@ +extends /auxiliary/layout + +block content + include /auxiliary/include-from-root \ No newline at end of file diff --git a/test/cases/auxiliary/include-from-root.jade b/test/cases/auxiliary/include-from-root.jade new file mode 100644 index 000000000..93c364b50 --- /dev/null +++ b/test/cases/auxiliary/include-from-root.jade @@ -0,0 +1 @@ +h1 hello \ No newline at end of file diff --git a/test/cases/include-extends-from-root.html b/test/cases/include-extends-from-root.html new file mode 100644 index 000000000..3916f5d9b --- /dev/null +++ b/test/cases/include-extends-from-root.html @@ -0,0 +1,8 @@ + + + My Application + + +

hello

+ + \ No newline at end of file diff --git a/test/cases/include-extends-from-root.jade b/test/cases/include-extends-from-root.jade new file mode 100644 index 000000000..f682dc609 --- /dev/null +++ b/test/cases/include-extends-from-root.jade @@ -0,0 +1 @@ +include /auxiliary/extends-from-root \ No newline at end of file diff --git a/test/run.js b/test/run.js index 2ea08b6b5..15aad21d7 100644 --- a/test/run.js +++ b/test/run.js @@ -20,7 +20,7 @@ cases.forEach(function(test){ var path = 'test/cases/' + test + '.jade'; var str = fs.readFileSync(path, 'utf8'); var html = fs.readFileSync('test/cases/' + test + '.html', 'utf8').trim().replace(/\r/g, ''); - var fn = jade.compile(str, { filename: path, pretty: true }); + var fn = jade.compile(str, { filename: path, pretty: true, basedir: 'test/cases' }); var actual = fn({ title: 'Jade' }); actual.trim().should.equal(html); })