summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/book.js339
-rw-r--r--lib/configuration.js179
-rw-r--r--lib/generators/website.js9
-rw-r--r--lib/index.js126
-rw-r--r--lib/init.js83
-rw-r--r--lib/pluginslist.js52
-rw-r--r--lib/utils/page.js146
7 files changed, 448 insertions, 486 deletions
diff --git a/lib/book.js b/lib/book.js
index 514a719..72f0ec2 100644
--- a/lib/book.js
+++ b/lib/book.js
@@ -1,23 +1,22 @@
-var Q = require("q");
-var _ = require("lodash");
-var path = require("path");
-var lunr = require("lunr");
-var parsers = require("gitbook-parsers");
-
-var fs = require("./utils/fs");
-var parseNavigation = require("./utils/navigation");
-var parseProgress = require("./utils/progress");
-var pageUtil = require("./utils/page");
-var pathUtil = require("./utils/path");
-var links = require("./utils/links");
-var i18n = require("./utils/i18n");
-var logger = require("./utils/logger");
-
-var Configuration = require("./configuration");
-var TemplateEngine = require("./template");
-var PluginsList = require("./pluginslist");
-
-var generators = require("./generators");
+var Q = require('q');
+var _ = require('lodash');
+var path = require('path');
+var parsers = require('gitbook-parsers');
+
+var fs = require('./utils/fs');
+var parseNavigation = require('./utils/navigation');
+var parseProgress = require('./utils/progress');
+var pageUtil = require('./utils/page');
+var pathUtil = require('./utils/path');
+var links = require('./utils/links');
+var i18n = require('./utils/i18n');
+var logger = require('./utils/logger');
+
+var Configuration = require('./configuration');
+var TemplateEngine = require('./template');
+var PluginsList = require('./pluginslist');
+
+var generators = require('./generators');
var Book = function(root, context, parent) {
this.context = _.defaults(context || {}, {
@@ -30,7 +29,7 @@ var Book = function(root, context, parent) {
},
// Log level
- logLevel: "info"
+ logLevel: 'info'
});
// Log
@@ -44,7 +43,7 @@ var Book = function(root, context, parent) {
// Configuration
this.config = new Configuration(this, this.context.config);
- Object.defineProperty(this, "options", {
+ Object.defineProperty(this, 'options', {
get: function () {
return this.config.options;
}
@@ -78,23 +77,13 @@ var Book = function(root, context, parent) {
this.readmeFile = null;
this.langsFile = null;
- // Search Index
- this.searchIndexEnabled = true;
- this.searchIndexSize = 0;
- this.searchIndex = lunr(function () {
- this.ref("url");
-
- this.field("title", { boost: 10 });
- this.field("body");
- });
-
// Bind methods
_.bindAll(this);
};
// Return string representation
Book.prototype.toString = function() {
- return "[Book "+this.root+"]";
+ return '[Book '+this.root+']';
};
// Initialize and parse the book: config, summary, glossary
@@ -112,17 +101,17 @@ Book.prototype.parse = function() {
return that.parseLangs()
.then(function() {
multilingual = that.langs.length > 0;
- if (multilingual) that.log.info.ln("Parsing multilingual book, with", that.langs.length, "languages");
+ if (multilingual) that.log.info.ln('Parsing multilingual book, with', that.langs.length, 'languages');
// Sub-books that inherit from the current book configuration
that.books = _.map(that.langs, function(lang) {
- that.log.info.ln("Preparing language book", lang.lang);
+ that.log.info.ln('Preparing language book', lang.lang);
return new Book(
path.join(that.root, lang.path),
_.merge({}, that.context, {
config: _.extend({}, that.options, {
- "output": path.join(that.options.output, lang.lang),
- "language": lang.lang
+ 'output': path.join(that.options.output, lang.lang),
+ 'language': lang.lang
})
}),
that
@@ -165,15 +154,15 @@ Book.prototype.generate = function(generator) {
var that = this;
that.options.generator = generator || that.options.generator;
- that.log.info.ln("start generation with", that.options.generator, "generator");
+ that.log.info.ln('start generation with', that.options.generator, 'generator');
return Q()
// Clean output folder
.then(function() {
- that.log.info("clean", that.options.generator, "generator");
+ that.log.info('clean', that.options.generator, 'generator');
return fs.clean(that.options.output)
.progress(function(p) {
- that.log.debug.ln("remove", p.file, "("+p.i+"/"+p.count+")");
+ that.log.debug.ln('remove', p.file, '('+p.i+'/'+p.count+')');
})
.then(function() {
that.log.info.ok();
@@ -183,7 +172,7 @@ Book.prototype.generate = function(generator) {
// Create generator
.then(function() {
var Generator = generators[generator];
- if (!Generator) throw "Generator \""+that.options.generator+"\" doesn't exist";
+ if (!Generator) throw 'Generator \''+that.options.generator+'\' doesn\'t exist';
generator = new Generator(that);
return generator.prepare();
@@ -196,43 +185,43 @@ Book.prototype.generate = function(generator) {
} else {
// Separate list of files into the different operations needed
var ops = _.groupBy(that.files, function(file) {
- if (file[file.length -1] == "/") {
- return "directories";
+ if (file[file.length -1] == '/') {
+ return 'directories';
} else if (_.contains(parsers.extensions, path.extname(file)) && that.navigation[file]) {
- return "content";
+ return 'content';
} else {
- return "files";
+ return 'files';
}
});
return Q()
- // First, let"s create folder
+ // First, let's create folder
.then(function() {
return _.reduce(ops.directories || [], function(prev, folder) {
return prev.then(function() {
- that.log.debug.ln("transferring folder", folder);
+ that.log.debug.ln('transferring folder', folder);
return Q(generator.transferFolder(folder));
});
}, Q());
})
- // Then, let"s copy other files
+ // Then, let's copy other files
.then(function() {
return Q.all(_.map(ops.files || [], function(file) {
- that.log.debug.ln("transferring file", file);
+ that.log.debug.ln('transferring file', file);
return Q(generator.transferFile(file));
}));
})
- // Finally let"s generate content
+ // Finally let's generate content
.then(function() {
var nFiles = (ops.content || []).length;
return _.reduce(ops.content || [], function(prev, file, i) {
return prev.then(function() {
- var p = ((i*100)/nFiles).toFixed(0)+"%";
- that.log.debug.ln("processing", file, p);
+ var p = ((i*100)/nFiles).toFixed(0)+'%';
+ that.log.debug.ln('processing', file, p);
return Q(generator.convertFile(file))
.fail(function(err) {
@@ -249,16 +238,16 @@ Book.prototype.generate = function(generator) {
// Finish generation
.then(function() {
- return generator.callHook("finish:before");
+ return generator.callHook('finish:before');
})
.then(function() {
return generator.finish();
})
.then(function() {
- return generator.callHook("finish");
+ return generator.callHook('finish');
})
.then(function() {
- that.log.info.ln("generation is finished");
+ that.log.info.ln('generation is finished');
});
};
@@ -284,7 +273,7 @@ Book.prototype.generateFile = function(output, options) {
options = _.defaults(options || {}, {
ebookFormat: path.extname(output).slice(1)
});
- output = output || path.resolve(book.root, "book."+options.ebookFormat);
+ output = output || path.resolve(book.root, 'book.'+options.ebookFormat);
return fs.tmp.dir()
.then(function(tmpDir) {
@@ -297,13 +286,13 @@ Book.prototype.generateFile = function(output, options) {
var _tmpDir = tmpDir;
if (lang) {
- _outputFile = _outputFile.slice(0, -path.extname(_outputFile).length)+"_"+lang+path.extname(_outputFile);
+ _outputFile = _outputFile.slice(0, -path.extname(_outputFile).length)+'_'+lang+path.extname(_outputFile);
_tmpDir = path.join(_tmpDir, lang);
}
- book.log.debug.ln("copy ebook to", _outputFile);
+ book.log.debug.ln('copy ebook to', _outputFile);
return fs.copy(
- path.join(_tmpDir, "index."+options.ebookFormat),
+ path.join(_tmpDir, 'index.'+options.ebookFormat),
_outputFile
);
};
@@ -323,7 +312,7 @@ Book.prototype.generateFile = function(output, options) {
}
})
.then(function(n) {
- book.log.info.ok(n+" file(s) generated");
+ book.log.info.ok(n+' file(s) generated');
return fs.remove(tmpDir);
});
@@ -335,7 +324,7 @@ Book.prototype.generateFile = function(output, options) {
Book.prototype.parseConfig = function() {
var that = this;
- that.log.info("loading book configuration....");
+ that.log.info('loading book configuration....');
return that.config.load()
.then(function() {
that.log.info.ok();
@@ -349,34 +338,34 @@ Book.prototype.parsePlugins = function() {
// Load plugins
return that.plugins.load(that.options.plugins)
.then(function() {
- if (_.size(that.plugins.failed) > 0) return Q.reject(new Error("Error loading plugins: "+that.plugins.failed.join(",")+". Run \"gitbook install\" to install plugins from NPM."));
+ if (_.size(that.plugins.failed) > 0) return Q.reject(new Error('Error loading plugins: '+that.plugins.failed.join(',')+'. Run \'gitbook install\' to install plugins from NPM.'));
- that.log.info.ok(that.plugins.count()+" plugins loaded");
- that.log.debug.ln("normalize plugins list");
+ that.log.info.ok(that.plugins.count()+' plugins loaded');
+ that.log.debug.ln('normalize plugins list');
});
};
// Parse readme to extract defaults title and description
Book.prototype.parseReadme = function() {
var that = this;
- var structure = that.config.getStructure("readme");
- that.log.debug.ln("start parsing readme:", structure);
+ var structure = that.config.getStructure('readme');
+ that.log.debug.ln('start parsing readme:', structure);
return that.findFile(structure)
.then(function(readme) {
- if (!readme) throw "No README file";
- if (!_.contains(that.files, readme.path)) throw "README file is ignored";
+ if (!readme) throw 'No README file';
+ if (!_.contains(that.files, readme.path)) throw 'README file is ignored';
that.readmeFile = readme.path;
that._defaultsStructure(that.readmeFile);
- that.log.debug.ln("readme located at", that.readmeFile);
+ that.log.debug.ln('readme located at', that.readmeFile);
return that.template.renderFile(that.readmeFile)
.then(function(content) {
return readme.parser.readme(content)
.fail(function(err) {
throw that.normError(err, {
- name: err.name || "Readme Parse Error",
+ name: err.name || 'Readme Parse Error',
fileName: that.readmeFile
});
});
@@ -393,8 +382,8 @@ Book.prototype.parseReadme = function() {
Book.prototype.parseLangs = function() {
var that = this;
- var structure = that.config.getStructure("langs");
- that.log.debug.ln("start parsing languages index:", structure);
+ var structure = that.config.getStructure('langs');
+ that.log.debug.ln('start parsing languages index:', structure);
return that.findFile(structure)
.then(function(langs) {
@@ -403,13 +392,13 @@ Book.prototype.parseLangs = function() {
that.langsFile = langs.path;
that._defaultsStructure(that.langsFile);
- that.log.debug.ln("languages index located at", that.langsFile);
+ that.log.debug.ln('languages index located at', that.langsFile);
return that.template.renderFile(that.langsFile)
.then(function(content) {
return langs.parser.langs(content)
.fail(function(err) {
throw that.normError(err, {
- name: err.name || "Langs Parse Error",
+ name: err.name || 'Langs Parse Error',
fileName: that.langsFile
});
});
@@ -424,29 +413,29 @@ Book.prototype.parseLangs = function() {
Book.prototype.parseSummary = function() {
var that = this;
- var structure = that.config.getStructure("summary");
- that.log.debug.ln("start parsing summary:", structure);
+ var structure = that.config.getStructure('summary');
+ that.log.debug.ln('start parsing summary:', structure);
return that.findFile(structure)
.then(function(summary) {
- if (!summary) throw "No SUMMARY file";
+ if (!summary) throw 'No SUMMARY file';
// Remove the summary from the list of files to parse
that.summaryFile = summary.path;
that._defaultsStructure(that.summaryFile);
that.files = _.without(that.files, that.summaryFile);
- that.log.debug.ln("summary located at", that.summaryFile);
+ that.log.debug.ln('summary located at', that.summaryFile);
return that.template.renderFile(that.summaryFile)
.then(function(content) {
return summary.parser.summary(content, {
entryPoint: that.readmeFile,
- entryPointTitle: that.i18n("SUMMARY_INTRODUCTION"),
+ entryPointTitle: that.i18n('SUMMARY_INTRODUCTION'),
files: that.files
})
.fail(function(err) {
throw that.normError(err, {
- name: err.name || "Summary Parse Error",
+ name: err.name || 'Summary Parse Error',
fileName: that.summaryFile
});
});
@@ -462,8 +451,8 @@ Book.prototype.parseSummary = function() {
Book.prototype.parseGlossary = function() {
var that = this;
- var structure = that.config.getStructure("glossary");
- that.log.debug.ln("start parsing glossary: ", structure);
+ var structure = that.config.getStructure('glossary');
+ that.log.debug.ln('start parsing glossary: ', structure);
return that.findFile(structure)
.then(function(glossary) {
@@ -474,13 +463,13 @@ Book.prototype.parseGlossary = function() {
that._defaultsStructure(that.glossaryFile);
that.files = _.without(that.files, that.glossaryFile);
- that.log.debug.ln("glossary located at", that.glossaryFile);
+ that.log.debug.ln('glossary located at', that.glossaryFile);
return that.template.renderFile(that.glossaryFile)
.then(function(content) {
return glossary.parser.glossary(content)
.fail(function(err) {
throw that.normError(err, {
- name: err.name || "Glossary Parse Error",
+ name: err.name || 'Glossary Parse Error',
fileName: that.glossaryFile
});
});
@@ -512,12 +501,12 @@ Book.prototype.parsePage = function(filename, options) {
});
};
- that.log.debug.ln("start parsing file", filename);
+ that.log.debug.ln('start parsing file', filename);
var extension = path.extname(filename);
var filetype = parsers.get(extension);
- if (!filetype) return Q.reject(new Error("Can't parse file: "+filename));
+ if (!filetype) return Q.reject(new Error('Can\'t parse file: '+filename));
// Type of parser used
page.type = filetype.name;
@@ -531,7 +520,7 @@ Book.prototype.parsePage = function(filename, options) {
// Progress in the book
page.progress = parseProgress(that.navigation, filename);
- that.log.debug.ln("render template", filename);
+ that.log.debug.ln('render template', filename);
// Read file content
return that.readFile(page.path)
@@ -558,7 +547,7 @@ Book.prototype.parsePage = function(filename, options) {
.then(function(content) {
page.content = content;
- that.log.debug.ln("use file parser", filetype.name, "for", filename);
+ that.log.debug.ln('use file parser', filetype.name, 'for', filename);
return filetype.page(page.content);
})
@@ -566,7 +555,7 @@ Book.prototype.parsePage = function(filename, options) {
.then(function(_page) {
return _.reduce(_page.sections, function(prev, section) {
return prev.then(function(_sections) {
- return that.template.postProcess(section.content || "")
+ return that.template.postProcess(section.content || '')
.then(function(content) {
section.content = content;
return _sections.concat([section]);
@@ -582,8 +571,8 @@ Book.prototype.parsePage = function(filename, options) {
convertImages: options.convertImages,
input: filename,
navigation: that.navigation,
- base: path.dirname(filename) || "./",
- output: path.dirname(filename) || "./",
+ base: path.dirname(filename) || './',
+ output: path.dirname(filename) || './',
glossary: that.glossary
});
})
@@ -595,7 +584,6 @@ Book.prototype.parsePage = function(filename, options) {
})
.then(function() {
- that.indexPage(page);
return page;
});
};
@@ -623,6 +611,24 @@ Book.prototype.findFile = function(filename) {
}, Q(null));
};
+// Format a string using a specific markup language
+Book.prototype.formatString = function(extension, content) {
+ return Q()
+ .then(function() {
+ var filetype = parsers.get(extension);
+ if (!filetype) throw new Error('Filetype doesn\'t exist: '+filetype);
+
+ return filetype.page(content);
+ })
+
+ // Merge sections
+ .then(function(page) {
+ return _.reduce(page.sections, function(content, section) {
+ return content + section.content;
+ }, '');
+ });
+};
+
// Check if a file exists in the book
Book.prototype.fileExists = function(filename) {
return fs.exists(
@@ -639,7 +645,7 @@ Book.prototype.fileIsInBook = function(filename) {
Book.prototype.readFile = function(filename) {
return fs.readFile(
this.resolve(filename),
- { encoding: "utf8" }
+ { encoding: 'utf8' }
);
};
@@ -653,28 +659,28 @@ Book.prototype.listAllFiles = function() {
var that = this;
return fs.list(this.root, {
- ignoreFiles: [".ignore", ".gitignore", ".bookignore"],
+ ignoreFiles: ['.ignore', '.gitignore', '.bookignore'],
ignoreRules: [
// Skip Git stuff
- ".git/",
- ".gitignore",
+ '.git/',
+ '.gitignore',
// Skip OS X meta data
- ".DS_Store",
+ '.DS_Store',
// Skip stuff installed by plugins
- "node_modules",
+ 'node_modules',
// Skip book outputs
- "_book",
- "*.pdf",
- "*.epub",
- "*.mobi",
+ '_book',
+ '*.pdf',
+ '*.epub',
+ '*.mobi',
// Skip config files
- ".ignore",
- ".bookignore",
- "book.json",
+ '.ignore',
+ '.bookignore',
+ 'book.json',
]
})
.then(function(_files) {
@@ -693,7 +699,7 @@ Book.prototype.parentRoot = function() {
return this.root;
};
-// Return true if it"s a sub-book
+// Return true if it's a sub-book
Book.prototype.isSubBook = function() {
return !!this.parent;
};
@@ -722,13 +728,13 @@ Book.prototype.relative = function(p) {
// Normalize a path to .html and convert README -> index
Book.prototype.contentPath = function(link) {
if (
- path.basename(link, path.extname(link)) == "README" ||
+ path.basename(link, path.extname(link)) == 'README' ||
link == this.readmeFile
) {
- link = path.join(path.dirname(link), "index"+path.extname(link));
+ link = path.join(path.dirname(link), 'index'+path.extname(link));
}
- link = links.changeExtension(link, ".html");
+ link = links.changeExtension(link, '.html');
return link;
};
@@ -737,40 +743,15 @@ Book.prototype.contentLink = function(link) {
return links.normalize(this.contentPath(link));
};
-// Index a page into the search index
-Book.prototype.indexPage = function(page) {
- var nav = this.navigation[page.path];
- if (!nav || !this.searchIndexEnabled) return;
-
- this.log.debug.ln("index page", page.path);
-
- // Extract text from the page
- var text = pageUtil.extractText(page.sections);
-
- // Limit size of index (to avoid #941)
- this.searchIndexSize = this.searchIndexSize + text.length;
- if (this.searchIndexSize > this.config.get('search.maxIndexSize')) {
- this.log.warn.ln("search index is too big, indexing is now disabled");
- this.searchIndexEnabled = false;
- return;
- }
-
- this.searchIndex.add({
- url: this.contentLink(page.path),
- title: nav.title,
- body: text
- });
-};
-
// Default structure paths to an extension
Book.prototype._defaultsStructure = function(filename) {
var that = this;
var extension = path.extname(filename);
- that.readmeFile = that.readmeFile || that.config.getStructure("readme")+extension;
- that.summaryFile = that.summaryFile || that.config.getStructure("summary")+extension;
- that.glossaryFile = that.glossaryFile || that.config.getStructure("glossary")+extension;
- that.langsFile = that.langsFile || that.config.getStructure("langs")+extension;
+ that.readmeFile = that.readmeFile || that.config.getStructure('readme')+extension;
+ that.summaryFile = that.summaryFile || that.config.getStructure('summary')+extension;
+ that.glossaryFile = that.glossaryFile || that.config.getStructure('glossary')+extension;
+ that.langsFile = that.langsFile || that.config.getStructure('langs')+extension;
};
// Change output path
@@ -803,87 +784,13 @@ Book.prototype.normError = function(err, opts, defs) {
err.toString = function() {
var attributes = [];
- if (this.fileName) attributes.push("In file \""+this.fileName+"\"");
- if (this.lineNumber) attributes.push("Line "+this.lineNumber);
- if (this.columnNumber) attributes.push("Column "+this.columnNumber);
- return (this.name || "Error")+": "+this.message+((attributes.length > 0)? " ("+attributes.join(", ")+")" : "");
+ if (this.fileName) attributes.push('In file \''+this.fileName+'\'');
+ if (this.lineNumber) attributes.push('Line '+this.lineNumber);
+ if (this.columnNumber) attributes.push('Column '+this.columnNumber);
+ return (this.name || 'Error')+': '+this.message+((attributes.length > 0)? ' ('+attributes.join(', ')+')' : '');
};
return err;
};
-// Init and return a book
-Book.init = function(root, opts) {
- var book = new Book(root, opts);
- var extensionToUse = ".md";
-
- var chaptersPaths = function(chapters) {
- return _.reduce(chapters || [], function(accu, chapter) {
- var o = {
- title: chapter.title
- };
- if (chapter.path) o.path = chapter.path;
-
- return accu.concat(
- [o].concat(chaptersPaths(chapter.articles))
- );
- }, []);
- };
-
- book.log.info.ln("init book at", root);
- return fs.mkdirp(root)
- .then(function() {
- book.log.info.ln("detect structure from SUMMARY (if it exists)");
- return book.parseSummary();
- })
- .fail(function() {
- return Q();
- })
- .then(function() {
- var summary = book.summaryFile || "SUMMARY.md";
- var chapters = book.summary.chapters || [];
- extensionToUse = path.extname(summary);
-
- if (chapters.length === 0) {
- chapters = [
- {
- title: "Summary",
- path: "SUMMARY"+extensionToUse
- },
- {
- title: "Introduction",
- path: "README"+extensionToUse
- }
- ];
- }
-
- return Q(chaptersPaths(chapters));
- })
- .then(function(chapters) {
- // Create files that don"t exist
- return Q.all(_.map(chapters, function(chapter) {
- if (!chapter.path) return Q();
- var absolutePath = path.resolve(book.root, chapter.path);
-
- return fs.exists(absolutePath)
- .then(function(exists) {
- if(exists) {
- book.log.info.ln("found", chapter.path);
- return;
- } else {
- book.log.info.ln("create", chapter.path);
- }
-
- return fs.mkdirp(path.dirname(absolutePath))
- .then(function() {
- return fs.writeFile(absolutePath, "# "+chapter.title+"\n");
- });
- });
- }));
- })
- .then(function() {
- book.log.info.ln("initialization is finished");
- });
-};
-
module.exports= Book;
diff --git a/lib/configuration.js b/lib/configuration.js
index c8b15b8..3b6b47b 100644
--- a/lib/configuration.js
+++ b/lib/configuration.js
@@ -1,13 +1,13 @@
-var _ = require("lodash");
-var Q = require("q");
-var path = require("path");
-var semver = require("semver");
+var _ = require('lodash');
+var Q = require('q');
+var path = require('path');
+var semver = require('semver');
-var pkg = require("../package.json");
-var i18n = require("./utils/i18n");
+var pkg = require('../package.json');
+var i18n = require('./utils/i18n');
// Default plugins added to each books
-var DEFAULT_PLUGINS = ["highlight"];
+var DEFAULT_PLUGINS = ['highlight', 'search', 'sharing', 'fontsettings'];
// Check if a plugin is a default plugin
// Plugin should be in the list
@@ -26,29 +26,29 @@ function isDefaultPlugin(name, version) {
// Normalize a list of plugins to use
function normalizePluginsList(plugins, addDefaults) {
// Normalize list to an array
- plugins = _.isString(plugins) ? plugins.split(",") : (plugins || []);
+ plugins = _.isString(plugins) ? plugins.split(',') : (plugins || []);
// Remove empty parts
plugins = _.compact(plugins);
- // Divide as {name, version} to handle format like "myplugin@1.0.0"
+ // Divide as {name, version} to handle format like 'myplugin@1.0.0'
plugins = _.map(plugins, function(plugin) {
if (plugin.name) return plugin;
- var parts = plugin.split("@");
+ var parts = plugin.split('@');
var name = parts[0];
var version = parts[1];
return {
- "name": name,
- "version": version, // optional
- "isDefault": isDefaultPlugin(name, version)
+ 'name': name,
+ 'version': version, // optional
+ 'isDefault': isDefaultPlugin(name, version)
};
});
// List plugins to remove
var toremove = _.chain(plugins)
.filter(function(plugin) {
- return plugin.name.length > 0 && plugin.name[0] == "-";
+ return plugin.name.length > 0 && plugin.name[0] == '-';
})
.map(function(plugin) {
return plugin.name.slice(1);
@@ -63,15 +63,15 @@ function normalizePluginsList(plugins, addDefaults) {
}
plugins.push({
- "name": plugin,
- "isDefault": true
+ 'name': plugin,
+ 'isDefault': true
});
});
}
// Remove plugin that start with '-'
plugins = _.filter(plugins, function(plugin) {
- return !_.contains(toremove, plugin.name) && !(plugin.name.length > 0 && plugin.name[0] == "-");
+ return !_.contains(toremove, plugin.name) && !(plugin.name.length > 0 && plugin.name[0] == '-');
});
// Remove duplicates
@@ -89,21 +89,21 @@ var Configuration = function(book, options) {
this.options = _.merge(this.options, options || {});
// options.input == book.root
- Object.defineProperty(this.options, "input", {
+ Object.defineProperty(this.options, 'input', {
get: function () {
return that.book.root;
}
});
// options.originalInput == book.parent.root
- Object.defineProperty(this.options, "originalInput", {
+ Object.defineProperty(this.options, 'originalInput', {
get: function () {
return that.book.parent? that.book.parent.root : undefined;
}
});
// options.originalOutput == book.parent.options.output
- Object.defineProperty(this.options, "originalOutput", {
+ Object.defineProperty(this.options, 'originalOutput', {
get: function () {
return that.book.parent? that.book.parent.options.output : undefined;
}
@@ -129,7 +129,7 @@ Configuration.prototype.load = function() {
_config = require(configPath);
that.options = _.merge(
that.options,
- _.omit(_config, "configFile", "defaultsPlugins", "generator", "extension")
+ _.omit(_config, 'configFile', 'defaultsPlugins', 'generator', 'extension')
);
}
catch(err) {
@@ -140,18 +140,18 @@ Configuration.prototype.load = function() {
.then(function() {
if (!that.book.isSubBook()) {
if (!semver.satisfies(pkg.version, that.options.gitbook)) {
- throw new Error("GitBook version doesn't satisfy version required by the book: "+that.options.gitbook);
+ throw new Error('GitBook version doesn\'t satisfy version required by the book: '+that.options.gitbook);
}
- if (that.options.gitbook != "*" && !semver.satisfies(semver.inc(pkg.version, "patch"), that.options.gitbook)) {
- that.book.log.warn.ln("gitbook version specified in your book.json might be too strict for future patches, \""+(_.first(pkg.version.split("."))+".x.x")+"\" is more adequate");
+ if (that.options.gitbook != '*' && !semver.satisfies(semver.inc(pkg.version, 'patch'), that.options.gitbook)) {
+ that.book.log.warn.ln('gitbook version specified in your book.json might be too strict for future patches, \''+(_.first(pkg.version.split('.'))+'.x.x')+'\' is more adequate');
}
}
- that.options.output = path.resolve(that.options.output || that.book.resolve("_book"));
+ that.options.output = path.resolve(that.options.output || that.book.resolve('_book'));
that.options.plugins = normalizePluginsList(that.options.plugins);
- that.options.defaultsPlugins = normalizePluginsList(that.options.defaultsPlugins || "", false);
+ that.options.defaultsPlugins = normalizePluginsList(that.options.defaultsPlugins || '', false);
that.options.plugins = _.union(that.options.plugins, that.options.defaultsPlugins);
- that.options.plugins = _.uniq(that.options.plugins, "name");
+ that.options.plugins = _.uniq(that.options.plugins, 'name');
// Default value for text direction (from language)
if (!that.options.direction) {
@@ -170,7 +170,7 @@ Configuration.prototype.extend = function(options) {
// Get structure file
Configuration.prototype.getStructure = function(name) {
- return this.options.structure[name].split(".").slice(0, -1).join(".");
+ return this.options.structure[name].split('.').slice(0, -1).join('.');
};
// Return normalized language
@@ -185,120 +185,109 @@ Configuration.prototype.get = function(key, def) {
// Default configuration
Configuration.DEFAULT = {
- // Options that can"t be extend
- "configFile": "book",
- "generator": "website",
- "extension": null,
+ // 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,
+ 'title': null,
+ 'description': null,
+ 'isbn': null,
+ 'language': 'en',
+ 'direction': null,
+ 'author': null,
// version of gitbook to use
- "gitbook": "*",
-
- // Search index
- "search": {
- "maxIndexSize": 1000000
- },
+ 'gitbook': '*',
// Structure
- "structure": {
- "langs": "LANGS.md",
- "readme": "README.md",
- "glossary": "GLOSSARY.md",
- "summary": "SUMMARY.md"
+ '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"
+ '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": [],
+ // Plugins list, can contain '-name' for removing default plugins
+ 'plugins': [],
// Global configuration for plugins
- "pluginsConfig": {
- "fontSettings": {
- "theme": null, //"sepia", "night" or "white",
- "family": "sans",// "serif" or "sans",
- "size": 2 // 1 - 4
- }
- },
+ 'pluginsConfig': {},
// Variables for templating
- "variables": {},
+ 'variables': {},
// Set another theme with your own layout
- // It"s recommended to use plugins or add more options for default theme, though
+ // 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"),
+ 'theme': path.resolve(__dirname, '../theme'),
// Links in template (null: default, false: remove, string: new value)
- "links": {
+ 'links': {
// Custom links at top of sidebar
- "sidebar": {
- //"Custom link name": "https://customlink.com"
+ 'sidebar': {
+ // 'Custom link name': 'https://customlink.com'
},
// Sharing links
- "sharing": {
- "google": null,
- "facebook": null,
- "twitter": null,
- "weibo": null,
- "all": null
+ 'sharing': {
+ 'google': null,
+ 'facebook': null,
+ 'twitter': null,
+ 'weibo': null,
+ 'all': null
}
},
// Options for PDF generation
- "pdf": {
+ 'pdf': {
// Add toc at the end of the file
- "toc": true,
+ 'toc': true,
// Add page numbers to the bottom of every page
- "pageNumbers": false,
+ 'pageNumbers': false,
// Font size for the file content
- "fontSize": 12,
+ '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",
+ 'paperSize': 'a4',
// How to mark detected chapters.
- // Choices are “pagebreak”, “rule”, "both" or “none”.
- "chapterMark" : "pagebreak",
+ // 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": "/",
+ // To disable use the expression: '/'
+ 'pageBreaksBefore': '/',
// Margin (in pts)
// Note: 72 pts equals 1 inch
- "margin": {
- "right": 62,
- "left": 62,
- "top": 56,
- "bottom": 56
+ 'margin': {
+ 'right': 62,
+ 'left': 62,
+ 'top': 56,
+ 'bottom': 56
},
- //Header HTML template. Available variables: _PAGENUM_, _TITLE_, _AUTHOR_ and _SECTION_.
- "headerTemplate": "",
+ // Header HTML template. Available variables: _PAGENUM_, _TITLE_, _AUTHOR_ and _SECTION_.
+ 'headerTemplate': '',
- //Footer HTML template. Available variables: _PAGENUM_, _TITLE_, _AUTHOR_ and _SECTION_.
- "footerTemplate": ""
+ // Footer HTML template. Available variables: _PAGENUM_, _TITLE_, _AUTHOR_ and _SECTION_.
+ 'footerTemplate': ''
}
};
diff --git a/lib/generators/website.js b/lib/generators/website.js
index 4bde473..e1a3cce 100644
--- a/lib/generators/website.js
+++ b/lib/generators/website.js
@@ -112,7 +112,6 @@ Generator.prototype.finish = function() {
return this.copyAssets()
.then(this.copyCover)
.then(this.writeGlossary)
- .then(this.writeSearchIndex)
.then(this.writeLangsIndex);
};
@@ -167,14 +166,6 @@ Generator.prototype.writeGlossary = function() {
return this._writeTemplate(this.templates.glossary, {}, path.join(this.options.output, "GLOSSARY.html"));
};
-// Write the search index
-Generator.prototype.writeSearchIndex = function() {
- return fs.writeFile(
- path.join(this.options.output, "search_index.json"),
- JSON.stringify(this.book.searchIndex)
- );
-};
-
// Convert a page into a normalized data set
Generator.prototype.normalizePage = function(page) {
var that = this;
diff --git a/lib/index.js b/lib/index.js
index 89d5d3c..5a93a54 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -1,50 +1,56 @@
-var Q = require("q");
-var _ = require("lodash");
-var path = require("path");
-var tinylr = require("tiny-lr");
-var color = require("bash-color");
-
-var Book = require("./book");
-var Server = require("./utils/server");
-var stringUtils = require("./utils/string");
-var watch = require("./utils/watch");
-var logger = require("./utils/logger");
+/*eslint no-console: 0*/
+
+var Q = require('q');
+var _ = require('lodash');
+var path = require('path');
+var tinylr = require('tiny-lr');
+var color = require('bash-color');
+
+var Book = require('./book');
+var initBook = require('./init');
+var Server = require('./utils/server');
+var stringUtils = require('./utils/string');
+var watch = require('./utils/watch');
+var logger = require('./utils/logger');
var LOG_OPTION = {
- name: "log",
- description: "Minimum log level to display",
+ name: 'log',
+ description: 'Minimum log level to display',
values: _.chain(logger.LEVELS).keys().map(stringUtils.toLowerCase).value(),
- defaults: "info"
+ defaults: 'info'
};
var FORMAT_OPTION = {
- name: "format",
- description: "Format to build to",
- values: ["website", "json", "ebook"],
- defaults: "website"
+ name: 'format',
+ description: 'Format to build to',
+ values: ['website', 'json', 'ebook'],
+ defaults: 'website'
};
+// Export init to gitbook library
+Book.init = initBook;
+
module.exports = {
Book: Book,
LOG_LEVELS: logger.LEVELS,
commands: _.flatten([
{
- name: "build [book] [output]",
- description: "build a book",
+ name: 'build [book] [output]',
+ description: 'build a book',
options: [
FORMAT_OPTION,
LOG_OPTION
],
exec: function(args, kwargs) {
var input = args[0] || process.cwd();
- var output = args[1] || path.join(input, "_book");
+ var output = args[1] || path.join(input, '_book');
var book = new Book(input, _.extend({}, {
- "config": {
- "output": output
+ 'config': {
+ 'output': output
},
- "logLevel": kwargs.log
+ 'logLevel': kwargs.log
}));
return book.parse()
@@ -52,16 +58,16 @@ module.exports = {
return book.generate(kwargs.format);
})
.then(function(){
- console.log("");
- console.log(color.green("Done, without error"));
+ console.log('');
+ console.log(color.green('Done, without error'));
});
}
},
- _.map(["pdf", "epub", "mobi"], function(ebookType) {
+ _.map(['pdf', 'epub', 'mobi'], function(ebookType) {
return {
- name: ebookType+" [book] [output]",
- description: "build a book to "+ebookType,
+ name: ebookType+' [book] [output]',
+ description: 'build a book to '+ebookType,
options: [
LOG_OPTION
],
@@ -70,7 +76,7 @@ module.exports = {
var output = args[1];
var book = new Book(input, _.extend({}, {
- "logLevel": kwargs.log
+ 'logLevel': kwargs.log
}));
return book.parse()
@@ -80,30 +86,30 @@ module.exports = {
});
})
.then(function(){
- console.log("");
- console.log(color.green("Done, without error"));
+ console.log('');
+ console.log(color.green('Done, without error'));
});
}
};
}),
{
- name: "serve [book]",
- description: "Build then serve a gitbook from a directory",
+ name: 'serve [book]',
+ description: 'Build then serve a gitbook from a directory',
options: [
{
- name: "port",
- description: "Port for server to listen on",
+ name: 'port',
+ description: 'Port for server to listen on',
defaults: 4000
},
{
- name: "lrport",
- description: "Port for livereload server to listen on",
+ name: 'lrport',
+ description: 'Port for livereload server to listen on',
defaults: 35729
},
{
- name: "watch",
- description: "Enable/disable file watcher",
+ name: 'watch',
+ description: 'Enable/disable file watcher',
defaults: true
},
FORMAT_OPTION,
@@ -118,15 +124,15 @@ module.exports = {
var lrPath;
var generate = function() {
- if (server.isRunning()) console.log("Stopping server");
+ if (server.isRunning()) console.log('Stopping server');
return server.stop()
.then(function() {
var book = new Book(input, _.extend({}, {
- "config": {
- "defaultsPlugins": ["livereload"]
+ 'config': {
+ 'defaultsPlugins': ['livereload']
},
- "logLevel": kwargs.log
+ 'logLevel': kwargs.log
}));
return book.parse()
@@ -137,10 +143,10 @@ module.exports = {
})
.then(function(book) {
console.log();
- console.log("Starting server ...");
+ console.log('Starting server ...');
return server.start(book.options.output, kwargs.port)
.then(function() {
- console.log("Serving book on http://localhost:"+kwargs.port);
+ console.log('Serving book on http://localhost:'+kwargs.port);
if (lrPath) {
// trigger livereload
@@ -157,8 +163,8 @@ module.exports = {
.then(function(filepath) {
// set livereload path
lrPath = filepath;
- console.log("Restart after change in file", filepath);
- console.log("");
+ console.log('Restart after change in file', filepath);
+ console.log('');
return generate();
});
});
@@ -167,17 +173,17 @@ module.exports = {
return Q.nfcall(lrServer.listen.bind(lrServer), kwargs.lrport)
.then(function() {
- console.log("Live reload server started on port:", kwargs.lrport);
- console.log("Press CTRL+C to quit ...");
- console.log("");
+ console.log('Live reload server started on port:', kwargs.lrport);
+ console.log('Press CTRL+C to quit ...');
+ console.log('');
return generate();
});
}
},
{
- name: "install [book]",
- description: "install plugins dependencies",
+ name: 'install [book]',
+ description: 'install plugins dependencies',
exec: function(args) {
var input = args[0] || process.cwd();
@@ -188,20 +194,20 @@ module.exports = {
return book.plugins.install();
})
.then(function(){
- console.log("");
- console.log(color.green("Done, without error"));
+ console.log('');
+ console.log(color.green('Done, without error'));
});
}
},
{
- name: "init [directory]",
- description: "create files and folders based on contents of SUMMARY.md",
+ name: 'init [directory]',
+ description: 'create files and folders based on contents of SUMMARY.md',
exec: function(args) {
- return Book.init(args[0] || process.cwd())
+ return initBook(args[0] || process.cwd())
.then(function(){
- console.log("");
- console.log(color.green("Done, without error"));
+ console.log('');
+ console.log(color.green('Done, without error'));
});
}
}
diff --git a/lib/init.js b/lib/init.js
new file mode 100644
index 0000000..2fc8016
--- /dev/null
+++ b/lib/init.js
@@ -0,0 +1,83 @@
+var _ = require('lodash');
+var Q = require('q');
+var path = require('path');
+
+var Book = require('./book');
+var fs = require('./utils/fs');
+
+// Initialize folder structure for a book
+// Read SUMMARY to created the right chapter
+function initBook(root, opts) {
+ var book = new Book(root, opts);
+ var extensionToUse = '.md';
+
+ var chaptersPaths = function(chapters) {
+ return _.reduce(chapters || [], function(accu, chapter) {
+ var o = {
+ title: chapter.title
+ };
+ if (chapter.path) o.path = chapter.path;
+
+ return accu.concat(
+ [o].concat(chaptersPaths(chapter.articles))
+ );
+ }, []);
+ };
+
+ book.log.info.ln('init book at', root);
+ return fs.mkdirp(root)
+ .then(function() {
+ book.log.info.ln('detect structure from SUMMARY (if it exists)');
+ return book.parseSummary();
+ })
+ .fail(function() {
+ return Q();
+ })
+ .then(function() {
+ var summary = book.summaryFile || 'SUMMARY.md';
+ var chapters = book.summary.chapters || [];
+ extensionToUse = path.extname(summary);
+
+ if (chapters.length === 0) {
+ chapters = [
+ {
+ title: 'Summary',
+ path: 'SUMMARY'+extensionToUse
+ },
+ {
+ title: 'Introduction',
+ path: 'README'+extensionToUse
+ }
+ ];
+ }
+
+ return Q(chaptersPaths(chapters));
+ })
+ .then(function(chapters) {
+ // Create files that don't exist
+ return Q.all(_.map(chapters, function(chapter) {
+ if (!chapter.path) return Q();
+ var absolutePath = path.resolve(book.root, chapter.path);
+
+ return fs.exists(absolutePath)
+ .then(function(exists) {
+ if(exists) {
+ book.log.info.ln('found', chapter.path);
+ return;
+ } else {
+ book.log.info.ln('create', chapter.path);
+ }
+
+ return fs.mkdirp(path.dirname(absolutePath))
+ .then(function() {
+ return fs.writeFile(absolutePath, '# '+chapter.title+'\n');
+ });
+ });
+ }));
+ })
+ .then(function() {
+ book.log.info.ln('initialization is finished');
+ });
+}
+
+module.exports = initBook;
diff --git a/lib/pluginslist.js b/lib/pluginslist.js
index 80e1d3e..e4594d6 100644
--- a/lib/pluginslist.js
+++ b/lib/pluginslist.js
@@ -1,14 +1,14 @@
-var _ = require("lodash");
-var Q = require("q");
-var npmi = require("npmi");
-var npm = require("npm");
-var semver = require("semver");
+var _ = require('lodash');
+var Q = require('q');
+var npmi = require('npmi');
+var npm = require('npm');
+var semver = require('semver');
-var Plugin = require("./plugin");
-var pkg = require("../package.json");
+var Plugin = require('./plugin');
+var pkg = require('../package.json');
var initNPM = _.memoize(function() {
- return Q.nfcall(npm.load, { silent: true, loglevel: "silent" });
+ return Q.nfcall(npm.load, { silent: true, loglevel: 'silent' });
});
@@ -23,7 +23,7 @@ var PluginsList = function(book, plugins) {
this.failed = [];
// Namespaces
- this.namespaces = _.chain(["website", "ebook"])
+ this.namespaces = _.chain(['website', 'ebook'])
.map(function(namespace) {
return [
namespace,
@@ -66,7 +66,7 @@ PluginsList.prototype.load = function(plugin) {
if (_.isObject(plugin) && !(plugin instanceof Plugin)) plugin = plugin.name;
if (_.isString(plugin)) plugin = new Plugin(this.book, plugin);
- that.log.info("load plugin", plugin.name, "....");
+ that.log.info('load plugin', plugin.name, '....');
if (!plugin.isValid()) {
that.log.info.fail();
that.failed.push(plugin.name);
@@ -135,7 +135,7 @@ PluginsList.prototype.html = function(namespace, tag, context, options) {
var htmlSnippets = this.namespaces[namespace].html[tag];
return _.map(htmlSnippets || [], function(code) {
return code.call(context, options);
- }).join("\n");
+ }).join('\n');
};
// Return a resources map for a namespace
@@ -153,10 +153,10 @@ PluginsList.prototype.install = function() {
});
// Install plugins one by one
- that.book.log.info.ln(plugins.length+" plugins to install");
+ that.book.log.info.ln(plugins.length+' plugins to install');
return _.reduce(plugins, function(prev, plugin) {
return prev.then(function() {
- var fullname = "gitbook-plugin-"+plugin.name;
+ var fullname = 'gitbook-plugin-'+plugin.name;
return Q()
@@ -164,10 +164,10 @@ PluginsList.prototype.install = function() {
.then(function() {
if (plugin.version) return plugin.version;
- that.book.log.info.ln("No version specified, resolve plugin", plugin.name);
+ that.book.log.info.ln('No version specified, resolve plugin', plugin.name);
return initNPM()
.then(function() {
- return Q.nfcall(npm.commands.view, [fullname+"@*", "engines"], true);
+ return Q.nfcall(npm.commands.view, [fullname+'@*', 'engines'], true);
})
.then(function(versions) {
return _.chain(versions)
@@ -184,7 +184,7 @@ PluginsList.prototype.install = function() {
.sort(function(v1, v2) {
return semver.lt(v1.version, v2.version)? 1 : -1;
})
- .pluck("version")
+ .pluck('version')
.first()
.value();
});
@@ -193,23 +193,23 @@ PluginsList.prototype.install = function() {
// Install the plugin with the resolved version
.then(function(version) {
if (!version) {
- throw "Found no satisfactory version for plugin "+plugin.name;
+ throw 'Found no satisfactory version for plugin '+plugin.name;
}
- that.book.log.info.ln("install plugin", plugin.name, "from npm ("+fullname+") with version", version);
+ that.book.log.info.ln('install plugin', plugin.name, 'from npm ('+fullname+') with version', version);
return Q.nfcall(npmi, {
- "name": fullname,
- "version": version,
- "path": that.book.root,
- "npmLoad": {
- "loglevel": "silent",
- "loaded": true,
- "prefix": that.book.root
+ 'name': fullname,
+ 'version': version,
+ 'path': that.book.root,
+ 'npmLoad': {
+ 'loglevel': 'silent',
+ 'loaded': true,
+ 'prefix': that.book.root
}
});
})
.then(function() {
- that.book.log.info.ok("plugin", plugin.name, "installed with success");
+ that.book.log.info.ok('plugin', plugin.name, 'installed with success');
});
});
}, Q());
diff --git a/lib/utils/page.js b/lib/utils/page.js
index 2c57421..8adce8f 100644
--- a/lib/utils/page.js
+++ b/lib/utils/page.js
@@ -1,18 +1,18 @@
-var Q = require("q");
-var _ = require("lodash");
-var url = require("url");
-var path = require("path");
-var cheerio = require("cheerio");
-var domSerializer = require("dom-serializer");
-var request = require("request");
-var crc = require("crc");
-
-var links = require("./links");
-var imgUtils = require("./images");
-var fs = require("./fs");
-var batch = require("./batch");
-
-var parsableExtensions = require("gitbook-parsers").extensions;
+var Q = require('q');
+var _ = require('lodash');
+var url = require('url');
+var path = require('path');
+var cheerio = require('cheerio');
+var domSerializer = require('dom-serializer');
+var request = require('request');
+var crc = require('crc');
+
+var links = require('./links');
+var imgUtils = require('./images');
+var fs = require('./fs');
+var batch = require('./batch');
+
+var parsableExtensions = require('gitbook-parsers').extensions;
// Render a cheerio dom as html
var renderDom = function($, dom, options) {
@@ -59,7 +59,7 @@ function replaceText($, el, search, replace, text_only ) {
// robust way.
$(node).before( new_val );
- // Don"t remove the node yet, or the loop will lose its place.
+ // Don't remove the node yet, or the loop will lose its place.
remove.push( node );
} else {
// The new value contains no HTML, so it can be set in this
@@ -79,7 +79,7 @@ function replaceText($, el, search, replace, text_only ) {
}
function pregQuote( str ) {
- return (str+"").replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1");
+ return (str+'').replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, '\\$1');
}
@@ -101,23 +101,23 @@ function normalizeHtml(src, options) {
// Find svg images to extract and process
if (options.convertImages) {
- $("svg").each(function() {
+ $('svg').each(function() {
var content = renderDom($, $(this));
- var svgId = _.uniqueId("svg");
- var dest = svgId+".svg";
+ var svgId = _.uniqueId('svg');
+ var dest = svgId+'.svg';
// Generate filename
- dest = "/"+fs.getUniqueFilename(outputRoot, dest);
+ dest = '/'+fs.getUniqueFilename(outputRoot, dest);
- svgContent[dest] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+content;
- $(this).replaceWith($("<img>").attr("src", dest));
+ svgContent[dest] = '<?xml version="1.0" encoding="UTF-8"?>'+content;
+ $(this).replaceWith($('<img>').attr('src', dest));
});
}
// Find images to normalize
- $("img").each(function() {
+ $('img').each(function() {
var origin;
- var src = $(this).attr("src");
+ var src = $(this).attr('src');
if (!src) return;
var isExternal = links.isExternal(src);
@@ -132,13 +132,13 @@ function normalizeHtml(src, options) {
// If image is external and ebook, then downlaod the images
if (isExternal) {
origin = src;
- src = "/"+crc.crc32(origin).toString(16)+path.extname(origin);
+ src = '/'+crc.crc32(origin).toString(16)+path.extname(origin);
src = links.toAbsolute(src, options.base, options.output);
isExternal = false;
}
var ext = path.extname(src);
- var srcAbs = links.join("/", options.base, src);
+ var srcAbs = links.join('/', options.base, src);
// Test image extension
if (_.contains(imgUtils.INVALID, ext)) {
@@ -147,29 +147,29 @@ function normalizeHtml(src, options) {
src = imgConversionCache[outputRoot][srcAbs];
} else {
// Not converted yet
- var dest = "";
+ var dest = '';
// Replace extension
- dest = links.join(path.dirname(srcAbs), path.basename(srcAbs, ext)+".png");
- dest = dest[0] == "/"? dest.slice(1) : dest;
+ dest = links.join(path.dirname(srcAbs), path.basename(srcAbs, ext)+'.png');
+ dest = dest[0] == '/'? dest.slice(1) : dest;
- // Get a name that doesn"t exists
+ // Get a name that doesn't exists
dest = fs.getUniqueFilename(outputRoot, dest);
- options.book.log.debug.ln("detect invalid image (will be converted to png):", srcAbs);
+ options.book.log.debug.ln('detect invalid image (will be converted to png):', srcAbs);
// Add to cache
- imgConversionCache[outputRoot][srcAbs] = "/"+dest;
+ imgConversionCache[outputRoot][srcAbs] = '/'+dest;
// Push to convert
toConvert.push({
origin: origin,
content: svgContent[srcAbs],
- source: isExternal? srcAbs : path.join("./", srcAbs),
- dest: path.join("./", dest)
+ source: isExternal? srcAbs : path.join('./', srcAbs),
+ dest: path.join('./', dest)
});
- src = links.join("/", dest);
+ src = links.join('/', dest);
}
// Reset as relative to output
@@ -180,17 +180,17 @@ function normalizeHtml(src, options) {
// Need to downlaod image
toConvert.push({
origin: origin,
- source: path.join("./", srcAbs)
+ source: path.join('./', srcAbs)
});
}
}
- $(this).attr("src", src);
+ $(this).attr('src', src);
});
// Normalize links
- $("a").each(function() {
- var href = $(this).attr("href");
+ $('a').each(function() {
+ var href = $(this).attr('href');
if (!href) return;
if (links.isAnchor(href)) {
@@ -198,7 +198,7 @@ function normalizeHtml(src, options) {
} else if (links.isRelative(href)) {
var parts = url.parse(href);
var absolutePath = links.join(options.base, parts.pathname);
- var anchor = parts.hash || "";
+ var anchor = parts.hash || '';
// If is in navigation relative: transform as content
@@ -209,33 +209,33 @@ function normalizeHtml(src, options) {
// If md/adoc/rst files is not in summary
// or for ebook, signal all files that are outside the summary
else if (_.contains(parsableExtensions, path.extname(absolutePath)) ||
- _.contains(["epub", "pdf", "mobi"], options.book.options.generator)) {
- options.book.log.warn.ln("page", options.input, "contains an hyperlink to resource outside spine \""+href+"\"");
+ _.contains(['epub', 'pdf', 'mobi'], options.book.options.generator)) {
+ options.book.log.warn.ln('page', options.input, 'contains an hyperlink to resource outside spine \''+href+'\'');
}
// Transform as absolute
- href = links.toAbsolute("/"+absolutePath, options.base, options.output)+anchor;
+ href = links.toAbsolute('/'+absolutePath, options.base, options.output)+anchor;
} else {
// External links
- $(this).attr("target", "_blank");
+ $(this).attr('target', '_blank');
}
// Transform extension
- $(this).attr("href", href);
+ $(this).attr('href', href);
});
// Highlight code blocks
- $("code").each(function() {
+ $('code').each(function() {
// Normalize language
var lang = _.chain(
- ($(this).attr("class") || "").split(" ")
+ ($(this).attr('class') || '').split(' ')
)
.map(function(cl) {
// Markdown
- if (cl.search("lang-") === 0) return cl.slice("lang-".length);
+ if (cl.search('lang-') === 0) return cl.slice('lang-'.length);
// Asciidoc
- if (cl.search("language-") === 0) return cl.slice("language-".length);
+ if (cl.search('language-') === 0) return cl.slice('language-'.length);
return null;
})
@@ -244,7 +244,7 @@ function normalizeHtml(src, options) {
.value();
var source = $(this).text();
- var blk = options.book.template.applyBlock("code", {
+ var blk = options.book.template.applyBlock('code', {
body: source,
kwargs: {
language: lang
@@ -261,12 +261,12 @@ function normalizeHtml(src, options) {
});
_.each(glossary, function(term) {
- var r = new RegExp( "\\b(" + pregQuote(term.name.toLowerCase()) + ")\\b" , "gi" );
+ var r = new RegExp( '\\b(' + pregQuote(term.name.toLowerCase()) + ')\\b' , 'gi' );
var includedInFiles = false;
- $("*").each(function() {
+ $('*').each(function() {
// Ignore codeblocks
- if (_.contains(["code", "pre", "a"], this.name.toLowerCase())) return;
+ if (_.contains(['code', 'pre', 'a'], this.name.toLowerCase())) return;
replaceText($, this, r, function(match) {
// Add to files index in glossary
@@ -275,7 +275,7 @@ function normalizeHtml(src, options) {
term.files = term.files || [];
term.files.push(options.navigation[options.input]);
}
- return "<a href=\""+links.toAbsolute("/GLOSSARY.html", options.base, options.output) + "#" + term.id+"\" class=\"glossary-term\" title=\""+_.escape(term.description)+"\">"+match+"</a>";
+ return '<a href=\''+links.toAbsolute('/GLOSSARY.html', options.base, options.output) + '#' + term.id+'\' class=\'glossary-term\' title=\''+_.escape(term.description)+'\'>'+match+'</a>';
});
});
});
@@ -291,7 +291,7 @@ function convertImages(images, options) {
if (!options.convertImages) return Q();
var downloaded = [];
- options.book.log.debug.ln("convert ", images.length, "images to png");
+ options.book.log.debug.ln('convert ', images.length, 'images to png');
return batch.execEach(images, {
max: 100,
@@ -303,13 +303,13 @@ function convertImages(images, options) {
// Write image if need to be download
.then(function() {
if (!image.origin && !_.contains(downloaded, image.origin)) return;
- options.book.log.debug("download image", image.origin, "...");
+ options.book.log.debug('download image', image.origin, '...');
downloaded.push(image.origin);
return options.book.log.debug.promise(fs.writeStream(imgin, request(image.origin)))
.fail(function(err) {
if (!_.isError(err)) err = new Error(err);
- err.message = "Fail downloading "+image.origin+": "+err.message;
+ err.message = 'Fail downloading '+image.origin+': '+err.message;
throw err;
});
})
@@ -324,13 +324,13 @@ function convertImages(images, options) {
.then(function() {
if (!image.dest) return;
var imgout = path.resolve(options.book.options.output, image.dest);
- options.book.log.debug("convert image", image.source, "to", image.dest, "...");
+ options.book.log.debug('convert image', image.source, 'to', image.dest, '...');
return options.book.log.debug.promise(imgUtils.convertSVG(imgin, imgout));
});
}
})
.then(function() {
- options.book.log.debug.ok(images.length+" images converted with success");
+ options.book.log.debug.ok(images.length+' images converted with success');
});
}
@@ -344,16 +344,16 @@ function normalizePage(sections, options) {
convertImages: false,
// Current file path
- input: ".",
+ input: '.',
// Navigation to use to transform path
navigation: {},
// Directory parent of the file currently in rendering process
- base: "./",
+ base: './',
// Directory parent from the html output
- output: "./",
+ output: './',
// Glossary terms
glossary: []
@@ -363,7 +363,7 @@ function normalizePage(sections, options) {
var toConvert = [];
sections = _.map(sections, function(section) {
- if (section.type != "normal") return section;
+ if (section.type != 'normal') return section;
var out = normalizeHtml(section.content, options);
@@ -374,27 +374,13 @@ function normalizePage(sections, options) {
return Q()
.then(function() {
- toConvert = _.uniq(toConvert, "source");
+ toConvert = _.uniq(toConvert, 'source');
return convertImages(toConvert, options);
})
.thenResolve(sections);
}
-// Extract text from sections
-function extractText(sections) {
- return _.reduce(sections, function(prev, section) {
- if (section.type != "normal") return prev;
-
- var $ = cheerio.load(section.content);
- $("*").each(function() {
- prev = prev+" "+$(this).text();
- });
-
- return prev;
- }, "");
-}
module.exports = {
- normalize: normalizePage,
- extractText: extractText
+ normalize: normalizePage
};