diff options
author | Samy Pesse <samypesse@gmail.com> | 2016-04-26 15:23:28 +0200 |
---|---|---|
committer | Samy Pesse <samypesse@gmail.com> | 2016-04-26 15:23:28 +0200 |
commit | fa17f1671685a97e88c84fdba6a94744c54a09b8 (patch) | |
tree | 63083c0645a1f88bc7e96d891ef9ec9509d7680a | |
parent | ce99c8c7061eb9b4a2a5f4ff534d7fbeaf37cad0 (diff) | |
download | gitbook-fa17f1671685a97e88c84fdba6a94744c54a09b8.zip gitbook-fa17f1671685a97e88c84fdba6a94744c54a09b8.tar.gz gitbook-fa17f1671685a97e88c84fdba6a94744c54a09b8.tar.bz2 |
Add base for commands
Improve plugins installation
-rw-r--r-- | book.js | 2 | ||||
-rw-r--r-- | lib/cli/build.js | 30 | ||||
-rw-r--r-- | lib/cli/getBook.js | 23 | ||||
-rw-r--r-- | lib/cli/index.js | 198 | ||||
-rw-r--r-- | lib/cli/indexe.js | 199 | ||||
-rw-r--r-- | lib/cli/install.js | 21 | ||||
-rw-r--r-- | lib/cli/options.js | 23 | ||||
-rw-r--r-- | lib/cli/parse.js | 68 | ||||
-rw-r--r-- | lib/cli/serve.js | 19 | ||||
-rw-r--r-- | lib/cli/watch.js | 7 | ||||
-rw-r--r-- | lib/index.js | 4 | ||||
-rw-r--r-- | lib/models/config.js | 4 | ||||
-rw-r--r-- | lib/output/index.js | 24 | ||||
-rw-r--r-- | lib/plugins/installPlugins.js | 35 | ||||
-rw-r--r-- | lib/plugins/listAll.js | 4 |
15 files changed, 451 insertions, 210 deletions
@@ -9,7 +9,7 @@ module.exports = { gitbook: '>=3.0.0-pre.0', // Use the "official" theme - //plugins: ['theme-official', 'sitemap'], + plugins: ['theme-official', 'sitemap'], variables: { version: pkg.version diff --git a/lib/cli/build.js b/lib/cli/build.js new file mode 100644 index 0000000..49931bd --- /dev/null +++ b/lib/cli/build.js @@ -0,0 +1,30 @@ +var path = require('path'); + +var options = require('./options'); +var getBook = require('./getBook'); + +var Parse = require('../parse'); +var Output = require('../output'); + +module.exports = { + name: 'build [book] [output]', + description: 'build a book', + options: [ + options.log, + options.format + ], + exec: function(args, kwargs) { + var book = getBook(args, kwargs); + var Generator = Output.getGenerator(kwargs.format); + + return Parse.parseBook(book) + .then(function(resultBook) { + var defaultOutputRoot = path.join(resultBook.getRoot(), '_book'); + var outputFolder = args[1]? path.resolve(process.cwd(), args[1]) : defaultOutputRoot; + + return Output.generate(Generator, resultBook, { + root: outputFolder + }); + }); + } +}; diff --git a/lib/cli/getBook.js b/lib/cli/getBook.js new file mode 100644 index 0000000..5c29078 --- /dev/null +++ b/lib/cli/getBook.js @@ -0,0 +1,23 @@ +var path = require('path'); +var Book = require('../models/book'); +var createNodeFS = require('../fs/node'); + +/** + Return a book instance to work on from + command line args/kwargs + + @param {Array} args + @param {Object} kwargs + @return {Book} +*/ +function getBook(args, kwargs) { + var input = path.resolve(args[0] || process.cwd()); + var logLevel = kwargs.log; + + var fs = createNodeFS(input); + var book = Book.createForFS(fs); + + return book; +} + +module.exports = getBook; diff --git a/lib/cli/index.js b/lib/cli/index.js index eea707f..b93b7b1 100644 --- a/lib/cli/index.js +++ b/lib/cli/index.js @@ -1,199 +1,9 @@ -/* eslint-disable no-console */ - -var _ = require('lodash'); -var path = require('path'); -var tinylr = require('tiny-lr'); - -var Promise = require('../utils/promise'); -var PluginsManager = require('../plugins'); -var Book = require('../book'); - -var helper = require('./helper'); -var Server = require('./server'); -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]', - description: 'parse and returns debug information for a book', - options: [ - helper.options.log - ], - exec: helper.bookCmd(function(book) { - return book.parse() - .then(function() { - book.log.info.ln('Book located in:', book.root); - book.log.info.ln(''); - - if (book.config.exists()) book.log.info.ln('Configuration:', book.config.path); - - if (book.isMultilingual()) { - book.log.info.ln('Multilingual book detected:', book.langs.path); - } else { - book.log.info.ln('Readme:', book.readme.path); - book.log.info.ln('Summary:', book.summary.path); - if (book.glossary.exists()) book.log.info.ln('Glossary:', book.glossary.path); - - book.log.info.ln('Pages:'); - _.each(book.pages, function(page) { - book.log.info.ln('\t-', page.path); - }); - } - }); - }) - }, - - { - name: 'install [book]', - description: 'install all plugins dependencies', - options: [ - helper.options.log - ], - exec: helper.bookCmd(function(book, args) { - var plugins = new PluginsManager(book); - - return book.config.load() - .then(function() { - return plugins.install(); - }); - }) - }, - - { - name: 'build [book] [output]', - description: 'build a book', - options: [ - helper.options.log, - helper.options.format - ], - exec: helper.outputCmd(function(output, args, kwargs) { - return output.book.parse() - .then(function() { - return output.generate(); - }); - }) - }, - - helper.ebookCmd('pdf'), - helper.ebookCmd('epub'), - helper.ebookCmd('mobi'), - - { - name: 'serve [book]', - description: 'Build then serve a book from a directory', - options: [ - { - name: 'port', - description: 'Port for server to listen on', - defaults: 4000 - }, - { - name: 'lrport', - description: 'Port for livereload server to listen on', - defaults: 35729 - }, - { - name: 'watch', - description: 'Enable/disable file watcher', - defaults: true - }, - helper.options.format, - helper.options.log - ], - exec: function(args, kwargs) { - var input = path.resolve(args[0] || process.cwd()); - var server = new Server(); - - // Init livereload server - var lrServer = tinylr({}); - var port = kwargs.port; - var lrPath; - - var generate = function() { - - // Stop server if running - if (server.isRunning()) console.log('Stopping server'); - return server.stop() - - // Generate the book - .then(function() { - var book = new Book({ - fs: helper.nodeFS, - root: input, - logLevel: kwargs.log - }); - - return book.parse() - .then(function() { - // Add livereload plugin - book.config.set('plugins', - book.config.get('plugins') - .concat([ - { name: 'livereload' } - ]) - ); - - var Out = helper.FORMATS[kwargs.format]; - var output = new Out(book); - - return output.generate() - .thenResolve(output); - }); - }) - - // Start server and watch changes - .then(function(output) { - console.log(); - console.log('Starting server ...'); - return server.start(output.root(), port) - .then(function() { - console.log('Serving book on http://localhost:'+port); - - if (lrPath) { - // trigger livereload - lrServer.changed({ - body: { - files: [lrPath] - } - }); - } - - if (!kwargs.watch) return; - - return watch(output.book.root) - .then(function(filepath) { - // set livereload path - lrPath = filepath; - console.log('Restart after change in file', filepath); - console.log(''); - return generate(); - }); - }); - }); - }; - - return Promise.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(''); - return generate(); - }); - } - } - + require('./parse'), + require('./build'), + require('./serve'), + require('./install') ] }; diff --git a/lib/cli/indexe.js b/lib/cli/indexe.js new file mode 100644 index 0000000..eea707f --- /dev/null +++ b/lib/cli/indexe.js @@ -0,0 +1,199 @@ +/* eslint-disable no-console */ + +var _ = require('lodash'); +var path = require('path'); +var tinylr = require('tiny-lr'); + +var Promise = require('../utils/promise'); +var PluginsManager = require('../plugins'); +var Book = require('../book'); + +var helper = require('./helper'); +var Server = require('./server'); +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]', + description: 'parse and returns debug information for a book', + options: [ + helper.options.log + ], + exec: helper.bookCmd(function(book) { + return book.parse() + .then(function() { + book.log.info.ln('Book located in:', book.root); + book.log.info.ln(''); + + if (book.config.exists()) book.log.info.ln('Configuration:', book.config.path); + + if (book.isMultilingual()) { + book.log.info.ln('Multilingual book detected:', book.langs.path); + } else { + book.log.info.ln('Readme:', book.readme.path); + book.log.info.ln('Summary:', book.summary.path); + if (book.glossary.exists()) book.log.info.ln('Glossary:', book.glossary.path); + + book.log.info.ln('Pages:'); + _.each(book.pages, function(page) { + book.log.info.ln('\t-', page.path); + }); + } + }); + }) + }, + + { + name: 'install [book]', + description: 'install all plugins dependencies', + options: [ + helper.options.log + ], + exec: helper.bookCmd(function(book, args) { + var plugins = new PluginsManager(book); + + return book.config.load() + .then(function() { + return plugins.install(); + }); + }) + }, + + { + name: 'build [book] [output]', + description: 'build a book', + options: [ + helper.options.log, + helper.options.format + ], + exec: helper.outputCmd(function(output, args, kwargs) { + return output.book.parse() + .then(function() { + return output.generate(); + }); + }) + }, + + helper.ebookCmd('pdf'), + helper.ebookCmd('epub'), + helper.ebookCmd('mobi'), + + { + name: 'serve [book]', + description: 'Build then serve a book from a directory', + options: [ + { + name: 'port', + description: 'Port for server to listen on', + defaults: 4000 + }, + { + name: 'lrport', + description: 'Port for livereload server to listen on', + defaults: 35729 + }, + { + name: 'watch', + description: 'Enable/disable file watcher', + defaults: true + }, + helper.options.format, + helper.options.log + ], + exec: function(args, kwargs) { + var input = path.resolve(args[0] || process.cwd()); + var server = new Server(); + + // Init livereload server + var lrServer = tinylr({}); + var port = kwargs.port; + var lrPath; + + var generate = function() { + + // Stop server if running + if (server.isRunning()) console.log('Stopping server'); + return server.stop() + + // Generate the book + .then(function() { + var book = new Book({ + fs: helper.nodeFS, + root: input, + logLevel: kwargs.log + }); + + return book.parse() + .then(function() { + // Add livereload plugin + book.config.set('plugins', + book.config.get('plugins') + .concat([ + { name: 'livereload' } + ]) + ); + + var Out = helper.FORMATS[kwargs.format]; + var output = new Out(book); + + return output.generate() + .thenResolve(output); + }); + }) + + // Start server and watch changes + .then(function(output) { + console.log(); + console.log('Starting server ...'); + return server.start(output.root(), port) + .then(function() { + console.log('Serving book on http://localhost:'+port); + + if (lrPath) { + // trigger livereload + lrServer.changed({ + body: { + files: [lrPath] + } + }); + } + + if (!kwargs.watch) return; + + return watch(output.book.root) + .then(function(filepath) { + // set livereload path + lrPath = filepath; + console.log('Restart after change in file', filepath); + console.log(''); + return generate(); + }); + }); + }); + }; + + return Promise.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(''); + return generate(); + }); + } + } + + ] +}; diff --git a/lib/cli/install.js b/lib/cli/install.js new file mode 100644 index 0000000..c001711 --- /dev/null +++ b/lib/cli/install.js @@ -0,0 +1,21 @@ +var options = require('./options'); +var getBook = require('./getBook'); + +var Parse = require('../parse'); +var Plugins = require('../plugins'); + +module.exports = { + name: 'install [book]', + description: 'install all plugins dependencies', + options: [ + options.log + ], + exec: function(args, kwargs) { + var book = getBook(args, kwargs); + + return Parse.parseConfig(book) + .then(function(resultBook) { + return Plugins.installPlugins(resultBook); + }); + } +}; diff --git a/lib/cli/options.js b/lib/cli/options.js new file mode 100644 index 0000000..26581cb --- /dev/null +++ b/lib/cli/options.js @@ -0,0 +1,23 @@ +var Logger = require('../utils/logger'); + +var logOptions = { + name: 'log', + description: 'Minimum log level to display', + values: Object.keys(Logger.LEVELS) + .map(function(s) { + return s.toLowerCase(); + }), + defaults: 'info' +}; + +var formatOption = { + name: 'format', + description: 'Format to build to', + values: ['website', 'json', 'ebook'], + defaults: 'website' +}; + +module.exports = { + log: logOptions, + format: formatOption +}; diff --git a/lib/cli/parse.js b/lib/cli/parse.js new file mode 100644 index 0000000..0421b3e --- /dev/null +++ b/lib/cli/parse.js @@ -0,0 +1,68 @@ +var options = require('./options'); +var getBook = require('./getBook'); + +var Parse = require('../parse'); + +function printBook(book) { + var logger = book.getLogger(); + + var config = book.getConfig(); + var configFile = config.getFile(); + + var summary = book.getSummary(); + var summaryFile = summary.getFile(); + + var readme = book.getReadme(); + var readmeFile = readme.getFile(); + + var glossary = book.getGlossary(); + var glossaryFile = glossary.getFile(); + + if (configFile.exists()) { + logger.info.ln('configuration file is', configFile.getPath()); + } + + if (readmeFile.exists()) { + logger.info.ln('Introduction file is', readmeFile.getPath()); + } + + if (glossaryFile.exists()) { + logger.info.ln('Glossary file is', glossaryFile.getPath()); + } + + if (summaryFile.exists()) { + logger.info.ln('Table of Contents file is', summaryFile.getPath()); + } + + //logger.info.ln('Table of Contents:'); +} + + +module.exports = { + name: 'parse [book]', + description: 'parse and print debug information about a book', + options: [ + options.log + ], + exec: function(args, kwargs) { + var book = getBook(args, kwargs); + var logger = book.getLogger(); + + return Parse.parseBook(book) + .then(function(resultBook) { + var rootFolder = book.getRoot(); + var contentFolder = book.getContentRoot(); + + logger.info.ln('Book located in:', rootFolder); + if (contentFolder != rootFolder) { + logger.info.ln('Content located in:', contentFolder); + } + + if (resultBook.isMultilingual()) { + + } else { + printBook(resultBook); + } + }); + } +}; diff --git a/lib/cli/serve.js b/lib/cli/serve.js new file mode 100644 index 0000000..d97cfed --- /dev/null +++ b/lib/cli/serve.js @@ -0,0 +1,19 @@ +var path = require('path'); + +var options = require('./options'); +var getBook = require('./getBook'); + +var Parse = require('../parse'); +var Output = require('../output'); + +module.exports = { + name: 'serve [book] [output]', + description: 'serve the book as a website for testing', + options: [ + options.log, + options.format + ], + exec: function(args, kwargs) { + + } +}; diff --git a/lib/cli/watch.js b/lib/cli/watch.js index 130b0d4..0d1ab17 100644 --- a/lib/cli/watch.js +++ b/lib/cli/watch.js @@ -5,7 +5,12 @@ var chokidar = require('chokidar'); var Promise = require('../utils/promise'); var parsers = require('../parsers'); -// Watch a folder and resolve promise once a file is modified +/** + Watch a folder and resolve promise once a file is modified + + @param {String} dir + @return {Promise} +*/ function watch(dir) { var d = Promise.defer(); dir = path.resolve(dir); diff --git a/lib/index.js b/lib/index.js index 5a3c00e..3a1802a 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,7 +1,9 @@ var Book = require('./models/book'); var Parse = require('./parse'); +var cli = require('./cli'); module.exports = { Book: Book, - Parse: Parse + Parse: Parse, + commands: cli.commands }; diff --git a/lib/models/config.js b/lib/models/config.js index 720ac57..547007a 100644 --- a/lib/models/config.js +++ b/lib/models/config.js @@ -9,8 +9,8 @@ var Config = Immutable.Record({ values: configDefault }, 'Config'); -Config.prototype.getPath = function() { - return this.get('path'); +Config.prototype.getFile = function() { + return this.get('file'); }; Config.prototype.getValues = function() { diff --git a/lib/output/index.js b/lib/output/index.js index 9112666..9b8ec17 100644 --- a/lib/output/index.js +++ b/lib/output/index.js @@ -1,6 +1,24 @@ +var Immutable = require('immutable'); + +var generators = Immutable.List([ + require('./json'), + require('./website'), + require('./ebook') +]); + +/** + Return a specific generator by its name + + @param {String} + @return {Generator} +*/ +function getGenerator(name) { + return generators.find(function(generator) { + return generator.name == name; + }); +} + module.exports = { generate: require('./generateBook'), - JSONGenerator: require('./json'), - WebsiteGenerator: require('./website'), - EbookGenerator: require('./ebook') + getGenerator: getGenerator }; diff --git a/lib/plugins/installPlugins.js b/lib/plugins/installPlugins.js index 77ecfce..05a5316 100644 --- a/lib/plugins/installPlugins.js +++ b/lib/plugins/installPlugins.js @@ -3,9 +3,12 @@ var npmi = require('npmi'); var semver = require('semver'); var Immutable = require('immutable'); +var pkg = require('../../package.json'); +var DEFAULT_PLUGINS = require('../constants/defaultPlugins'); var Promise = require('../utils/promise'); var Plugin = require('../models/plugin'); var gitbook = require('../gitbook'); +var listForBook = require('./listForBook'); var npmIsReady; @@ -42,7 +45,7 @@ function resolveVersion(plugin) { return Promise.nfcall(npm.commands.view, [npmId + '@' + requiredVersion, 'engines'], true); }) .then(function(versions) { - versions = Immutable.Map(versions).entries().toList(); + versions = Immutable.Map(versions).entrySeq(); var result = versions .map(function(entry) { @@ -62,7 +65,7 @@ function resolveVersion(plugin) { if (!result) { return undefined; } else { - return result.get('version'); + return result.version; } }); } @@ -82,7 +85,7 @@ function installPlugin(book, plugin) { var name = plugin.getName(); var requirement = plugin.getVersion(); - logger.info.ln('installing plugin', name); + logger.info.ln('installing plugin "' + name + '"'); // Find a version to install return resolveVersion(plugin) @@ -91,7 +94,7 @@ function installPlugin(book, plugin) { throw new Error('Found no satisfactory version for plugin "' + name + '" with requirement "' + requirement + '"'); } - logger.info.ln('install plugin "' + plugin +'" from NPM with version', requirement); + logger.info.ln('install plugin "' + name +'" from NPM with version', requirement); return Promise.nfcall(npmi, { 'name': plugin.getNpmID(), 'version': version, @@ -104,7 +107,7 @@ function installPlugin(book, plugin) { }); }) .then(function() { - logger.info.ok('plugin "' + plugin + '" installed with success'); + logger.info.ok('plugin "' + name + '" installed with success'); }); } @@ -113,10 +116,28 @@ function installPlugin(book, plugin) { Install plugin requirements for a book @param {Book} - @param {OrderedMap<String:Plugin>} @return {Promise} */ -function installPlugins(book, plugins) { +function installPlugins(book) { + var logger = book.getLogger(); + var plugins = listForBook(book); + + // Remove default plugins + // (only if version is same as installed) + plugins = plugins.filterNot(function(plugin) { + return ( + DEFAULT_PLUGINS.includes(plugin.getName()) && + plugin.getVersion() === pkg.dependencies[plugin.getNpmID()] + ); + }); + + if (plugins.size == 0) { + logger.info.ln('nothing to install!'); + return Promise(); + } + + logger.info.ln('installing', plugins.size, 'plugins'); + return Promise.forEach(plugins, function(plugin) { return installPlugin(book, plugin); }); diff --git a/lib/plugins/listAll.js b/lib/plugins/listAll.js index 46eaea0..8a0fc07 100644 --- a/lib/plugins/listAll.js +++ b/lib/plugins/listAll.js @@ -2,6 +2,7 @@ var is = require('is'); var Immutable = require('immutable'); var Plugin = require('../models/plugin'); +var pkg = require('../../package.json'); var DEFAULT_PLUGINS = require('../constants/defaultPlugins'); /** @@ -41,7 +42,8 @@ function listAll(plugins) { if (plugins.has(pluginName)) return; plugins = plugins.set(pluginName, new Plugin({ - name: pluginName + name: pluginName, + version: pkg.dependencies[Plugin.nameToNpmID(pluginName)] })); }); |