summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamy Pessé <samypesse@gmail.com>2015-10-05 10:07:04 +0200
committerSamy Pessé <samypesse@gmail.com>2015-10-05 10:07:04 +0200
commit74396e7240f00b6f38239eedf2b10547a4868b4c (patch)
treea1630e4c74ac6ae32726c8ca31b1c99d5e005509
parent6c2539e886a2893aa7d9bd4c4f84260145de6bd1 (diff)
downloadgitbook-74396e7240f00b6f38239eedf2b10547a4868b4c.zip
gitbook-74396e7240f00b6f38239eedf2b10547a4868b4c.tar.gz
gitbook-74396e7240f00b6f38239eedf2b10547a4868b4c.tar.bz2
Add method book.formatString
-rw-r--r--lib/book.js240
-rw-r--r--package.json2
-rw-r--r--test/configuration.js34
-rw-r--r--test/format.js11
4 files changed, 158 insertions, 129 deletions
diff --git a/lib/book.js b/lib/book.js
index fa72618..c755c27 100644
--- a/lib/book.js
+++ b/lib/book.js
@@ -1,23 +1,23 @@
-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 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 Book = function(root, context, parent) {
this.context = _.defaults(context || {}, {
@@ -30,7 +30,7 @@ var Book = function(root, context, parent) {
},
// Log level
- logLevel: "info"
+ logLevel: 'info'
});
// Log
@@ -44,7 +44,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;
}
@@ -82,10 +82,10 @@ var Book = function(root, context, parent) {
this.searchIndexEnabled = true;
this.searchIndexSize = 0;
this.searchIndex = lunr(function () {
- this.ref("url");
+ this.ref('url');
- this.field("title", { boost: 10 });
- this.field("body");
+ this.field('title', { boost: 10 });
+ this.field('body');
});
// Bind methods
@@ -94,7 +94,7 @@ var Book = function(root, context, parent) {
// 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 +112,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 +165,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 +183,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 +196,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 +249,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 +284,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 +297,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 +323,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 +335,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 +349,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 +393,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 +403,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 +424,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 +462,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 +474,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 +512,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 +531,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 +558,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 +566,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 +582,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
});
})
@@ -623,6 +623,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 +657,7 @@ Book.prototype.fileIsInBook = function(filename) {
Book.prototype.readFile = function(filename) {
return fs.readFile(
this.resolve(filename),
- { encoding: "utf8" }
+ { encoding: 'utf8' }
);
};
@@ -653,28 +671,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 +711,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 +740,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;
};
@@ -742,7 +760,7 @@ Book.prototype.indexPage = function(page) {
var nav = this.navigation[page.path];
if (!nav || !this.searchIndexEnabled) return;
- this.log.debug.ln("index page", page.path);
+ this.log.debug.ln('index page', page.path);
// Extract text from the page
var text = pageUtil.extractText(page.sections);
@@ -750,7 +768,7 @@ Book.prototype.indexPage = function(page) {
// 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.log.warn.ln('search index is too big, indexing is now disabled');
this.searchIndexEnabled = false;
return;
}
@@ -767,10 +785,10 @@ 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,10 +821,10 @@ 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;
diff --git a/package.json b/package.json
index cb0b1ad..aa8f69a 100644
--- a/package.json
+++ b/package.json
@@ -12,7 +12,7 @@
"resolve": "0.6.3",
"fs-extra": "0.16.5",
"fstream-ignore": "1.0.2",
- "gitbook-parsers": "0.8.3",
+ "gitbook-parsers": "0.8.4",
"gitbook-plugin-highlight": "1.0.3",
"nunjucks": "2.1.0",
"nunjucks-autoescape": "1.0.0",
diff --git a/test/configuration.js b/test/configuration.js
index c96c10d..d30fd61 100644
--- a/test/configuration.js
+++ b/test/configuration.js
@@ -1,37 +1,37 @@
-describe("Configuration", function () {
- it("should extract default title from README", function() {
- return books.parse("basic")
+describe('Configuration', function () {
+ it('should extract default title from README', function() {
+ return books.parse('basic')
.then(function(book) {
- book.options.title.should.be.equal("Readme");
+ book.options.title.should.be.equal('Readme');
});
});
- it("should extract default description from README", function() {
- return books.parse("basic")
+ it('should extract default description from README', function() {
+ return books.parse('basic')
.then(function(book) {
- book.options.description.should.be.equal("Default description for the book.");
+ book.options.description.should.be.equal('Default description for the book.');
});
});
- it("should correctly load from json (book.json)", function() {
- return books.parse("config-json")
+ it('should correctly load from json (book.json)', function() {
+ return books.parse('config-json')
.then(function(book) {
- book.options.title.should.be.equal("json-config");
+ book.options.title.should.be.equal('json-config');
});
});
- it("should correctly load from JavaScript (book.js)", function() {
- return books.parse("config-js")
+ it('should correctly load from JavaScript (book.js)', function() {
+ return books.parse('config-js')
.then(function(book) {
- book.options.title.should.be.equal("js-config");
+ book.options.title.should.be.equal('js-config');
});
});
- it("should provide configuration on book.config.get", function() {
- return books.parse("basic")
+ it('should provide configuration on book.config.get', function() {
+ return books.parse('basic')
.then(function(book) {
- book.config.get("description").should.be.equal("Default description for the book.");
- book.getConfig("description").should.be.equal("Default description for the book.");
+ book.config.get('description').should.be.equal('Default description for the book.');
+ book.getConfig('description').should.be.equal('Default description for the book.');
});
});
});
diff --git a/test/format.js b/test/format.js
new file mode 100644
index 0000000..2ec1a6f
--- /dev/null
+++ b/test/format.js
@@ -0,0 +1,11 @@
+describe('Formatting', function () {
+ it('should provide formatting with book.formatString', function() {
+ return books.parse('basic')
+ .then(function(book) {
+ return book.formatString('markdown', 'this is a **test**');
+ })
+ .then(function(content) {
+ content.should.equal('<p>this is a <strong>test</strong></p>\n');
+ });
+ });
+});