summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamy Pessé <samypesse@gmail.com>2016-04-15 11:33:24 +0200
committerSamy Pessé <samypesse@gmail.com>2016-04-15 11:33:24 +0200
commit663291c51507837689b7281be5c07802f19c3d0e (patch)
tree23fcddecc5d01f4d051cd117f3055007a9bc9784
parent99253eeceaab70a7e85504b7867a9999d34890c4 (diff)
downloadgitbook-663291c51507837689b7281be5c07802f19c3d0e.zip
gitbook-663291c51507837689b7281be5c07802f19c3d0e.tar.gz
gitbook-663291c51507837689b7281be5c07802f19c3d0e.tar.bz2
Output context as global for themes
-rw-r--r--lib/output/ebook.js10
-rw-r--r--lib/output/website/index.js (renamed from lib/output/website.js)167
-rw-r--r--lib/output/website/templateEnv.js87
-rw-r--r--lib/output/website/themeLoader.js (renamed from lib/template/fs-loader.js)25
-rw-r--r--test/node_modules/gitbook-plugin-dep1/package.json10
-rw-r--r--test/node_modules/gitbook-plugin-dep2/package.json7
6 files changed, 200 insertions, 106 deletions
diff --git a/lib/output/ebook.js b/lib/output/ebook.js
index b0b05ca..2b8fac9 100644
--- a/lib/output/ebook.js
+++ b/lib/output/ebook.js
@@ -44,13 +44,7 @@ EbookOutput.prototype.finish = function() {
// Generate SUMMARY.html
.then(function() {
- return that.render('summary', that.getContext())
- .then(function(html) {
- return that.writeFile(
- 'SUMMARY.html',
- html
- );
- });
+ return that.render('summary', 'SUMMARY.html', that.getContext());
})
// Start ebook-convert
@@ -100,7 +94,7 @@ EbookOutput.prototype.getPDFTemplate = function(tpl) {
this.getContext()
);
- return this.render('pdf_'+tpl, context)
+ return this.renderAsString('pdf_'+tpl, context)
// Inline css, include css relative to the output folder
.then(function(output) {
diff --git a/lib/output/website.js b/lib/output/website/index.js
index 1eaf98a..9ef87b6 100644
--- a/lib/output/website.js
+++ b/lib/output/website/index.js
@@ -1,22 +1,14 @@
var _ = require('lodash');
var path = require('path');
var util = require('util');
-var nunjucks = require('nunjucks');
var I18n = require('i18n-t');
-var Promise = require('../utils/promise');
-var location = require('../utils/location');
-var fs = require('../utils/fs');
-var defaultFilters = require('../template/filters');
-var FSLoader = require('../template/fs-loader');
-var conrefsLoader = require('./conrefs');
-var Output = require('./base');
-
-
-// Directory for a theme with the templates
-function templatesPath(dir) {
- return path.join(dir, '_layouts');
-}
+var Promise = require('../../utils/promise');
+var location = require('../../utils/location');
+var fs = require('../../utils/fs');
+var conrefsLoader = require('../conrefs');
+var Output = require('../base');
+var setupTemplateEnv = require('./templateEnv');
function _WebsiteOutput() {
Output.apply(this, arguments);
@@ -68,58 +60,7 @@ WebsiteOutput.prototype.prepare = function() {
that.i18n.load(i18nRoot);
});
- that.env = new nunjucks.Environment(new FSLoader(_.map(searchPaths, templatesPath)));
-
- // Add GitBook default filters
- _.each(defaultFilters, function(fn, filter) {
- that.env.addFilter(filter, fn);
- });
-
- // Translate using _i18n locales
- that.env.addFilter('t', function(s) {
- return that.i18n.t(that.book.config.get('language'), s);
- });
-
- // Transform an absolute path into a relative path
- // using this.ctx.page.path
- that.env.addFilter('resolveFile', function(href) {
- return location.normalize(that.resolveForPage(this.ctx.file.path, href));
- });
-
- // Test if a file exists
- that.env.addFilter('fileExists', function(href) {
- return fs.existsSync(that.resolve(href));
- });
-
- // Transform a '.md' into a '.html' (README -> index)
- that.env.addFilter('contentURL', function(s) {
- return that.toURL(s);
- });
-
- // Get an article using its path
- that.env.addFilter('getArticleByPath', function(s) {
- var article = that.book.summary.getArticle(s);
- if (!article) return undefined;
-
- return article.getContext();
- });
-
- // Relase path to an asset
- that.env.addFilter('resolveAsset', function(href) {
- href = path.join('gitbook', href);
-
- // Resolve for current file
- if (this.ctx.file) {
- href = that.resolveForPage(this.ctx.file.path, '/' + href);
- }
-
- // Use assets from parent
- if (that.book.isLanguageBook()) {
- href = path.join('../', href);
- }
-
- return location.normalize(href);
- });
+ that.searchPaths = searchPaths;
})
// Copy assets from themes before copying files from book
@@ -164,15 +105,7 @@ WebsiteOutput.prototype.onPage = function(page) {
// Render the page template with the same context as the json output
.then(function() {
- return that.render('page', page.getOutputContext(that));
- })
-
- // Write the HTML file
- .then(function(html) {
- return that.writeFile(
- that.outputPath(page.path),
- html
- );
+ return that.render('page', that.outputPath(page.path), page.getOutputContext(that));
});
};
@@ -204,46 +137,87 @@ WebsiteOutput.prototype.finish = function() {
WebsiteOutput.prototype.outputMultilingualIndex = function() {
var that = this;
- return that.render('languages', that.getContext())
- .then(function(html) {
- return that.writeFile(
- 'index.html',
- html
- );
+ return that.render('languages', 'index.html', that.getContext());
+};
+
+/*
+ Render a template as an HTML string
+ Templates are stored in `_layouts` folders
+
+
+ @param {String} tpl: template name (ex: "page")
+ @param {String} outputFile: filename to write, relative to the output
+ @param {Object} context: context for the page
+ @return {Promise}
+*/
+WebsiteOutput.prototype.renderAsString = function(tpl, context) {
+ // Calcul template name
+ var filename = this.templateName(tpl);
+
+ // Extend context
+ // Setup complete context
+ context.template = _.extend(context.template || {}, {
+ self: filename
});
+
+ context = _.extend(context, {
+ plugins: {
+ resources: this.resources
+ },
+
+ options: this.opts
+ });
+
+ // Create environment
+ var env = setupTemplateEnv(this, context);
+
+ return Promise.nfcall(env.render.bind(env), filename, context);
};
-// Render a template using nunjucks
-// Templates are stored in `_layouts` folders
-WebsiteOutput.prototype.render = function(tpl, context) {
+/*
+ Render a template using nunjucks
+ Templates are stored in `_layouts` folders
+
+
+ @param {String} tpl: template name (ex: "page")
+ @param {String} outputFile: filename to write, relative to the output
+ @param {Object} context: context for the page
+ @return {Promise}
+*/
+WebsiteOutput.prototype.render = function(tpl, outputFile, context) {
var that = this;
- var filename = this.templateName(tpl);
+ // Calcul relative path to the root
+ var outputDirName = path.dirname(outputFile);
+ var basePath = location.normalize(path.relative(outputDirName, './'));
+
+ // Setup complete context
context = _.extend(context, {
+ basePath: basePath,
+
template: {
- self: filename,
getJSContext: function() {
return {
page: _.omit(context.page, 'content'),
config: context.config,
file: context.file,
gitbook: context.gitbook,
- basePath: location.normalize(that.resolveForPage(context.file.path, './')),
+ basePath: basePath,
book: {
language: context.book.language
}
};
}
- },
-
- plugins: {
- resources: this.resources
- },
-
- options: this.opts
+ }
});
- return Promise.nfcall(this.env.render.bind(this.env), filename, context);
+ return this.renderAsString(tpl, context)
+ .then(function(html) {
+ return that.writeFile(
+ outputFile,
+ html
+ );
+ });
};
// Return a complete name for a template
@@ -252,3 +226,6 @@ WebsiteOutput.prototype.templateName = function(name) {
};
module.exports = WebsiteOutput;
+
+
+
diff --git a/lib/output/website/templateEnv.js b/lib/output/website/templateEnv.js
new file mode 100644
index 0000000..ea2b521
--- /dev/null
+++ b/lib/output/website/templateEnv.js
@@ -0,0 +1,87 @@
+var _ = require('lodash');
+var nunjucks = require('nunjucks');
+var path = require('path');
+var fs = require('fs');
+
+var location = require('../../utils/location');
+var defaultFilters = require('../../template/filters');
+
+var ThemeLoader = require('./themeLoader');
+
+// Directory for a theme with the templates
+function templatesPath(dir) {
+ return path.join(dir, '_layouts');
+}
+
+/*
+ Create and setup at Nunjucks template environment
+
+ @return {Nunjucks.Environment}
+*/
+function setupTemplateEnv(output, context) {
+ var loader = new ThemeLoader(
+ _.map(output.searchPaths, templatesPath)
+ );
+ var env = new nunjucks.Environment(loader);
+
+ // Add context as global
+ _.each(context, function(value, key) {
+ env.addGlobal(key, value);
+ });
+
+ // Add GitBook default filters
+ _.each(defaultFilters, function(fn, filter) {
+ env.addFilter(filter, fn);
+ });
+
+ // Translate using _i18n locales
+ env.addFilter('t', function t(s) {
+ return output.i18n.t(output.book.config.get('language'), s);
+ });
+
+ // Transform an absolute path into a relative path
+ // using this.ctx.page.path
+ env.addFilter('resolveFile', function resolveFile(href) {
+ return location.normalize(output.resolveForPage(context.file.path, href));
+ });
+
+ // Test if a file exists
+ env.addFilter('fileExists', function fileExists(href) {
+ return fs.existsSync(output.resolve(href));
+ });
+
+ // Transform a '.md' into a '.html' (README -> index)
+ env.addFilter('contentURL', function contentURL(s) {
+ return output.toURL(s);
+ });
+
+ // Get an article using its path
+ env.addFilter('getArticleByPath', function getArticleByPath(s) {
+ var article = output.book.summary.getArticle(s);
+ if (!article) return undefined;
+
+ return article.getContext();
+ });
+
+ // Relase path to an asset
+ env.addFilter('resolveAsset', function resolveAsset(href) {
+ href = path.join('gitbook', href);
+
+ // Resolve for current file
+ if (context.file) {
+ href = output.resolveForPage(context.file.path, '/' + href);
+ }
+
+ // Use assets from parent
+ if (output.book.isLanguageBook()) {
+ href = path.join('../', href);
+ }
+
+ return location.normalize(href);
+ });
+
+
+ return env;
+}
+
+module.exports = setupTemplateEnv;
diff --git a/lib/template/fs-loader.js b/lib/output/website/themeLoader.js
index 7f469bb..013b81c 100644
--- a/lib/template/fs-loader.js
+++ b/lib/output/website/themeLoader.js
@@ -7,15 +7,24 @@ var nunjucks = require('nunjucks');
Nunjucks loader similar to FileSystemLoader, but avoid infinite looping
*/
+/*
+ Return true if a filename is relative.
+*/
function isRelative(filename) {
return (filename.indexOf('./') === 0 || filename.indexOf('../') === 0);
}
-var Loader = nunjucks.Loader.extend({
+var ThemeLoader = nunjucks.Loader.extend({
init: function(searchPaths) {
this.searchPaths = _.map(searchPaths, path.normalize);
},
+ /*
+ Read source of a resolved filepath
+
+ @param {String}
+ @return {Object}
+ */
getSource: function(fullpath) {
if (!fullpath) return null;
@@ -32,11 +41,21 @@ var Loader = nunjucks.Loader.extend({
};
},
- // We handle absolute paths ourselves in ".resolve"
+ /*
+ Nunjucks calls "isRelative" to determine when to call "resolve".
+ We handle absolute paths ourselves in ".resolve" so we always return true
+ */
isRelative: function() {
return true;
},
+ /*
+ Resolve a template from a current template
+
+ @param {String|null} from
+ @param {String} to
+ @return {String|null}
+ */
resolve: function(from, to) {
var searchPaths = this.searchPaths;
@@ -77,4 +96,4 @@ var Loader = nunjucks.Loader.extend({
}
});
-module.exports = Loader;
+module.exports = ThemeLoader;
diff --git a/test/node_modules/gitbook-plugin-dep1/package.json b/test/node_modules/gitbook-plugin-dep1/package.json
new file mode 100644
index 0000000..908ca02
--- /dev/null
+++ b/test/node_modules/gitbook-plugin-dep1/package.json
@@ -0,0 +1,10 @@
+{
+ "name": "gitbook-plugin-dep1",
+ "version": "1.0.0",
+ "engines": {
+ "gitbook": "*"
+ },
+ "dependencies": {
+ "gitbook-plugin-dep2": "*"
+ }
+} \ No newline at end of file
diff --git a/test/node_modules/gitbook-plugin-dep2/package.json b/test/node_modules/gitbook-plugin-dep2/package.json
new file mode 100644
index 0000000..2046f5d
--- /dev/null
+++ b/test/node_modules/gitbook-plugin-dep2/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "gitbook-plugin-dep2",
+ "version": "1.0.0",
+ "engines": {
+ "gitbook": "*"
+ }
+} \ No newline at end of file