mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-19 17:15:24 +00:00
Merge pull request #482 from GitbookIO/feature/includes
Add include support, with variables and the whole shebang
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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));
|
||||
});
|
||||
};
|
||||
|
||||
+18
-17
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
};
|
||||
@@ -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;
|
||||
});
|
||||
};
|
||||
+5
-10
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user