diff options
-rw-r--r-- | lib/book.js | 2 | ||||
-rw-r--r-- | lib/fs/index.js | 2 | ||||
-rw-r--r-- | lib/template/index.js | 24 | ||||
-rw-r--r-- | lib/template/loader.js | 8 | ||||
-rw-r--r-- | lib/utils/error.js | 12 | ||||
-rw-r--r-- | lib/utils/git.js | 5 | ||||
-rw-r--r-- | package.json | 5 | ||||
-rw-r--r-- | test/mock.js | 1 | ||||
-rw-r--r-- | test/template.js | 49 |
9 files changed, 82 insertions, 26 deletions
diff --git a/lib/book.js b/lib/book.js index a2a11a7..914b48a 100644 --- a/lib/book.js +++ b/lib/book.js @@ -291,7 +291,7 @@ Book.prototype.isMultilingual = function() { Book.prototype.isInBook = function(filename) { return pathUtil.isInRoot( this.root, - this.resolve(filename) + filename ); }; diff --git a/lib/fs/index.js b/lib/fs/index.js index 4fd63e9..3e0d711 100644 --- a/lib/fs/index.js +++ b/lib/fs/index.js @@ -51,7 +51,7 @@ FS.prototype.readdir = function(folder) { // Allocate a new temporary directory FS.prototype.tmpdir = function() { - return path.resolve(os.tmpdir(), _.uniqueId('gitbook_tmp_')); + return path.resolve(os.tmpdir(), 'gitbook_tmp_'+Date.now()); }; // List files in a directory diff --git a/lib/template/index.js b/lib/template/index.js index a3021e6..b59dd04 100644 --- a/lib/template/index.js +++ b/lib/template/index.js @@ -2,6 +2,7 @@ var _ = require('lodash'); var path = require('path'); var nunjucks = require('nunjucks'); var parsers = require('gitbook-parsers'); +var escapeStringRegexp = require('escape-string-regexp'); var Promise = require('../utils/promise'); var error = require('../utils/error'); @@ -333,7 +334,7 @@ TemplateEngine.prototype.renderString = function(content, context, options) { } // Replace shortcuts - //content = this.applyShortcuts(options.type, content); + content = this.applyShortcuts(options.type, content); return Promise.nfcall(this.env.renderString.bind(this.env), content, context, options) .fail(function(err) { @@ -343,5 +344,26 @@ TemplateEngine.prototype.renderString = function(content, context, options) { }); }; +// Apply a shortcut to a string +TemplateEngine.prototype.applyShortcut = function(content, shortcut) { + var regex = new RegExp( + escapeStringRegexp(shortcut.start) + '([\\s\\S]*?[^\\$])' + escapeStringRegexp(shortcut.end), + 'g' + ); + return content.replace(regex, function(all, match) { + return '{% '+shortcut.tag.start+' %}'+ match + '{% '+shortcut.tag.end+' %}'; + }); +}; + +// Apply all shortcuts to a template +TemplateEngine.prototype.applyShortcuts = function(type, content) { + return _.chain(this.shortcuts) + .filter(function(shortcut) { + return _.contains(shortcut.parsers, type); + }) + .reduce(this.applyShortcut, content) + .value(); +}; + module.exports = TemplateEngine; diff --git a/lib/template/loader.js b/lib/template/loader.js index 23ffb77..5d30fb2 100644 --- a/lib/template/loader.js +++ b/lib/template/loader.js @@ -16,16 +16,16 @@ var Loader = nunjucks.Loader.extend({ this.git = new Git(this.fs.tmpdir()); }, - getSource: function(soureURL, callback) { + getSource: function(sourceURL, callback) { var that = this; - this.git.resolveFile(soureURL) + this.git.resolve(sourceURL) .then(function(filepath) { // Is local file if (!filepath) { - filepath = that.book.resolve(soureURL); + filepath = that.book.resolve(sourceURL); } else { - that.book.log.debug.ln('resolve from git', soureURL, 'to', filepath); + that.book.log.debug.ln('resolve from git', sourceURL, 'to', filepath); } // Read file from absolute path diff --git a/lib/utils/error.js b/lib/utils/error.js index 4ccf83d..5ee6a0e 100644 --- a/lib/utils/error.js +++ b/lib/utils/error.js @@ -13,30 +13,30 @@ function enforce(err) { // Random error wrappers during parsing/generation var ParsingError = WrappedError({ message: 'Parsing Error: {origMessage}', - type: 'server.parsing-failed' + type: 'parse' }); var GenerationError = WrappedError({ message: 'Generation Error: {origMessage}', - type: 'server.parsing-failed' + type: 'generate' }); // Error when output generator does not exists var GeneratorNotFoundError = TypedError({ - type: 'server.404', + type: 'generator.not-found', message: 'Generator "{generator}" does not exists', generator: null }); // A file does not exists var FileNotFoundError = TypedError({ - type: 'server.404', + type: 'file.not-found', message: 'No "{filename}" file (or is ignored)', filename: null }); // A file is outside the scope var FileOutOfScopeError = TypedError({ - type: 'server.404', + type: 'file.out-of-scope', message: '"{filename}" not in "{root}"', filename: null, root: null, @@ -46,7 +46,7 @@ var FileOutOfScopeError = TypedError({ // Error for nunjucks templates var TemplateError = WrappedError({ message: 'Error compiling template "{filename}": {origMessage}', - type: 'client.template-failed', + type: 'template', filename: null }); diff --git a/lib/utils/git.js b/lib/utils/git.js index 9fca73f..baf0fab 100644 --- a/lib/utils/git.js +++ b/lib/utils/git.js @@ -51,6 +51,11 @@ Git.prototype.clone = function(host, ref) { // Get file from a git repo Git.prototype.resolve = function(giturl) { + // Path to a file in a git repo? + if (!Git.isUrl(giturl)) { + if (this.resolveRoot(giturl)) return Promise(giturl); + return Promise(null); + } if (_.isString(giturl)) giturl = Git.parseUrl(giturl); if (!giturl) return Promise(null); diff --git a/package.json b/package.json index fa333fb..7dce193 100644 --- a/package.json +++ b/package.json @@ -47,9 +47,8 @@ }, "devDependencies": { "eslint": "1.5.0", - "mocha": "2.3.2", - "should": "7.1.0", - "should-promised": "0.3.1", + "mocha": "2.4.5", + "should": "8.2.2", "gulp": "^3.8.11", "gulp-rename": "^1.2.2", "gulp-uglify": "1.1.0", diff --git a/test/mock.js b/test/mock.js index 6d53ed8..1f7e7d5 100644 --- a/test/mock.js +++ b/test/mock.js @@ -5,7 +5,6 @@ var tmp = require('tmp'); var path = require('path'); var should = require('should'); -require('should-promised'); var Book = require('../').Book; var Output = require('../lib/output'); diff --git a/test/template.js b/test/template.js index b55693f..f338a84 100644 --- a/test/template.js +++ b/test/template.js @@ -1,32 +1,63 @@ var mock = require('./mock'); -var TemplateEngine = require('../lib/template'); - var pkg = require('../package.json'); describe('Template', function() { - var book, tpl; + var book; before(function() { - return mock.setupDefaultBook() + return mock.setupDefaultBook({ + 'test.md': 'World' + }) .then(function(_book) { book = _book; return book.parse(); - }) - .then(function() { - tpl = new TemplateEngine(book); }); }); describe('.renderString', function() { it('should render a simple string', function() { - return tpl.renderString('Hello World') + return book.template.renderString('Hello World') .should.be.fulfilledWith('Hello World'); }); it('should render with variable', function() { - return tpl.renderString('Version is {{ gitbook.version }}') + return book.template.renderString('Version is {{ gitbook.version }}') .should.be.fulfilledWith('Version is '+pkg.version); }); }); + describe('Conrefs Loader', function() { + it('should include a local file', function() { + return book.template.renderString('Hello {% include "./test.md" %}') + .should.be.fulfilledWith('Hello World'); + }); + + it('should include a git url', function() { + return book.template.renderString('Hello {% include "./test.md" %}') + .should.be.fulfilledWith('Hello World'); + }); + + it('should reject file out of scope', function() { + return book.template.renderString('Hello {% include "../test.md" %}') + .should.be.rejected(); + }); + + describe('Git Urls', function() { + it('should include a file from a git repo', function() { + return book.template.renderString('{% include "git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test.md" %}') + .should.be.fulfilledWith('Hello from git'); + }); + + it('should handle deep inclusion (1)', function() { + return book.template.renderString('{% include "git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test2.md" %}') + .should.be.fulfilledWith('First Hello. Hello from git'); + }); + + it('should handle deep inclusion (2)', function() { + return book.template.renderString('{% include "git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test3.md" %}') + .should.be.fulfilledWith('First Hello. Hello from git'); + }); + }); + }); + }); |