Compare commits

...

20 Commits

Author SHA1 Message Date
Samy Pessé 38ab9fa05a Bump version to 3.2.0 2016-07-11 16:48:13 +02:00
Samy Pessé 12e20c5fcc Update theme-default@1.0.5 2016-07-11 16:47:16 +02:00
Samy Pessé 6b103f4532 Fix #1408: fix i18n in website generator and add tests for it 2016-07-11 16:27:22 +02:00
Soreine d4fa5c18a8 editPlugin and getPluginConfig 2016-07-11 15:18:35 +02:00
Soreine 2a116dfdb0 Fix reducedObject when default property is undefined 2016-07-11 15:18:35 +02:00
Samy Pessé 0349f54f3c Export file model 2016-07-07 16:41:05 +02:00
Samy Pessé 695bda312c Bump version to 3.2.0-pre.1 2016-07-05 17:15:48 +02:00
Samy Pessé 144bd4c97a Update gitbook-markdown@2.0.1 2016-07-05 11:07:51 +02:00
Samy Pessé e105983cf8 Add back property "output" to page/template context 2016-07-04 18:08:44 +02:00
Soreine ea3afbed75 Update gitbook-plugin-lunr@1.2.0 2016-07-01 17:52:15 +02:00
Soreine d563abe3df Reduce size of logo to give room to version number 2016-06-30 15:37:31 +02:00
Soreine 70fd4ded29 Update theme-official for doc 2016-06-30 12:15:50 +02:00
Samy Pessé 9ce9388dfc Bump version to 3.2.0-pre.0 2016-06-30 11:09:18 +02:00
Samy Pessé c575ad83ae Update gitbook-markdown@2.0.0 2016-06-30 10:51:46 +02:00
Samy Pessé 936fa1545b Add tests for locationUtils.flatten 2016-06-29 10:32:49 +02:00
Samy Pessé c9c2dde2b6 Add method "isFile" and "isReadme" in SummaryArticle 2016-06-29 10:31:06 +02:00
Samy Pessé d9a1d387c7 Merge pull request #1397 from mpfeil/master
add open and browser args to serve command
2016-06-23 11:40:05 +02:00
Matthias Pfeil bf29d187c8 disable open by default 2016-06-20 17:24:08 +02:00
Matthias Pfeil d86f9b2667 add open and browser args to serve command 2016-06-17 16:00:53 +02:00
Samy Pesse aca4313fc3 Enable long stack support when process.env.CI is true 2016-06-11 12:38:19 +02:00
37 changed files with 473 additions and 230 deletions
+9
View File
@@ -2,6 +2,15 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## 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
+2 -2
View File
@@ -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
+4
View File
@@ -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 ;
}
+1
View File
@@ -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'),
+17
View File
@@ -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
],
+4
View File
@@ -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'
+6 -6
View File
@@ -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();
+5 -5
View File
@@ -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();
+23
View File
@@ -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;
+1
View File
@@ -2,6 +2,7 @@
module.exports = {
encodeOutput: require('./encodeOutput'),
encodeBookWithPage: require('./encodeBookWithPage'),
encodeOutputWithPage: require('./encodeOutputWithPage'),
encodeBook: require('./encodeBook'),
encodeFile: require('./encodeFile'),
encodePage: require('./encodePage'),
+30
View File
@@ -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);
});
});
});
+30 -3
View File
@@ -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);
};
/**
@@ -106,6 +107,32 @@ SummaryArticle.prototype.isPage = function() {
return !this.isExternal() && this.getRef();
};
/**
* 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
*
+1 -1
View File
@@ -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;
+20
View File
@@ -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;
+1
View File
@@ -5,5 +5,6 @@ module.exports = {
togglePlugin: require('./togglePlugin'),
editPlugin: require('./editPlugin'),
hasPlugin: require('./hasPlugin'),
getPluginConfig: require('./getPluginConfig'),
isDefaultPlugin: require('./isDefaultPlugin')
};
+38
View File
@@ -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;
+1 -1
View File
@@ -1,4 +1,4 @@
var generateMock = require('../generateMock');
var generateMock = require('./generateMock');
var EbookGenerator = require('../ebook');
describe('EbookGenerator', function() {
@@ -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);
+1 -1
View File
@@ -1,4 +1,4 @@
var generateMock = require('../generateMock');
var generateMock = require('./generateMock');
var JSONGenerator = require('../json');
describe('JSONGenerator', function() {
+1 -1
View File
@@ -1,5 +1,5 @@
var fs = require('fs');
var generateMock = require('../generateMock');
var generateMock = require('./generateMock');
var WebsiteGenerator = require('../website');
describe('WebsiteGenerator', function() {
+26 -28
View File
@@ -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();
+7 -7
View File
@@ -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({
+5 -5
View File
@@ -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();
+6 -6
View File
@@ -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();
+6 -6
View File
@@ -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, '', '');
+5 -5
View File
@@ -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();
+9 -10
View File
@@ -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);
+5 -5
View File
@@ -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();
+38
View File
@@ -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');
});
});
});
+27 -31
View File
@@ -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);
+6 -6
View File
@@ -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()
};
+5 -5
View File
@@ -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();
+15
View File
@@ -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');
+51 -35
View File
@@ -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));
}
@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}
*/
return href;
}
/**
* 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
};
+44 -43
View File
@@ -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);
+5
View File
@@ -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);
+5 -4
View File
@@ -1,6 +1,6 @@
{
"name": "gitbook",
"version": "3.1.1",
"version": "3.2.0",
"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.5",
"github-slugid": "1.0.1",
"graceful-fs": "4.1.4",
"i18n-t": "1.0.1",
@@ -48,6 +48,7 @@
"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",