diff options
author | Aaron O'Mullan <aaron.omullan@gmail.com> | 2014-10-15 21:29:23 +0200 |
---|---|---|
committer | Aaron O'Mullan <aaron.omullan@gmail.com> | 2014-10-15 21:29:23 +0200 |
commit | ce50b893e926fed8905419efc8bce4a64ab2d5dc (patch) | |
tree | 83cf19e47f26fd77072ac63aeaf2152a4b30ffa6 | |
parent | 49e3bbc3d6e9e128df721494e9a10eaf15b7ddc8 (diff) | |
parent | 225ff27dd15b904d6a4a784c219522a28f316a5b (diff) | |
download | gitbook-ce50b893e926fed8905419efc8bce4a64ab2d5dc.zip gitbook-ce50b893e926fed8905419efc8bce4a64ab2d5dc.tar.gz gitbook-ce50b893e926fed8905419efc8bce4a64ab2d5dc.tar.bz2 |
Merge pull request #482 from GitbookIO/feature/includes
Add include support, with variables and the whole shebang
-rw-r--r-- | lib/generate/generator.js | 23 | ||||
-rw-r--r-- | lib/generate/index.js | 2 | ||||
-rw-r--r-- | lib/generate/site/index.js | 35 | ||||
-rw-r--r-- | lib/parse/code_include.js | 20 | ||||
-rw-r--r-- | lib/parse/include.js | 48 | ||||
-rw-r--r-- | lib/parse/page.js | 15 | ||||
-rw-r--r-- | lib/parse/renderer.js | 5 |
7 files changed, 96 insertions, 52 deletions
diff --git a/lib/generate/generator.js b/lib/generate/generator.js index 8724a4f..84c65d7 100644 --- a/lib/generate/generator.js +++ b/lib/generate/generator.js @@ -14,12 +14,35 @@ var BaseGenerator = function(options) { this.options.plugins = Plugin.normalizeNames(this.options.plugins); this.options.plugins = _.union(this.options.plugins, this.options.defaultsPlugins); this.plugins = []; + + // Include variables (not yet loaded) + this.variables = {}; }; BaseGenerator.prototype.callHook = function(name, data) { return this.plugins.hook(name, data); }; +// Sets up generator +BaseGenerator.prototype.load = function() { + return this.loadVariables() + .then(this.loadPlugins.bind(this)); +}; + +BaseGenerator.prototype.loadVariables = function() { + var that = this; + + return fs.readFile(path.join(this.options.input, 'variables.json'), 'utf8') + .then(function(content) { + try { + that.variables = JSON.parse(content); + } catch(err) { + console.log('No variables.json'); + } + }) + .fail(function() {}); +}; + BaseGenerator.prototype.loadPlugins = function() { var that = this; diff --git a/lib/generate/index.js b/lib/generate/index.js index 4fc78a7..2118c46 100644 --- a/lib/generate/index.js +++ b/lib/generate/index.js @@ -40,7 +40,7 @@ var loadGenerator = function(options) { .then(function() { var generator = new generators[options.generator](options); - return generator.loadPlugins() + return generator.load() .then(_.constant(generator)); }); }; diff --git a/lib/generate/site/index.js b/lib/generate/site/index.js index a694f39..4179917 100644 --- a/lib/generate/site/index.js +++ b/lib/generate/site/index.js @@ -23,6 +23,16 @@ var Generator = function() { }; util.inherits(Generator, BaseGenerator); +// Add template loading to load +Generator.prototype.load = function() { + var that = this; + + return BaseGenerator.prototype.load.apply(this) + .then(function() { + return that.loadTemplates(); + }); +}; + // Load all templates Generator.prototype.loadTemplates = function() { this.template = swig.compileFile( @@ -36,16 +46,6 @@ Generator.prototype.loadTemplates = function() { ); }; -// Load plugins -Generator.prototype.loadPlugins = function() { - var that = this; - - return BaseGenerator.prototype.loadPlugins.apply(this) - .then(function() { - return that.loadTemplates(); - }); -}; - // Generate a template Generator.prototype._writeTemplate = function(tpl, options, output, interpolate) { var that = this; @@ -118,16 +118,17 @@ Generator.prototype.prepareFile = function(content, _input) { return _callHook("page:before"); }) .then(function() { - // Lex page - return parse.lex(page.content); - }) - .then(function(lexed) { - page.lexed = lexed; - + // Lex, parse includes and get // Get HTML generated sections - return parse.page(lexed, { + return parse.page(page.content, { + // Local files path dir: path.dirname(_input) || '/', + // Project's include folder + includes_dir: path.join(that.options.input, '_includes'), + // Output directory outdir: path.dirname(_input) || '/', + // Templating variables + variables: that.variables, }); }) .then(function(sections) { diff --git a/lib/parse/code_include.js b/lib/parse/code_include.js deleted file mode 100644 index 977dc3d..0000000 --- a/lib/parse/code_include.js +++ /dev/null @@ -1,20 +0,0 @@ -var fs = require('graceful-fs'); -var path = require('path'); - -module.exports = function(code, folder) { - folder = folder || ''; - - return code.replace(/{{([\s\S]+?)}}/g, function(match, filename) { - // Normalize filename - var fname = path.join(folder, filename.trim()); - - // Try including snippet from FS - try { - // Trim trailing newlines/space of imported snippets - return fs.readFileSync(fname, 'utf8').trimRight(); - } catch(err) {} - - // If fails leave content as is - return match; - }); -}; diff --git a/lib/parse/include.js b/lib/parse/include.js new file mode 100644 index 0000000..5fba2be --- /dev/null +++ b/lib/parse/include.js @@ -0,0 +1,48 @@ +var _ = require('lodash'); +var fs = require('graceful-fs'); +var path = require('path'); + + +// Include helper +function importInclude(name, paths) { + return paths + .map(function(folder) { + // Try including snippet from FS + try { + var fname = path.join(folder, name); + // Trim trailing newlines/space of imported snippets + return fs.readFileSync(fname, 'utf8').trimRight(); + } catch(err) {} + }) + .filter(Boolean)[0]; +} + +function includer(ctx, folders) { + return function(key) { + key = key.trim(); + return ctx[key] || importInclude(key, folders); + }; +} + +module.exports = function(markdown, folder, ctx) { + // List of folders to search for includes + var folders = []; + + // Handle folder arg (string or array) + if(_.isString(folder)) { + folders = [folder]; + } else if(_.isArray(folder)) { + folders = folder; + } + + // variable context + ctx = ctx || {}; + + // Memoized include function (to cache lookups) + var _include = _.memoize(includer(ctx, folders)); + + return markdown.replace(/{{([\s\S]+?)}}/g, function(match, key) { + // If fails leave content as is + return _include(key) || match; + }); +}; diff --git a/lib/parse/page.js b/lib/parse/page.js index ae71666..e694f1c 100644 --- a/lib/parse/page.js +++ b/lib/parse/page.js @@ -5,7 +5,7 @@ var hljs = require('highlight.js'); var lex = require('./lex'); var renderer = require('./renderer'); -var codeInclude = require('./code_include'); +var include = require('./include'); var lnormalize = require('../utils/lang').normalize; @@ -51,7 +51,7 @@ function parsePage(src, options) { options = options || {}; // Lex if not already lexed - return (_.isArray(src) ? src : lex(src)) + return (_.isArray(src) ? src : lex(include(src, [options.dir, options.includes_dir], options.variables))) .map(function(section) { // Transform given type if(section.type === 'exercise') { @@ -74,20 +74,15 @@ function parsePage(src, options) { // Main language var lang = validLangs ? langs[0] : null; - // codeInclude shortcut - var ci = function(code) { - return codeInclude(code, options.dir); - }; - return { id: section.id, type: section.type, content: render(nonCodeNodes, options), lang: lang, code: { - base: ci(codeNodes[0].text), - solution: ci(codeNodes[1].text), - validation: ci(codeNodes[2].text), + base: codeNodes[0].text, + solution: codeNodes[1].text, + validation: codeNodes[2].text, // Context is optional context: codeNodes[3] ? codeNodes[3].text : null, } diff --git a/lib/parse/renderer.js b/lib/parse/renderer.js index faa416c..61b3d9b 100644 --- a/lib/parse/renderer.js +++ b/lib/parse/renderer.js @@ -1,8 +1,6 @@ var url = require('url'); var inherits = require('util').inherits; var links = require('../utils').links; -var codeInclude = require('./code_include'); - var path = require('path'); @@ -130,8 +128,7 @@ GitBookRenderer.prototype.listitem = function(text) { GitBookRenderer.prototype.code = function(code, lang, escaped) { return GitBookRenderer.super_.prototype.code.call( this, - // Import code snippets - codeInclude(code, this._extra_options.dir), + code, lang, escaped ); |