summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE.md19
-rw-r--r--.travis.yml3
-rw-r--r--CHANGES.md13
-rw-r--r--book.js4
-rw-r--r--docs/examples.md2
-rw-r--r--docs/plugins/testing.md4
-rw-r--r--docs/styles/website.css4
-rw-r--r--lib/browser.js1
-rw-r--r--lib/cli/serve.js17
-rw-r--r--lib/constants/configSchema.js4
-rw-r--r--lib/json/encodeBookWithPage.js12
-rw-r--r--lib/json/encodeOutput.js10
-rw-r--r--lib/json/encodeOutputWithPage.js23
-rw-r--r--lib/json/index.js1
-rw-r--r--lib/models/__tests__/summaryArticle.js30
-rw-r--r--lib/models/summaryArticle.js33
-rw-r--r--lib/modifiers/config/editPlugin.js2
-rw-r--r--lib/modifiers/config/getPluginConfig.js20
-rw-r--r--lib/modifiers/config/index.js1
-rw-r--r--lib/output/__tests__/createMock.js38
-rw-r--r--lib/output/__tests__/ebook.js2
-rw-r--r--lib/output/__tests__/generateMock.js (renamed from lib/output/generateMock.js)27
-rw-r--r--lib/output/__tests__/json.js2
-rw-r--r--lib/output/__tests__/website.js2
-rw-r--r--lib/output/generateBook.js54
-rw-r--r--lib/output/generatePage.js14
-rw-r--r--lib/output/getModifiers.js10
-rw-r--r--lib/output/helper/fileToOutput.js12
-rw-r--r--lib/output/helper/resolveFileToURL.js12
-rw-r--r--lib/output/json/onPage.js10
-rw-r--r--lib/output/modifiers/annotateText.js19
-rw-r--r--lib/output/preparePlugins.js10
-rw-r--r--lib/output/website/__tests__/i18n.js38
-rw-r--r--lib/output/website/createTemplateEngine.js58
-rw-r--r--lib/output/website/onPage.js12
-rw-r--r--lib/output/website/prepareI18n.js10
-rw-r--r--lib/utils/__tests__/location.js15
-rw-r--r--lib/utils/location.js86
-rw-r--r--lib/utils/promise.js87
-rw-r--r--lib/utils/reducedObject.js5
-rw-r--r--package.json11
41 files changed, 504 insertions, 233 deletions
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 0000000..4311ae2
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,19 @@
+Thank you for giving us your feedback! We listed some guidelines to help you:
+
+If possible, open separate issues for each bug report. Avoid grouping bugs that are unrelated.
+
+### What is the current behavior?
+
+If the current behavior is a bug, please provide the steps to reproduce. if possible, provide the GitBook version being used (`gitbook -V`) and the system infromations (OS and version).
+
+### What is the expected behavior?
+
+How do you think, or how would you like it should behave.
+
+#### For GitBook.com
+
+Provide, if possible, your username and the URL of the concerned book.
+
+----
+
+The GitBook Team
diff --git a/.travis.yml b/.travis.yml
index 45ba3e1..b35331d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,8 @@
sudo: false
language: node_js
+os:
+ - linux
+ - osx
node_js:
- "stable"
- "4.1"
diff --git a/CHANGES.md b/CHANGES.md
index 992073f..199e5dd 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -2,6 +2,19 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
+## 3.2.1
+- Fix bug on Firefox when navigating to an url containing an hash
+- Update nunjucks to fix JS error when page contains a lot of templating blocks
+
+## 3.2.0
+- Switch markdown parser from `kramed` to `markup-it`
+- Fix support of `|` in tables
+- Fix access to `output.name` in templating
+- Fix i18n for website and PDF
+- Fix minor scrolling issues on website
+- Improve options of default search indexer (keywords, disabling per pages)
+- Improve pertinence of search results
+
## 3.1.1
- Fix order of plugins during loading
- Fix error when using math and conrefs
diff --git a/book.js b/book.js
index cb2a360..31d751b 100644
--- a/book.js
+++ b/book.js
@@ -6,10 +6,10 @@ module.exports = {
title: 'GitBook Toolchain Documentation',
// Enforce use of GitBook v3
- gitbook: '>=3.0.0-pre.0',
+ gitbook: '3.1.1',
// Use the "official" theme
- plugins: ['theme-official', 'sitemap'],
+ plugins: ['theme-official@2.1.1', '-sharing', '-fontsettings', 'sitemap'],
variables: {
version: pkg.version
diff --git a/docs/examples.md b/docs/examples.md
index a748c33..2bfcdb3 100644
--- a/docs/examples.md
+++ b/docs/examples.md
@@ -23,5 +23,7 @@ More than 50,000 books have been published on [GitBook.com](https://www.gitbook.
### Documentation
- [DuckDuckHack Documentation](http://docs.duckduckhack.com) by [DuckDuckGo](https://duckduckgo.com/about)
+- [Loomio Handbook](http://loomio.coop/) by [Loomio](https://www.loomio.org/)
+- [Enspiral Handbook](http://handbook.enspiral.com/) by [Enspiral](http://enspiral.com/)
- This documentation
diff --git a/docs/plugins/testing.md b/docs/plugins/testing.md
index bf00da2..c832f11 100644
--- a/docs/plugins/testing.md
+++ b/docs/plugins/testing.md
@@ -2,7 +2,7 @@
### Testing your plugin locally
-Testing your plugin on your book before plushing it is possible using [npm link](https://docs.npmjs.com/cli/link).
+Testing your plugin on your book before publishing it is possible using [npm link](https://docs.npmjs.com/cli/link).
In the plugin's folder, run:
@@ -10,7 +10,7 @@ In the plugin's folder, run:
$ npm link
```
-The nin your book's folder:
+Then in your book's folder:
```
$ npm link gitbook-plugin-<plugin's name>
diff --git a/docs/styles/website.css b/docs/styles/website.css
new file mode 100644
index 0000000..c5e8889
--- /dev/null
+++ b/docs/styles/website.css
@@ -0,0 +1,4 @@
+/* Reduce size of logo to allow long versions like 3.0.0-pre.1 */
+.gb-page-header .container .logo h1 {
+ font-size: 24px ;
+}
diff --git a/lib/browser.js b/lib/browser.js
index 7329d74..87a4dc4 100644
--- a/lib/browser.js
+++ b/lib/browser.js
@@ -6,6 +6,7 @@ module.exports = {
// Models
Book: require('./models/book'),
FS: require('./models/fs'),
+ File: require('./models/file'),
Summary: require('./models/summary'),
Glossary: require('./models/glossary'),
Config: require('./models/config'),
diff --git a/lib/cli/serve.js b/lib/cli/serve.js
index 4ba5148..5340851 100644
--- a/lib/cli/serve.js
+++ b/lib/cli/serve.js
@@ -1,6 +1,7 @@
/* eslint-disable no-console */
var tinylr = require('tiny-lr');
+var open = require('open');
var Parse = require('../parse');
var Output = require('../output');
@@ -32,9 +33,11 @@ function generateBook(args, kwargs) {
var outputFolder = getOutputFolder(args);
var book = getBook(args, kwargs);
var Generator = Output.getGenerator(kwargs.format);
+ var browser = kwargs['browser'];
var hasWatch = kwargs['watch'];
var hasLiveReloading = kwargs['live'];
+ var hasOpen = kwargs['open'];
// Stop server if running
if (server.isRunning()) console.log('Stopping server');
@@ -71,6 +74,10 @@ function generateBook(args, kwargs) {
}
});
}
+
+ if (hasOpen) {
+ open('http://localhost:'+port, browser);
+ }
})
.then(function() {
if (!hasWatch) {
@@ -112,6 +119,16 @@ module.exports = {
description: 'Enable live reloading',
defaults: true
},
+ {
+ name: 'open',
+ description: 'Enable opening book in browser',
+ defaults: false
+ },
+ {
+ name: 'browser',
+ description: 'Specify browser for opening book',
+ defaults: ''
+ },
options.log,
options.format
],
diff --git a/lib/constants/configSchema.js b/lib/constants/configSchema.js
index e693977..d2126c6 100644
--- a/lib/constants/configSchema.js
+++ b/lib/constants/configSchema.js
@@ -18,6 +18,10 @@ module.exports = {
'type': 'string',
'title': 'ISBN for published book'
},
+ 'language': {
+ 'type': 'string',
+ 'title': 'Language of the book'
+ },
'author': {
'type': 'string',
'title': 'Name of the author'
diff --git a/lib/json/encodeBookWithPage.js b/lib/json/encodeBookWithPage.js
index 5600a82..1c5c7a3 100644
--- a/lib/json/encodeBookWithPage.js
+++ b/lib/json/encodeBookWithPage.js
@@ -3,12 +3,12 @@ var encodePage = require('./encodePage');
var encodeFile = require('./encodeFile');
/**
- Return a JSON representation of a book with a specific file
-
- @param {Book} output
- @param {Page} page
- @return {Object}
-*/
+ * Return a JSON representation of a book with a specific file
+ *
+ * @param {Book} output
+ * @param {Page} page
+ * @return {Object}
+ */
function encodeBookWithPage(book, page) {
var file = page.getFile();
diff --git a/lib/json/encodeOutput.js b/lib/json/encodeOutput.js
index 9054124..7347e57 100644
--- a/lib/json/encodeOutput.js
+++ b/lib/json/encodeOutput.js
@@ -1,11 +1,11 @@
var encodeBook = require('./encodeBook');
/**
- Encode an output to JSON
-
- @param {Output}
- @return {Object}
-*/
+ * Encode an output to JSON
+ *
+ * @param {Output}
+ * @return {Object}
+ */
function encodeOutputToJson(output) {
var book = output.getBook();
var generator = output.getGenerator();
diff --git a/lib/json/encodeOutputWithPage.js b/lib/json/encodeOutputWithPage.js
new file mode 100644
index 0000000..8b21e3d
--- /dev/null
+++ b/lib/json/encodeOutputWithPage.js
@@ -0,0 +1,23 @@
+var encodeOutput = require('./encodeOutput');
+var encodePage = require('./encodePage');
+var encodeFile = require('./encodeFile');
+
+/**
+ * Return a JSON representation of a book with a specific file
+ *
+ * @param {Book} output
+ * @param {Page} page
+ * @return {Object}
+ */
+function encodeOutputWithPage(output, page) {
+ var file = page.getFile();
+ var book = output.getBook();
+
+ var result = encodeOutput(output);
+ result.page = encodePage(page, book.getSummary());
+ result.file = encodeFile(file);
+
+ return result;
+}
+
+module.exports = encodeOutputWithPage;
diff --git a/lib/json/index.js b/lib/json/index.js
index 4387ae0..3b68f5e 100644
--- a/lib/json/index.js
+++ b/lib/json/index.js
@@ -2,6 +2,7 @@
module.exports = {
encodeOutput: require('./encodeOutput'),
encodeBookWithPage: require('./encodeBookWithPage'),
+ encodeOutputWithPage: require('./encodeOutputWithPage'),
encodeBook: require('./encodeBook'),
encodeFile: require('./encodeFile'),
encodePage: require('./encodePage'),
diff --git a/lib/models/__tests__/summaryArticle.js b/lib/models/__tests__/summaryArticle.js
index 7c4bc57..22a7a20 100644
--- a/lib/models/__tests__/summaryArticle.js
+++ b/lib/models/__tests__/summaryArticle.js
@@ -1,4 +1,5 @@
var SummaryArticle = require('../summaryArticle');
+var File = require('../file');
describe('SummaryArticle', function() {
describe('createChildLevel', function() {
@@ -18,6 +19,35 @@ describe('SummaryArticle', function() {
expect(article.createChildLevel()).toBe('1.1.2');
});
});
+
+ describe('isFile', function() {
+ it('must return true when exactly the file', function() {
+ var article = SummaryArticle.create({
+ ref: 'hello.md'
+ }, '1.1');
+ var file = File.createWithFilepath('hello.md');
+
+ expect(article.isFile(file)).toBe(true);
+ });
+
+ it('must return true when path is not normalized', function() {
+ var article = SummaryArticle.create({
+ ref: '/hello.md'
+ }, '1.1');
+ var file = File.createWithFilepath('hello.md');
+
+ expect(article.isFile(file)).toBe(true);
+ });
+
+ it('must return false when has anchor', function() {
+ var article = SummaryArticle.create({
+ ref: 'hello.md#world'
+ }, '1.1');
+ var file = File.createWithFilepath('hello.md');
+
+ expect(article.isFile(file)).toBe(false);
+ });
+ });
});
diff --git a/lib/models/summaryArticle.js b/lib/models/summaryArticle.js
index 9b5b653..6da8d1d 100644
--- a/lib/models/summaryArticle.js
+++ b/lib/models/summaryArticle.js
@@ -40,7 +40,8 @@ SummaryArticle.prototype.getDepth = function() {
};
/**
- * Get path (without anchor) to the pointing file
+ * Get path (without anchor) to the pointing file.
+ * It also normalizes the file path.
*
* @return {String}
*/
@@ -58,8 +59,8 @@ SummaryArticle.prototype.getPath = function() {
var pathname = (parts.length > 1? parts.slice(0, -1).join('#') : ref);
- // Normalize path to remove ('./', etc)
- return location.normalize(pathname);
+ // Normalize path to remove ('./', '/...', etc)
+ return location.flatten(pathname);
};
/**
@@ -107,6 +108,32 @@ SummaryArticle.prototype.isPage = function() {
};
/**
+ * Check if this article is a file (exatcly)
+ *
+ * @param {File} file
+ * @return {Boolean}
+ */
+SummaryArticle.prototype.isFile = function(file) {
+ return (
+ file.getPath() === this.getPath()
+ && this.getAnchor() === undefined
+ );
+};
+
+/**
+ * Check if this article is the introduction of the book
+ *
+ * @param {Book|Readme} book
+ * @return {Boolean}
+ */
+SummaryArticle.prototype.isReadme = function(book) {
+ var readme = book.getFile? book : book.getReadme();
+ var file = readme.getFile();
+
+ return this.isFile(file);
+};
+
+/**
* Is article pointing to aan absolute url
*
* @return {Boolean}
diff --git a/lib/modifiers/config/editPlugin.js b/lib/modifiers/config/editPlugin.js
index f9b6551..a792acd 100644
--- a/lib/modifiers/config/editPlugin.js
+++ b/lib/modifiers/config/editPlugin.js
@@ -7,7 +7,7 @@
* @return {Config}
*/
function editPlugin(config, pluginName, pluginConfig) {
- return config.set('pluginsConfig.'+pluginName, pluginConfig);
+ return config.setValue('pluginsConfig.'+pluginName, pluginConfig);
}
module.exports = editPlugin;
diff --git a/lib/modifiers/config/getPluginConfig.js b/lib/modifiers/config/getPluginConfig.js
new file mode 100644
index 0000000..ae76de8
--- /dev/null
+++ b/lib/modifiers/config/getPluginConfig.js
@@ -0,0 +1,20 @@
+/**
+ * Return the configuration for a plugin
+ * @param {Config} config
+ * @param {String} pluginName
+ * @return {Object}
+ */
+function getPluginConfig(config, pluginName) {
+ var pluginsConfig = config.getValues().get('pluginsConfig');
+ if (pluginsConfig === undefined) {
+ return {};
+ }
+ var pluginConf = pluginsConfig.get(pluginName);
+ if (pluginConf === undefined) {
+ return {};
+ } else {
+ return pluginConf.toJS();
+ }
+}
+
+module.exports = getPluginConfig;
diff --git a/lib/modifiers/config/index.js b/lib/modifiers/config/index.js
index 5705dbb..b3de0b0 100644
--- a/lib/modifiers/config/index.js
+++ b/lib/modifiers/config/index.js
@@ -5,5 +5,6 @@ module.exports = {
togglePlugin: require('./togglePlugin'),
editPlugin: require('./editPlugin'),
hasPlugin: require('./hasPlugin'),
+ getPluginConfig: require('./getPluginConfig'),
isDefaultPlugin: require('./isDefaultPlugin')
};
diff --git a/lib/output/__tests__/createMock.js b/lib/output/__tests__/createMock.js
new file mode 100644
index 0000000..f21c544
--- /dev/null
+++ b/lib/output/__tests__/createMock.js
@@ -0,0 +1,38 @@
+var Immutable = require('immutable');
+
+var Output = require('../../models/output');
+var Book = require('../../models/book');
+var parseBook = require('../../parse/parseBook');
+var createMockFS = require('../../fs/mock');
+var preparePlugins = require('../preparePlugins');
+
+/**
+ * Create an output using a generator
+ *
+ * FOR TESTING PURPOSE ONLY
+ *
+ * @param {Generator} generator
+ * @param {Map<String:String|Map>} files
+ * @return {Promise<Output>}
+ */
+function createMockOutput(generator, files, options) {
+ var fs = createMockFS(files);
+ var book = Book.createForFS(fs);
+ var state = generator.State? generator.State({}) : Immutable.Map();
+
+ book = book.setLogLevel('disabled');
+ options = generator.Options(options);
+
+ return parseBook(book)
+ .then(function(resultBook) {
+ return new Output({
+ book: resultBook,
+ options: options,
+ state: state,
+ generator: generator.name
+ });
+ })
+ .then(preparePlugins);
+}
+
+module.exports = createMockOutput;
diff --git a/lib/output/__tests__/ebook.js b/lib/output/__tests__/ebook.js
index bcac990..9266e9f 100644
--- a/lib/output/__tests__/ebook.js
+++ b/lib/output/__tests__/ebook.js
@@ -1,4 +1,4 @@
-var generateMock = require('../generateMock');
+var generateMock = require('./generateMock');
var EbookGenerator = require('../ebook');
describe('EbookGenerator', function() {
diff --git a/lib/output/generateMock.js b/lib/output/__tests__/generateMock.js
index ac1e193..691ee2d 100644
--- a/lib/output/generateMock.js
+++ b/lib/output/__tests__/generateMock.js
@@ -1,21 +1,20 @@
var tmp = require('tmp');
-var Book = require('../models/book');
-var createMockFS = require('../fs/mock');
-var parseBook = require('../parse/parseBook');
-var generateBook = require('./generateBook');
-
+var Book = require('../../models/book');
+var createMockFS = require('../../fs/mock');
+var parseBook = require('../../parse/parseBook');
+var generateBook = require('../generateBook');
/**
- Generate a book using JSON generator
- And returns the path to the output dir.
-
- FOR TESTING PURPOSE ONLY
-
- @param {Generator}
- @param {Map<String:String|Map>} files
- @return {Promise<String>}
-*/
+ * Generate a book using a generator
+ * And returns the path to the output dir.
+ *
+ * FOR TESTING PURPOSE ONLY
+ *
+ * @param {Generator}
+ * @param {Map<String:String|Map>} files
+ * @return {Promise<String>}
+ */
function generateMock(Generator, files) {
var fs = createMockFS(files);
var book = Book.createForFS(fs);
diff --git a/lib/output/__tests__/json.js b/lib/output/__tests__/json.js
index 9897813..12ab567 100644
--- a/lib/output/__tests__/json.js
+++ b/lib/output/__tests__/json.js
@@ -1,4 +1,4 @@
-var generateMock = require('../generateMock');
+var generateMock = require('./generateMock');
var JSONGenerator = require('../json');
describe('JSONGenerator', function() {
diff --git a/lib/output/__tests__/website.js b/lib/output/__tests__/website.js
index 501503a..1f8c3c0 100644
--- a/lib/output/__tests__/website.js
+++ b/lib/output/__tests__/website.js
@@ -1,5 +1,5 @@
var fs = require('fs');
-var generateMock = require('../generateMock');
+var generateMock = require('./generateMock');
var WebsiteGenerator = require('../website');
describe('WebsiteGenerator', function() {
diff --git a/lib/output/generateBook.js b/lib/output/generateBook.js
index 3c10b1a..46712bd 100644
--- a/lib/output/generateBook.js
+++ b/lib/output/generateBook.js
@@ -13,13 +13,12 @@ var generateAssets = require('./generateAssets');
var generatePages = require('./generatePages');
/**
- Process an output to generate the book
-
- @param {Generator} generator
- @param {Output} output
-
- @return {Promise<Output>}
-*/
+ * Process an output to generate the book
+ *
+ * @param {Generator} generator
+ * @param {Output} output
+ * @return {Promise<Output>}
+ */
function processOutput(generator, startOutput) {
return Promise(startOutput)
.then(preparePlugins)
@@ -133,27 +132,26 @@ function processOutput(generator, startOutput) {
}
/**
- Generate a book using a generator.
-
- The overall process is:
- 1. List and load plugins for this book
- 2. Call hook "config"
- 3. Call hook "init"
- 4. Initialize generator
- 5. List all assets and pages
- 6. Copy all assets to output
- 7. Generate all pages
- 8. Call hook "finish:before"
- 9. Finish generation
- 10. Call hook "finish"
-
-
- @param {Generator} generator
- @param {Book} book
- @param {Object} options
-
- @return {Promise<Output>}
-*/
+ * Generate a book using a generator.
+ *
+ * The overall process is:
+ * 1. List and load plugins for this book
+ * 2. Call hook "config"
+ * 3. Call hook "init"
+ * 4. Initialize generator
+ * 5. List all assets and pages
+ * 6. Copy all assets to output
+ * 7. Generate all pages
+ * 8. Call hook "finish:before"
+ * 9. Finish generation
+ * 10. Call hook "finish"
+ *
+ *
+ * @param {Generator} generator
+ * @param {Book} book
+ * @param {Object} options
+ * @return {Promise<Output>}
+ */
function generateBook(generator, book, options) {
options = generator.Options(options);
var state = generator.State? generator.State({}) : Immutable.Map();
diff --git a/lib/output/generatePage.js b/lib/output/generatePage.js
index fa6fc0e..090a870 100644
--- a/lib/output/generatePage.js
+++ b/lib/output/generatePage.js
@@ -10,12 +10,12 @@ var createTemplateEngine = require('./createTemplateEngine');
var callPageHook = require('./callPageHook');
/**
- Prepare and generate HTML for a page
-
- @param {Output} output
- @param {Page} page
- @return {Promise<Page>}
-*/
+ * Prepare and generate HTML for a page
+ *
+ * @param {Output} output
+ * @param {Page} page
+ * @return {Promise<Page>}
+ */
function generatePage(output, page) {
var book = output.getBook();
var engine = createTemplateEngine(output);
@@ -27,7 +27,7 @@ function generatePage(output, page) {
var file = resultPage.getFile();
var filePath = file.getPath();
var parser = file.getParser();
- var context = JSONUtils.encodeBookWithPage(book, resultPage);
+ var context = JSONUtils.encodeOutputWithPage(output, resultPage);
if (!parser) {
return Promise.reject(error.FileNotParsableError({
diff --git a/lib/output/getModifiers.js b/lib/output/getModifiers.js
index 66fbc1a..bb44e80 100644
--- a/lib/output/getModifiers.js
+++ b/lib/output/getModifiers.js
@@ -9,11 +9,11 @@ var fileToOutput = require('./helper/fileToOutput');
var CODEBLOCK = 'code';
/**
- Return default modifier to prepare a page for
- rendering.
-
- @return {Array<Modifier>}
-*/
+ * Return default modifier to prepare a page for
+ * rendering.
+ *
+ * @return {Array<Modifier>}
+ */
function getModifiers(output, page) {
var book = output.getBook();
var plugins = output.getPlugins();
diff --git a/lib/output/helper/fileToOutput.js b/lib/output/helper/fileToOutput.js
index 9673162..361c6eb 100644
--- a/lib/output/helper/fileToOutput.js
+++ b/lib/output/helper/fileToOutput.js
@@ -6,12 +6,12 @@ var LocationUtils = require('../../utils/location');
var OUTPUT_EXTENSION = '.html';
/**
- Convert a filePath (absolute) to a filename for output
-
- @param {Output} output
- @param {String} filePath
- @return {String}
-*/
+ * Convert a filePath (absolute) to a filename for output
+ *
+ * @param {Output} output
+ * @param {String} filePath
+ * @return {String}
+ */
function fileToOutput(output, filePath) {
var book = output.getBook();
var readme = book.getReadme();
diff --git a/lib/output/helper/resolveFileToURL.js b/lib/output/helper/resolveFileToURL.js
index 026b0e5..3f52713 100644
--- a/lib/output/helper/resolveFileToURL.js
+++ b/lib/output/helper/resolveFileToURL.js
@@ -3,12 +3,12 @@ var LocationUtils = require('../../utils/location');
var fileToURL = require('./fileToURL');
/**
- Resolve an absolute path (extracted from a link)
-
- @param {Output} output
- @param {String} filePath
- @return {String}
-*/
+ * Resolve an absolute path (extracted from a link)
+ *
+ * @param {Output} output
+ * @param {String} filePath
+ * @return {String}
+ */
function resolveFileToURL(output, filePath) {
// Convert /test.png -> test.png
filePath = LocationUtils.toAbsolute(filePath, '', '');
diff --git a/lib/output/json/onPage.js b/lib/output/json/onPage.js
index fece540..2315ba0 100644
--- a/lib/output/json/onPage.js
+++ b/lib/output/json/onPage.js
@@ -7,11 +7,11 @@ var getModifiers = require('../getModifiers');
var JSON_VERSION = '3';
/**
- Write a page as a json file
-
- @param {Output} output
- @param {Page} page
-*/
+ * Write a page as a json file
+ *
+ * @param {Output} output
+ * @param {Page} page
+ */
function onPage(output, page) {
var file = page.getFile();
var readme = output.getBook().getReadme().getFile();
diff --git a/lib/output/modifiers/annotateText.js b/lib/output/modifiers/annotateText.js
index 2b4b439..490c228 100644
--- a/lib/output/modifiers/annotateText.js
+++ b/lib/output/modifiers/annotateText.js
@@ -59,19 +59,18 @@ function replaceText($, el, search, replace, text_only ) {
}
/**
- Annotate text using a list of GlossaryEntry
-
- @param {List<GlossaryEntry>}
- @param {String} glossaryFilePath
- @param {HTMLDom} $
-*/
+ * Annotate text using a list of GlossaryEntry
+ *
+ * @param {List<GlossaryEntry>}
+ * @param {String} glossaryFilePath
+ * @param {HTMLDom} $
+ */
function annotateText(entries, glossaryFilePath, $) {
entries.forEach(function(entry) {
- var entryId = entry.getID();
- var name = entry.getName();
+ var entryId = entry.getID();
+ var name = entry.getName();
var description = entry.getDescription();
-
- var searchRegex = new RegExp( '\\b(' + pregQuote(name.toLowerCase()) + ')\\b' , 'gi' );
+ var searchRegex = new RegExp( '\\b(' + pregQuote(name.toLowerCase()) + ')\\b' , 'gi' );
$('*').each(function() {
var $this = $(this);
diff --git a/lib/output/preparePlugins.js b/lib/output/preparePlugins.js
index 54837ed..5c4be93 100644
--- a/lib/output/preparePlugins.js
+++ b/lib/output/preparePlugins.js
@@ -2,11 +2,11 @@ var Plugins = require('../plugins');
var Promise = require('../utils/promise');
/**
- Load and setup plugins
-
- @param {Output}
- @return {Promise<Output>}
-*/
+ * Load and setup plugins
+ *
+ * @param {Output}
+ * @return {Promise<Output>}
+ */
function preparePlugins(output) {
var book = output.getBook();
diff --git a/lib/output/website/__tests__/i18n.js b/lib/output/website/__tests__/i18n.js
new file mode 100644
index 0000000..fd610fb
--- /dev/null
+++ b/lib/output/website/__tests__/i18n.js
@@ -0,0 +1,38 @@
+var createMockOutput = require('../../__tests__/createMock');
+var prepareI18n = require('../prepareI18n');
+var createTemplateEngine = require('../createTemplateEngine');
+
+var WebsiteGenerator = require('../');
+
+describe('i18n', function() {
+ it('should correctly use english as default language', function() {
+ return createMockOutput(WebsiteGenerator, {
+ 'README.md': 'Hello World'
+ })
+ .then(function(output) {
+ return prepareI18n(output);
+ })
+ .then(function(output) {
+ var engine = createTemplateEngine(output, 'README.md');
+ var t = engine.getFilters().get('t');
+
+ expect(t('SUMMARY_INTRODUCTION')).toEqual('Introduction');
+ });
+ });
+
+ it('should correctly use language from book.json', function() {
+ return createMockOutput(WebsiteGenerator, {
+ 'README.md': 'Hello World',
+ 'book.json': JSON.stringify({ language: 'fr' })
+ })
+ .then(function(output) {
+ return prepareI18n(output);
+ })
+ .then(function(output) {
+ var engine = createTemplateEngine(output, 'README.md');
+ var t = engine.getFilters().get('t');
+
+ expect(t('GITBOOK_LINK')).toEqual('PubliƩ avec GitBook');
+ });
+ });
+});
diff --git a/lib/output/website/createTemplateEngine.js b/lib/output/website/createTemplateEngine.js
index c60b3a1..02ec796 100644
--- a/lib/output/website/createTemplateEngine.js
+++ b/lib/output/website/createTemplateEngine.js
@@ -18,19 +18,19 @@ var fileToURL = require('../helper/fileToURL');
var resolveFileToURL = require('../helper/resolveFileToURL');
/**
- Directory for a theme with the templates
-*/
+ * Directory for a theme with the templates
+ */
function templateFolder(dir) {
return path.join(dir, templatesFolder);
}
/**
- Create templating engine to render themes
-
- @param {Output} output
- @param {String} currentFile
- @return {TemplateEngine}
-*/
+ * Create templating engine to render themes
+ *
+ * @param {Output} output
+ * @param {String} currentFile
+ * @return {TemplateEngine}
+ */
function createTemplateEngine(output, currentFile) {
var book = output.getBook();
var state = output.getState();
@@ -47,18 +47,17 @@ function createTemplateEngine(output, currentFile) {
var loader = new Templating.ThemesLoader(tplSearchPaths);
// Get languages
- var language = config.get('language');
+ var language = config.getValue('language');
// Create API context
var context = Api.encodeGlobal(output);
/**
- Check if a file exists
-
- @param {String} fileName
- @return {Boolean}
- */
+ * Check if a file exists
+ * @param {String} fileName
+ * @return {Boolean}
+ */
function fileExists(fileName) {
if (!fileName) {
return false;
@@ -69,11 +68,10 @@ function createTemplateEngine(output, currentFile) {
}
/**
- Return an article by its path
-
- @param {String} filePath
- @return {Object|undefined}
- */
+ * Return an article by its path
+ * @param {String} filePath
+ * @return {Object|undefined}
+ */
function getArticleByPath(filePath) {
var article = summary.getByPath(filePath);
if (!article) return undefined;
@@ -82,11 +80,10 @@ function createTemplateEngine(output, currentFile) {
}
/**
- Return a page by its path
-
- @param {String} filePath
- @return {Object|undefined}
- */
+ * Return a page by its path
+ * @param {String} filePath
+ * @return {Object|undefined}
+ */
function getPageByPath(filePath) {
var page = output.getPage(filePath);
if (!page) return undefined;
@@ -94,7 +91,6 @@ function createTemplateEngine(output, currentFile) {
return JSONUtils.encodePage(page, summary);
}
-
return TemplateEngine.create({
loader: loader,
@@ -108,17 +104,17 @@ function createTemplateEngine(output, currentFile) {
filters: defaultFilters.merge({
/**
- Translate a sentence
- */
+ * Translate a sentence
+ */
t: function t(s) {
return i18n.t(language, s);
},
/**
- Resolve an absolute file path into a
- relative path.
- it also resolve pages
- */
+ * Resolve an absolute file path into a
+ * relative path.
+ * it also resolve pages
+ */
resolveFile: function(filePath) {
filePath = resolveFileToURL(output, filePath);
return LocationUtils.relativeForFile(currentFile, filePath);
diff --git a/lib/output/website/onPage.js b/lib/output/website/onPage.js
index 14c7b22..5fb40a7 100644
--- a/lib/output/website/onPage.js
+++ b/lib/output/website/onPage.js
@@ -12,11 +12,11 @@ var createTemplateEngine = require('./createTemplateEngine');
var fileToOutput = require('../helper/fileToOutput');
/**
- Write a page as a json file
-
- @param {Output} output
- @param {Page} page
-*/
+ * Write a page as a json file
+ *
+ * @param {Output} output
+ * @param {Page} page
+ */
function onPage(output, page) {
var options = output.getOptions();
var prefix = options.get('prefix');
@@ -40,7 +40,7 @@ function onPage(output, page) {
return Modifiers.modifyHTML(page, getModifiers(output, page))
.then(function(resultPage) {
// Generate the context
- var context = JSONUtils.encodeBookWithPage(output.getBook(), resultPage);
+ var context = JSONUtils.encodeOutputWithPage(output, resultPage);
context.plugins = {
resources: Plugins.listResources(plugins, resources).toJS()
};
diff --git a/lib/output/website/prepareI18n.js b/lib/output/website/prepareI18n.js
index b57d178..cedd3b9 100644
--- a/lib/output/website/prepareI18n.js
+++ b/lib/output/website/prepareI18n.js
@@ -5,11 +5,11 @@ var Promise = require('../../utils/promise');
var listSearchPaths = require('./listSearchPaths');
/**
- Prepare i18n, load translations from plugins and book
-
- @param {Output}
- @return {Promise<Output>}
-*/
+ * Prepare i18n, load translations from plugins and book
+ *
+ * @param {Output}
+ * @return {Promise<Output>}
+ */
function prepareI18n(output) {
var state = output.getState();
var i18n = state.getI18n();
diff --git a/lib/utils/__tests__/location.js b/lib/utils/__tests__/location.js
index 2d01714..822338e 100644
--- a/lib/utils/__tests__/location.js
+++ b/lib/utils/__tests__/location.js
@@ -39,6 +39,21 @@ describe('LocationUtils', function() {
});
});
+ describe('.flatten', function() {
+ it('should remove leading slash', function() {
+ expect(LocationUtils.flatten('/test.md')).toBe('test.md');
+ expect(LocationUtils.flatten('/hello/cool.md')).toBe('hello/cool.md');
+ });
+
+ it('should remove leading slashes', function() {
+ expect(LocationUtils.flatten('///test.md')).toBe('test.md');
+ });
+
+ it('should not break paths', function() {
+ expect(LocationUtils.flatten('hello/cool.md')).toBe('hello/cool.md');
+ });
+ });
+
describe('.toAbsolute', function() {
it('should correctly transform as absolute', function() {
expect(LocationUtils.toAbsolute('http://google.fr')).toBe('http://google.fr');
diff --git a/lib/utils/location.js b/lib/utils/location.js
index 17edc00..00d8004 100644
--- a/lib/utils/location.js
+++ b/lib/utils/location.js
@@ -40,13 +40,28 @@ function normalize(s) {
}
/**
- Convert a relative path to absolute
+ * Flatten a path, it removes the leading "/"
+ *
+ * @param {String} href
+ * @return {String}
+ */
+function flatten(href) {
+ href = normalize(href);
+ if (href[0] == '/') {
+ href = normalize(href.slice(1));
+ }
+
+ return href;
+}
- @param {String} href
- @param {String} dir: directory parent of the file currently in rendering process
- @param {String} outdir: directory parent from the html output
- @return {String}
-*/
+/**
+ * Convert a relative path to absolute
+ *
+ * @param {String} href
+ * @param {String} dir: directory parent of the file currently in rendering process
+ * @param {String} outdir: directory parent from the html output
+ * @return {String}
+ */
function toAbsolute(_href, dir, outdir) {
if (isExternal(_href) || isDataURI(_href)) {
return _href;
@@ -74,50 +89,51 @@ function toAbsolute(_href, dir, outdir) {
}
/**
- Convert an absolute path to a relative path for a specific folder (dir)
- ('test/', 'hello.md') -> '../hello.md'
-
- @param {String} dir: current directory
- @param {String} file: absolute path of file
- @return {String}
-*/
+ * Convert an absolute path to a relative path for a specific folder (dir)
+ * ('test/', 'hello.md') -> '../hello.md'
+ *
+ * @param {String} dir: current directory
+ * @param {String} file: absolute path of file
+ * @return {String}
+ */
function relative(dir, file) {
var isDirectory = file.slice(-1) === '/';
return normalize(path.relative(dir, file)) + (isDirectory? '/': '');
}
/**
- Convert an absolute path to a relative path for a specific folder (dir)
- ('test/test.md', 'hello.md') -> '../hello.md'
-
- @param {String} baseFile: current file
- @param {String} file: absolute path of file
- @return {String}
-*/
+ * Convert an absolute path to a relative path for a specific folder (dir)
+ * ('test/test.md', 'hello.md') -> '../hello.md'
+ *
+ * @param {String} baseFile: current file
+ * @param {String} file: absolute path of file
+ * @return {String}
+ */
function relativeForFile(baseFile, file) {
return relative(path.dirname(baseFile), file);
}
/**
- Compare two paths, return true if they are identical
- ('README.md', './README.md') -> true
-
- @param {String} p1: first path
- @param {String} p2: second path
- @return {Boolean}
-*/
+ * Compare two paths, return true if they are identical
+ * ('README.md', './README.md') -> true
+ *
+ * @param {String} p1: first path
+ * @param {String} p2: second path
+ * @return {Boolean}
+ */
function areIdenticalPaths(p1, p2) {
return normalize(p1) === normalize(p2);
}
module.exports = {
areIdenticalPaths: areIdenticalPaths,
- isDataURI: isDataURI,
- isExternal: isExternal,
- isRelative: isRelative,
- isAnchor: isAnchor,
- normalize: normalize,
- toAbsolute: toAbsolute,
- relative: relative,
- relativeForFile: relativeForFile
+ isDataURI: isDataURI,
+ isExternal: isExternal,
+ isRelative: isRelative,
+ isAnchor: isAnchor,
+ normalize: normalize,
+ toAbsolute: toAbsolute,
+ relative: relative,
+ relativeForFile: relativeForFile,
+ flatten: flatten
};
diff --git a/lib/utils/promise.js b/lib/utils/promise.js
index 138546b..b5cca4b 100644
--- a/lib/utils/promise.js
+++ b/lib/utils/promise.js
@@ -2,34 +2,35 @@ var Q = require('q');
var Immutable = require('immutable');
// Debugging for long stack traces
-if (global.__DEV__ || process.env.DEBUG) {
+if (process.env.DEBUG || process.env.CI) {
Q.longStackSupport = true;
}
/**
- Reduce an array to a promise
-
- @param {Array|List} arr
- @param {Function(value, element, index)}
- @return {Promise<Mixed>}
-*/
+ * Reduce an array to a promise
+ *
+ * @param {Array|List} arr
+ * @param {Function(value, element, index)}
+ * @return {Promise<Mixed>}
+ */
function reduce(arr, iter, base) {
arr = Immutable.Iterable.isIterable(arr)? arr : Immutable.List(arr);
return arr.reduce(function(prev, elem, key) {
- return prev.then(function(val) {
+ return prev
+ .then(function(val) {
return iter(val, elem, key);
});
}, Q(base));
}
/**
- Iterate over an array using an async iter
-
- @param {Array|List} arr
- @param {Function(value, element, index)}
- @return {Promise}
-*/
+ * Iterate over an array using an async iter
+ *
+ * @param {Array|List} arr
+ * @param {Function(value, element, index)}
+ * @return {Promise}
+ */
function forEach(arr, iter) {
return reduce(arr, function(val, el, key) {
return iter(el, key);
@@ -37,12 +38,12 @@ function forEach(arr, iter) {
}
/**
- Transform an array
-
- @param {Array|List} arr
- @param {Function(value, element, index)}
- @return {Promise}
-*/
+ * Transform an array
+ *
+ * @param {Array|List} arr
+ * @param {Function(value, element, index)}
+ * @return {Promise}
+ */
function serie(arr, iter, base) {
return reduce(arr, function(before, item, key) {
return Q(iter(item, key))
@@ -54,12 +55,12 @@ function serie(arr, iter, base) {
}
/**
- Iter over an array and return first result (not null)
-
- @param {Array|List} arr
- @param {Function(element, index)}
- @return {Promise<Mixed>}
-*/
+ * Iter over an array and return first result (not null)
+ *
+ * @param {Array|List} arr
+ * @param {Function(element, index)}
+ * @return {Promise<Mixed>}
+ */
function some(arr, iter) {
arr = Immutable.List(arr);
@@ -73,12 +74,12 @@ function some(arr, iter) {
}
/**
- Map an array using an async (promised) iterator
-
- @param {Array|List} arr
- @param {Function(element, index)}
- @return {Promise<List>}
-*/
+ * Map an array using an async (promised) iterator
+ *
+ * @param {Array|List} arr
+ * @param {Function(element, index)}
+ * @return {Promise<List>}
+ */
function mapAsList(arr, iter) {
return reduce(arr, function(prev, entry, i) {
return Q(iter(entry, i))
@@ -90,12 +91,12 @@ function mapAsList(arr, iter) {
}
/**
- Map an array or map
-
- @param {Array|List|Map|OrderedMap} arr
- @param {Function(element, key)}
- @return {Promise<List|Map|OrderedMap>}
-*/
+ * Map an array or map
+ *
+ * @param {Array|List|Map|OrderedMap} arr
+ * @param {Function(element, key)}
+ * @return {Promise<List|Map|OrderedMap>}
+ */
function map(arr, iter) {
if (Immutable.Map.isMap(arr)) {
var type = 'Map';
@@ -122,11 +123,11 @@ function map(arr, iter) {
/**
- Wrap a function in a promise
-
- @param {Function} func
- @return {Funciton}
-*/
+ * Wrap a function in a promise
+ *
+ * @param {Function} func
+ * @return {Funciton}
+ */
function wrap(func) {
return function() {
var args = Array.prototype.slice.call(arguments, 0);
diff --git a/lib/utils/reducedObject.js b/lib/utils/reducedObject.js
index fa5d32c..7bcfd5b 100644
--- a/lib/utils/reducedObject.js
+++ b/lib/utils/reducedObject.js
@@ -4,8 +4,13 @@ var Immutable = require('immutable');
* Reduce the difference between a map and its default version
* @param {Map} defaultVersion
* @param {Map} currentVersion
+ * @return {Map} The properties of currentVersion that differs from defaultVersion
*/
function reducedObject(defaultVersion, currentVersion) {
+ if(defaultVersion === undefined) {
+ return currentVersion;
+ }
+
return currentVersion.reduce(function(result, value, key) {
var defaultValue = defaultVersion.get(key);
diff --git a/package.json b/package.json
index b91620e..04be84b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "gitbook",
- "version": "3.1.1",
+ "version": "3.2.1",
"homepage": "https://www.gitbook.com",
"description": "Library and cmd utility to generate GitBooks",
"main": "lib/index.js",
@@ -22,14 +22,14 @@
"fresh-require": "1.0.3",
"front-matter": "^2.1.0",
"gitbook-asciidoc": "1.2.2",
- "gitbook-markdown": "1.3.2",
+ "gitbook-markdown": "2.0.1",
"gitbook-plugin-fontsettings": "2.0.0",
"gitbook-plugin-highlight": "2.0.2",
"gitbook-plugin-livereload": "0.0.1",
- "gitbook-plugin-lunr": "1.1.0",
+ "gitbook-plugin-lunr": "1.2.0",
"gitbook-plugin-search": "2.2.1",
"gitbook-plugin-sharing": "1.0.2",
- "gitbook-plugin-theme-default": "1.0.4",
+ "gitbook-plugin-theme-default": "1.0.6",
"github-slugid": "1.0.1",
"graceful-fs": "4.1.4",
"i18n-t": "1.0.1",
@@ -44,10 +44,11 @@
"moment": "2.13.0",
"npm": "3.9.2",
"npmi": "2.0.1",
- "nunjucks": "2.4.2",
+ "nunjucks": "2.5.2",
"nunjucks-do": "1.0.0",
"object-path": "^0.9.2",
"omit-keys": "^0.1.0",
+ "open": "0.0.5",
"q": "1.4.1",
"read-installed": "^4.0.3",
"request": "2.72.0",