mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-26 04:07:07 +00:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ce50a1d50f | |||
| a76e018d36 | |||
| b06f1fd677 | |||
| 3d8b1880dc | |||
| 1a13c8c9bb | |||
| 852fae3a09 | |||
| d342d31c8e | |||
| 5b3f54fbc8 | |||
| 308ece784c | |||
| 0758ddf04e | |||
| f24d9aef73 | |||
| f8bb55f258 | |||
| 76daebeb84 | |||
| b0d366b7e8 | |||
| 3d0054dd64 | |||
| 13bc89ff44 | |||
| bb910f984e | |||
| e576fdea14 | |||
| c7864927ec | |||
| 54956de59f | |||
| 2cbd30d1f2 | |||
| 55614f1675 |
@@ -5,12 +5,14 @@ var fs = require('../utils/fs');
|
||||
|
||||
var Plugins = require('../plugins');
|
||||
var deprecate = require('./deprecate');
|
||||
var encodeConfig = require('./encodeConfig');
|
||||
var encodeNavigation = require('./encodeNavigation');
|
||||
var fileToURL = require('../output/helper/fileToURL');
|
||||
var defaultBlocks = require('../constants/defaultBlocks');
|
||||
var gitbook = require('../gitbook');
|
||||
|
||||
var encodeConfig = require('./encodeConfig');
|
||||
var encodeSummary = require('./encodeSummary');
|
||||
var encodeNavigation = require('./encodeNavigation');
|
||||
|
||||
/**
|
||||
Encode a global context into a JS object
|
||||
It's the context for page's hook, etc
|
||||
@@ -29,6 +31,7 @@ function encodeGlobal(output) {
|
||||
var result = {
|
||||
log: logger,
|
||||
config: encodeConfig(output, book.getConfig()),
|
||||
summary: encodeSummary(output, book.getSummary()),
|
||||
|
||||
/**
|
||||
Check if the book is a multilingual book
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
var encodeSummaryArticle = require('../json/encodeSummaryArticle');
|
||||
|
||||
/**
|
||||
Encode summary to provide an API to plugin
|
||||
|
||||
@param {Output} output
|
||||
@param {Config} config
|
||||
@return {Object}
|
||||
*/
|
||||
function encodeSummary(output, summary) {
|
||||
var result = {
|
||||
/**
|
||||
Iterate over the summary, it stops when the "iter" returns false
|
||||
|
||||
@param {Function} iter
|
||||
*/
|
||||
walk: function (iter) {
|
||||
summary.getArticle(function(article) {
|
||||
var jsonArticle = encodeSummaryArticle(article, false);
|
||||
|
||||
return iter(jsonArticle);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
Get an article by its level
|
||||
|
||||
@param {String} level
|
||||
@return {Object}
|
||||
*/
|
||||
getArticleByLevel: function(level) {
|
||||
var article = summary.getByLevel(level);
|
||||
return (article? encodeSummaryArticle(article) : undefined);
|
||||
},
|
||||
|
||||
/**
|
||||
Get an article by its path
|
||||
|
||||
@param {String} level
|
||||
@return {Object}
|
||||
*/
|
||||
getArticleByPath: function(level) {
|
||||
var article = summary.getByPath(level);
|
||||
return (article? encodeSummaryArticle(article) : undefined);
|
||||
}
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = encodeSummary;
|
||||
+1
-1
@@ -4,7 +4,7 @@ var options = require('./options');
|
||||
var initBook = require('../init');
|
||||
|
||||
module.exports = {
|
||||
name: 'install [book]',
|
||||
name: 'init [book]',
|
||||
description: 'setup and create files for chapters',
|
||||
options: [
|
||||
options.log
|
||||
|
||||
+45
-10
@@ -16,12 +16,26 @@ var watch = require('./watch');
|
||||
|
||||
var server, lrServer, lrPath;
|
||||
|
||||
function waitForCtrlC() {
|
||||
var d = Promise.defer();
|
||||
|
||||
process.on('SIGINT', function() {
|
||||
d.resolve();
|
||||
});
|
||||
|
||||
return d.promise;
|
||||
}
|
||||
|
||||
|
||||
function generateBook(args, kwargs) {
|
||||
var port = kwargs.port;
|
||||
var outputFolder = getOutputFolder(args);
|
||||
var book = getBook(args, kwargs);
|
||||
var Generator = Output.getGenerator(kwargs.format);
|
||||
|
||||
var hasWatch = kwargs['watch'];
|
||||
var hasLiveReloading = kwargs['live'];
|
||||
|
||||
// Stop server if running
|
||||
if (server.isRunning()) console.log('Stopping server');
|
||||
|
||||
@@ -29,8 +43,10 @@ function generateBook(args, kwargs) {
|
||||
.then(function() {
|
||||
return Parse.parseBook(book)
|
||||
.then(function(resultBook) {
|
||||
// Enable livereload plugin
|
||||
resultBook = ConfigModifier.addPlugin(resultBook, 'livereload');
|
||||
if (hasLiveReloading) {
|
||||
// Enable livereload plugin
|
||||
resultBook = ConfigModifier.addPlugin(resultBook, 'livereload');
|
||||
}
|
||||
|
||||
return Output.generate(Generator, resultBook, {
|
||||
root: outputFolder
|
||||
@@ -45,7 +61,7 @@ function generateBook(args, kwargs) {
|
||||
.then(function() {
|
||||
console.log('Serving book on http://localhost:'+port);
|
||||
|
||||
if (lrPath) {
|
||||
if (lrPath && hasLiveReloading) {
|
||||
// trigger livereload
|
||||
lrServer.changed({
|
||||
body: {
|
||||
@@ -55,7 +71,9 @@ function generateBook(args, kwargs) {
|
||||
}
|
||||
})
|
||||
.then(function() {
|
||||
if (!kwargs.watch) return;
|
||||
if (!hasWatch) {
|
||||
return waitForCtrlC();
|
||||
}
|
||||
|
||||
return watch(book.getRoot())
|
||||
.then(function(filepath) {
|
||||
@@ -84,7 +102,12 @@ module.exports = {
|
||||
},
|
||||
{
|
||||
name: 'watch',
|
||||
description: 'Enable/disable file watcher',
|
||||
description: 'Enable file watcher and live reloading',
|
||||
defaults: true
|
||||
},
|
||||
{
|
||||
name: 'live',
|
||||
description: 'Enable live reloading',
|
||||
defaults: true
|
||||
},
|
||||
options.log,
|
||||
@@ -92,13 +115,25 @@ module.exports = {
|
||||
],
|
||||
exec: function(args, kwargs) {
|
||||
server = new Server();
|
||||
lrServer = tinylr({});
|
||||
var hasWatch = kwargs['watch'];
|
||||
var hasLiveReloading = kwargs['live'];
|
||||
|
||||
return Promise.nfcall(lrServer.listen.bind(lrServer), kwargs.lrport)
|
||||
return Promise()
|
||||
.then(function() {
|
||||
if (!hasWatch || !hasLiveReloading) {
|
||||
return;
|
||||
}
|
||||
|
||||
lrServer = tinylr({});
|
||||
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('');
|
||||
|
||||
});
|
||||
})
|
||||
.then(function() {
|
||||
console.log('Live reload server started on port:', kwargs.lrport);
|
||||
console.log('Press CTRL+C to quit ...');
|
||||
console.log('');
|
||||
return generateBook(args, kwargs);
|
||||
});
|
||||
}
|
||||
|
||||
+5
-2
@@ -47,8 +47,11 @@ function initBook(rootFolder) {
|
||||
|
||||
// Write pages
|
||||
return Promise.forEach(articles, function(article) {
|
||||
var filePath = path.join(rootFolder, article.getPath());
|
||||
if (!filePath) return;
|
||||
var articlePath = article.getPath();
|
||||
var filePath = articlePath? path.join(rootFolder, articlePath) : null;
|
||||
if (!filePath) {
|
||||
return;
|
||||
}
|
||||
|
||||
return fs.assertFile(filePath, function() {
|
||||
return fs.ensureFile(filePath)
|
||||
|
||||
@@ -20,6 +20,7 @@ function encodeSummaryArticle(article, recursive) {
|
||||
anchor: article.getAnchor(),
|
||||
url: article.getUrl(),
|
||||
path: article.getPath(),
|
||||
ref: article.getRef(),
|
||||
articles: articles
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,11 +8,18 @@ describe('Summary', function() {
|
||||
articles: [
|
||||
{
|
||||
title: 'My First Article',
|
||||
path: 'README.md'
|
||||
ref: 'README.md'
|
||||
},
|
||||
{
|
||||
title: 'My Second Article',
|
||||
path: 'article.md'
|
||||
ref: 'article.md'
|
||||
},
|
||||
{
|
||||
title: 'Article without ref'
|
||||
},
|
||||
{
|
||||
title: 'Article with absolute ref',
|
||||
ref: 'https://google.fr'
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -33,7 +40,7 @@ describe('Summary', function() {
|
||||
var part = summary.getByLevel('1');
|
||||
|
||||
expect(part).toBeDefined();
|
||||
expect(part.getArticles().size).toBe(2);
|
||||
expect(part.getArticles().size).toBe(4);
|
||||
});
|
||||
|
||||
it('can return a Part (2)', function() {
|
||||
@@ -66,6 +73,12 @@ describe('Summary', function() {
|
||||
expect(article).toBeDefined();
|
||||
expect(article.getTitle()).toBe('My Second Article');
|
||||
});
|
||||
|
||||
it('return undefined if not found', function() {
|
||||
var article = summary.getByPath('NOT_EXISTING.md');
|
||||
|
||||
expect(article).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('toText', function() {
|
||||
|
||||
@@ -8,12 +8,14 @@ describe('TemplateBlock', function() {
|
||||
describe('create', function() {
|
||||
pit('must initialize a simple TemplateBlock from a function', function() {
|
||||
var templateBlock = TemplateBlock.create('sayhello', function(block) {
|
||||
return '<p>Hello, World!</p>';
|
||||
return {
|
||||
body: '<p>Hello, World!</p>',
|
||||
parse: true
|
||||
};
|
||||
});
|
||||
|
||||
// Check basic templateBlock properties
|
||||
expect(templateBlock.getName()).toBe('sayhello');
|
||||
expect(templateBlock.getParse()).toBeTruthy();
|
||||
expect(templateBlock.getEndTag()).toBe('endsayhello');
|
||||
expect(templateBlock.getBlocks().size).toBe(0);
|
||||
expect(templateBlock.getExtensionName()).toBe('BlocksayhelloExtension');
|
||||
@@ -33,7 +35,10 @@ describe('TemplateBlock', function() {
|
||||
describe('getShortcuts', function() {
|
||||
it('must return undefined if no shortcuts', function() {
|
||||
var templateBlock = TemplateBlock.create('sayhello', function(block) {
|
||||
return '<p>Hello, World!</p>';
|
||||
return {
|
||||
body: '<p>Hello, World!</p>',
|
||||
parse: true
|
||||
};
|
||||
});
|
||||
|
||||
expect(templateBlock.getShortcuts()).not.toBeDefined();
|
||||
@@ -62,9 +67,42 @@ describe('TemplateBlock', function() {
|
||||
});
|
||||
|
||||
describe('toNunjucksExt()', function() {
|
||||
pit('should replace by block anchor', function() {
|
||||
var templateBlock = TemplateBlock.create('sayhello', function(block) {
|
||||
return 'Hello';
|
||||
});
|
||||
|
||||
var blocks = {};
|
||||
|
||||
// Create a fresh Nunjucks environment
|
||||
var env = new nunjucks.Environment(null, { autoescape: false });
|
||||
|
||||
// Add template block to environement
|
||||
var Ext = templateBlock.toNunjucksExt({}, blocks);
|
||||
env.addExtension(templateBlock.getExtensionName(), new Ext());
|
||||
|
||||
// Render a template using the block
|
||||
var src = '{% sayhello %}{% endsayhello %}';
|
||||
return Promise.nfcall(env.renderString.bind(env), src)
|
||||
.then(function(res) {
|
||||
blocks = Immutable.fromJS(blocks);
|
||||
expect(blocks.size).toBe(1);
|
||||
|
||||
var blockId = blocks.keySeq().get(0);
|
||||
var block = blocks.get(blockId);
|
||||
|
||||
expect(res).toBe('{{-%' + blockId + '%-}}');
|
||||
expect(block.get('body')).toBe('Hello');
|
||||
expect(block.get('name')).toBe('sayhello');
|
||||
});
|
||||
});
|
||||
|
||||
pit('must create a valid nunjucks extension', function() {
|
||||
var templateBlock = TemplateBlock.create('sayhello', function(block) {
|
||||
return '<p>Hello, World!</p>';
|
||||
return {
|
||||
body: '<p>Hello, World!</p>',
|
||||
parse: true
|
||||
};
|
||||
});
|
||||
|
||||
// Create a fresh Nunjucks environment
|
||||
@@ -84,7 +122,10 @@ describe('TemplateBlock', function() {
|
||||
|
||||
pit('must apply block arguments correctly', function() {
|
||||
var templateBlock = TemplateBlock.create('sayhello', function(block) {
|
||||
return '<'+block.kwargs.tag+'>Hello, '+block.kwargs.name+'!</'+block.kwargs.tag+'>';
|
||||
return {
|
||||
body: '<'+block.kwargs.tag+'>Hello, '+block.kwargs.name+'!</'+block.kwargs.tag+'>',
|
||||
parse: true
|
||||
};
|
||||
});
|
||||
|
||||
// Create a fresh Nunjucks environment
|
||||
@@ -106,7 +147,10 @@ describe('TemplateBlock', function() {
|
||||
var templateBlock = TemplateBlock.create('sayhello', function(block) {
|
||||
return Promise()
|
||||
.then(function() {
|
||||
return 'Hello ' + block.body;
|
||||
return {
|
||||
body: 'Hello ' + block.body,
|
||||
parse: true
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
@@ -136,7 +180,10 @@ describe('TemplateBlock', function() {
|
||||
nested[blk.name] = blk.body.trim();
|
||||
});
|
||||
|
||||
return '<p class="yoda">'+nested.end+' '+nested.start+'</p>';
|
||||
return {
|
||||
body: '<p class="yoda">'+nested.end+' '+nested.start+'</p>',
|
||||
parse: true
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -74,7 +74,12 @@ Summary.prototype.getByLevel = function(level) {
|
||||
*/
|
||||
Summary.prototype.getByPath = function(filePath) {
|
||||
return this.getArticle(function(article) {
|
||||
return (LocationUtils.areIdenticalPaths(article.getPath(), filePath));
|
||||
var articlePath = article.getPath();
|
||||
|
||||
return (
|
||||
articlePath &&
|
||||
LocationUtils.areIdenticalPaths(articlePath, filePath)
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -30,12 +30,13 @@ SummaryArticle.prototype.getArticles = function() {
|
||||
};
|
||||
|
||||
/**
|
||||
Return how deep the article is
|
||||
Return how deep the article is.
|
||||
The README has a depth of 1
|
||||
|
||||
@return {Number}
|
||||
*/
|
||||
SummaryArticle.prototype.getDepth = function() {
|
||||
return this.getLevel().split('.').length;
|
||||
return (this.getLevel().split('.').length - 1);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,19 +22,13 @@ var TemplateBlock = Immutable.Record({
|
||||
blocks: Immutable.List(),
|
||||
|
||||
// List of shortcuts to replace with this block
|
||||
shortcuts: Immutable.Map(),
|
||||
|
||||
parse: true
|
||||
shortcuts: Immutable.Map()
|
||||
}, 'TemplateBlock');
|
||||
|
||||
TemplateBlock.prototype.getName = function() {
|
||||
return this.get('name');
|
||||
};
|
||||
|
||||
TemplateBlock.prototype.getParse = function() {
|
||||
return this.get('parse');
|
||||
};
|
||||
|
||||
TemplateBlock.prototype.getEndTag = function() {
|
||||
return this.get('end') || ('end' + this.getName());
|
||||
};
|
||||
@@ -77,6 +71,8 @@ TemplateBlock.prototype.getExtensionName = function() {
|
||||
@return {Nunjucks.Extension}
|
||||
*/
|
||||
TemplateBlock.prototype.toNunjucksExt = function(mainContext, blocksOutput) {
|
||||
blocksOutput = blocksOutput || {};
|
||||
|
||||
var that = this;
|
||||
var name = this.getName();
|
||||
var endTag = this.getEndTag();
|
||||
@@ -241,9 +237,8 @@ TemplateBlock.prototype.normalizeBlockResult = function(result) {
|
||||
@return {String}
|
||||
*/
|
||||
TemplateBlock.prototype.blockResultToHtml = function(result, blocksOutput) {
|
||||
var parse = this.getParse();
|
||||
var indexedKey;
|
||||
var toIndex = (!parse) || (result.post !== undefined);
|
||||
var toIndex = (!result.parse) || (result.post !== undefined);
|
||||
|
||||
if (toIndex) {
|
||||
indexedKey = genKey();
|
||||
@@ -251,7 +246,7 @@ TemplateBlock.prototype.blockResultToHtml = function(result, blocksOutput) {
|
||||
}
|
||||
|
||||
// Parsable block, just return it
|
||||
if (parse) {
|
||||
if (result.parse) {
|
||||
return result.body;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,7 @@ function getPDFTemplate(output, type) {
|
||||
var context = JSONUtils.encodeOutput(output);
|
||||
context.page = {
|
||||
num: '_PAGENUM_',
|
||||
title: '_TITLE_',
|
||||
section: '_SECTION_'
|
||||
title: '_SECTION_'
|
||||
};
|
||||
|
||||
// Render the theme
|
||||
|
||||
@@ -36,7 +36,7 @@ function postRender(engine, output) {
|
||||
var content = output.getContent();
|
||||
var blocks = output.getBlocks();
|
||||
|
||||
var result = replaceBlocks(content);
|
||||
var result = replaceBlocks(content, blocks);
|
||||
|
||||
return Promise.forEach(blocks, function(block) {
|
||||
var post = block.get('post');
|
||||
|
||||
+3
-3
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "gitbook",
|
||||
"version": "3.0.0-pre.13",
|
||||
"version": "3.0.0-pre.14",
|
||||
"homepage": "https://www.gitbook.com",
|
||||
"description": "Library and cmd utility to generate GitBooks",
|
||||
"main": "lib/index.js",
|
||||
"browser": "./lib/browser.js",
|
||||
"dependencies": {
|
||||
"bash-color": "0.0.3",
|
||||
"bash-color": "0.0.4",
|
||||
"cheerio": "0.20.0",
|
||||
"chokidar": "1.4.3",
|
||||
"cp": "0.2.0",
|
||||
@@ -29,7 +29,7 @@
|
||||
"gitbook-plugin-lunr": "1.1.0",
|
||||
"gitbook-plugin-search": "2.2.1",
|
||||
"gitbook-plugin-sharing": "1.0.2",
|
||||
"gitbook-plugin-theme-default": "1.0.0-pre.9",
|
||||
"gitbook-plugin-theme-default": "1.0.0-pre.10",
|
||||
"github-slugid": "1.0.1",
|
||||
"graceful-fs": "4.1.3",
|
||||
"i18n-t": "1.0.0",
|
||||
|
||||
Reference in New Issue
Block a user