summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamy Pesse <samypesse@gmail.com>2016-02-11 17:30:58 +0100
committerSamy Pesse <samypesse@gmail.com>2016-02-11 17:30:58 +0100
commit98a13cf487e3b2823cfde38ab1d1b8f97f614517 (patch)
tree81d07c7095822867ba180a79e9a5b1343d81de0e
parent7f9aa214a412f3d173ac52042bd7250aacda6143 (diff)
downloadgitbook-98a13cf487e3b2823cfde38ab1d1b8f97f614517.zip
gitbook-98a13cf487e3b2823cfde38ab1d1b8f97f614517.tar.gz
gitbook-98a13cf487e3b2823cfde38ab1d1b8f97f614517.tar.bz2
Add conrefs loader for nunjucks
-rw-r--r--lib/book.js8
-rw-r--r--lib/fs/index.js7
-rw-r--r--lib/template/index.js13
-rw-r--r--lib/template/loader.js75
-rw-r--r--test/all.js2
5 files changed, 103 insertions, 2 deletions
diff --git a/lib/book.js b/lib/book.js
index f615833..a2a11a7 100644
--- a/lib/book.js
+++ b/lib/book.js
@@ -287,6 +287,14 @@ Book.prototype.isMultilingual = function() {
return this.langs.count() > 0;
};
+// Return true if file is in the scope of this book
+Book.prototype.isInBook = function(filename) {
+ return pathUtil.isInRoot(
+ this.root,
+ this.resolve(filename)
+ );
+};
+
// Return true if file is in the scope of a child book
Book.prototype.isInLanguageBook = function(filename) {
return _.some(this.langs.list(), function(lang) {
diff --git a/lib/fs/index.js b/lib/fs/index.js
index bcd9345..4fd63e9 100644
--- a/lib/fs/index.js
+++ b/lib/fs/index.js
@@ -2,6 +2,7 @@ var _ = require('lodash');
var path = require('path');
var Buffer = require('buffer').Buffer;
var destroy = require('destroy');
+var os = require('os');
var Promise = require('../utils/promise');
@@ -45,10 +46,14 @@ FS.prototype.readdir = function(folder) {
// To implement for each fs
};
-
// These methods don't require to be redefined, by default it uses .exists, .read, .write, .list
// For optmization, it can be redefined:
+// Allocate a new temporary directory
+FS.prototype.tmpdir = function() {
+ return path.resolve(os.tmpdir(), _.uniqueId('gitbook_tmp_'));
+};
+
// List files in a directory
FS.prototype.listFiles = function(folder) {
return this.readdir(folder)
diff --git a/lib/template/index.js b/lib/template/index.js
index 833ff76..a3021e6 100644
--- a/lib/template/index.js
+++ b/lib/template/index.js
@@ -7,6 +7,7 @@ var Promise = require('../utils/promise');
var error = require('../utils/error');
var gitbook = require('../gitbook');
var defaultBlocks = require('./blocks');
+var Loader = require('./loader');
// Return extension name for a specific block
function blockExtName(name) {
@@ -23,6 +24,10 @@ function TemplateEngine(book) {
this.book = book;
this.log = book.log;
+ // Create file loader
+ this.loader = new Loader(this);
+
+ // Create nunjucks instance
this.env = new nunjucks.Environment(
this.loader,
{
@@ -57,6 +62,14 @@ function TemplateEngine(book) {
this.addBlocks(defaultBlocks);
}
+// Interpolate a string content to replace shortcuts according to the filetype
+TemplateEngine.prototype.interpolate = function(filepath, source) {
+ var parser = parsers.get(path.extname(filepath));
+ var type = parser? parser.name : null;
+
+ return this.applyShortcuts(type, source);
+};
+
// Add a new custom filter
TemplateEngine.prototype.addFilter = function(filterName, func) {
try {
diff --git a/lib/template/loader.js b/lib/template/loader.js
index e69de29..23ffb77 100644
--- a/lib/template/loader.js
+++ b/lib/template/loader.js
@@ -0,0 +1,75 @@
+var path = require('path');
+var nunjucks = require('nunjucks');
+
+var Git = require('../utils/git');
+var pathUtil = require('../utils/path');
+
+// The loader should handle relative and git url
+var Loader = nunjucks.Loader.extend({
+ async: true,
+
+ init: function(engine, opts) {
+ this.engine = engine;
+ this.book = engine.book;
+ this.fs = engine.book.fs;
+
+ this.git = new Git(this.fs.tmpdir());
+ },
+
+ getSource: function(soureURL, callback) {
+ var that = this;
+
+ this.git.resolveFile(soureURL)
+ .then(function(filepath) {
+ // Is local file
+ if (!filepath) {
+ filepath = that.book.resolve(soureURL);
+ } else {
+ that.book.log.debug.ln('resolve from git', soureURL, 'to', filepath);
+ }
+
+ // Read file from absolute path
+ return that.fs.readAsString(filepath)
+ .then(function(source) {
+ return that.engine.interpolate(filepath, source);
+ })
+ .then(function(source) {
+ return {
+ src: source,
+ path: filepath,
+
+ // We disable cache since content is modified (shortcuts, ...)
+ noCache: true
+ };
+ });
+ })
+ .nodeify(callback);
+ },
+
+ resolve: function(from, to) {
+ // If origin is in the book, we enforce result file to be in the book
+ if (this.book.isInBook(from)) {
+ return this.book.resolve(
+ this.book.relative(path.dirname(from)),
+ to
+ );
+ }
+
+ // If origin is in a git repository, we resolve file in the git repository
+ var gitRoot = this.git.resolveRoot(from);
+ if (gitRoot) {
+ return pathUtil.resolveInRoot(gitRoot, to);
+ }
+
+ // If origin is not in the book (include from a git content ref)
+ return path.resolve(path.dirname(from), to);
+ },
+
+ // Handle all files as relative, so that nunjucks pass responsability to 'resolve'
+ // Only git urls are considered as absolute
+ isRelative: function(filename) {
+ return !Git.isUrl(filename);
+ }
+});
+
+module.exports = Loader;
diff --git a/test/all.js b/test/all.js
index 0f55603..827a182 100644
--- a/test/all.js
+++ b/test/all.js
@@ -7,8 +7,8 @@ require('./glossary');
require('./langs');
require('./parse');
-require('./template');
require('./git');
+require('./template');
// Output
require('./output-json');