Add hook "config" to transform configuration before generation

This commit is contained in:
Samy Pessé
2015-10-12 10:43:14 +02:00
parent 4ae5b2e050
commit 9ba1075f48
5 changed files with 172 additions and 146 deletions
+15 -2
View File
@@ -178,6 +178,14 @@ Book.prototype.generate = function(generator) {
return generator.prepare();
})
// Transform configuration
.then(function() {
return that.callHook('config', that.config.dump())
.then(function(newConfig) {
that.config.replace(newConfig);
});
})
// Generate content
.then(function() {
if (that.isMultilingual()) {
@@ -238,13 +246,13 @@ Book.prototype.generate = function(generator) {
// Finish generation
.then(function() {
return generator.callHook('finish:before');
return that.callHook('finish:before');
})
.then(function() {
return generator.finish();
})
.then(function() {
return generator.callHook('finish');
return that.callHook('finish');
})
.then(function() {
that.log.info.ln('generation is finished');
@@ -793,4 +801,9 @@ Book.prototype.normError = function(err, opts, defs) {
return err;
};
// Call a hook in plugins
Book.prototype.callHook = function(name, data) {
return this.plugins.hook(name, data);
};
module.exports= Book;
+108
View File
@@ -0,0 +1,108 @@
var path = require('path');
module.exports = {
// Options that can't be extend
'configFile': 'book',
'generator': 'website',
'extension': null,
// Book metadats (somes are extracted from the README by default)
'title': null,
'description': null,
'isbn': null,
'language': 'en',
'direction': null,
'author': null,
// version of gitbook to use
'gitbook': '*',
// Structure
'structure': {
'langs': 'LANGS.md',
'readme': 'README.md',
'glossary': 'GLOSSARY.md',
'summary': 'SUMMARY.md'
},
// CSS Styles
'styles': {
'website': 'styles/website.css',
'print': 'styles/print.css',
'ebook': 'styles/ebook.css',
'pdf': 'styles/pdf.css',
'mobi': 'styles/mobi.css',
'epub': 'styles/epub.css'
},
// Plugins list, can contain '-name' for removing default plugins
'plugins': [],
// Global configuration for plugins
'pluginsConfig': {},
// Variables for templating
'variables': {},
// Set another theme with your own layout
// It's recommended to use plugins or add more options for default theme, though
// See https://github.com/GitbookIO/gitbook/issues/209
'theme': path.resolve(__dirname, '../theme'),
// Links in template (null: default, false: remove, string: new value)
'links': {
// Custom links at top of sidebar
'sidebar': {
// 'Custom link name': 'https://customlink.com'
},
// Sharing links
'sharing': {
'google': null,
'facebook': null,
'twitter': null,
'weibo': null,
'all': null
}
},
// Options for PDF generation
'pdf': {
// Add toc at the end of the file
'toc': true,
// Add page numbers to the bottom of every page
'pageNumbers': false,
// Font size for the file content
'fontSize': 12,
// Paper size for the pdf
// Choices are [u’a0’, u’a1’, u’a2’, u’a3’, u’a4’, u’a5’, u’a6’, u’b0’, u’b1’, u’b2’, u’b3’, u’b4’, u’b5’, u’b6’, u’legal’, u’letter’]
'paperSize': 'a4',
// How to mark detected chapters.
// Choices are “pagebreak”, “rule”, 'both' or “none”.
'chapterMark' : 'pagebreak',
// An XPath expression. Page breaks are inserted before the specified elements.
// To disable use the expression: '/'
'pageBreaksBefore': '/',
// Margin (in pts)
// Note: 72 pts equals 1 inch
'margin': {
'right': 62,
'left': 62,
'top': 56,
'bottom': 56
},
// Header HTML template. Available variables: _PAGENUM_, _TITLE_, _AUTHOR_ and _SECTION_.
'headerTemplate': null,
// Footer HTML template. Available variables: _PAGENUM_, _TITLE_, _AUTHOR_ and _SECTION_.
'footerTemplate': null
}
};
+15 -110
View File
@@ -1,12 +1,13 @@
var _ = require('lodash');
var Q = require('q');
var fs = require('fs');
var path = require('path');
var semver = require('semver');
var pkg = require('../package.json');
var i18n = require('./utils/i18n');
var DEFAULT_CONFIG = require('./config_default');
// Default plugins added to each books
var DEFAULT_PLUGINS = ['highlight', 'search', 'sharing', 'fontsettings'];
@@ -85,9 +86,7 @@ var Configuration = function(book, options) {
var that = this;
this.book = book;
this.options = _.cloneDeep(Configuration.DEFAULT);
this.options = _.merge(this.options, options || {});
this.replace(options);
// options.input == book.root
Object.defineProperty(this.options, 'input', {
@@ -169,6 +168,17 @@ Configuration.prototype.extend = function(options) {
_.extend(this.options, options);
};
// Replace the configuration
Configuration.prototype.replace = function(options) {
this.options = _.cloneDeep(DEFAULT_CONFIG);
this.options = _.merge(this.options, options || {});
};
// Dump configuration as json object
Configuration.prototype.dump = function() {
return _.cloneDeep(this.options);
};
// Get structure file
Configuration.prototype.getStructure = function(name) {
return this.options.structure[name].split('.').slice(0, -1).join('.');
@@ -185,111 +195,6 @@ Configuration.prototype.get = function(key, def) {
};
// Default configuration
Configuration.DEFAULT = {
// Options that can't be extend
'configFile': 'book',
'generator': 'website',
'extension': null,
// Book metadats (somes are extracted from the README by default)
'title': null,
'description': null,
'isbn': null,
'language': 'en',
'direction': null,
'author': null,
// version of gitbook to use
'gitbook': '*',
// Structure
'structure': {
'langs': 'LANGS.md',
'readme': 'README.md',
'glossary': 'GLOSSARY.md',
'summary': 'SUMMARY.md'
},
// CSS Styles
'styles': {
'website': 'styles/website.css',
'print': 'styles/print.css',
'ebook': 'styles/ebook.css',
'pdf': 'styles/pdf.css',
'mobi': 'styles/mobi.css',
'epub': 'styles/epub.css'
},
// Plugins list, can contain '-name' for removing default plugins
'plugins': [],
// Global configuration for plugins
'pluginsConfig': {},
// Variables for templating
'variables': {},
// Set another theme with your own layout
// It's recommended to use plugins or add more options for default theme, though
// See https://github.com/GitbookIO/gitbook/issues/209
'theme': path.resolve(__dirname, '../theme'),
// Links in template (null: default, false: remove, string: new value)
'links': {
// Custom links at top of sidebar
'sidebar': {
// 'Custom link name': 'https://customlink.com'
},
// Sharing links
'sharing': {
'google': null,
'facebook': null,
'twitter': null,
'weibo': null,
'all': null
}
},
// Options for PDF generation
'pdf': {
// Add toc at the end of the file
'toc': true,
// Add page numbers to the bottom of every page
'pageNumbers': false,
// Font size for the file content
'fontSize': 12,
// Paper size for the pdf
// Choices are [u’a0’, u’a1’, u’a2’, u’a3’, u’a4’, u’a5’, u’a6’, u’b0’, u’b1’, u’b2’, u’b3’, u’b4’, u’b5’, u’b6’, u’legal’, u’letter’]
'paperSize': 'a4',
// How to mark detected chapters.
// Choices are “pagebreak”, “rule”, 'both' or “none”.
'chapterMark' : 'pagebreak',
// An XPath expression. Page breaks are inserted before the specified elements.
// To disable use the expression: '/'
'pageBreaksBefore': '/',
// Margin (in pts)
// Note: 72 pts equals 1 inch
'margin': {
'right': 62,
'left': 62,
'top': 56,
'bottom': 56
},
// Header HTML template. Available variables: _PAGENUM_, _TITLE_, _AUTHOR_ and _SECTION_.
'headerTemplate': null,
// Footer HTML template. Available variables: _PAGENUM_, _TITLE_, _AUTHOR_ and _SECTION_.
'footerTemplate': null
}
};
Configuration.DEFAULT = DEFAULT_CONFIG;
module.exports= Configuration;
+13 -13
View File
@@ -1,12 +1,12 @@
var _ = require("lodash");
var path = require("path");
var Q = require("q");
var fs = require("./utils/fs");
var _ = require('lodash');
var path = require('path');
var Q = require('q');
var fs = require('./utils/fs');
var BaseGenerator = function(book) {
this.book = book;
Object.defineProperty(this, "options", {
Object.defineProperty(this, 'options', {
get: function () {
return this.book.options;
}
@@ -16,19 +16,19 @@ var BaseGenerator = function(book) {
};
BaseGenerator.prototype.callHook = function(name, data) {
return this.book.plugins.hook(name, data);
return this.book.callHook(name, data);
};
// Prepare the genertor
BaseGenerator.prototype.prepare = function() {
var that = this;
return that.callHook("init");
return that.callHook('init');
};
// Write a parsed file to the output
BaseGenerator.prototype.convertFile = function(input) {
return Q.reject(new Error("Could not convert "+input));
return Q.reject(new Error('Could not convert '+input));
};
// Copy file to the output (non parsable)
@@ -51,16 +51,16 @@ BaseGenerator.prototype.copyCover = function() {
var that = this;
return Q.all([
fs.copy(that.book.resolve("cover.jpg"), path.join(that.options.output, "cover.jpg")),
fs.copy(that.book.resolve("cover_small.jpg"), path.join(that.options.output, "cover_small.jpg"))
fs.copy(that.book.resolve('cover.jpg'), path.join(that.options.output, 'cover.jpg')),
fs.copy(that.book.resolve('cover_small.jpg'), path.join(that.options.output, 'cover_small.jpg'))
])
.fail(function() {
// If orignaly from multi-lang, try copy from parent
if (!that.book.isSubBook()) return;
return Q.all([
fs.copy(path.join(that.book.parentRoot(), "cover.jpg"), path.join(that.options.output, "cover.jpg")),
fs.copy(path.join(that.book.parentRoot(), "cover_small.jpg"), path.join(that.options.output, "cover_small.jpg"))
fs.copy(path.join(that.book.parentRoot(), 'cover.jpg'), path.join(that.options.output, 'cover.jpg')),
fs.copy(path.join(that.book.parentRoot(), 'cover_small.jpg'), path.join(that.options.output, 'cover_small.jpg'))
]);
})
.fail(function() {
@@ -70,7 +70,7 @@ BaseGenerator.prototype.copyCover = function() {
// At teh end of the generation
BaseGenerator.prototype.finish = function() {
return Q.reject(new Error("Could not finish generation"));
return Q.reject(new Error('Could not finish generation'));
};
module.exports = BaseGenerator;
+21 -21
View File
@@ -1,12 +1,12 @@
var _ = require("lodash");
var Q = require("q");
var semver = require("semver");
var path = require("path");
var url = require("url");
var fs = require("./utils/fs");
var resolve = require("resolve");
var _ = require('lodash');
var Q = require('q');
var semver = require('semver');
var path = require('path');
var url = require('url');
var fs = require('./utils/fs');
var resolve = require('resolve');
var pkg = require("../package.json");
var pkg = require('../package.json');
var Plugin = function(book, name) {
this.book = book;
@@ -18,8 +18,8 @@ var Plugin = function(book, name) {
_.bindAll(this);
_.each([
"gitbook-plugin-"+name,
"gitbook-"+name,
'gitbook-plugin-'+name,
'gitbook-'+name,
name,
], function(_name) {
// Load from the book
@@ -31,15 +31,15 @@ var Plugin = function(book, name) {
};
// Type of plugins resources
Plugin.RESOURCES = ["js", "css"];
Plugin.RESOURCES = ['js', 'css'];
Plugin.HOOKS = [
"init", "finish", "finish:before", "page", "page:before"
'init', 'finish', 'finish:before', 'config', 'page', 'page:before'
];
// Load from a name
Plugin.prototype.load = function(name, baseDir) {
try {
var res = resolve.sync(name+"/package.json", { basedir: baseDir });
var res = resolve.sync(name+'/package.json', { basedir: baseDir });
this.baseDir = path.dirname(res);
this.packageInfos = require(res);
@@ -62,13 +62,13 @@ Plugin.prototype.normalizeResource = function(resource) {
// so we will simply link to using it's URL
if (parsed.protocol) {
return {
"url": resource
'url': resource
};
}
// This will be copied over from disk
// and shipped with the book's build
return { "path": this.name+"/"+resource };
return { 'path': this.name+'/'+resource };
};
// Return resources
@@ -77,7 +77,7 @@ Plugin.prototype._getResources = function(base) {
var book = this.infos[base];
// Compatibility with version 1.x.x
if (base == "website") book = book || this.infos.book;
if (base == 'website') book = book || this.infos.book;
// Nothing specified, fallback to default
if (!book) {
@@ -85,7 +85,7 @@ Plugin.prototype._getResources = function(base) {
}
// Dynamic function
if(typeof book === "function") {
if(typeof book === 'function') {
// Call giving it the context of our book
return Q().then(book.bind(this.book));
}
@@ -133,7 +133,7 @@ Plugin.prototype.isValid = function() {
// Valid hooks
_.each(this.infos.hooks, function(hook, hookName) {
if (_.contains(Plugin.HOOKS, hookName)) return;
that.book.log.warn.ln("Hook '"+hookName+" 'used by plugin '"+that.packageInfos.name+"' has been removed or is deprecated");
that.book.log.warn.ln('Hook ''+hookName+' 'used by plugin ''+that.packageInfos.name+'' has been removed or is deprecated');
});
return isValid;
@@ -154,8 +154,8 @@ Plugin.prototype.callHook = function(name, data) {
if (!hookFunc) return Q(data);
this.book.log.debug.ln("call hook", name);
if (!_.contains(Plugin.HOOKS, name)) this.book.log.warn.ln("hook '"+name+"' used by plugin '"+this.name+"' is deprecated, and will be removed in the coming versions");
this.book.log.debug.ln('call hook', name);
if (!_.contains(Plugin.HOOKS, name)) this.book.log.warn.ln('hook ''+name+'' used by plugin ''+this.name+'' is deprecated, and will be removed in the coming versions');
return Q()
.then(function() {
@@ -168,7 +168,7 @@ Plugin.prototype.copyAssets = function(out, base) {
var that = this;
return this.getResources(base)
.get("assets")
.get('assets')
.then(function(assets) {
// Assets are undefined
if(!assets) return false;