diff options
author | Samy Pessé <samypesse@gmail.com> | 2016-01-28 18:39:44 +0100 |
---|---|---|
committer | Samy Pessé <samypesse@gmail.com> | 2016-01-28 18:39:44 +0100 |
commit | 4b465bedea94688a9adfb9136c9d2970d5496274 (patch) | |
tree | 7e29cc10d07b86d86239bd1cd59fab7996b412ce | |
parent | 461ef2c68e9086bd77f0a25d57956ebf60308f7c (diff) | |
download | gitbook-4b465bedea94688a9adfb9136c9d2970d5496274.zip gitbook-4b465bedea94688a9adfb9136c9d2970d5496274.tar.gz gitbook-4b465bedea94688a9adfb9136c9d2970d5496274.tar.bz2 |
Fix tests for languages parsing
-rw-r--r-- | lib/backbone/file.js | 3 | ||||
-rw-r--r-- | lib/backbone/page.js | 7 | ||||
-rw-r--r-- | lib/book.js | 14 | ||||
-rw-r--r-- | lib/config/index.js | 30 | ||||
-rw-r--r-- | lib/fs/index.js | 7 | ||||
-rw-r--r-- | lib/fs/node.js | 23 | ||||
-rw-r--r-- | lib/generators/json.js | 3 | ||||
-rw-r--r-- | lib/output.js | 13 | ||||
-rw-r--r-- | lib/utils/promise.js | 12 | ||||
-rw-r--r-- | package.json | 2 | ||||
-rw-r--r-- | test/1-config.js | 50 | ||||
-rw-r--r-- | test/4-langs.js | 31 | ||||
-rw-r--r-- | test/6-parse.js | 25 | ||||
-rw-r--r-- | test/mock.js | 2 |
14 files changed, 168 insertions, 54 deletions
diff --git a/lib/backbone/file.js b/lib/backbone/file.js index 34cf066..a58063c 100644 --- a/lib/backbone/file.js +++ b/lib/backbone/file.js @@ -1,3 +1,4 @@ +var _ = require('lodash'); function BackboneFile(book) { if (!(this instanceof BackboneFile)) return new BackboneFile(book); @@ -8,6 +9,8 @@ function BackboneFile(book) { // Filename in the book this.filename = ''; this.parser; + + _.bindAll(this); } // Type of the backbone file diff --git a/lib/backbone/page.js b/lib/backbone/page.js index 33bd636..a17e413 100644 --- a/lib/backbone/page.js +++ b/lib/backbone/page.js @@ -1,3 +1,4 @@ +var path = require('path'); /* A page represent a parsable file in the book (Markdown, Asciidoc, etc) @@ -11,8 +12,12 @@ function Page(book, filename) { } // Return the filename of the page with another extension +// "README.md" -> "README.html" Page.prototype.withExtension = function(ext) { - return + return path.join( + path.dirname(this.filename), + path.basename(this.filename, path.extname(this.filename)) + ext + ); }; diff --git a/lib/book.js b/lib/book.js index c211adf..477283f 100644 --- a/lib/book.js +++ b/lib/book.js @@ -50,7 +50,6 @@ function Book(opts) { this.ignore.addPattern([ // Skip Git stuff '.git/', - '.gitignore', // Skip OS X meta data '.DS_Store', @@ -62,12 +61,7 @@ function Book(opts) { '_book', '*.pdf', '*.epub', - '*.mobi', - - // Skip config files - '.ignore', - '.bookignore', - 'book.json' + '*.mobi' ]); // Create a logger for the book @@ -124,7 +118,7 @@ Book.prototype.isFileInScope = function(filename) { Book.prototype.parseIgnoreRules = function() { var that = this; - return Promise.series([ + return Promise.serie([ '.ignore', '.gitignore', '.bookignore' @@ -132,6 +126,8 @@ Book.prototype.parseIgnoreRules = function() { return that.readFile(filename) .then(function(content) { that.ignore.addPattern(content.toString().split(/\r?\n/)); + }, function() { + return Promise(); }); }); }; @@ -158,7 +154,7 @@ Book.prototype.parse = function() { that.log.info.ln('Parsing multilingual book, with', that.langs.count(), 'languages'); // Create a new book for each language and parse it - return Promise.serial(that.langs.list(), function(lang) { + return Promise.serie(that.langs.list(), function(lang) { that.log.debug.ln('Preparing book for language', lang.id); var langBook = new Book({ fs: that.fs, diff --git a/lib/config/index.js b/lib/config/index.js index 267f650..7734392 100644 --- a/lib/config/index.js +++ b/lib/config/index.js @@ -1,9 +1,15 @@ -var Q = require('q'); var _ = require('lodash'); var semver = require('semver'); var gitbook = require('../gitbook'); var configDefault = require('./default'); +var Promise = require('../utils/promise'); + +// Config files to tested (sorted) +var CONFIG_FILES = [ + 'book.js', + 'book.json' +]; /* Config is an interface for the book's configuration stored in "book.json" (or "book.js") @@ -13,6 +19,7 @@ function Config(book, baseConfig) { this.book = book; this.fs = book.fs; this.log = book.log; + this.filename = null; this.replace(baseConfig || {}); } @@ -22,11 +29,17 @@ function Config(book, baseConfig) { Config.prototype.load = function() { var that = this; - this.log.debug.ln('loading configuration'); - return this.fs.loadAsObject(this.book.resolve('book')) - .fail(function(err) { - if (err.code != 'MODULE_NOT_FOUND') throw(err); - else return Q({}); + this.log.info.ln('loading configuration'); + + // Try all potential configuration file + return Promise.some(CONFIG_FILES, function(filename) { + that.log.debug.ln('try loading configuration from', filename); + + return that.fs.loadAsObject(that.book.resolve(filename)) + .fail(function(err) { + if (err.code != 'MODULE_NOT_FOUND') throw(err); + else return Promise(false); + }); }) .then(function(_config) { return that.replace(_config); @@ -86,6 +99,11 @@ Config.prototype.replace = function(options) { }); }; +// Return true if book has a configuration file +Config.prototype.exists = function() { + return Boolean(this.filename); +}; + // Return path to a structure file // Strip the extension by default Config.prototype.getStructure = function(name, dontStripExt) { diff --git a/lib/fs/index.js b/lib/fs/index.js index 1961b07..7b8fc46 100644 --- a/lib/fs/index.js +++ b/lib/fs/index.js @@ -1,9 +1,10 @@ -var Q = require('q'); var _ = require('lodash'); var path = require('path'); var Buffer = require('buffer').Buffer; var destroy = require('destroy'); +var Promise = require('../utils/promise'); + /* A filesystem is an interface to read/write files GitBook can works with a virtual filesystem, for example in the browser. @@ -73,7 +74,7 @@ FS.prototype.listAllFiles = function(folder) { }); } }); - }, Q([])); + }, Promise([])); }); }; @@ -88,7 +89,7 @@ FS.prototype.readAsString = function(filename) { // Write a stream to a file and returns a promise FS.prototype.writeStream = function(filename, stream) { var bufs = []; - var d = Q.defer(); + var d = Promise.defer(); var cleanup = function() { destroy(stream); diff --git a/lib/fs/node.js b/lib/fs/node.js index 0c470d7..28383cf 100644 --- a/lib/fs/node.js +++ b/lib/fs/node.js @@ -1,9 +1,10 @@ -var Q = require('q'); var _ = require('lodash'); var util = require('util'); var path = require('path'); var fs = require('fs'); +var mkdirp = require('mkdirp'); +var Promise = require('../utils/promise'); var BaseFS = require('./'); function NodeFS() { @@ -13,7 +14,7 @@ util.inherits(NodeFS, BaseFS); // Check if a file exists, run a Promise(true) if that's the case, Promise(false) otherwise NodeFS.prototype.exists = function(filename) { - var d = Q.defer(); + var d = Promise.defer(); fs.exists(filename, function(exists) { d.resolve(exists); @@ -24,17 +25,25 @@ NodeFS.prototype.exists = function(filename) { // Read a file and returns a promise with the content as a buffer NodeFS.prototype.read = function(filename) { - return Q.nfcall(fs.readFile, filename); + return Promise.nfcall(fs.readFile, filename); }; // Write a file and returns a promise NodeFS.prototype.write = function(filename, buffer) { - return Q.nfcall(fs.writeFile, filename, buffer); + var folder = path.dirname(filename); + return Promise() + .then(function() { + if (!folder) return; + return Promise.nfcall(mkdirp, folder); + }) + .then(function() { + return Promise.nfcall(fs.writeFile, filename, buffer); + }); }; // List files in a directory NodeFS.prototype.readdir = function(folder) { - return Q.nfcall(fs.readdir, folder) + return Promise.nfcall(fs.readdir, folder) .then(function(files) { return _.chain(files) .map(function(file) { @@ -51,7 +60,7 @@ NodeFS.prototype.readdir = function(folder) { // Load a JSON/JS file NodeFS.prototype.loadAsObject = function(filename) { - return Q() + return Promise() .then(function() { var jsFile; @@ -64,7 +73,7 @@ NodeFS.prototype.loadAsObject = function(filename) { return require(jsFile); } catch(err) { - return Q.reject(err); + return Promise.reject(err); } }); }; diff --git a/lib/generators/json.js b/lib/generators/json.js index 820574b..19182bc 100644 --- a/lib/generators/json.js +++ b/lib/generators/json.js @@ -8,9 +8,10 @@ util.inherits(JSONGenerator, Generator); // Write a page (parsable file) Generator.prototype.writePage = function(page) { + var json = {}; - return this.output.writeFile(page.withExtension('.json')); + return this.output.writeFile(page.withExtension('.json'), JSON.stringify(json, null, 4)); }; diff --git a/lib/output.js b/lib/output.js index d09f29d..c22e8de 100644 --- a/lib/output.js +++ b/lib/output.js @@ -1,3 +1,5 @@ +var Ignore = require('ignore'); + var Promise = require('./utils/promise'); var generators = require('./generators'); var PluginsManager = require('./plugins'); @@ -9,6 +11,17 @@ function Output(book, type) { this.type = type; this.plugins = new PluginsManager(book); this.generator = new generators[type](this, type); + + // Files to ignore in output + this.ignore = Ignore(); + this.ignore.addPattern([ + '.gitignore', + '.ignore', + '.bookignore', + + // The configuration file should not be copied in the output + this.book.config.filename + ]); } // Write a file to the output folder diff --git a/lib/utils/promise.js b/lib/utils/promise.js index c25b349..82f4a60 100644 --- a/lib/utils/promise.js +++ b/lib/utils/promise.js @@ -21,6 +21,18 @@ function serie(arr, iter, base) { }, []); } +// Iter over an array and return first result (not null) +function some(arr, iter) { + return _.reduce(arr, function(prev, elem, i) { + return prev.then(function(val) { + if (val) return val; + + return iter(elem, i); + }); + }, Q()); +} + module.exports = Q; module.exports.reduce = reduce; module.exports.serie = serie; +module.exports.some = some; diff --git a/package.json b/package.json index 14f9f24..7129e73 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "lodash": "3.10.1", "graceful-fs": "3.0.5", "resolve": "0.6.3", - "fs-extra": "0.16.5", + "mkdirp": "0.5.1", "fstream-ignore": "1.0.2", "gitbook-parsers": "0.8.9", "gitbook-plugin-highlight": "1.0.3", diff --git a/test/1-config.js b/test/1-config.js index 474ffea..3ec76ca 100644 --- a/test/1-config.js +++ b/test/1-config.js @@ -2,38 +2,56 @@ var mock = require('./mock'); describe('Config', function() { - describe('config.load()', function() { - it('should not fail if no configuration file', function() { + describe('No configuration', function() { + var book; + + before(function() { return mock.setupDefaultBook() - .then(function(book) { + .then(function(_book) { + book = _book; return book.prepareConfig(); }); }); - it('should load from a JSON file', function() { + it('should signal that configuration is not defined', function() { + book.config.exists().should.not.be.ok(); + }); + }); + + describe('JSON file', function() { + var book; + + before(function() { return mock.setupDefaultBook({ 'book.json': { title: 'Hello World' } }) - .then(function(book) { - return book.prepareConfig() - .then(function() { - book.config.get('title', '').should.equal('Hello World'); - }); + .then(function(_book) { + book = _book; + return book.prepareConfig(); }); }); - it('should load from a JS file', function() { + it('should correctly extend configuration', function() { + book.config.get('title', '').should.equal('Hello World'); + }); + }); + + describe('JS file', function() { + var book; + + before(function() { return mock.setupDefaultBook({ 'book.js': 'module.exports = { title: "Hello World" };' }) - .then(function(book) { - return book.prepareConfig() - .then(function() { - book.config.get('title', '').should.equal('Hello World'); - }); + .then(function(_book) { + book = _book; + return book.prepareConfig(); }); }); - }); + it('should correctly extend configuration', function() { + book.config.get('title', '').should.equal('Hello World'); + }); + }); }); diff --git a/test/4-langs.js b/test/4-langs.js index 599cb43..dbde992 100644 --- a/test/4-langs.js +++ b/test/4-langs.js @@ -18,18 +18,29 @@ describe('Langs', function() { }); }); - it('should parse languages list', function() { - return mock.setupDefaultBook({ - 'LANGS.md': '# Languages\n\n' - + '* [en](./en)\n' - + '* [fr](./fr)\n\n' - }) - .then(function(book) { - return book.langs.load() - .then(function() { - book.langs.count().should.equal(2); + describe('Non-empty languages list', function() { + var book; + + before(function() { + return mock.setupDefaultBook({ + 'LANGS.md': '# Languages\n\n' + + '* [en](./en)\n' + + '* [fr](./fr)\n\n' + }) + .then(function(_book) { + book = _book; + + return book.langs.load(); }); }); + + it('should correctly count languages', function() { + book.langs.count().should.equal(2); + }); + + it('should correctly define book as multilingual', function() { + book.isMultilingual().should.equal(true); + }); }); }); diff --git a/test/6-parse.js b/test/6-parse.js index 422744d..a575720 100644 --- a/test/6-parse.js +++ b/test/6-parse.js @@ -18,5 +18,30 @@ describe('Parsing', function() { return book.parse().should.be.rejected; }); }); + + + describe('Multilingual book', function() { + var book; + + before(function() { + return mock.setupBook({ + 'LANGS.md': '# Languages\n\n' + + '* [English](./en)\n' + + '* [French](./fr)\n\n', + 'en/README.md': '# English', + 'en/SUMMARY.md': '# Summary', + 'fr/README.md': '# French', + 'fr/SUMMARY.md': '# Summary' + }) + .then(function(_book) { + book = _book; + return book.parse(); + }); + }); + + it('should list language books', function() { + + }); + }); }); diff --git a/test/mock.js b/test/mock.js index f562fa9..919a992 100644 --- a/test/mock.js +++ b/test/mock.js @@ -35,11 +35,13 @@ function setupFS(fs, rootFolder, files) { // Setup a mock book for testing using a map of files function setupBook(files, opts) { opts = opts || {}; + opts.log = function() { }; return Q.nfcall(tmp.dir.bind(tmp)).get(0) .then(function(folder) { opts.fs = fs; opts.root = folder; + return setupFS(fs, folder, files); }) .then(function(fs) { |