diff options
author | Samy Pessé <samypesse@gmail.com> | 2016-04-15 11:33:24 +0200 |
---|---|---|
committer | Samy Pessé <samypesse@gmail.com> | 2016-04-15 11:33:24 +0200 |
commit | 663291c51507837689b7281be5c07802f19c3d0e (patch) | |
tree | 23fcddecc5d01f4d051cd117f3055007a9bc9784 | |
parent | 99253eeceaab70a7e85504b7867a9999d34890c4 (diff) | |
download | gitbook-663291c51507837689b7281be5c07802f19c3d0e.zip gitbook-663291c51507837689b7281be5c07802f19c3d0e.tar.gz gitbook-663291c51507837689b7281be5c07802f19c3d0e.tar.bz2 |
Output context as global for themes
-rw-r--r-- | lib/output/ebook.js | 10 | ||||
-rw-r--r-- | lib/output/website/index.js (renamed from lib/output/website.js) | 167 | ||||
-rw-r--r-- | lib/output/website/templateEnv.js | 87 | ||||
-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.json | 10 | ||||
-rw-r--r-- | test/node_modules/gitbook-plugin-dep2/package.json | 7 |
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 |