diff options
author | Samy Pessé <samypesse@gmail.com> | 2015-10-05 10:07:04 +0200 |
---|---|---|
committer | Samy Pessé <samypesse@gmail.com> | 2015-10-05 10:07:04 +0200 |
commit | 74396e7240f00b6f38239eedf2b10547a4868b4c (patch) | |
tree | a1630e4c74ac6ae32726c8ca31b1c99d5e005509 | |
parent | 6c2539e886a2893aa7d9bd4c4f84260145de6bd1 (diff) | |
download | gitbook-74396e7240f00b6f38239eedf2b10547a4868b4c.zip gitbook-74396e7240f00b6f38239eedf2b10547a4868b4c.tar.gz gitbook-74396e7240f00b6f38239eedf2b10547a4868b4c.tar.bz2 |
Add method book.formatString
-rw-r--r-- | lib/book.js | 240 | ||||
-rw-r--r-- | package.json | 2 | ||||
-rw-r--r-- | test/configuration.js | 34 | ||||
-rw-r--r-- | test/format.js | 11 |
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'); + }); + }); +}); |