diff options
author | Samy Pessé <samypesse@gmail.com> | 2016-02-28 14:47:34 +0100 |
---|---|---|
committer | Samy Pessé <samypesse@gmail.com> | 2016-02-28 14:47:34 +0100 |
commit | 4aa66338fce505566a2fe6ba6aee79ddf3f656a2 (patch) | |
tree | ffce4b558735f6a41228542f8c36e3a6ba1e562d | |
parent | 8cda844ef12cf87525024348c104413def02ed7f (diff) | |
download | gitbook-4aa66338fce505566a2fe6ba6aee79ddf3f656a2.zip gitbook-4aa66338fce505566a2fe6ba6aee79ddf3f656a2.tar.gz gitbook-4aa66338fce505566a2fe6ba6aee79ddf3f656a2.tar.bz2 |
Add init command
-rw-r--r-- | lib/backbone/summary.js | 17 | ||||
-rw-r--r-- | lib/book.js | 11 | ||||
-rw-r--r-- | lib/cli/index.js | 12 | ||||
-rw-r--r-- | lib/init.js | 68 | ||||
-rw-r--r-- | test/all.js | 3 | ||||
-rw-r--r-- | test/assertions.js | 19 | ||||
-rw-r--r-- | test/init.js | 57 |
7 files changed, 179 insertions, 8 deletions
diff --git a/lib/backbone/summary.js b/lib/backbone/summary.js index 4ae3453..a79b1e9 100644 --- a/lib/backbone/summary.js +++ b/lib/backbone/summary.js @@ -6,7 +6,6 @@ var location = require('../utils/location'); var error = require('../utils/error'); var BackboneFile = require('./file'); - /* An article represent an entry in the Summary. It's defined by a title, a reference, and children articles, @@ -37,8 +36,9 @@ function TOCArticle(def, parent) { var parts = url.parse(this.ref); if (!this.isExternal()) { - this.path = parts.pathname; - this.anchor = parts.hash; + var parts = this.ref.split('#'); + this.path = (parts.length > 1? parts.slice(0, -1).join('#') : this.ref); + this.anchor = (parts.length > 1? '#' + _.last(parts) : null); } } @@ -264,6 +264,17 @@ Summary.prototype.find = function(filter) { return result; }; +// Flatten the list of articles +Summary.prototype.flatten = function() { + var result = []; + + this.walk(function(article) { + result.push(article); + }); + + return result; +}; + // Return the first TOCArticle for a specific page (or path) Summary.prototype.getArticle = function(page) { if (!_.isString(page)) page = page.path; diff --git a/lib/book.js b/lib/book.js index a678181..09bd59f 100644 --- a/lib/book.js +++ b/lib/book.js @@ -13,6 +13,7 @@ var error = require('./utils/error'); var Promise = require('./utils/promise'); var Logger = require('./utils/logger'); var parsers = require('./parsers'); +var initBook = require('./init'); /* @@ -103,10 +104,10 @@ function Book(opts) { } }); + _.bindAll(this); + // Loop for template filters/blocks error.deprecateField(this, 'book', this, '"book" property is deprecated, use "this" directly instead'); - - _.bindAll(this); } // Return templating context for the book @@ -368,5 +369,11 @@ Book.setup = function(fs, root, opts) { }); }; +// Initialize a book +Book.init = function(fs, root, opts) { + return Book.setup(fs, root, opts) + .then(initBook); +}; + module.exports = Book; diff --git a/lib/cli/index.js b/lib/cli/index.js index 4d3d364..f1aca5e 100644 --- a/lib/cli/index.js +++ b/lib/cli/index.js @@ -7,6 +7,7 @@ var tinylr = require('tiny-lr'); var Promise = require('../utils/promise'); var PluginsManager = require('../plugins'); var Book = require('../book'); +var initBook = require('../init'); var helper = require('./helper'); var Server = require('./server'); @@ -14,6 +15,17 @@ var watch = require('./watch'); module.exports = { commands: [ + { + name: 'init [book]', + description: 'setup and create files for chapters', + options: [ + helper.options.log + ], + exec: function(args) { + var input = path.resolve(args[0] || process.cwd()); + return Book.init(helper.nodeFS, input); + } + }, { name: 'parse [book]', diff --git a/lib/init.js b/lib/init.js new file mode 100644 index 0000000..ea75a77 --- /dev/null +++ b/lib/init.js @@ -0,0 +1,68 @@ +var _ = require('lodash'); +var path = require('path'); + +var fs = require('./utils/fs'); +var Promise = require('./utils/promise'); + +// Initialize folder structure for a book +// Read SUMMARY to created the right chapter +function initBook(book) { + var extensionToUse = '.md'; + + book.log.info.ln('init book at', book.root); + return fs.mkdirp(book.root) + .then(function() { + return book.config.load(); + }) + .then(function() { + book.log.info.ln('detect structure from SUMMARY (if it exists)'); + return book.summary.load(); + }) + .then(function() { + var summary = book.summary.path || 'SUMMARY.md'; + var articles = book.summary.flatten(); + + // Use extension of summary + extensionToUse = path.extname(summary); + + // Readme doesn't have a path + if (!articles[0].path) { + articles[0].path = 'README' + extensionToUse; + } + + // Summary doesn't exists? create one + if (!book.summary.path) { + articles.push({ + title: 'Summary', + path: 'SUMMARY'+extensionToUse + }); + } + + // Create files that don't exist + return Promise.serie(articles, function(article) { + if (!article.path) return; + + var absolutePath = book.resolve(article.path); + + return fs.exists(absolutePath) + .then(function(exists) { + if(exists) { + book.log.info.ln('found', article.path); + return; + } else { + book.log.info.ln('create', article.path); + } + + return fs.mkdirp(path.dirname(absolutePath)) + .then(function() { + return fs.writeFile(absolutePath, '# '+article.title+'\n\n'); + }); + }); + }); + }) + .then(function() { + book.log.info.ln('initialization is finished'); + }); +} + +module.exports = initBook; diff --git a/test/all.js b/test/all.js index 9c82c91..67b1661 100644 --- a/test/all.js +++ b/test/all.js @@ -25,3 +25,6 @@ require('./assets-inliner'); require('./output-json'); require('./output-website'); require('./output-ebook'); + +// Misc +require('./init'); diff --git a/test/assertions.js b/test/assertions.js index 56da249..f96fdc1 100644 --- a/test/assertions.js +++ b/test/assertions.js @@ -1,18 +1,31 @@ var fs = require('fs'); +var path = require('path'); var _ = require('lodash'); var cheerio = require('cheerio'); var should = require('should'); // Assertions to test if an Output has generated a file should.Assertion.add('file', function(file, description) { + var rootFolder; + if (_.isFunction(this.obj.root)) { + rootFolder = this.obj.root(); + } else { + rootFolder = this.obj; + } + this.params = { - actual: this.obj.root(), + actual: rootFolder, operator: 'have file ' + file, message: description }; - this.obj.should.have.property('resolve').which.is.a.Function; - this.assert(fs.existsSync(this.obj.resolve(file))); + if (_.isFunction(this.obj.resolve)) { + file = this.obj.resolve(file); + } else { + file = path.resolve(rootFolder, file); + } + + this.assert(fs.existsSync(file)); }); should.Assertion.add('html', function(rules, description) { diff --git a/test/init.js b/test/init.js new file mode 100644 index 0000000..e1e8a4a --- /dev/null +++ b/test/init.js @@ -0,0 +1,57 @@ +var Book = require('../lib/book'); +var mock = require('./mock'); + +describe('Init', function() { + + it('should create file according to summary', function() { + return mock.setupFS({ + 'SUMMARY.md': '# Summary\n\n' + + '* [Hello](hello.md)\n' + + '* [Hello 2](hello 2.md)\n' + }) + .then(function(rootFolder) { + return Book.init(mock.fs, rootFolder, { + log: function() {} + }) + .then(function() { + rootFolder.should.have.file('SUMMARY.md'); + rootFolder.should.have.file('README.md'); + rootFolder.should.have.file('hello.md'); + rootFolder.should.have.file('hello 2.md'); + }); + }) + }); + + it('should create file subfolder', function() { + return mock.setupFS({ + 'SUMMARY.md': '# Summary\n\n' + + '* [Hello](test/hello.md)\n' + + '* [Hello 2](test/test2/world.md)\n' + }) + .then(function(rootFolder) { + return Book.init(mock.fs, rootFolder, { + log: function() {} + }) + .then(function() { + rootFolder.should.have.file('README.md'); + rootFolder.should.have.file('SUMMARY.md'); + rootFolder.should.have.file('test/hello.md'); + rootFolder.should.have.file('test/test2/world.md'); + }); + }) + }); + + it('should create SUMMARY if non-existant', function() { + return mock.setupFS({}) + .then(function(rootFolder) { + return Book.init(mock.fs, rootFolder, { + log: function() {} + }) + .then(function() { + rootFolder.should.have.file('SUMMARY.md'); + rootFolder.should.have.file('README.md'); + }); + }) + }); + +}); |