mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-28 13:08:57 +00:00
Compare commits
53 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fdf4a48638 | |||
| 58a3c5634e | |||
| f0ddb6e89f | |||
| 2b408db7cb | |||
| 4e4bd23e2b | |||
| 62d0eb606e | |||
| 0e9beeae14 | |||
| 5e4dbdee24 | |||
| 9435dae6cd | |||
| 813210bf47 | |||
| c372dfc544 | |||
| ac77200683 | |||
| f5afbc90a4 | |||
| b24760c819 | |||
| 6732957e42 | |||
| 1fd0006859 | |||
| 5a205346e3 | |||
| e193004659 | |||
| fe3a9c33d0 | |||
| d83116b88f | |||
| 5f56098ae7 | |||
| 0f935f4372 | |||
| df5c5a8c01 | |||
| 57a0c3bad8 | |||
| 2a52326a45 | |||
| 87e4ee1eeb | |||
| 45833eea9a | |||
| baf10e9b15 | |||
| 463a947df1 | |||
| cceebb4fd9 | |||
| afd5465a61 | |||
| fe604733de | |||
| da22f9f39f | |||
| 284ebbf75d | |||
| 2c08ccad87 | |||
| fa4e234bab | |||
| 35c4179ca1 | |||
| c14ba7ce34 | |||
| 601ce3add3 | |||
| 08ff39fd0b | |||
| 82a6ee3875 | |||
| 3bf592f870 | |||
| 241e205717 | |||
| fb2720ea8d | |||
| 14853befda | |||
| e7f2803d11 | |||
| 320015dd8f | |||
| 471c124a98 | |||
| aa44a109c6 | |||
| 41e5ca8422 | |||
| d699dff872 | |||
| dbc75f7352 | |||
| db841a8578 |
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"strict": false,
|
||||||
|
"browser": false,
|
||||||
|
"quotmark": true,
|
||||||
|
"node": true,
|
||||||
|
"mocha": true
|
||||||
|
}
|
||||||
+23
@@ -2,6 +2,29 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
## 2.4.2
|
||||||
|
- Default plugins should not be installed by `gitbook install`
|
||||||
|
- Limit search index size to avoid crash during generation
|
||||||
|
- Fix code highlighting for html without language specified
|
||||||
|
- Fix warning message for gitbook version when building a multilingual book
|
||||||
|
|
||||||
|
## 2.4.1
|
||||||
|
- Fix disabling of default plugins, ex: `-highlight`
|
||||||
|
|
||||||
|
## 2.4.0
|
||||||
|
- Fix page being updated when user wants to open a link in a new tab
|
||||||
|
- Plugins can now replaced default code highlighter
|
||||||
|
- Add semantic information for screen readers (web version)
|
||||||
|
- Content references accept absolute paths, resolved to book folder
|
||||||
|
- Improve overall reliability
|
||||||
|
|
||||||
|
## 2.3.3
|
||||||
|
- Fix bug in SUMMARY parsing preventing multiple entries without filenames
|
||||||
|
|
||||||
|
## 2.3.2
|
||||||
|
- Fix blocks (like maths) in Asciidoc
|
||||||
|
- Fix error when checking gitbook version
|
||||||
|
|
||||||
## 2.3.1
|
## 2.3.1
|
||||||
- Fix black font color for ebooks (mobi, pdf and epub)
|
- Fix black font color for ebooks (mobi, pdf and epub)
|
||||||
- Fix ISO code for korean language
|
- Fix ISO code for korean language
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ GitBook
|
|||||||
|
|
||||||
GitBook is a command line tool (and Node.js library) for building beautiful books using GitHub/Git and Markdown (or AsciiDoc). Here is an example: [Learn Javascript](https://www.gitbook.com/book/GitBookIO/javascript).
|
GitBook is a command line tool (and Node.js library) for building beautiful books using GitHub/Git and Markdown (or AsciiDoc). Here is an example: [Learn Javascript](https://www.gitbook.com/book/GitBookIO/javascript).
|
||||||
|
|
||||||
You can publish and host book easily online using [gitbook.com](https://www.gitbook.com), a web-editor is [also available](https://www.gitbook.com/editor).
|
You can publish and host book easily online using [gitbook.com](https://www.gitbook.com), a desktop editor is [also available](https://www.gitbook.com/editor).
|
||||||
|
|
||||||
Stay updated by following [@GitBookIO](https://twitter.com/GitBookIO) on Twitter or [GitBook](https://www.facebook.com/gitbookcom) on Facebook.
|
Stay updated by following [@GitBookIO](https://twitter.com/GitBookIO) on Twitter or [GitBook](https://www.facebook.com/gitbookcom) on Facebook.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
var _ = require('lodash');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// Return non-parsed html
|
||||||
|
// since blocks are by default non-parsable, a simple identity method works fine
|
||||||
|
html: _.identity,
|
||||||
|
|
||||||
|
// Highlight a code block
|
||||||
|
// This block can be extent by plugins
|
||||||
|
code: _.identity
|
||||||
|
};
|
||||||
+89
-63
@@ -1,30 +1,27 @@
|
|||||||
var Q = require("q");
|
var Q = require("q");
|
||||||
var _ = require("lodash");
|
var _ = require("lodash");
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
var util = require("util");
|
|
||||||
var lunr = require("lunr");
|
var lunr = require("lunr");
|
||||||
var parsers = require("gitbook-parsers");
|
var parsers = require("gitbook-parsers");
|
||||||
var color = require("bash-color");
|
|
||||||
|
|
||||||
var fs = require("./utils/fs");
|
var fs = require("./utils/fs");
|
||||||
var parseNavigation = require("./utils/navigation");
|
var parseNavigation = require("./utils/navigation");
|
||||||
var parseProgress = require("./utils/progress");
|
var parseProgress = require("./utils/progress");
|
||||||
var pageUtil = require("./utils/page");
|
var pageUtil = require("./utils/page");
|
||||||
var batch = require("./utils/batch");
|
var pathUtil = require("./utils/path");
|
||||||
var links = require("./utils/links");
|
var links = require("./utils/links");
|
||||||
var i18n = require("./utils/i18n");
|
var i18n = require("./utils/i18n");
|
||||||
var logger = require("./utils/logger");
|
var logger = require("./utils/logger");
|
||||||
|
|
||||||
var Configuration = require("./configuration");
|
var Configuration = require("./configuration");
|
||||||
var TemplateEngine = require("./template");
|
var TemplateEngine = require("./template");
|
||||||
var Plugin = require("./plugin");
|
|
||||||
var PluginsList = require("./pluginslist");
|
var PluginsList = require("./pluginslist");
|
||||||
|
|
||||||
var generators = require("./generators");
|
var generators = require("./generators");
|
||||||
|
|
||||||
var Book = function(root, context, parent) {
|
var SEARCHINDEX_MAXSIZE = 1000000;
|
||||||
var that = this;
|
|
||||||
|
|
||||||
|
var Book = function(root, context, parent) {
|
||||||
this.context = _.defaults(context || {}, {
|
this.context = _.defaults(context || {}, {
|
||||||
// Extend book configuration
|
// Extend book configuration
|
||||||
config: {},
|
config: {},
|
||||||
@@ -84,11 +81,13 @@ var Book = function(root, context, parent) {
|
|||||||
this.langsFile = null;
|
this.langsFile = null;
|
||||||
|
|
||||||
// Search Index
|
// Search Index
|
||||||
|
this.searchIndexEnabled = true;
|
||||||
|
this.searchIndexSize = 0;
|
||||||
this.searchIndex = lunr(function () {
|
this.searchIndex = lunr(function () {
|
||||||
this.ref('url');
|
this.ref("url");
|
||||||
|
|
||||||
this.field('title', { boost: 10 });
|
this.field("title", { boost: 10 });
|
||||||
this.field('body');
|
this.field("body");
|
||||||
});
|
});
|
||||||
|
|
||||||
// Bind methods
|
// Bind methods
|
||||||
@@ -124,12 +123,12 @@ Book.prototype.parse = function() {
|
|||||||
path.join(that.root, lang.path),
|
path.join(that.root, lang.path),
|
||||||
_.merge({}, that.context, {
|
_.merge({}, that.context, {
|
||||||
config: _.extend({}, that.options, {
|
config: _.extend({}, that.options, {
|
||||||
'output': path.join(that.options.output, lang.lang),
|
"output": path.join(that.options.output, lang.lang),
|
||||||
'language': lang.lang
|
"language": lang.lang
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
that
|
that
|
||||||
)
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -186,7 +185,7 @@ Book.prototype.generate = function(generator) {
|
|||||||
// Create generator
|
// Create generator
|
||||||
.then(function() {
|
.then(function() {
|
||||||
var Generator = generators[generator];
|
var Generator = generators[generator];
|
||||||
if (!Generator) throw "Generator '"+that.options.generator+"' doesn't exist";
|
if (!Generator) throw "Generator \""+that.options.generator+"\" doesn't exist";
|
||||||
generator = new Generator(that);
|
generator = new Generator(that);
|
||||||
|
|
||||||
return generator.prepare();
|
return generator.prepare();
|
||||||
@@ -211,9 +210,9 @@ Book.prototype.generate = function(generator) {
|
|||||||
|
|
||||||
return Q()
|
return Q()
|
||||||
|
|
||||||
// First, let's create folder
|
// First, let"s create folder
|
||||||
.then(function() {
|
.then(function() {
|
||||||
return _.reduce(ops["directories"] || [], function(prev, folder) {
|
return _.reduce(ops.directories || [], function(prev, folder) {
|
||||||
return prev.then(function() {
|
return prev.then(function() {
|
||||||
that.log.debug.ln("transferring folder", folder);
|
that.log.debug.ln("transferring folder", folder);
|
||||||
return Q(generator.transferFolder(folder));
|
return Q(generator.transferFolder(folder));
|
||||||
@@ -221,18 +220,18 @@ Book.prototype.generate = function(generator) {
|
|||||||
}, Q());
|
}, Q());
|
||||||
})
|
})
|
||||||
|
|
||||||
// Then, let's copy other files
|
// Then, let"s copy other files
|
||||||
.then(function() {
|
.then(function() {
|
||||||
return Q.all(_.map(ops["files"] || [], function(file) {
|
return Q.all(_.map(ops.files || [], function(file) {
|
||||||
that.log.debug.ln("transferring file", file);
|
that.log.debug.ln("transferring file", file);
|
||||||
return Q(generator.transferFile(file));
|
return Q(generator.transferFile(file));
|
||||||
}));
|
}));
|
||||||
})
|
})
|
||||||
|
|
||||||
// Finally let's generate content
|
// Finally let"s generate content
|
||||||
.then(function() {
|
.then(function() {
|
||||||
var nFiles = (ops["content"] || []).length;
|
var nFiles = (ops.content || []).length;
|
||||||
return _.reduce(ops["content"] || [], function(prev, file, i) {
|
return _.reduce(ops.content || [], function(prev, file, i) {
|
||||||
return prev.then(function() {
|
return prev.then(function() {
|
||||||
var p = ((i*100)/nFiles).toFixed(0)+"%";
|
var p = ((i*100)/nFiles).toFixed(0)+"%";
|
||||||
that.log.debug.ln("processing", file, p);
|
that.log.debug.ln("processing", file, p);
|
||||||
@@ -266,7 +265,7 @@ Book.prototype.generate = function(generator) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Generate the output for a multilingual book
|
// Generate the output for a multilingual book
|
||||||
Book.prototype.generateMultiLingual = function(generator) {
|
Book.prototype.generateMultiLingual = function() {
|
||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
return Q()
|
return Q()
|
||||||
@@ -294,7 +293,7 @@ Book.prototype.generateFile = function(output, options) {
|
|||||||
book.setOutput(tmpDir);
|
book.setOutput(tmpDir);
|
||||||
|
|
||||||
return book.generate(options.ebookFormat)
|
return book.generate(options.ebookFormat)
|
||||||
.then(function(_options) {
|
.then(function() {
|
||||||
var copyFile = function(lang) {
|
var copyFile = function(lang) {
|
||||||
var _outputFile = output;
|
var _outputFile = output;
|
||||||
var _tmpDir = tmpDir;
|
var _tmpDir = tmpDir;
|
||||||
@@ -338,7 +337,7 @@ Book.prototype.generateFile = function(output, options) {
|
|||||||
Book.prototype.parseConfig = function() {
|
Book.prototype.parseConfig = function() {
|
||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
that.log.info("loading book configuration....")
|
that.log.info("loading book configuration....");
|
||||||
return that.config.load()
|
return that.config.load()
|
||||||
.then(function() {
|
.then(function() {
|
||||||
that.log.info.ok();
|
that.log.info.ok();
|
||||||
@@ -348,12 +347,11 @@ Book.prototype.parseConfig = function() {
|
|||||||
// Parse list of plugins
|
// Parse list of plugins
|
||||||
Book.prototype.parsePlugins = function() {
|
Book.prototype.parsePlugins = function() {
|
||||||
var that = this;
|
var that = this;
|
||||||
var failed = [];
|
|
||||||
|
|
||||||
// Load plugins
|
// Load plugins
|
||||||
return that.plugins.load(that.options.plugins)
|
return that.plugins.load(that.options.plugins)
|
||||||
.then(function() {
|
.then(function() {
|
||||||
if (_.size(that.plugins.failed) > 0) return Q.reject(new Error("Error loading plugins: "+that.plugins.failed.join(",")+". Run 'gitbook install' to install plugins from NPM."));
|
if (_.size(that.plugins.failed) > 0) return Q.reject(new Error("Error loading plugins: "+that.plugins.failed.join(",")+". Run \"gitbook install\" to install plugins from NPM."));
|
||||||
|
|
||||||
that.log.info.ok(that.plugins.count()+" plugins loaded");
|
that.log.info.ok(that.plugins.count()+" plugins loaded");
|
||||||
that.log.debug.ln("normalize plugins list");
|
that.log.debug.ln("normalize plugins list");
|
||||||
@@ -445,7 +443,7 @@ Book.prototype.parseSummary = function() {
|
|||||||
.then(function(content) {
|
.then(function(content) {
|
||||||
return summary.parser.summary(content, {
|
return summary.parser.summary(content, {
|
||||||
entryPoint: that.readmeFile,
|
entryPoint: that.readmeFile,
|
||||||
entryPointTitle: that.i18n('SUMMARY_INTRODUCTION'),
|
entryPointTitle: that.i18n("SUMMARY_INTRODUCTION"),
|
||||||
files: that.files
|
files: that.files
|
||||||
})
|
})
|
||||||
.fail(function(err) {
|
.fail(function(err) {
|
||||||
@@ -574,7 +572,7 @@ Book.prototype.parsePage = function(filename, options) {
|
|||||||
.then(function(content) {
|
.then(function(content) {
|
||||||
section.content = content;
|
section.content = content;
|
||||||
return _sections.concat([section]);
|
return _sections.concat([section]);
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
}, Q([]));
|
}, Q([]));
|
||||||
})
|
})
|
||||||
@@ -586,8 +584,8 @@ Book.prototype.parsePage = function(filename, options) {
|
|||||||
convertImages: options.convertImages,
|
convertImages: options.convertImages,
|
||||||
input: filename,
|
input: filename,
|
||||||
navigation: that.navigation,
|
navigation: that.navigation,
|
||||||
base: path.dirname(filename) || './',
|
base: path.dirname(filename) || "./",
|
||||||
output: path.dirname(filename) || './',
|
output: path.dirname(filename) || "./",
|
||||||
glossary: that.glossary
|
glossary: that.glossary
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -622,7 +620,7 @@ Book.prototype.findFile = function(filename) {
|
|||||||
parser: parsers.get(ext),
|
parser: parsers.get(ext),
|
||||||
path: filepath
|
path: filepath
|
||||||
};
|
};
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
}, Q(null));
|
}, Q(null));
|
||||||
};
|
};
|
||||||
@@ -630,21 +628,26 @@ Book.prototype.findFile = function(filename) {
|
|||||||
// Check if a file exists in the book
|
// Check if a file exists in the book
|
||||||
Book.prototype.fileExists = function(filename) {
|
Book.prototype.fileExists = function(filename) {
|
||||||
return fs.exists(
|
return fs.exists(
|
||||||
path.join(this.root, filename)
|
this.resolve(filename)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Check if a file path is inside the book
|
||||||
|
Book.prototype.fileIsInBook = function(filename) {
|
||||||
|
return pathUtil.isInRoot(this.root, filename);
|
||||||
|
};
|
||||||
|
|
||||||
// Read a file
|
// Read a file
|
||||||
Book.prototype.readFile = function(filename) {
|
Book.prototype.readFile = function(filename) {
|
||||||
return fs.readFile(
|
return fs.readFile(
|
||||||
path.join(this.root, filename),
|
this.resolve(filename),
|
||||||
{ encoding: "utf8" }
|
{ encoding: "utf8" }
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return stat for a file
|
// Return stat for a file
|
||||||
Book.prototype.statFile = function(filename) {
|
Book.prototype.statFile = function(filename) {
|
||||||
return fs.stat(path.join(this.root, filename));
|
return fs.stat(this.resolve(filename));
|
||||||
};
|
};
|
||||||
|
|
||||||
// List all files in the book
|
// List all files in the book
|
||||||
@@ -652,28 +655,28 @@ Book.prototype.listAllFiles = function() {
|
|||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
return fs.list(this.root, {
|
return fs.list(this.root, {
|
||||||
ignoreFiles: ['.ignore', '.gitignore', '.bookignore'],
|
ignoreFiles: [".ignore", ".gitignore", ".bookignore"],
|
||||||
ignoreRules: [
|
ignoreRules: [
|
||||||
// Skip Git stuff
|
// Skip Git stuff
|
||||||
'.git/',
|
".git/",
|
||||||
'.gitignore',
|
".gitignore",
|
||||||
|
|
||||||
// Skip OS X meta data
|
// Skip OS X meta data
|
||||||
'.DS_Store',
|
".DS_Store",
|
||||||
|
|
||||||
// Skip stuff installed by plugins
|
// Skip stuff installed by plugins
|
||||||
'node_modules',
|
"node_modules",
|
||||||
|
|
||||||
// Skip book outputs
|
// Skip book outputs
|
||||||
'_book',
|
"_book",
|
||||||
'*.pdf',
|
"*.pdf",
|
||||||
'*.epub',
|
"*.epub",
|
||||||
'*.mobi',
|
"*.mobi",
|
||||||
|
|
||||||
// Skip config files
|
// Skip config files
|
||||||
'.ignore',
|
".ignore",
|
||||||
'.bookignore',
|
".bookignore",
|
||||||
'book.json',
|
"book.json",
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
.then(function(_files) {
|
.then(function(_files) {
|
||||||
@@ -682,7 +685,7 @@ Book.prototype.listAllFiles = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Return true if the book is a multilingual book
|
// Return true if the book is a multilingual book
|
||||||
Book.prototype.isMultilingual = function(filename) {
|
Book.prototype.isMultilingual = function() {
|
||||||
return this.books.length > 0;
|
return this.books.length > 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -692,7 +695,7 @@ Book.prototype.parentRoot = function() {
|
|||||||
return this.root;
|
return this.root;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return true if it's a sub-book
|
// Return true if it"s a sub-book
|
||||||
Book.prototype.isSubBook = function() {
|
Book.prototype.isSubBook = function() {
|
||||||
return !!this.parent;
|
return !!this.parent;
|
||||||
};
|
};
|
||||||
@@ -702,39 +705,62 @@ Book.prototype.isEntryPoint = function(fp) {
|
|||||||
return fp == this.readmeFile;
|
return fp == this.readmeFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Resolve a path in book
|
// Alias to book.config.get
|
||||||
Book.prototype.resolve = function(p) {
|
Book.prototype.getConfig = function(key, def) {
|
||||||
return path.resolve(this.root, p);
|
return this.config.get(key, def);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Resolve a path in the book source
|
||||||
|
// Enforce that the output path in the root folder
|
||||||
|
Book.prototype.resolve = function() {
|
||||||
|
return pathUtil.resolveInRoot.apply(null, [this.root].concat(_.toArray(arguments)));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Convert an abslute path into a relative path to this
|
||||||
|
Book.prototype.relative = function(p) {
|
||||||
|
return path.relative(this.root, p);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Normalize a path to .html and convert README -> index
|
// Normalize a path to .html and convert README -> index
|
||||||
Book.prototype.contentPath = function(link) {
|
Book.prototype.contentPath = function(link) {
|
||||||
if (
|
if (
|
||||||
path.basename(link, path.extname(link)) == "README"
|
path.basename(link, path.extname(link)) == "README" ||
|
||||||
|| link == this.readmeFile
|
link == this.readmeFile
|
||||||
) {
|
) {
|
||||||
link = path.join(path.dirname(link), "index"+path.extname(link));
|
link = path.join(path.dirname(link), "index"+path.extname(link));
|
||||||
}
|
}
|
||||||
|
|
||||||
link = links.changeExtension(link, ".html");
|
link = links.changeExtension(link, ".html");
|
||||||
return link;
|
return link;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Normalize a link to .html and convert README -> index
|
// Normalize a link to .html and convert README -> index
|
||||||
Book.prototype.contentLink = function(link) {
|
Book.prototype.contentLink = function(link) {
|
||||||
return links.normalize(this.contentPath(link));
|
return links.normalize(this.contentPath(link));
|
||||||
}
|
};
|
||||||
|
|
||||||
// Index a page into the search index
|
// Index a page into the search index
|
||||||
Book.prototype.indexPage = function(page) {
|
Book.prototype.indexPage = function(page) {
|
||||||
var nav = this.navigation[page.path];
|
var nav = this.navigation[page.path];
|
||||||
if (!nav) return;
|
if (!nav || !this.searchIndexEnabled) return;
|
||||||
|
|
||||||
this.log.debug.ln("index page", page.path);
|
this.log.debug.ln("index page", page.path);
|
||||||
|
|
||||||
|
// Extract text from the page
|
||||||
|
var text = pageUtil.extractText(page.sections);
|
||||||
|
|
||||||
|
// Limit size of index (to avoid #941)
|
||||||
|
this.searchIndexSize = this.searchIndexSize + text.length;
|
||||||
|
if (this.searchIndexSize > SEARCHINDEX_MAXSIZE) {
|
||||||
|
this.log.warn.ln("search index is too big, indexing is now disabled");
|
||||||
|
this.searchIndexEnabled = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.searchIndex.add({
|
this.searchIndex.add({
|
||||||
url: this.contentLink(page.path),
|
url: this.contentLink(page.path),
|
||||||
title: nav.title,
|
title: nav.title,
|
||||||
body: pageUtil.extractText(page.sections),
|
body: text
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -747,7 +773,7 @@ Book.prototype._defaultsStructure = function(filename) {
|
|||||||
that.summaryFile = that.summaryFile || that.config.getStructure("summary")+extension;
|
that.summaryFile = that.summaryFile || that.config.getStructure("summary")+extension;
|
||||||
that.glossaryFile = that.glossaryFile || that.config.getStructure("glossary")+extension;
|
that.glossaryFile = that.glossaryFile || that.config.getStructure("glossary")+extension;
|
||||||
that.langsFile = that.langsFile || that.config.getStructure("langs")+extension;
|
that.langsFile = that.langsFile || that.config.getStructure("langs")+extension;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Change output path
|
// Change output path
|
||||||
Book.prototype.setOutput = function(p) {
|
Book.prototype.setOutput = function(p) {
|
||||||
@@ -760,7 +786,7 @@ Book.prototype.setOutput = function(p) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Translate a strign according to the book language
|
// Translate a strign according to the book language
|
||||||
Book.prototype.i18n = function(phrase) {
|
Book.prototype.i18n = function() {
|
||||||
var args = Array.prototype.slice.call(arguments);
|
var args = Array.prototype.slice.call(arguments);
|
||||||
return i18n.__.apply({}, [this.config.normalizeLanguage()].concat(args));
|
return i18n.__.apply({}, [this.config.normalizeLanguage()].concat(args));
|
||||||
};
|
};
|
||||||
@@ -779,10 +805,10 @@ Book.prototype.normError = function(err, opts, defs) {
|
|||||||
err.toString = function() {
|
err.toString = function() {
|
||||||
var attributes = [];
|
var attributes = [];
|
||||||
|
|
||||||
if (this.fileName) attributes.push("In file '"+this.fileName+"'");
|
if (this.fileName) attributes.push("In file \""+this.fileName+"\"");
|
||||||
if (this.lineNumber) attributes.push("Line "+this.lineNumber);
|
if (this.lineNumber) attributes.push("Line "+this.lineNumber);
|
||||||
if (this.columnNumber) attributes.push("Column "+this.columnNumber);
|
if (this.columnNumber) attributes.push("Column "+this.columnNumber);
|
||||||
return (this.name || "Error")+": "+this.message+((attributes.length > 0)? " ("+attributes.join(", ")+")" : "")
|
return (this.name || "Error")+": "+this.message+((attributes.length > 0)? " ("+attributes.join(", ")+")" : "");
|
||||||
};
|
};
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
@@ -820,7 +846,7 @@ Book.init = function(root, opts) {
|
|||||||
var chapters = book.summary.chapters || [];
|
var chapters = book.summary.chapters || [];
|
||||||
extensionToUse = path.extname(summary);
|
extensionToUse = path.extname(summary);
|
||||||
|
|
||||||
if (chapters.length == 0) {
|
if (chapters.length === 0) {
|
||||||
chapters = [
|
chapters = [
|
||||||
{
|
{
|
||||||
title: "Summary",
|
title: "Summary",
|
||||||
@@ -836,7 +862,7 @@ Book.init = function(root, opts) {
|
|||||||
return Q(chaptersPaths(chapters));
|
return Q(chaptersPaths(chapters));
|
||||||
})
|
})
|
||||||
.then(function(chapters) {
|
.then(function(chapters) {
|
||||||
// Create files that don't exist
|
// Create files that don"t exist
|
||||||
return Q.all(_.map(chapters, function(chapter) {
|
return Q.all(_.map(chapters, function(chapter) {
|
||||||
if (!chapter.path) return Q();
|
if (!chapter.path) return Q();
|
||||||
var absolutePath = path.resolve(book.root, chapter.path);
|
var absolutePath = path.resolve(book.root, chapter.path);
|
||||||
@@ -852,7 +878,7 @@ Book.init = function(root, opts) {
|
|||||||
|
|
||||||
return fs.mkdirp(path.dirname(absolutePath))
|
return fs.mkdirp(path.dirname(absolutePath))
|
||||||
.then(function() {
|
.then(function() {
|
||||||
return fs.writeFile(absolutePath, '# '+chapter.title+'\n');
|
return fs.writeFile(absolutePath, "# "+chapter.title+"\n");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|||||||
+55
-33
@@ -1,17 +1,30 @@
|
|||||||
var _ = require("lodash");
|
var _ = require("lodash");
|
||||||
var Q = require("q");
|
var Q = require("q");
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
var semver = require('semver');
|
var semver = require("semver");
|
||||||
|
|
||||||
var pkg = require('../package.json');
|
var pkg = require("../package.json");
|
||||||
var fs = require("./utils/fs");
|
|
||||||
var i18n = require("./utils/i18n");
|
var i18n = require("./utils/i18n");
|
||||||
|
|
||||||
// Default plugins added to each books
|
// Default plugins added to each books
|
||||||
var defaultsPlugins = [];
|
var DEFAULT_PLUGINS = ["highlight"];
|
||||||
|
|
||||||
|
// Check if a plugin is a default plugin
|
||||||
|
// Plugin should be in the list
|
||||||
|
// And version from book.json specified for this plugin should be satisfied
|
||||||
|
function isDefaultPlugin(name, version) {
|
||||||
|
if (!_.contains(DEFAULT_PLUGINS, name)) return false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
var pluginPkg = require('gitbook-plugin-'+name+'/package.json');
|
||||||
|
return semver.satisfies(pluginPkg.version, version || '*');
|
||||||
|
} catch(e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Normalize a list of plugins to use
|
// Normalize a list of plugins to use
|
||||||
function normalizePluginsList(plugins) {
|
function normalizePluginsList(plugins, addDefaults) {
|
||||||
// Normalize list to an array
|
// Normalize list to an array
|
||||||
plugins = _.isString(plugins) ? plugins.split(",") : (plugins || []);
|
plugins = _.isString(plugins) ? plugins.split(",") : (plugins || []);
|
||||||
|
|
||||||
@@ -23,10 +36,13 @@ function normalizePluginsList(plugins) {
|
|||||||
if (plugin.name) return plugin;
|
if (plugin.name) return plugin;
|
||||||
|
|
||||||
var parts = plugin.split("@");
|
var parts = plugin.split("@");
|
||||||
|
var name = parts[0];
|
||||||
|
var version = parts[1];
|
||||||
return {
|
return {
|
||||||
'name': parts[0],
|
"name": name,
|
||||||
'version': parts[1] // optional
|
"version": version, // optional
|
||||||
}
|
"isDefault": isDefaultPlugin(name, version)
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// List plugins to remove
|
// List plugins to remove
|
||||||
@@ -40,26 +56,30 @@ function normalizePluginsList(plugins) {
|
|||||||
.value();
|
.value();
|
||||||
|
|
||||||
// Merge with defaults
|
// Merge with defaults
|
||||||
plugins = _.chain(plugins)
|
if (addDefaults !== false) {
|
||||||
.concat(_.map(defaultsPlugins, function(plugin) {
|
_.each(DEFAULT_PLUGINS, function(plugin) {
|
||||||
return { 'name': plugin }
|
if (_.find(plugins, { name: plugin })) {
|
||||||
}))
|
return;
|
||||||
.uniq()
|
}
|
||||||
.value();
|
|
||||||
|
|
||||||
// Build final list
|
plugins.push({
|
||||||
|
"name": plugin,
|
||||||
|
"isDefault": true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove plugin that start with '-'
|
||||||
plugins = _.filter(plugins, function(plugin) {
|
plugins = _.filter(plugins, function(plugin) {
|
||||||
return !_.contains(toremove, plugin.name) && !(plugin.name.length > 0 && plugin.name[0] == "-");
|
return !_.contains(toremove, plugin.name) && !(plugin.name.length > 0 && plugin.name[0] == "-");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Remove duplicates
|
||||||
|
plugins = _.uniq(plugins, 'name');
|
||||||
|
|
||||||
return plugins;
|
return plugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalize a list of plugin name to use
|
|
||||||
function normalizePluginsNames(plugins) {
|
|
||||||
return _.pluck(normalizePluginsList(plugins), "name");
|
|
||||||
};
|
|
||||||
|
|
||||||
var Configuration = function(book, options) {
|
var Configuration = function(book, options) {
|
||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
@@ -96,11 +116,11 @@ Configuration.prototype.load = function() {
|
|||||||
|
|
||||||
return Q()
|
return Q()
|
||||||
.then(function() {
|
.then(function() {
|
||||||
var configPath, config;
|
var configPath, _config;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
configPath = require.resolve(
|
configPath = require.resolve(
|
||||||
path.resolve(that.book.root, that.options.configFile)
|
that.book.resolve(that.options.configFile)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Invalidate node.js cache for livreloading
|
// Invalidate node.js cache for livreloading
|
||||||
@@ -109,7 +129,7 @@ Configuration.prototype.load = function() {
|
|||||||
_config = require(configPath);
|
_config = require(configPath);
|
||||||
that.options = _.merge(
|
that.options = _.merge(
|
||||||
that.options,
|
that.options,
|
||||||
_.omit(_config, 'configFile', 'defaultsPlugins', 'generator', 'extension')
|
_.omit(_config, "configFile", "defaultsPlugins", "generator", "extension")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
catch(err) {
|
catch(err) {
|
||||||
@@ -118,16 +138,18 @@ Configuration.prototype.load = function() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(function() {
|
.then(function() {
|
||||||
if (!semver.satisfies(pkg.version, that.options.gitbook)) {
|
if (!that.book.isSubBook()) {
|
||||||
throw "GitBook version doesn't satisfy version required by the book: "+that.options.gitbook;
|
if (!semver.satisfies(pkg.version, that.options.gitbook)) {
|
||||||
}
|
throw new Error("GitBook version doesn't satisfy version required by the book: "+that.options.gitbook);
|
||||||
if (that.options.gitbook != '*' && !semver.satisfies(that.options.gitbook, semver.inc(pkg.version, 'patch'))) {
|
}
|
||||||
that.book.log.warn.ln("gitbook version specified in your book.json might be too strict for future patches, \""+(_.first(pkg.version.split("."))+".x.x")+"\" is more adequate");
|
if (that.options.gitbook != "*" && !semver.satisfies(semver.inc(pkg.version, "patch"), that.options.gitbook)) {
|
||||||
|
that.book.log.warn.ln("gitbook version specified in your book.json might be too strict for future patches, \""+(_.first(pkg.version.split("."))+".x.x")+"\" is more adequate");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
that.options.output = path.resolve(that.options.output || path.join(that.book.root, "_book"));
|
that.options.output = path.resolve(that.options.output || that.book.resolve("_book"));
|
||||||
that.options.plugins = normalizePluginsList(that.options.plugins);
|
that.options.plugins = normalizePluginsList(that.options.plugins);
|
||||||
that.options.defaultsPlugins = normalizePluginsList(that.options.defaultsPlugins || "");
|
that.options.defaultsPlugins = normalizePluginsList(that.options.defaultsPlugins || "", false);
|
||||||
that.options.plugins = _.union(that.options.plugins, that.options.defaultsPlugins);
|
that.options.plugins = _.union(that.options.plugins, that.options.defaultsPlugins);
|
||||||
that.options.plugins = _.uniq(that.options.plugins, "name");
|
that.options.plugins = _.uniq(that.options.plugins, "name");
|
||||||
|
|
||||||
@@ -163,7 +185,7 @@ Configuration.prototype.get = function(key, def) {
|
|||||||
|
|
||||||
// Default configuration
|
// Default configuration
|
||||||
Configuration.DEFAULT = {
|
Configuration.DEFAULT = {
|
||||||
// Options that can't be extend
|
// Options that can"t be extend
|
||||||
"configFile": "book",
|
"configFile": "book",
|
||||||
"generator": "website",
|
"generator": "website",
|
||||||
"extension": null,
|
"extension": null,
|
||||||
@@ -213,9 +235,9 @@ Configuration.DEFAULT = {
|
|||||||
"variables": {},
|
"variables": {},
|
||||||
|
|
||||||
// Set another theme with your own layout
|
// Set another theme with your own layout
|
||||||
// It's recommended to use plugins or add more options for default theme, though
|
// It"s recommended to use plugins or add more options for default theme, though
|
||||||
// See https://github.com/GitbookIO/gitbook/issues/209
|
// See https://github.com/GitbookIO/gitbook/issues/209
|
||||||
"theme": path.resolve(__dirname, '../theme'),
|
"theme": path.resolve(__dirname, "../theme"),
|
||||||
|
|
||||||
// Links in template (null: default, false: remove, string: new value)
|
// Links in template (null: default, false: remove, string: new value)
|
||||||
"links": {
|
"links": {
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
var path = require("path");
|
||||||
|
var nunjucks = require("nunjucks");
|
||||||
|
|
||||||
|
var git = require("./utils/git");
|
||||||
|
var fs = require("./utils/fs");
|
||||||
|
var pathUtil = require("./utils/path");
|
||||||
|
|
||||||
|
// The loader should handle relative and git url
|
||||||
|
var BookLoader = nunjucks.Loader.extend({
|
||||||
|
async: true,
|
||||||
|
|
||||||
|
init: function(book) {
|
||||||
|
this.book = book;
|
||||||
|
},
|
||||||
|
|
||||||
|
getSource: function(fileurl, callback) {
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
git.resolveFile(fileurl)
|
||||||
|
.then(function(filepath) {
|
||||||
|
// Is local file
|
||||||
|
if (!filepath) filepath = path.resolve(fileurl);
|
||||||
|
else that.book.log.debug.ln("resolve from git", fileurl, "to", filepath);
|
||||||
|
|
||||||
|
// Read file from absolute path
|
||||||
|
return fs.readFile(filepath)
|
||||||
|
.then(function(source) {
|
||||||
|
return {
|
||||||
|
src: source.toString(),
|
||||||
|
path: filepath
|
||||||
|
};
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.nodeify(callback);
|
||||||
|
},
|
||||||
|
|
||||||
|
resolve: function(from, to) {
|
||||||
|
// If origin is in the book, we enforce result file to be in the book
|
||||||
|
if (this.book.fileIsInBook(from)) {
|
||||||
|
return this.book.resolve(
|
||||||
|
this.book.relative(path.dirname(from)),
|
||||||
|
to
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If origin is in a git repository, we resolve file in the git repository
|
||||||
|
var gitRoot = git.resolveRoot(from);
|
||||||
|
if (gitRoot) {
|
||||||
|
return pathUtil.resolveInRoot(gitRoot, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If origin is not in the book (include from a git content ref)
|
||||||
|
return path.resolve(path.dirname(from), to);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Handle all files as relative, so that nunjucks pass responsability to "resolve"
|
||||||
|
// Only git urls are considered as absolute
|
||||||
|
isRelative: function(filename) {
|
||||||
|
return !git.checkUrl(filename);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = BookLoader;
|
||||||
+4
-6
@@ -3,8 +3,6 @@ var path = require("path");
|
|||||||
var Q = require("q");
|
var Q = require("q");
|
||||||
var fs = require("./utils/fs");
|
var fs = require("./utils/fs");
|
||||||
|
|
||||||
var Plugin = require("./plugin");
|
|
||||||
|
|
||||||
var BaseGenerator = function(book) {
|
var BaseGenerator = function(book) {
|
||||||
this.book = book;
|
this.book = book;
|
||||||
|
|
||||||
@@ -36,7 +34,7 @@ BaseGenerator.prototype.convertFile = function(input) {
|
|||||||
// Copy file to the output (non parsable)
|
// Copy file to the output (non parsable)
|
||||||
BaseGenerator.prototype.transferFile = function(input) {
|
BaseGenerator.prototype.transferFile = function(input) {
|
||||||
return fs.copy(
|
return fs.copy(
|
||||||
path.join(this.book.root, input),
|
this.book.resolve(input),
|
||||||
path.join(this.options.output, input)
|
path.join(this.options.output, input)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -53,8 +51,8 @@ BaseGenerator.prototype.copyCover = function() {
|
|||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
return Q.all([
|
return Q.all([
|
||||||
fs.copy(path.join(that.book.root, "cover.jpg"), path.join(that.options.output, "cover.jpg")),
|
fs.copy(that.book.resolve("cover.jpg"), path.join(that.options.output, "cover.jpg")),
|
||||||
fs.copy(path.join(that.book.root, "cover_small.jpg"), path.join(that.options.output, "cover_small.jpg"))
|
fs.copy(that.book.resolve("cover_small.jpg"), path.join(that.options.output, "cover_small.jpg"))
|
||||||
])
|
])
|
||||||
.fail(function() {
|
.fail(function() {
|
||||||
// If orignaly from multi-lang, try copy from parent
|
// If orignaly from multi-lang, try copy from parent
|
||||||
@@ -65,7 +63,7 @@ BaseGenerator.prototype.copyCover = function() {
|
|||||||
fs.copy(path.join(that.book.parentRoot(), "cover_small.jpg"), path.join(that.options.output, "cover_small.jpg"))
|
fs.copy(path.join(that.book.parentRoot(), "cover_small.jpg"), path.join(that.options.output, "cover_small.jpg"))
|
||||||
]);
|
]);
|
||||||
})
|
})
|
||||||
.fail(function(err) {
|
.fail(function() {
|
||||||
return Q();
|
return Q();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
+10
-10
@@ -2,7 +2,7 @@ var util = require("util");
|
|||||||
var path = require("path");
|
var path = require("path");
|
||||||
var Q = require("q");
|
var Q = require("q");
|
||||||
var _ = require("lodash");
|
var _ = require("lodash");
|
||||||
var exec = require('child_process').exec;
|
var exec = require("child_process").exec;
|
||||||
|
|
||||||
var fs = require("../utils/fs");
|
var fs = require("../utils/fs");
|
||||||
var stringUtils = require("../utils/string");
|
var stringUtils = require("../utils/string");
|
||||||
@@ -26,9 +26,9 @@ var Generator = function(book, format) {
|
|||||||
util.inherits(Generator, BaseGenerator);
|
util.inherits(Generator, BaseGenerator);
|
||||||
|
|
||||||
Generator.prototype.prepareTemplates = function() {
|
Generator.prototype.prepareTemplates = function() {
|
||||||
this.templates["page"] = this.book.plugins.template("ebook:page") || path.resolve(this.options.theme, 'templates/ebook/page.html');
|
this.templates.page = this.book.plugins.template("ebook:page") || path.resolve(this.options.theme, "templates/ebook/page.html");
|
||||||
this.templates["summary"] = this.book.plugins.template("ebook:summary") || path.resolve(this.options.theme, 'templates/ebook/summary.html');
|
this.templates.summary = this.book.plugins.template("ebook:summary") || path.resolve(this.options.theme, "templates/ebook/summary.html");
|
||||||
this.templates["glossary"] = this.book.plugins.template("ebook:glossary") || path.resolve(this.options.theme, 'templates/ebook/glossary.html');
|
this.templates.glossary = this.book.plugins.template("ebook:glossary") || path.resolve(this.options.theme, "templates/ebook/glossary.html");
|
||||||
|
|
||||||
return Q();
|
return Q();
|
||||||
};
|
};
|
||||||
@@ -38,7 +38,7 @@ Generator.prototype.writeSummary = function() {
|
|||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
that.book.log.info.ln("write SUMMARY.html");
|
that.book.log.info.ln("write SUMMARY.html");
|
||||||
return this._writeTemplate(this.templates["summary"], {}, path.join(this.options.output, "SUMMARY.html"));
|
return this._writeTemplate(this.templates.summary, {}, path.join(this.options.output, "SUMMARY.html"));
|
||||||
};
|
};
|
||||||
|
|
||||||
Generator.prototype.finish = function() {
|
Generator.prototype.finish = function() {
|
||||||
@@ -52,12 +52,12 @@ Generator.prototype.finish = function() {
|
|||||||
.then(function() {
|
.then(function() {
|
||||||
if (!that.ebookFormat) return Q();
|
if (!that.ebookFormat) return Q();
|
||||||
|
|
||||||
var d = Q.defer();
|
|
||||||
|
|
||||||
if (!that.options.cover && fs.existsSync(path.join(that.options.output, "cover.jpg"))) {
|
if (!that.options.cover && fs.existsSync(path.join(that.options.output, "cover.jpg"))) {
|
||||||
that.options.cover = path.join(that.options.output, "cover.jpg");
|
that.options.cover = path.join(that.options.output, "cover.jpg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var d = Q.defer();
|
||||||
|
|
||||||
var _options = {
|
var _options = {
|
||||||
"--cover": that.options.cover,
|
"--cover": that.options.cover,
|
||||||
"--title": that.options.title,
|
"--title": that.options.title,
|
||||||
@@ -108,7 +108,7 @@ Generator.prototype.finish = function() {
|
|||||||
|
|
||||||
that.book.log.info("start conversion to", that.ebookFormat, "....");
|
that.book.log.info("start conversion to", that.ebookFormat, "....");
|
||||||
|
|
||||||
var child = exec(command, function (error, stdout, stderr) {
|
var child = exec(command, function (error, stdout) {
|
||||||
if (error) {
|
if (error) {
|
||||||
that.book.log.info.fail();
|
that.book.log.info.fail();
|
||||||
|
|
||||||
@@ -124,11 +124,11 @@ Generator.prototype.finish = function() {
|
|||||||
d.resolve();
|
d.resolve();
|
||||||
});
|
});
|
||||||
|
|
||||||
child.stdout.on('data', function (data) {
|
child.stdout.on("data", function (data) {
|
||||||
that.book.log.debug(data);
|
that.book.log.debug(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
child.stderr.on('data', function (data) {
|
child.stderr.on("data", function (data) {
|
||||||
that.book.log.debug(data);
|
that.book.log.debug(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ var Generator = function() {
|
|||||||
util.inherits(Generator, BaseGenerator);
|
util.inherits(Generator, BaseGenerator);
|
||||||
|
|
||||||
// Ignore some methods
|
// Ignore some methods
|
||||||
Generator.prototype.transferFile = function(input) { };
|
Generator.prototype.transferFile = function() { };
|
||||||
|
|
||||||
// Convert an input file
|
// Convert an input file
|
||||||
Generator.prototype.convertFile = function(input) {
|
Generator.prototype.convertFile = function(input) {
|
||||||
@@ -44,7 +44,7 @@ Generator.prototype.finish = function() {
|
|||||||
// Write README.json
|
// Write README.json
|
||||||
Generator.prototype.writeReadme = function() {
|
Generator.prototype.writeReadme = function() {
|
||||||
var that = this;
|
var that = this;
|
||||||
var mainlang, langs;
|
var mainLang, langs, readme;
|
||||||
|
|
||||||
return Q()
|
return Q()
|
||||||
.then(function() {
|
.then(function() {
|
||||||
|
|||||||
+16
-21
@@ -10,7 +10,6 @@ var FilterExtension = require("nunjucks-filter")(nunjucks);
|
|||||||
var fs = require("../utils/fs");
|
var fs = require("../utils/fs");
|
||||||
var BaseGenerator = require("../generator");
|
var BaseGenerator = require("../generator");
|
||||||
var links = require("../utils/links");
|
var links = require("../utils/links");
|
||||||
var pageUtil = require("../utils/page");
|
|
||||||
var i18n = require("../utils/i18n");
|
var i18n = require("../utils/i18n");
|
||||||
|
|
||||||
var pkg = require("../../package.json");
|
var pkg = require("../../package.json");
|
||||||
@@ -50,7 +49,7 @@ Generator.prototype.prepareStyles = function() {
|
|||||||
this.styles = _.chain(this.styles)
|
this.styles = _.chain(this.styles)
|
||||||
.map(function(style) {
|
.map(function(style) {
|
||||||
var stylePath = that.options.styles[style];
|
var stylePath = that.options.styles[style];
|
||||||
if (stylePath && fs.existsSync(path.resolve(that.book.root, stylePath))) {
|
if (stylePath && fs.existsSync(that.book.resolve(stylePath))) {
|
||||||
return [style, stylePath];
|
return [style, stylePath];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -64,9 +63,9 @@ Generator.prototype.prepareStyles = function() {
|
|||||||
|
|
||||||
// Prepare templates
|
// Prepare templates
|
||||||
Generator.prototype.prepareTemplates = function() {
|
Generator.prototype.prepareTemplates = function() {
|
||||||
this.templates["page"] = this.book.plugins.template("site:page") || path.resolve(this.options.theme, 'templates/website/page.html');
|
this.templates.page = this.book.plugins.template("site:page") || path.resolve(this.options.theme, "templates/website/page.html");
|
||||||
this.templates["langs"] = this.book.plugins.template("site:langs") || path.resolve(this.options.theme, 'templates/website/langs.html');
|
this.templates.langs = this.book.plugins.template("site:langs") || path.resolve(this.options.theme, "templates/website/langs.html");
|
||||||
this.templates["glossary"] = this.book.plugins.template("site:glossary") || path.resolve(this.options.theme, 'templates/website/glossary.html');
|
this.templates.glossary = this.book.plugins.template("site:glossary") || path.resolve(this.options.theme, "templates/website/glossary.html");
|
||||||
|
|
||||||
return Q();
|
return Q();
|
||||||
};
|
};
|
||||||
@@ -98,13 +97,13 @@ Generator.prototype.prepareTemplateEngine = function() {
|
|||||||
|
|
||||||
// Add filter
|
// Add filter
|
||||||
that.env.addFilter("contentLink", that.book.contentLink.bind(that.book));
|
that.env.addFilter("contentLink", that.book.contentLink.bind(that.book));
|
||||||
that.env.addFilter('lvl', function(lvl) {
|
that.env.addFilter("lvl", function(lvl) {
|
||||||
return lvl.split(".").length;
|
return lvl.split(".").length;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add extension
|
// Add extension
|
||||||
that.env.addExtension('AutoEscapeExtension', new AutoEscapeExtension(that.env));
|
that.env.addExtension("AutoEscapeExtension", new AutoEscapeExtension(that.env));
|
||||||
that.env.addExtension('FilterExtension', new FilterExtension(that.env));
|
that.env.addExtension("FilterExtension", new FilterExtension(that.env));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -114,7 +113,7 @@ Generator.prototype.finish = function() {
|
|||||||
.then(this.copyCover)
|
.then(this.copyCover)
|
||||||
.then(this.writeGlossary)
|
.then(this.writeGlossary)
|
||||||
.then(this.writeSearchIndex)
|
.then(this.writeSearchIndex)
|
||||||
.then(this.writeLangsIndex)
|
.then(this.writeLangsIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Convert an input file
|
// Convert an input file
|
||||||
@@ -135,11 +134,11 @@ Generator.prototype.convertFile = function(input) {
|
|||||||
var output = path.join(that.options.output, relativeOutput);
|
var output = path.join(that.options.output, relativeOutput);
|
||||||
|
|
||||||
var basePath = path.relative(path.dirname(output), that.options.output) || ".";
|
var basePath = path.relative(path.dirname(output), that.options.output) || ".";
|
||||||
if (process.platform === 'win32') basePath = basePath.replace(/\\/g, '/');
|
if (process.platform === "win32") basePath = basePath.replace(/\\/g, "/");
|
||||||
|
|
||||||
that.book.log.debug.ln("write parsed file", page.path, "to", relativeOutput);
|
that.book.log.debug.ln("write parsed file", page.path, "to", relativeOutput);
|
||||||
|
|
||||||
return that._writeTemplate(that.templates["page"], {
|
return that._writeTemplate(that.templates.page, {
|
||||||
progress: page.progress,
|
progress: page.progress,
|
||||||
|
|
||||||
_input: page.path,
|
_input: page.path,
|
||||||
@@ -153,27 +152,23 @@ Generator.prototype.convertFile = function(input) {
|
|||||||
|
|
||||||
// Write the index for langs
|
// Write the index for langs
|
||||||
Generator.prototype.writeLangsIndex = function() {
|
Generator.prototype.writeLangsIndex = function() {
|
||||||
var that = this;
|
|
||||||
if (!this.book.langs.length) return Q();
|
if (!this.book.langs.length) return Q();
|
||||||
return this._writeTemplate(this.templates["langs"], {
|
|
||||||
|
return this._writeTemplate(this.templates.langs, {
|
||||||
langs: this.book.langs
|
langs: this.book.langs
|
||||||
}, path.join(this.options.output, "index.html"));
|
}, path.join(this.options.output, "index.html"));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Write glossary
|
// Write glossary
|
||||||
Generator.prototype.writeGlossary = function() {
|
Generator.prototype.writeGlossary = function() {
|
||||||
var that = this;
|
|
||||||
|
|
||||||
// No glossary
|
// No glossary
|
||||||
if (this.book.glossary.length == 0) return Q();
|
if (this.book.glossary.length === 0) return Q();
|
||||||
|
|
||||||
return this._writeTemplate(this.templates["glossary"], {}, path.join(this.options.output, "GLOSSARY.html"));
|
return this._writeTemplate(this.templates.glossary, {}, path.join(this.options.output, "GLOSSARY.html"));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Write the search index
|
// Write the search index
|
||||||
Generator.prototype.writeSearchIndex = function() {
|
Generator.prototype.writeSearchIndex = function() {
|
||||||
var that = this;
|
|
||||||
|
|
||||||
return fs.writeFile(
|
return fs.writeFile(
|
||||||
path.join(this.options.output, "search_index.json"),
|
path.join(this.options.output, "search_index.json"),
|
||||||
JSON.stringify(this.book.searchIndex)
|
JSON.stringify(this.book.searchIndex)
|
||||||
@@ -207,7 +202,7 @@ Generator.prototype._writeTemplate = function(tpl, options, output, interpolate)
|
|||||||
|
|
||||||
interpolate = interpolate || _.identity;
|
interpolate = interpolate || _.identity;
|
||||||
return Q()
|
return Q()
|
||||||
.then(function(sections) {
|
.then(function() {
|
||||||
return that.env.render(
|
return that.env.render(
|
||||||
tpl,
|
tpl,
|
||||||
_.extend({
|
_.extend({
|
||||||
@@ -239,7 +234,7 @@ Generator.prototype._writeTemplate = function(tpl, options, output, interpolate)
|
|||||||
basePath: ".",
|
basePath: ".",
|
||||||
staticBase: path.join(".", "gitbook"),
|
staticBase: path.join(".", "gitbook"),
|
||||||
|
|
||||||
'__': that.book.i18n.bind(that.book)
|
"__": that.book.i18n.bind(that.book)
|
||||||
}, options)
|
}, options)
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
|||||||
+20
-21
@@ -1,11 +1,10 @@
|
|||||||
var Q = require("q");
|
var Q = require("q");
|
||||||
var _ = require("lodash");
|
var _ = require("lodash");
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
var tinylr = require('tiny-lr');
|
var tinylr = require("tiny-lr");
|
||||||
var color = require('bash-color');
|
var color = require("bash-color");
|
||||||
|
|
||||||
var Book = require("./book");
|
var Book = require("./book");
|
||||||
var Plugin = require("./plugin");
|
|
||||||
var Server = require("./utils/server");
|
var Server = require("./utils/server");
|
||||||
var stringUtils = require("./utils/string");
|
var stringUtils = require("./utils/string");
|
||||||
var watch = require("./utils/watch");
|
var watch = require("./utils/watch");
|
||||||
@@ -42,10 +41,10 @@ module.exports = {
|
|||||||
var output = args[1] || path.join(input, "_book");
|
var output = args[1] || path.join(input, "_book");
|
||||||
|
|
||||||
var book = new Book(input, _.extend({}, {
|
var book = new Book(input, _.extend({}, {
|
||||||
'config': {
|
"config": {
|
||||||
'output': output
|
"output": output
|
||||||
},
|
},
|
||||||
'logLevel': kwargs.log
|
"logLevel": kwargs.log
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return book.parse()
|
return book.parse()
|
||||||
@@ -71,7 +70,7 @@ module.exports = {
|
|||||||
var output = args[1];
|
var output = args[1];
|
||||||
|
|
||||||
var book = new Book(input, _.extend({}, {
|
var book = new Book(input, _.extend({}, {
|
||||||
'logLevel': kwargs.log
|
"logLevel": kwargs.log
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return book.parse()
|
return book.parse()
|
||||||
@@ -116,7 +115,7 @@ module.exports = {
|
|||||||
|
|
||||||
// Init livereload server
|
// Init livereload server
|
||||||
var lrServer = tinylr({});
|
var lrServer = tinylr({});
|
||||||
var lrPath = undefined;
|
var lrPath;
|
||||||
|
|
||||||
var generate = function() {
|
var generate = function() {
|
||||||
if (server.isRunning()) console.log("Stopping server");
|
if (server.isRunning()) console.log("Stopping server");
|
||||||
@@ -124,10 +123,10 @@ module.exports = {
|
|||||||
return server.stop()
|
return server.stop()
|
||||||
.then(function() {
|
.then(function() {
|
||||||
var book = new Book(input, _.extend({}, {
|
var book = new Book(input, _.extend({}, {
|
||||||
'config': {
|
"config": {
|
||||||
'defaultsPlugins': ["livereload"]
|
"defaultsPlugins": ["livereload"]
|
||||||
},
|
},
|
||||||
'logLevel': kwargs.log
|
"logLevel": kwargs.log
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return book.parse()
|
return book.parse()
|
||||||
@@ -138,10 +137,10 @@ module.exports = {
|
|||||||
})
|
})
|
||||||
.then(function(book) {
|
.then(function(book) {
|
||||||
console.log();
|
console.log();
|
||||||
console.log('Starting server ...');
|
console.log("Starting server ...");
|
||||||
return server.start(book.options.output, kwargs.port)
|
return server.start(book.options.output, kwargs.port)
|
||||||
.then(function() {
|
.then(function() {
|
||||||
console.log('Serving book on http://localhost:'+kwargs.port);
|
console.log("Serving book on http://localhost:"+kwargs.port);
|
||||||
|
|
||||||
if (lrPath) {
|
if (lrPath) {
|
||||||
// trigger livereload
|
// trigger livereload
|
||||||
@@ -159,18 +158,18 @@ module.exports = {
|
|||||||
// set livereload path
|
// set livereload path
|
||||||
lrPath = filepath;
|
lrPath = filepath;
|
||||||
console.log("Restart after change in file", filepath);
|
console.log("Restart after change in file", filepath);
|
||||||
console.log('');
|
console.log("");
|
||||||
return generate();
|
return generate();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return Q.nfcall(lrServer.listen.bind(lrServer), kwargs.lrport)
|
return Q.nfcall(lrServer.listen.bind(lrServer), kwargs.lrport)
|
||||||
.then(function() {
|
.then(function() {
|
||||||
console.log('Live reload server started on port:', kwargs.lrport);
|
console.log("Live reload server started on port:", kwargs.lrport);
|
||||||
console.log('Press CTRL+C to quit ...');
|
console.log("Press CTRL+C to quit ...");
|
||||||
console.log('')
|
console.log("");
|
||||||
return generate();
|
return generate();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -179,7 +178,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
name: "install [book]",
|
name: "install [book]",
|
||||||
description: "install plugins dependencies",
|
description: "install plugins dependencies",
|
||||||
exec: function(args, kwargs) {
|
exec: function(args) {
|
||||||
var input = args[0] || process.cwd();
|
var input = args[0] || process.cwd();
|
||||||
|
|
||||||
var book = new Book(input);
|
var book = new Book(input);
|
||||||
@@ -198,7 +197,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
name: "init [directory]",
|
name: "init [directory]",
|
||||||
description: "create files and folders based on contents of SUMMARY.md",
|
description: "create files and folders based on contents of SUMMARY.md",
|
||||||
exec: function(args, kwargs) {
|
exec: function(args) {
|
||||||
return Book.init(args[0] || process.cwd())
|
return Book.init(args[0] || process.cwd())
|
||||||
.then(function(){
|
.then(function(){
|
||||||
console.log("");
|
console.log("");
|
||||||
|
|||||||
+4
-4
@@ -4,7 +4,7 @@ var semver = require("semver");
|
|||||||
var path = require("path");
|
var path = require("path");
|
||||||
var url = require("url");
|
var url = require("url");
|
||||||
var fs = require("./utils/fs");
|
var fs = require("./utils/fs");
|
||||||
var resolve = require('resolve');
|
var resolve = require("resolve");
|
||||||
|
|
||||||
var pkg = require("../package.json");
|
var pkg = require("../package.json");
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ var Plugin = function(book, name) {
|
|||||||
Plugin.RESOURCES = ["js", "css"];
|
Plugin.RESOURCES = ["js", "css"];
|
||||||
Plugin.HOOKS = [
|
Plugin.HOOKS = [
|
||||||
"init", "finish", "finish:before", "page", "page:before"
|
"init", "finish", "finish:before", "page", "page:before"
|
||||||
]
|
];
|
||||||
|
|
||||||
// Load from a name
|
// Load from a name
|
||||||
Plugin.prototype.load = function(name, baseDir) {
|
Plugin.prototype.load = function(name, baseDir) {
|
||||||
@@ -77,7 +77,7 @@ Plugin.prototype._getResources = function(base) {
|
|||||||
var book = this.infos[base];
|
var book = this.infos[base];
|
||||||
|
|
||||||
// Compatibility with version 1.x.x
|
// Compatibility with version 1.x.x
|
||||||
if (base == "website") book = book || this.infos["book"];
|
if (base == "website") book = book || this.infos.book;
|
||||||
|
|
||||||
// Nothing specified, fallback to default
|
// Nothing specified, fallback to default
|
||||||
if (!book) {
|
if (!book) {
|
||||||
@@ -168,7 +168,7 @@ Plugin.prototype.copyAssets = function(out, base) {
|
|||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
return this.getResources(base)
|
return this.getResources(base)
|
||||||
.get('assets')
|
.get("assets")
|
||||||
.then(function(assets) {
|
.then(function(assets) {
|
||||||
// Assets are undefined
|
// Assets are undefined
|
||||||
if(!assets) return false;
|
if(!assets) return false;
|
||||||
|
|||||||
+19
-26
@@ -1,14 +1,14 @@
|
|||||||
var _ = require("lodash");
|
var _ = require("lodash");
|
||||||
var Q = require("q");
|
var Q = require("q");
|
||||||
var npmi = require('npmi');
|
var npmi = require("npmi");
|
||||||
var npm = require('npm');
|
var npm = require("npm");
|
||||||
var semver = require('semver');
|
var semver = require("semver");
|
||||||
|
|
||||||
var Plugin = require("./plugin");
|
var Plugin = require("./plugin");
|
||||||
var pkg = require("../package.json");
|
var pkg = require("../package.json");
|
||||||
|
|
||||||
var initNPM = _.memoize(function() {
|
var initNPM = _.memoize(function() {
|
||||||
return Q.nfcall(npm.load, { silent: true, loglevel: 'silent' });
|
return Q.nfcall(npm.load, { silent: true, loglevel: "silent" });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ PluginsList.prototype.count = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Add and load a plugin
|
// Add and load a plugin
|
||||||
PluginsList.prototype.load = function(plugin, options) {
|
PluginsList.prototype.load = function(plugin) {
|
||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
if (_.isArray(plugin)) {
|
if (_.isArray(plugin)) {
|
||||||
@@ -79,14 +79,10 @@ PluginsList.prototype.load = function(plugin, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Extract filters
|
// Extract filters
|
||||||
_.each(plugin.getFilters(), function(filterFunc, filterName) {
|
that.book.template.addFilters(plugin.getFilters());
|
||||||
that.book.template.addFilter(filterName, filterFunc);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Extract blocks
|
// Extract blocks
|
||||||
_.each(plugin.getBlocks(), function(block, blockName) {
|
that.book.template.addBlocks(plugin.getBlocks());
|
||||||
that.book.template.addBlock(blockName, block);
|
|
||||||
});
|
|
||||||
|
|
||||||
return _.reduce(_.keys(that.namespaces), function(prev, namespaceName) {
|
return _.reduce(_.keys(that.namespaces), function(prev, namespaceName) {
|
||||||
return prev.then(function() {
|
return prev.then(function() {
|
||||||
@@ -107,7 +103,7 @@ PluginsList.prototype.load = function(plugin, options) {
|
|||||||
namespace.html[tag] = namespace.html[tag] || [];
|
namespace.html[tag] = namespace.html[tag] || [];
|
||||||
namespace.html[tag].push(value);
|
namespace.html[tag].push(value);
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
}, Q());
|
}, Q());
|
||||||
};
|
};
|
||||||
@@ -150,11 +146,10 @@ PluginsList.prototype.resources = function(namespace) {
|
|||||||
// Install plugins from a book
|
// Install plugins from a book
|
||||||
PluginsList.prototype.install = function() {
|
PluginsList.prototype.install = function() {
|
||||||
var that = this;
|
var that = this;
|
||||||
var defaultsPlugins = _.pluck(that.book.options.defaultsPlugins)
|
|
||||||
|
|
||||||
// Remove defaults (no need to install)
|
// Remove defaults (no need to install)
|
||||||
var plugins = _.filter(that.book.options.plugins, function(plugin) {
|
var plugins = _.reject(that.book.options.plugins, {
|
||||||
return !_.contains(defaultsPlugins, plugin.name);
|
isDefault: true
|
||||||
});
|
});
|
||||||
|
|
||||||
// Install plugins one by one
|
// Install plugins one by one
|
||||||
@@ -180,8 +175,8 @@ PluginsList.prototype.install = function() {
|
|||||||
.map(function(v) {
|
.map(function(v) {
|
||||||
return {
|
return {
|
||||||
version: v[0],
|
version: v[0],
|
||||||
gitbook: (v[1].engines || {})["gitbook"]
|
gitbook: (v[1].engines || {}).gitbook
|
||||||
}
|
};
|
||||||
})
|
})
|
||||||
.filter(function(v) {
|
.filter(function(v) {
|
||||||
return v.gitbook && semver.satisfies(pkg.version, v.gitbook);
|
return v.gitbook && semver.satisfies(pkg.version, v.gitbook);
|
||||||
@@ -203,13 +198,13 @@ PluginsList.prototype.install = function() {
|
|||||||
|
|
||||||
that.book.log.info.ln("install plugin", plugin.name, "from npm ("+fullname+") with version", version);
|
that.book.log.info.ln("install plugin", plugin.name, "from npm ("+fullname+") with version", version);
|
||||||
return Q.nfcall(npmi, {
|
return Q.nfcall(npmi, {
|
||||||
'name': fullname,
|
"name": fullname,
|
||||||
'version': version,
|
"version": version,
|
||||||
'path': that.book.root,
|
"path": that.book.root,
|
||||||
'npmLoad': {
|
"npmLoad": {
|
||||||
'loglevel': 'silent',
|
"loglevel": "silent",
|
||||||
'loaded': true,
|
"loaded": true,
|
||||||
'prefix': that.book.root
|
"prefix": that.book.root
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -220,6 +215,4 @@ PluginsList.prototype.install = function() {
|
|||||||
}, Q());
|
}, Q());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = PluginsList;
|
module.exports = PluginsList;
|
||||||
|
|||||||
+123
-86
@@ -1,48 +1,18 @@
|
|||||||
var _ = require("lodash");
|
var _ = require("lodash");
|
||||||
var Q = require("q");
|
var Q = require("q");
|
||||||
var path = require("path");
|
|
||||||
var nunjucks = require("nunjucks");
|
var nunjucks = require("nunjucks");
|
||||||
var escapeStringRegexp = require("escape-string-regexp");
|
var escapeStringRegexp = require("escape-string-regexp");
|
||||||
|
|
||||||
var git = require("./utils/git");
|
|
||||||
var fs = require("./utils/fs");
|
|
||||||
var batch = require("./utils/batch");
|
var batch = require("./utils/batch");
|
||||||
var pkg = require("../package.json");
|
var pkg = require("../package.json");
|
||||||
|
var defaultBlocks = require("./blocks");
|
||||||
|
var BookLoader = require("./conrefs_loader");
|
||||||
|
|
||||||
|
// Normalize result from a block
|
||||||
// The loader should handle relative and git url
|
function normBlockResult(blk) {
|
||||||
var BookLoader = nunjucks.Loader.extend({
|
if (_.isString(blk)) blk = { body: blk };
|
||||||
async: true,
|
return blk;
|
||||||
|
}
|
||||||
init: function(book) {
|
|
||||||
this.book = book;
|
|
||||||
},
|
|
||||||
|
|
||||||
getSource: function(fileurl, callback) {
|
|
||||||
var that = this;
|
|
||||||
|
|
||||||
git.resolveFile(fileurl)
|
|
||||||
.then(function(filepath) {
|
|
||||||
// Is local file
|
|
||||||
if (!filepath) filepath = path.resolve(that.book.root, fileurl);
|
|
||||||
else that.book.log.debug.ln("resolve from git", fileurl, "to", filepath)
|
|
||||||
|
|
||||||
// Read file from absolute path
|
|
||||||
return fs.readFile(filepath)
|
|
||||||
.then(function(source) {
|
|
||||||
return {
|
|
||||||
src: source.toString(),
|
|
||||||
path: filepath
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.nodeify(callback);
|
|
||||||
},
|
|
||||||
|
|
||||||
resolve: function(from, to) {
|
|
||||||
return path.resolve(path.dirname(from), to);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
var TemplateEngine = function(book) {
|
var TemplateEngine = function(book) {
|
||||||
@@ -58,12 +28,12 @@ var TemplateEngine = function(book) {
|
|||||||
|
|
||||||
// Tags
|
// Tags
|
||||||
tags: {
|
tags: {
|
||||||
blockStart: '{%',
|
blockStart: "{%",
|
||||||
blockEnd: '%}',
|
blockEnd: "%}",
|
||||||
variableStart: '{{',
|
variableStart: "{{",
|
||||||
variableEnd: '}}',
|
variableEnd: "}}",
|
||||||
commentStart: '{###',
|
commentStart: "{###",
|
||||||
commentEnd: '###}'
|
commentEnd: "###}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -71,49 +41,48 @@ var TemplateEngine = function(book) {
|
|||||||
// List of tags shortcuts
|
// List of tags shortcuts
|
||||||
this.shortcuts = [];
|
this.shortcuts = [];
|
||||||
|
|
||||||
// Map of blocks
|
// Map of blocks bodies (that requires post-processing)
|
||||||
|
this.blockBodies = {};
|
||||||
|
|
||||||
|
// Map of added blocks
|
||||||
this.blocks = {};
|
this.blocks = {};
|
||||||
|
|
||||||
// Bind methods
|
// Bind methods
|
||||||
_.bindAll(this);
|
_.bindAll(this);
|
||||||
|
|
||||||
// Default block "html" that return html not parsed
|
// Add default blocks
|
||||||
this.addBlock("html", {
|
this.addBlocks(defaultBlocks);
|
||||||
process: _.identity
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Process a block in a context
|
// Process the result of block in a context
|
||||||
TemplateEngine.prototype.processBlock = function(blk) {
|
TemplateEngine.prototype.processBlock = function(blk) {
|
||||||
if (_.isString(blk)) blk = { body: blk };
|
|
||||||
|
|
||||||
blk = _.defaults(blk, {
|
blk = _.defaults(blk, {
|
||||||
parse: false,
|
parse: false,
|
||||||
post: undefined
|
post: undefined
|
||||||
});
|
});
|
||||||
blk.id = _.uniqueId("blk");
|
blk.id = _.uniqueId("blk");
|
||||||
|
|
||||||
var toAdd = (!blk.parse) || (blk.post != undefined);
|
var toAdd = (!blk.parse) || (blk.post !== undefined);
|
||||||
|
|
||||||
// Add to global map
|
// Add to global map
|
||||||
if (toAdd) this.blocks[blk.id] = blk;
|
if (toAdd) this.blockBodies[blk.id] = blk;
|
||||||
|
|
||||||
//Parsable block, just return it
|
//Parsable block, just return it
|
||||||
if (blk.parse) {
|
if (blk.parse) {
|
||||||
return blk.body;
|
return blk.body;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return it as a macro
|
// Return it as a position marker
|
||||||
return "%+%"+blk.id+"%+%";
|
return "@%@"+blk.id+"@%@";
|
||||||
};
|
};
|
||||||
|
|
||||||
// Replace blocks by body after processing
|
// Replace position markers of blocks by body after processing
|
||||||
// This is done to avoid that markdown processer parse the block content
|
// This is done to avoid that markdown/asciidoc processer parse the block content
|
||||||
TemplateEngine.prototype.replaceBlocks = function(content) {
|
TemplateEngine.prototype.replaceBlocks = function(content) {
|
||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
return content.replace(/\%\+\%([\s\S]+?)\%\+\%/g, function(match, key) {
|
return content.replace(/\@\%\@([\s\S]+?)\@\%\@/g, function(match, key) {
|
||||||
var blk = that.blocks[key];
|
var blk = that.blockBodies[key];
|
||||||
if (!blk) return match;
|
if (!blk) return match;
|
||||||
|
|
||||||
var body = blk.body;
|
var body = blk.body;
|
||||||
@@ -141,11 +110,11 @@ TemplateEngine.prototype.bindContext = function(func) {
|
|||||||
TemplateEngine.prototype.addFilter = function(filterName, func) {
|
TemplateEngine.prototype.addFilter = function(filterName, func) {
|
||||||
try {
|
try {
|
||||||
this.env.getFilter(filterName);
|
this.env.getFilter(filterName);
|
||||||
this.log.warn.ln("conflict in filters, '"+filterName+"' is already set");
|
this.log.warn.ln("conflict in filters, \""+filterName+"\" is already set");
|
||||||
return false;
|
return false;
|
||||||
} catch(e) {}
|
} catch(e) {}
|
||||||
|
|
||||||
this.log.debug.ln("add filter '"+filterName+"'");
|
this.log.debug.ln("add filter \""+filterName+"\"");
|
||||||
this.env.addFilter(filterName, this.bindContext(function() {
|
this.env.addFilter(filterName, this.bindContext(function() {
|
||||||
var ctx = this;
|
var ctx = this;
|
||||||
var args = Array.prototype.slice.apply(arguments);
|
var args = Array.prototype.slice.apply(arguments);
|
||||||
@@ -160,9 +129,41 @@ TemplateEngine.prototype.addFilter = function(filterName, func) {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Add multiple filters
|
||||||
|
TemplateEngine.prototype.addFilters = function(filters) {
|
||||||
|
_.each(filters, function(filter, name) {
|
||||||
|
this.addFilter(name, filter);
|
||||||
|
}, this);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return nunjucks extension name of a block
|
||||||
|
TemplateEngine.prototype.blockExtName = function(name) {
|
||||||
|
return "Block"+name+"Extension";
|
||||||
|
};
|
||||||
|
|
||||||
|
// Test if a block is defined
|
||||||
|
TemplateEngine.prototype.hasBlock = function(name) {
|
||||||
|
return this.env.hasExtension(this.blockExtName(name));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Remove a block
|
||||||
|
TemplateEngine.prototype.removeBlock = function(name) {
|
||||||
|
if (!this.hasBlock(name)) return;
|
||||||
|
|
||||||
|
// Remove nunjucks extension
|
||||||
|
this.env.removeExtension(this.blockExtName(name));
|
||||||
|
|
||||||
|
// Cleanup shortcuts
|
||||||
|
this.shortcuts = _.reject(this.shortcuts, {
|
||||||
|
block: name
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// Add a block
|
// Add a block
|
||||||
TemplateEngine.prototype.addBlock = function(name, block) {
|
TemplateEngine.prototype.addBlock = function(name, block) {
|
||||||
var that = this;
|
var that = this, Ext, extName;
|
||||||
|
|
||||||
|
if (_.isFunction(block)) block = { process: block };
|
||||||
|
|
||||||
block = _.defaults(block || {}, {
|
block = _.defaults(block || {}, {
|
||||||
shortcuts: [],
|
shortcuts: [],
|
||||||
@@ -171,18 +172,22 @@ TemplateEngine.prototype.addBlock = function(name, block) {
|
|||||||
blocks: []
|
blocks: []
|
||||||
});
|
});
|
||||||
|
|
||||||
var extName = 'Block'+name+'Extension';
|
extName = this.blockExtName(name);
|
||||||
if (this.env.getExtension(extName)) {
|
|
||||||
this.log.warn.ln("conflict in blocks, '"+name+"' is already defined");
|
if (this.hasBlock(name) && !defaultBlocks[name]) {
|
||||||
return false;
|
this.log.warn.ln("conflict in blocks, \""+name+"\" is already defined");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.log.debug.ln("add block '"+name+"'");
|
// Cleanup previous block
|
||||||
|
this.removeBlock(name);
|
||||||
|
|
||||||
var Ext = function () {
|
this.log.debug.ln("add block \""+name+"\"");
|
||||||
|
this.blocks[name] = block;
|
||||||
|
|
||||||
|
Ext = function () {
|
||||||
this.tags = [name];
|
this.tags = [name];
|
||||||
|
|
||||||
this.parse = function(parser, nodes, lexer) {
|
this.parse = function(parser, nodes) {
|
||||||
var body = null;
|
var body = null;
|
||||||
var lastBlockName = null;
|
var lastBlockName = null;
|
||||||
var lastBlockArgs = null;
|
var lastBlockArgs = null;
|
||||||
@@ -223,7 +228,7 @@ TemplateEngine.prototype.addBlock = function(name, block) {
|
|||||||
var bodies = [body];
|
var bodies = [body];
|
||||||
_.each(block.blocks, function(blockName) {
|
_.each(block.blocks, function(blockName) {
|
||||||
subbodies[blockName] = subbodies[blockName] || [];
|
subbodies[blockName] = subbodies[blockName] || [];
|
||||||
if (subbodies[blockName].length == 0) {
|
if (subbodies[blockName].length === 0) {
|
||||||
subbodies[blockName].push({
|
subbodies[blockName].push({
|
||||||
args: new nodes.NodeList(),
|
args: new nodes.NodeList(),
|
||||||
body: new nodes.NodeList()
|
body: new nodes.NodeList()
|
||||||
@@ -233,7 +238,7 @@ TemplateEngine.prototype.addBlock = function(name, block) {
|
|||||||
bodies.push(subbodies[blockName][0].body);
|
bodies.push(subbodies[blockName][0].body);
|
||||||
});
|
});
|
||||||
|
|
||||||
return new nodes.CallExtensionAsync(this, 'run', args, bodies);
|
return new nodes.CallExtensionAsync(this, "run", args, bodies);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.run = function(context) {
|
this.run = function(context) {
|
||||||
@@ -260,33 +265,31 @@ TemplateEngine.prototype.addBlock = function(name, block) {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
var func = that.bindContext(block.process);
|
|
||||||
|
|
||||||
Q()
|
Q()
|
||||||
.then(function() {
|
.then(function() {
|
||||||
return func.call(context, {
|
return that.applyBlock(name, {
|
||||||
body: body(),
|
body: body(),
|
||||||
args: args,
|
args: args,
|
||||||
kwargs: kwargs,
|
kwargs: kwargs,
|
||||||
blocks: _blocks
|
blocks: _blocks
|
||||||
});
|
}, context);
|
||||||
})
|
})
|
||||||
|
|
||||||
// process the block returned
|
// process the block returned
|
||||||
.then(that.processBlock)
|
.then(that.processBlock)
|
||||||
.nodeify(callback)
|
.nodeify(callback);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Add the Extension
|
// Add the Extension
|
||||||
this.env.addExtension(extName, new Ext());
|
this.env.addExtension(extName, new Ext());
|
||||||
|
|
||||||
// Add shortcuts
|
// Add shortcuts
|
||||||
if (!_.isArray(block.shortcuts)) block.shortcuts = [block.shortcuts];
|
if (!_.isArray(block.shortcuts)) block.shortcuts = [block.shortcuts];
|
||||||
_.each(block.shortcuts, function(shortcut) {
|
_.each(block.shortcuts, function(shortcut) {
|
||||||
this.log.debug.ln("add template shortcut from '"+shortcut.start+"' to block '"+name+"' for parsers ", shortcut.parsers);
|
this.log.debug.ln("add template shortcut from \""+shortcut.start+"\" to block \""+name+"\" for parsers ", shortcut.parsers);
|
||||||
this.shortcuts.push({
|
this.shortcuts.push({
|
||||||
|
block: name,
|
||||||
parsers: shortcut.parsers,
|
parsers: shortcut.parsers,
|
||||||
start: shortcut.start,
|
start: shortcut.start,
|
||||||
end: shortcut.end,
|
end: shortcut.end,
|
||||||
@@ -298,12 +301,46 @@ TemplateEngine.prototype.addBlock = function(name, block) {
|
|||||||
}, this);
|
}, this);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Add multiple blocks
|
||||||
|
TemplateEngine.prototype.addBlocks = function(blocks) {
|
||||||
|
_.each(blocks, function(block, name) {
|
||||||
|
this.addBlock(name, block);
|
||||||
|
}, this);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Apply a block to some content
|
||||||
|
// This method result depends on the type of block (async or sync)
|
||||||
|
TemplateEngine.prototype.applyBlock = function(name, blk, ctx) {
|
||||||
|
var func, block, r;
|
||||||
|
|
||||||
|
block = this.blocks[name];
|
||||||
|
if (!block) throw new Error("Block not found \""+name+"\"");
|
||||||
|
if (_.isString(blk)) {
|
||||||
|
blk = {
|
||||||
|
body: blk
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
blk = _.defaults(blk, {
|
||||||
|
args: [],
|
||||||
|
kwargs: {},
|
||||||
|
blocks: []
|
||||||
|
});
|
||||||
|
|
||||||
|
// Bind and call block processor
|
||||||
|
func = this.bindContext(block.process);
|
||||||
|
r = func.call(ctx || {}, blk);
|
||||||
|
|
||||||
|
if (Q.isPromise(r)) return r.then(normBlockResult);
|
||||||
|
else return normBlockResult(r);
|
||||||
|
};
|
||||||
|
|
||||||
// Apply a shortcut to a string
|
// Apply a shortcut to a string
|
||||||
TemplateEngine.prototype._applyShortcut = function(parser, content, shortcut) {
|
TemplateEngine.prototype._applyShortcut = function(parser, content, shortcut) {
|
||||||
if (!_.contains(shortcut.parsers, parser)) return content;
|
if (!_.contains(shortcut.parsers, parser)) return content;
|
||||||
var regex = new RegExp(
|
var regex = new RegExp(
|
||||||
escapeStringRegexp(shortcut.start) + "([\\s\\S]*?[^\\$])" + escapeStringRegexp(shortcut.end),
|
escapeStringRegexp(shortcut.start) + "([\\s\\S]*?[^\\$])" + escapeStringRegexp(shortcut.end),
|
||||||
'g'
|
"g"
|
||||||
);
|
);
|
||||||
return content.replace(regex, function(all, match) {
|
return content.replace(regex, function(all, match) {
|
||||||
return "{% "+shortcut.tag.start+" %}"+ match + "{% "+shortcut.tag.end+" %}";
|
return "{% "+shortcut.tag.start+" %}"+ match + "{% "+shortcut.tag.end+" %}";
|
||||||
@@ -312,7 +349,7 @@ TemplateEngine.prototype._applyShortcut = function(parser, content, shortcut) {
|
|||||||
|
|
||||||
// Render a string from the book
|
// Render a string from the book
|
||||||
TemplateEngine.prototype.renderString = function(content, context, options) {
|
TemplateEngine.prototype.renderString = function(content, context, options) {
|
||||||
var context = _.extend({}, context, {
|
context = _.extend({}, context, {
|
||||||
// Variables from book.json
|
// Variables from book.json
|
||||||
book: this.book.options.variables,
|
book: this.book.options.variables,
|
||||||
|
|
||||||
@@ -344,8 +381,8 @@ TemplateEngine.prototype.renderString = function(content, context, options) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Render a file from the book
|
// Render a file from the book
|
||||||
TemplateEngine.prototype.renderFile = function(filename, options) {
|
TemplateEngine.prototype.renderFile = function(filename) {
|
||||||
var that = this, context;
|
var that = this;
|
||||||
|
|
||||||
return that.book.readFile(filename)
|
return that.book.readFile(filename)
|
||||||
.then(function(content) {
|
.then(function(content) {
|
||||||
@@ -357,11 +394,11 @@ TemplateEngine.prototype.renderFile = function(filename, options) {
|
|||||||
|
|
||||||
// Render a page from the book
|
// Render a page from the book
|
||||||
TemplateEngine.prototype.renderPage = function(page) {
|
TemplateEngine.prototype.renderPage = function(page) {
|
||||||
var that = this, context;
|
var that = this;
|
||||||
|
|
||||||
return that.book.statFile(page.path)
|
return that.book.statFile(page.path)
|
||||||
.then(function(stat) {
|
.then(function(stat) {
|
||||||
context = {
|
var context = {
|
||||||
// infos about the file
|
// infos about the file
|
||||||
file: {
|
file: {
|
||||||
path: page.path,
|
path: page.path,
|
||||||
@@ -383,7 +420,7 @@ TemplateEngine.prototype.postProcess = function(content) {
|
|||||||
return Q(content)
|
return Q(content)
|
||||||
.then(that.replaceBlocks)
|
.then(that.replaceBlocks)
|
||||||
.then(function(_content) {
|
.then(function(_content) {
|
||||||
return batch.execEach(that.blocks, {
|
return batch.execEach(that.blockBodies, {
|
||||||
max: 20,
|
max: 20,
|
||||||
fn: function(blk, blkId) {
|
fn: function(blk, blkId) {
|
||||||
return Q()
|
return Q()
|
||||||
@@ -392,7 +429,7 @@ TemplateEngine.prototype.postProcess = function(content) {
|
|||||||
return blk.post();
|
return blk.post();
|
||||||
})
|
})
|
||||||
.then(function() {
|
.then(function() {
|
||||||
delete that.blocks[blkId];
|
delete that.blockBodies[blkId];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
+4
-4
@@ -3,12 +3,12 @@ var _ = require("lodash");
|
|||||||
|
|
||||||
// Execute a method for all element
|
// Execute a method for all element
|
||||||
function execEach(items, options) {
|
function execEach(items, options) {
|
||||||
if (_.size(items) == 0) return Q();
|
if (_.size(items) === 0) return Q();
|
||||||
var concurrents = 0, d = Q.defer(), pending = [];
|
var concurrents = 0, d = Q.defer(), pending = [];
|
||||||
|
|
||||||
options = _.defaults(options || {}, {
|
options = _.defaults(options || {}, {
|
||||||
max: 100,
|
max: 100,
|
||||||
fn: function(item) {}
|
fn: function() {}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ function execEach(items, options) {
|
|||||||
// Next pending
|
// Next pending
|
||||||
var next = pending.shift();
|
var next = pending.shift();
|
||||||
|
|
||||||
if (concurrents == 0 && !next) {
|
if (concurrents === 0 && !next) {
|
||||||
d.resolve();
|
d.resolve();
|
||||||
} else if (next) {
|
} else if (next) {
|
||||||
startItem.apply(null, next);
|
startItem.apply(null, next);
|
||||||
@@ -38,7 +38,7 @@ function execEach(items, options) {
|
|||||||
.fail(function(err) {
|
.fail(function(err) {
|
||||||
pending = [];
|
pending = [];
|
||||||
d.reject(err);
|
d.reject(err);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_.each(items, startItem);
|
_.each(items, startItem);
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
var hljs = require('highlight.js');
|
|
||||||
|
|
||||||
var MAP = {
|
|
||||||
'py': 'python',
|
|
||||||
'js': 'javascript',
|
|
||||||
'json': 'javascript',
|
|
||||||
'rb': 'ruby',
|
|
||||||
'csharp': 'cs',
|
|
||||||
};
|
|
||||||
|
|
||||||
function normalize(lang) {
|
|
||||||
if(!lang) { return null; }
|
|
||||||
|
|
||||||
var lower = lang.toLowerCase();
|
|
||||||
return MAP[lower] || lower;
|
|
||||||
}
|
|
||||||
|
|
||||||
function highlight(lang, code) {
|
|
||||||
if(!lang) return code;
|
|
||||||
|
|
||||||
// Normalize lang
|
|
||||||
lang = normalize(lang);
|
|
||||||
|
|
||||||
try {
|
|
||||||
return hljs.highlight(lang, code).value;
|
|
||||||
} catch(e) { }
|
|
||||||
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exports
|
|
||||||
module.exports = {
|
|
||||||
highlight: highlight,
|
|
||||||
normalize: normalize,
|
|
||||||
MAP: MAP
|
|
||||||
};
|
|
||||||
+16
-16
@@ -9,10 +9,10 @@ var Ignore = require("fstream-ignore");
|
|||||||
var fsUtils = {
|
var fsUtils = {
|
||||||
tmp: {
|
tmp: {
|
||||||
file: function(opt) {
|
file: function(opt) {
|
||||||
return Q.nfcall(tmp.file.bind(tmp), opt).get(0)
|
return Q.nfcall(tmp.file.bind(tmp), opt).get(0);
|
||||||
},
|
},
|
||||||
dir: function() {
|
dir: function() {
|
||||||
return Q.nfcall(tmp.dir.bind(tmp)).get(0)
|
return Q.nfcall(tmp.dir.bind(tmp)).get(0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
list: listFiles,
|
list: listFiles,
|
||||||
@@ -34,14 +34,14 @@ var fsUtils = {
|
|||||||
readFileSync: fs.readFileSync.bind(fs),
|
readFileSync: fs.readFileSync.bind(fs),
|
||||||
clean: cleanFolder,
|
clean: cleanFolder,
|
||||||
getUniqueFilename: getUniqueFilename,
|
getUniqueFilename: getUniqueFilename,
|
||||||
}
|
};
|
||||||
|
|
||||||
// Write a file
|
// Write a file
|
||||||
function writeFile(filename, data, options) {
|
function writeFile(filename, data, options) {
|
||||||
var d = Q.defer();
|
var d = Q.defer();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fs.writeFileSync(filename, data, options)
|
fs.writeFileSync(filename, data, options);
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
d.reject(err);
|
d.reject(err);
|
||||||
}
|
}
|
||||||
@@ -57,14 +57,14 @@ function writeStream(filename, st) {
|
|||||||
|
|
||||||
var wstream = fs.createWriteStream(filename);
|
var wstream = fs.createWriteStream(filename);
|
||||||
|
|
||||||
wstream.on('finish', function () {
|
wstream.on("finish", function () {
|
||||||
d.resolve();
|
d.resolve();
|
||||||
});
|
});
|
||||||
wstream.on('error', function (err) {
|
wstream.on("error", function (err) {
|
||||||
d.reject(err);
|
d.reject(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
st.on('error', function(err) {
|
st.on("error", function(err) {
|
||||||
d.reject(err);
|
d.reject(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -115,20 +115,20 @@ function listFiles(root, options) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Add extra rules to ignore common folders
|
// Add extra rules to ignore common folders
|
||||||
ig.addIgnoreRules(options.ignoreRules, '__custom_stuff');
|
ig.addIgnoreRules(options.ignoreRules, "__custom_stuff");
|
||||||
|
|
||||||
// Push each file to our list
|
// Push each file to our list
|
||||||
ig.on('child', function (c) {
|
ig.on("child", function (c) {
|
||||||
files.push(
|
files.push(
|
||||||
c.path.substr(c.root.path.length + 1) + (c.props.Directory === true ? '/' : '')
|
c.path.substr(c.root.path.length + 1) + (c.props.Directory === true ? "/" : "")
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
ig.on('end', function() {
|
ig.on("end", function() {
|
||||||
// Normalize paths on Windows
|
// Normalize paths on Windows
|
||||||
if(process.platform === 'win32') {
|
if(process.platform === "win32") {
|
||||||
return d.resolve(files.map(function(file) {
|
return d.resolve(files.map(function(file) {
|
||||||
return file.replace(/\\/g, '/');
|
return file.replace(/\\/g, "/");
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +136,7 @@ function listFiles(root, options) {
|
|||||||
return d.resolve(files);
|
return d.resolve(files);
|
||||||
});
|
});
|
||||||
|
|
||||||
ig.on('error', d.reject);
|
ig.on("error", d.reject);
|
||||||
|
|
||||||
return d.promise;
|
return d.promise;
|
||||||
}
|
}
|
||||||
@@ -150,8 +150,8 @@ function cleanFolder(root) {
|
|||||||
ignoreFiles: [],
|
ignoreFiles: [],
|
||||||
ignoreRules: [
|
ignoreRules: [
|
||||||
// Skip Git and SVN stuff
|
// Skip Git and SVN stuff
|
||||||
'.git/',
|
".git/",
|
||||||
'.svn/'
|
".svn/"
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
.then(function(files) {
|
.then(function(files) {
|
||||||
|
|||||||
+20
-5
@@ -1,11 +1,10 @@
|
|||||||
var Q = require("q");
|
var Q = require("q");
|
||||||
var _ = require("lodash");
|
var _ = require("lodash");
|
||||||
var url = require("url");
|
|
||||||
var tmp = require("tmp");
|
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
var crc = require("crc");
|
var crc = require("crc");
|
||||||
var exec = Q.denodeify(require("child_process").exec);
|
var exec = Q.denodeify(require("child_process").exec);
|
||||||
var URI = require("URIjs");
|
var URI = require("URIjs");
|
||||||
|
var pathUtil = require("./path");
|
||||||
|
|
||||||
var fs = require("./fs");
|
var fs = require("./fs");
|
||||||
|
|
||||||
@@ -89,7 +88,6 @@ function cloneGitRepo(host, ref) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Get file from a git repo
|
// Get file from a git repo
|
||||||
function resolveFileFromGit(giturl) {
|
function resolveFileFromGit(giturl) {
|
||||||
if (_.isString(giturl)) giturl = parseGitUrl(giturl);
|
if (_.isString(giturl)) giturl = parseGitUrl(giturl);
|
||||||
@@ -102,11 +100,28 @@ function resolveFileFromGit(giturl) {
|
|||||||
// Resolve relative path
|
// Resolve relative path
|
||||||
return path.resolve(repo, giturl.filepath);
|
return path.resolve(repo, giturl.filepath);
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
|
// Return root of git repo from a filepath
|
||||||
|
function resolveGitRoot(filepath) {
|
||||||
|
var relativeToGit, repoId;
|
||||||
|
|
||||||
|
// No git repo cloned, or file is not in a git repository
|
||||||
|
if (!GIT_TMP || !pathUtil.isInRoot(GIT_TMP, filepath)) return null;
|
||||||
|
|
||||||
|
// Extract first directory (is the repo id)
|
||||||
|
relativeToGit = path.relative(GIT_TMP, filepath);
|
||||||
|
repoId = _.first(relativeToGit.split(path.sep));
|
||||||
|
if (!repoId) return;
|
||||||
|
|
||||||
|
// Return an absolute file
|
||||||
|
return path.resolve(GIT_TMP, repoId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
checkUrl: checkGitUrl,
|
checkUrl: checkGitUrl,
|
||||||
parseUrl: parseGitUrl,
|
parseUrl: parseGitUrl,
|
||||||
resolveFile: resolveFileFromGit
|
resolveFile: resolveFileFromGit,
|
||||||
|
resolveRoot: resolveGitRoot
|
||||||
};
|
};
|
||||||
|
|||||||
+11
-11
@@ -4,7 +4,7 @@ var fs = require("fs");
|
|||||||
|
|
||||||
var i18n = require("i18n");
|
var i18n = require("i18n");
|
||||||
|
|
||||||
var I18N_PATH = path.resolve(__dirname, "../../theme/i18n/")
|
var I18N_PATH = path.resolve(__dirname, "../../theme/i18n/");
|
||||||
var DEFAULT_LANGUAGE = "en";
|
var DEFAULT_LANGUAGE = "en";
|
||||||
var LOCALES = _.map(fs.readdirSync(I18N_PATH), function(lang) {
|
var LOCALES = _.map(fs.readdirSync(I18N_PATH), function(lang) {
|
||||||
return path.basename(lang, ".json");
|
return path.basename(lang, ".json");
|
||||||
@@ -17,7 +17,7 @@ i18n.configure({
|
|||||||
updateFiles: false
|
updateFiles: false
|
||||||
});
|
});
|
||||||
|
|
||||||
var compareLocales = function(lang, locale) {
|
function compareLocales(lang, locale) {
|
||||||
var langMain = _.first(lang.split("-"));
|
var langMain = _.first(lang.split("-"));
|
||||||
var langSecond = _.last(lang.split("-"));
|
var langSecond = _.last(lang.split("-"));
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ var compareLocales = function(lang, locale) {
|
|||||||
if (localeMain == langMain) return 50;
|
if (localeMain == langMain) return 50;
|
||||||
if (localeSecond == langSecond) return 20;
|
if (localeSecond == langSecond) return 20;
|
||||||
return 0;
|
return 0;
|
||||||
};
|
}
|
||||||
|
|
||||||
var normalizeLanguage = _.memoize(function(lang) {
|
var normalizeLanguage = _.memoize(function(lang) {
|
||||||
var language = _.chain(LOCALES)
|
var language = _.chain(LOCALES)
|
||||||
@@ -37,7 +37,7 @@ var normalizeLanguage = _.memoize(function(lang) {
|
|||||||
return {
|
return {
|
||||||
locale: locale,
|
locale: locale,
|
||||||
score: compareLocales(lang, locale)
|
score: compareLocales(lang, locale)
|
||||||
}
|
};
|
||||||
})
|
})
|
||||||
.filter(function(lang) {
|
.filter(function(lang) {
|
||||||
return lang.score > 0;
|
return lang.score > 0;
|
||||||
@@ -49,25 +49,25 @@ var normalizeLanguage = _.memoize(function(lang) {
|
|||||||
return language || lang;
|
return language || lang;
|
||||||
});
|
});
|
||||||
|
|
||||||
var translate = function(locale, phrase) {
|
function translate(locale, phrase) {
|
||||||
var args = Array.prototype.slice.call(arguments, 2);
|
var args = Array.prototype.slice.call(arguments, 2);
|
||||||
|
|
||||||
return i18n.__.apply({}, [{
|
return i18n.__.apply({}, [{
|
||||||
locale: locale,
|
locale: locale,
|
||||||
phrase: phrase
|
phrase: phrase
|
||||||
}].concat(args));
|
}].concat(args));
|
||||||
};
|
}
|
||||||
|
|
||||||
var getCatalog = function(locale) {
|
function getCatalog(locale) {
|
||||||
locale = normalizeLanguage(locale);
|
locale = normalizeLanguage(locale);
|
||||||
return i18n.getCatalog(locale);
|
return i18n.getCatalog(locale);
|
||||||
};
|
}
|
||||||
|
|
||||||
var getLocales = function() {
|
function getLocales() {
|
||||||
return LOCALES;
|
return LOCALES;
|
||||||
};
|
}
|
||||||
|
|
||||||
var hasLocale = function(locale) {
|
function hasLocale(locale) {
|
||||||
return _.contains(LOCALES, locale);
|
return _.contains(LOCALES, locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-7
@@ -1,9 +1,7 @@
|
|||||||
var _ = require("lodash");
|
var _ = require("lodash");
|
||||||
var Q = require("q");
|
var Q = require("q");
|
||||||
var fs = require("./fs");
|
var fs = require("./fs");
|
||||||
var spawn = require('spawn-cmd').spawn;
|
var spawn = require("spawn-cmd").spawn;
|
||||||
|
|
||||||
var links = require("./links");
|
|
||||||
|
|
||||||
// Convert a svg file
|
// Convert a svg file
|
||||||
var convertSVG = function(source, dest, options) {
|
var convertSVG = function(source, dest, options) {
|
||||||
@@ -14,16 +12,16 @@ var convertSVG = function(source, dest, options) {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
//var command = shellescape(['svgexport', source, dest]);
|
//var command = shellescape(["svgexport", source, dest]);
|
||||||
var child = spawn('svgexport', [source, dest]);
|
var child = spawn("svgexport", [source, dest]);
|
||||||
|
|
||||||
child.on("error", function(error) {
|
child.on("error", function(error) {
|
||||||
if (error.code == "ENOENT") error = new Error("Need to install 'svgexport' using 'npm install svgexport -g'");
|
if (error.code == "ENOENT") error = new Error("Need to install \"svgexport\" using \"npm install svgexport -g\"");
|
||||||
return d.reject(error);
|
return d.reject(error);
|
||||||
});
|
});
|
||||||
|
|
||||||
child.on("close", function(code) {
|
child.on("close", function(code) {
|
||||||
if (code == 0 && fs.existsSync(dest)) {
|
if (code === 0 && fs.existsSync(dest)) {
|
||||||
d.resolve();
|
d.resolve();
|
||||||
} else {
|
} else {
|
||||||
d.reject(new Error("Error converting "+source+" into "+dest));
|
d.reject(new Error("Error converting "+source+" into "+dest));
|
||||||
|
|||||||
+4
-4
@@ -1,5 +1,5 @@
|
|||||||
var url = require('url');
|
var url = require("url");
|
||||||
var path = require('path');
|
var path = require("path");
|
||||||
|
|
||||||
// Is the link an external link
|
// Is the link an external link
|
||||||
var isExternal = function(href) {
|
var isExternal = function(href) {
|
||||||
@@ -33,7 +33,7 @@ var isAnchor = function(href) {
|
|||||||
|
|
||||||
// Normalize a path to be a link
|
// Normalize a path to be a link
|
||||||
var normalizeLink = function(s) {
|
var normalizeLink = function(s) {
|
||||||
return s.replace(/\\/g, '/');
|
return s.replace(/\\/g, "/");
|
||||||
};
|
};
|
||||||
|
|
||||||
// Relative to absolute path
|
// Relative to absolute path
|
||||||
@@ -43,7 +43,7 @@ var normalizeLink = function(s) {
|
|||||||
var toAbsolute = function(_href, dir, outdir) {
|
var toAbsolute = function(_href, dir, outdir) {
|
||||||
if (isExternal(_href)) return _href;
|
if (isExternal(_href)) return _href;
|
||||||
|
|
||||||
// Path '_href' inside the base folder
|
// Path "_href" inside the base folder
|
||||||
var hrefInRoot = path.normalize(path.join(dir, _href));
|
var hrefInRoot = path.normalize(path.join(dir, _href));
|
||||||
if (_href[0] == "/") hrefInRoot = path.normalize(_href.slice(1));
|
if (_href[0] == "/") hrefInRoot = path.normalize(_href.slice(1));
|
||||||
|
|
||||||
|
|||||||
+9
-9
@@ -1,6 +1,6 @@
|
|||||||
var _ = require('lodash');
|
var _ = require("lodash");
|
||||||
var util = require('util');
|
var util = require("util");
|
||||||
var color = require('bash-color');
|
var color = require("bash-color");
|
||||||
|
|
||||||
var LEVELS = {
|
var LEVELS = {
|
||||||
DEBUG: 0,
|
DEBUG: 0,
|
||||||
@@ -19,7 +19,7 @@ var COLORS = {
|
|||||||
|
|
||||||
module.exports = function(_write, logLevel) {
|
module.exports = function(_write, logLevel) {
|
||||||
var logger = {};
|
var logger = {};
|
||||||
var lastChar = '\n';
|
var lastChar = "\n";
|
||||||
if (_.isString(logLevel)) logLevel = LEVELS[logLevel.toUpperCase()];
|
if (_.isString(logLevel)) logLevel = LEVELS[logLevel.toUpperCase()];
|
||||||
|
|
||||||
// Write a simple message
|
// Write a simple message
|
||||||
@@ -47,14 +47,14 @@ module.exports = function(_write, logLevel) {
|
|||||||
var args = Array.prototype.slice.apply(arguments, [1]);
|
var args = Array.prototype.slice.apply(arguments, [1]);
|
||||||
var msg = logger.format.apply(logger, args);
|
var msg = logger.format.apply(logger, args);
|
||||||
|
|
||||||
if (lastChar == '\n') {
|
if (lastChar == "\n") {
|
||||||
msg = COLORS[levelKey](levelKey.toLowerCase()+":")+" "+msg;
|
msg = COLORS[levelKey](levelKey.toLowerCase()+":")+" "+msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
return logger.write(msg);
|
return logger.write(msg);
|
||||||
};
|
};
|
||||||
logger.logLn = function() {
|
logger.logLn = function() {
|
||||||
if (lastChar != '\n') logger.write("\n");
|
if (lastChar != "\n") logger.write("\n");
|
||||||
|
|
||||||
var args = Array.prototype.slice.apply(arguments);
|
var args = Array.prototype.slice.apply(arguments);
|
||||||
args.push("\n");
|
args.push("\n");
|
||||||
@@ -66,7 +66,7 @@ module.exports = function(_write, logLevel) {
|
|||||||
var args = Array.prototype.slice.apply(arguments, [1]);
|
var args = Array.prototype.slice.apply(arguments, [1]);
|
||||||
var msg = logger.format.apply(logger, args);
|
var msg = logger.format.apply(logger, args);
|
||||||
if (arguments.length > 1) {
|
if (arguments.length > 1) {
|
||||||
logger.logLn(level, color.green('>> ') + msg.trim().replace(/\n/g, color.green('\n>> ')));
|
logger.logLn(level, color.green(">> ") + msg.trim().replace(/\n/g, color.green("\n>> ")));
|
||||||
} else {
|
} else {
|
||||||
logger.log(level, color.green("OK"), "\n");
|
logger.log(level, color.green("OK"), "\n");
|
||||||
}
|
}
|
||||||
@@ -77,7 +77,7 @@ module.exports = function(_write, logLevel) {
|
|||||||
return logger.log(level, color.red("ERROR")+"\n");
|
return logger.log(level, color.red("ERROR")+"\n");
|
||||||
};
|
};
|
||||||
|
|
||||||
_.each(_.omit(LEVELS, 'DISABLED'), function(level, levelKey) {
|
_.each(_.omit(LEVELS, "DISABLED"), function(level, levelKey) {
|
||||||
levelKey = levelKey.toLowerCase();
|
levelKey = levelKey.toLowerCase();
|
||||||
|
|
||||||
logger[levelKey] = _.partial(logger.log, level);
|
logger[levelKey] = _.partial(logger.log, level);
|
||||||
@@ -93,7 +93,7 @@ module.exports = function(_write, logLevel) {
|
|||||||
logger[levelKey].fail();
|
logger[levelKey].fail();
|
||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
return logger;
|
return logger;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
var _ = require('lodash');
|
var _ = require("lodash");
|
||||||
|
|
||||||
// Cleans up an article/chapter object
|
// Cleans up an article/chapter object
|
||||||
// remove 'articles' attributes
|
// remove "articles" attributes
|
||||||
function clean(obj) {
|
function clean(obj) {
|
||||||
return obj && _.omit(obj, ['articles']);
|
return obj && _.omit(obj, ["articles"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function flattenChapters(chapters) {
|
function flattenChapters(chapters) {
|
||||||
@@ -27,7 +27,7 @@ function navigation(summary, files) {
|
|||||||
files = _.isArray(files) ? files : (_.isString(files) ? [files] : null);
|
files = _.isArray(files) ? files : (_.isString(files) ? [files] : null);
|
||||||
|
|
||||||
// List of all navNodes
|
// List of all navNodes
|
||||||
// Flatten chapters, then add in default README node if needed etc ...
|
// Flatten chapters
|
||||||
var navNodes = flattenChapters(summary.chapters);
|
var navNodes = flattenChapters(summary.chapters);
|
||||||
|
|
||||||
// Mapping of prev/next for a give path
|
// Mapping of prev/next for a give path
|
||||||
@@ -39,8 +39,7 @@ function navigation(summary, files) {
|
|||||||
if(!current.exists) return null;
|
if(!current.exists) return null;
|
||||||
|
|
||||||
// Find prev
|
// Find prev
|
||||||
prev = _.chain(navNodes)
|
prev = _.chain(navNodes.slice(0, i))
|
||||||
.slice(0, i)
|
|
||||||
.reverse()
|
.reverse()
|
||||||
.find(function(node) {
|
.find(function(node) {
|
||||||
return node.exists && !node.external;
|
return node.exists && !node.external;
|
||||||
@@ -48,14 +47,12 @@ function navigation(summary, files) {
|
|||||||
.value();
|
.value();
|
||||||
|
|
||||||
// Find next
|
// Find next
|
||||||
next = _.chain(navNodes)
|
next = _.chain(navNodes.slice(i+1))
|
||||||
.slice(i+1)
|
|
||||||
.find(function(node) {
|
.find(function(node) {
|
||||||
return node.exists && !node.external;
|
return node.exists && !node.external;
|
||||||
})
|
})
|
||||||
.value();
|
.value();
|
||||||
|
|
||||||
|
|
||||||
return [current.path, {
|
return [current.path, {
|
||||||
index: i,
|
index: i,
|
||||||
title: current.title,
|
title: current.title,
|
||||||
|
|||||||
+48
-44
@@ -1,19 +1,18 @@
|
|||||||
var Q = require('q');
|
var Q = require("q");
|
||||||
var _ = require('lodash');
|
var _ = require("lodash");
|
||||||
var url = require('url');
|
var url = require("url");
|
||||||
var path = require('path');
|
var path = require("path");
|
||||||
var cheerio = require('cheerio');
|
var cheerio = require("cheerio");
|
||||||
var domSerializer = require('dom-serializer');
|
var domSerializer = require("dom-serializer");
|
||||||
var request = require('request');
|
var request = require("request");
|
||||||
var crc = require("crc");
|
var crc = require("crc");
|
||||||
|
|
||||||
var links = require('./links');
|
var links = require("./links");
|
||||||
var imgUtils = require('./images');
|
var imgUtils = require("./images");
|
||||||
var fs = require('./fs');
|
var fs = require("./fs");
|
||||||
var batch = require('./batch');
|
var batch = require("./batch");
|
||||||
var code = require('./code');
|
|
||||||
|
|
||||||
var parsableExtensions = require('gitbook-parsers').extensions;
|
var parsableExtensions = require("gitbook-parsers").extensions;
|
||||||
|
|
||||||
// Render a cheerio dom as html
|
// Render a cheerio dom as html
|
||||||
var renderDom = function($, dom, options) {
|
var renderDom = function($, dom, options) {
|
||||||
@@ -41,7 +40,8 @@ function replaceText($, el, search, replace, text_only ) {
|
|||||||
if ( node ) {
|
if ( node ) {
|
||||||
|
|
||||||
// Loop over all childNodes.
|
// Loop over all childNodes.
|
||||||
do {
|
while (node) {
|
||||||
|
|
||||||
// Only process text nodes.
|
// Only process text nodes.
|
||||||
if ( node.nodeType === 3 ) {
|
if ( node.nodeType === 3 ) {
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ function replaceText($, el, search, replace, text_only ) {
|
|||||||
// robust way.
|
// robust way.
|
||||||
$(node).before( new_val );
|
$(node).before( new_val );
|
||||||
|
|
||||||
// Don't remove the node yet, or the loop will lose its place.
|
// Don"t remove the node yet, or the loop will lose its place.
|
||||||
remove.push( node );
|
remove.push( node );
|
||||||
} else {
|
} else {
|
||||||
// The new value contains no HTML, so it can be set in this
|
// The new value contains no HTML, so it can be set in this
|
||||||
@@ -69,17 +69,18 @@ function replaceText($, el, search, replace, text_only ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} while ( node = node.nextSibling );
|
node = node.nextSibling;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Time to remove those elements!
|
// Time to remove those elements!
|
||||||
remove.length && $(remove).remove();
|
if (remove.length) $(remove).remove();
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
function pregQuote( str ) {
|
function pregQuote( str ) {
|
||||||
return (str+'').replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1");
|
return (str+"").replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1");
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
// Adapt an html snippet to be relative to a base folder
|
// Adapt an html snippet to be relative to a base folder
|
||||||
@@ -108,15 +109,16 @@ function normalizeHtml(src, options) {
|
|||||||
// Generate filename
|
// Generate filename
|
||||||
dest = "/"+fs.getUniqueFilename(outputRoot, dest);
|
dest = "/"+fs.getUniqueFilename(outputRoot, dest);
|
||||||
|
|
||||||
svgContent[dest] = '<?xml version="1.0" encoding="UTF-8"?>'+content;
|
svgContent[dest] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+content;
|
||||||
$(this).replaceWith($("<img>").attr("src", dest));
|
$(this).replaceWith($("<img>").attr("src", dest));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find images to normalize
|
// Find images to normalize
|
||||||
$("img").each(function() {
|
$("img").each(function() {
|
||||||
var origin = undefined;
|
var origin;
|
||||||
var src = $(this).attr("src");
|
var src = $(this).attr("src");
|
||||||
|
|
||||||
if (!src) return;
|
if (!src) return;
|
||||||
var isExternal = links.isExternal(src);
|
var isExternal = links.isExternal(src);
|
||||||
|
|
||||||
@@ -151,7 +153,7 @@ function normalizeHtml(src, options) {
|
|||||||
dest = links.join(path.dirname(srcAbs), path.basename(srcAbs, ext)+".png");
|
dest = links.join(path.dirname(srcAbs), path.basename(srcAbs, ext)+".png");
|
||||||
dest = dest[0] == "/"? dest.slice(1) : dest;
|
dest = dest[0] == "/"? dest.slice(1) : dest;
|
||||||
|
|
||||||
// Get a name that doesn't exists
|
// Get a name that doesn"t exists
|
||||||
dest = fs.getUniqueFilename(outputRoot, dest);
|
dest = fs.getUniqueFilename(outputRoot, dest);
|
||||||
|
|
||||||
options.book.log.debug.ln("detect invalid image (will be converted to png):", srcAbs);
|
options.book.log.debug.ln("detect invalid image (will be converted to png):", srcAbs);
|
||||||
@@ -206,9 +208,9 @@ function normalizeHtml(src, options) {
|
|||||||
|
|
||||||
// If md/adoc/rst files is not in summary
|
// If md/adoc/rst files is not in summary
|
||||||
// or for ebook, signal all files that are outside the summary
|
// or for ebook, signal all files that are outside the summary
|
||||||
else if (_.contains(parsableExtensions, path.extname(absolutePath))
|
else if (_.contains(parsableExtensions, path.extname(absolutePath)) ||
|
||||||
|| _.contains(['epub', 'pdf', 'mobi'], options.book.options.generator)) {
|
_.contains(["epub", "pdf", "mobi"], options.book.options.generator)) {
|
||||||
options.book.log.warn.ln("page", options.input, "contains an hyperlink to resource outside spine '"+href+"'");
|
options.book.log.warn.ln("page", options.input, "contains an hyperlink to resource outside spine \""+href+"\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform as absolute
|
// Transform as absolute
|
||||||
@@ -224,7 +226,7 @@ function normalizeHtml(src, options) {
|
|||||||
|
|
||||||
// Highlight code blocks
|
// Highlight code blocks
|
||||||
$("code").each(function() {
|
$("code").each(function() {
|
||||||
// Extract language
|
// Normalize language
|
||||||
var lang = _.chain(
|
var lang = _.chain(
|
||||||
($(this).attr("class") || "").split(" ")
|
($(this).attr("class") || "").split(" ")
|
||||||
)
|
)
|
||||||
@@ -241,22 +243,25 @@ function normalizeHtml(src, options) {
|
|||||||
.first()
|
.first()
|
||||||
.value();
|
.value();
|
||||||
|
|
||||||
if (lang) {
|
var source = $(this).text();
|
||||||
var html = code.highlight(
|
var blk = options.book.template.applyBlock("code", {
|
||||||
lang,
|
body: source,
|
||||||
$(this).text()
|
kwargs: {
|
||||||
);
|
language: lang
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$(this).html(html);
|
if (blk.html === false) $(this).text(blk.body);
|
||||||
}
|
else $(this).html(blk.body);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Replace glossary terms
|
// Replace glossary terms
|
||||||
var glossary = _.sortBy(options.glossary, function(term) {
|
var glossary = _.sortBy(options.glossary, function(term) {
|
||||||
return -term.name.length;
|
return -term.name.length;
|
||||||
});
|
});
|
||||||
|
|
||||||
_.each(glossary, function(term) {
|
_.each(glossary, function(term) {
|
||||||
var r = new RegExp( "\\b(" + pregQuote(term.name.toLowerCase()) + ")\\b" , 'gi' );
|
var r = new RegExp( "\\b(" + pregQuote(term.name.toLowerCase()) + ")\\b" , "gi" );
|
||||||
var includedInFiles = false;
|
var includedInFiles = false;
|
||||||
|
|
||||||
$("*").each(function() {
|
$("*").each(function() {
|
||||||
@@ -270,7 +275,7 @@ function normalizeHtml(src, options) {
|
|||||||
term.files = term.files || [];
|
term.files = term.files || [];
|
||||||
term.files.push(options.navigation[options.input]);
|
term.files.push(options.navigation[options.input]);
|
||||||
}
|
}
|
||||||
return "<a href='"+links.toAbsolute("/GLOSSARY.html", options.base, options.output)+"#"+term.id+"' class='glossary-term' title='"+_.escape(term.description)+"'>"+match+"</a>";
|
return "<a href=\""+links.toAbsolute("/GLOSSARY.html", options.base, options.output) + "#" + term.id+"\" class=\"glossary-term\" title=\""+_.escape(term.description)+"\">"+match+"</a>";
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -279,7 +284,7 @@ function normalizeHtml(src, options) {
|
|||||||
html: renderDom($),
|
html: renderDom($),
|
||||||
images: toConvert
|
images: toConvert
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
// Convert svg images to png
|
// Convert svg images to png
|
||||||
function convertImages(images, options) {
|
function convertImages(images, options) {
|
||||||
@@ -304,7 +309,7 @@ function convertImages(images, options) {
|
|||||||
.fail(function(err) {
|
.fail(function(err) {
|
||||||
if (!_.isError(err)) err = new Error(err);
|
if (!_.isError(err)) err = new Error(err);
|
||||||
|
|
||||||
err.message = 'Fail downloading '+image.origin+': '+err.message;
|
err.message = "Fail downloading "+image.origin+": "+err.message;
|
||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -327,8 +332,7 @@ function convertImages(images, options) {
|
|||||||
.then(function() {
|
.then(function() {
|
||||||
options.book.log.debug.ok(images.length+" images converted with success");
|
options.book.log.debug.ok(images.length+" images converted with success");
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
// Adapt page content to be relative to a base folder
|
// Adapt page content to be relative to a base folder
|
||||||
function normalizePage(sections, options) {
|
function normalizePage(sections, options) {
|
||||||
@@ -361,7 +365,7 @@ function normalizePage(sections, options) {
|
|||||||
sections = _.map(sections, function(section) {
|
sections = _.map(sections, function(section) {
|
||||||
if (section.type != "normal") return section;
|
if (section.type != "normal") return section;
|
||||||
|
|
||||||
var out = normalizeHtml(section.content, options);;
|
var out = normalizeHtml(section.content, options);
|
||||||
|
|
||||||
toConvert = toConvert.concat(out.images);
|
toConvert = toConvert.concat(out.images);
|
||||||
section.content = out.html;
|
section.content = out.html;
|
||||||
@@ -370,11 +374,11 @@ function normalizePage(sections, options) {
|
|||||||
|
|
||||||
return Q()
|
return Q()
|
||||||
.then(function() {
|
.then(function() {
|
||||||
toConvert = _.uniq(toConvert, 'source');
|
toConvert = _.uniq(toConvert, "source");
|
||||||
return convertImages(toConvert, options);
|
return convertImages(toConvert, options);
|
||||||
})
|
})
|
||||||
.thenResolve(sections);
|
.thenResolve(sections);
|
||||||
};
|
}
|
||||||
|
|
||||||
// Extract text from sections
|
// Extract text from sections
|
||||||
function extractText(sections) {
|
function extractText(sections) {
|
||||||
@@ -388,7 +392,7 @@ function extractText(sections) {
|
|||||||
|
|
||||||
return prev;
|
return prev;
|
||||||
}, "");
|
}, "");
|
||||||
};
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
normalize: normalizePage,
|
normalize: normalizePage,
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
var _ = require("lodash");
|
||||||
|
var path = require("path");
|
||||||
|
|
||||||
|
// Return true if file path is inside a folder
|
||||||
|
function isInRoot(root, filename) {
|
||||||
|
filename = path.normalize(filename);
|
||||||
|
return (filename.substr(0, root.length) === root);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve paths in a specific folder
|
||||||
|
// Throw error if file is outside this folder
|
||||||
|
function resolveInRoot(root) {
|
||||||
|
var input, result, err;
|
||||||
|
|
||||||
|
input = _.chain(arguments)
|
||||||
|
.toArray()
|
||||||
|
.slice(1)
|
||||||
|
.reduce(function(current, p) {
|
||||||
|
// Handle path relative to book root ("/README.md")
|
||||||
|
if (p[0] == "/" || p[0] == "\\") return p.slice(1);
|
||||||
|
|
||||||
|
return current? path.join(current, p) : path.normalize(p);
|
||||||
|
}, "")
|
||||||
|
.value();
|
||||||
|
|
||||||
|
result = path.resolve(root, input);
|
||||||
|
|
||||||
|
if (!isInRoot(root, result)) {
|
||||||
|
err = new Error("EACCESS: \"" + result + "\" not in \"" + root + "\"");
|
||||||
|
err.code = "EACCESS";
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
isInRoot: isInRoot,
|
||||||
|
resolveInRoot: resolveInRoot
|
||||||
|
};
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
var _ = require("lodash");
|
var _ = require("lodash");
|
||||||
|
|
||||||
// Returns from a navigation and a current file, a snapshot of current detailed state
|
// Returns from a navigation and a current file, a snapshot of current detailed state
|
||||||
var calculProgress = function(navigation, current) {
|
function calculProgress(navigation, current) {
|
||||||
var n = _.size(navigation);
|
var n = _.size(navigation);
|
||||||
var percent = 0, prevPercent = 0, currentChapter = null;
|
var percent = 0, prevPercent = 0, currentChapter = null;
|
||||||
var done = true;
|
var done = true;
|
||||||
|
|||||||
+15
-17
@@ -1,11 +1,9 @@
|
|||||||
var Q = require('q');
|
var Q = require("q");
|
||||||
var _ = require('lodash');
|
var events = require("events");
|
||||||
|
var http = require("http");
|
||||||
var events = require('events');
|
var send = require("send");
|
||||||
var http = require('http');
|
var util = require("util");
|
||||||
var send = require('send');
|
var url = require("url");
|
||||||
var util = require('util');
|
|
||||||
var url = require('url');
|
|
||||||
|
|
||||||
var Server = function() {
|
var Server = function() {
|
||||||
this.running = null;
|
this.running = null;
|
||||||
@@ -17,7 +15,7 @@ util.inherits(Server, events.EventEmitter);
|
|||||||
|
|
||||||
// Return true if the server is running
|
// Return true if the server is running
|
||||||
Server.prototype.isRunning = function() {
|
Server.prototype.isRunning = function() {
|
||||||
return this.running != null;
|
return !!this.running;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Stop the server
|
// Stop the server
|
||||||
@@ -57,25 +55,25 @@ Server.prototype.start = function(dir, port) {
|
|||||||
res.end(err.message);
|
res.end(err.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redirect to directory's index.html
|
// Redirect to directory"s index.html
|
||||||
function redirect() {
|
function redirect() {
|
||||||
res.statusCode = 301;
|
res.statusCode = 301;
|
||||||
res.setHeader('Location', req.url + '/');
|
res.setHeader("Location", req.url + "/");
|
||||||
res.end('Redirecting to ' + req.url + '/');
|
res.end("Redirecting to " + req.url + "/");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send file
|
// Send file
|
||||||
send(req, url.parse(req.url).pathname)
|
send(req, url.parse(req.url).pathname)
|
||||||
.root(dir)
|
.root(dir)
|
||||||
.on('error', error)
|
.on("error", error)
|
||||||
.on('directory', redirect)
|
.on("directory", redirect)
|
||||||
.pipe(res);
|
.pipe(res);
|
||||||
});
|
});
|
||||||
|
|
||||||
that.running.on('connection', function (socket) {
|
that.running.on("connection", function (socket) {
|
||||||
that.sockets.push(socket);
|
that.sockets.push(socket);
|
||||||
socket.setTimeout(4000);
|
socket.setTimeout(4000);
|
||||||
socket.on('close', function () {
|
socket.on("close", function () {
|
||||||
that.sockets.splice(that.sockets.indexOf(socket), 1);
|
that.sockets.splice(that.sockets.indexOf(socket), 1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -91,6 +89,6 @@ Server.prototype.start = function(dir, port) {
|
|||||||
|
|
||||||
return d.promise;
|
return d.promise;
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
module.exports = Server;
|
module.exports = Server;
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
var _ = require("lodash");
|
var _ = require("lodash");
|
||||||
|
|
||||||
function escapeShellArg(arg) {
|
function escapeShellArg(arg) {
|
||||||
var ret = '';
|
var ret = "";
|
||||||
|
|
||||||
ret = arg.replace(/"/g, '\\"');
|
ret = arg.replace(/"/g, '\\"');
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ function escapeShellArg(arg) {
|
|||||||
function optionsToShellArgs(options) {
|
function optionsToShellArgs(options) {
|
||||||
return _.chain(options)
|
return _.chain(options)
|
||||||
.map(function(value, key) {
|
.map(function(value, key) {
|
||||||
if (value == null || value === false) return null;
|
if (value === null || value === undefined || value === false) return null;
|
||||||
if (value === true) return key;
|
if (value === true) return key;
|
||||||
return key+"="+escapeShellArg(value);
|
return key+"="+escapeShellArg(value);
|
||||||
})
|
})
|
||||||
|
|||||||
+6
-6
@@ -1,9 +1,9 @@
|
|||||||
var Q = require('q');
|
var Q = require("q");
|
||||||
var _ = require('lodash');
|
var _ = require("lodash");
|
||||||
var path = require('path');
|
var path = require("path");
|
||||||
var chokidar = require('chokidar');
|
var chokidar = require("chokidar");
|
||||||
|
|
||||||
var parsers = require('gitbook-parsers')
|
var parsers = require("gitbook-parsers");
|
||||||
|
|
||||||
function watch(dir) {
|
function watch(dir) {
|
||||||
var d = Q.defer();
|
var d = Q.defer();
|
||||||
@@ -19,7 +19,7 @@ function watch(dir) {
|
|||||||
|
|
||||||
var watcher = chokidar.watch(toWatch, {
|
var watcher = chokidar.watch(toWatch, {
|
||||||
cwd: dir,
|
cwd: dir,
|
||||||
ignored: '_book/**',
|
ignored: "_book/**",
|
||||||
ignoreInitial: true
|
ignoreInitial: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+8
-8
@@ -1,19 +1,20 @@
|
|||||||
{
|
{
|
||||||
"name": "gitbook",
|
"name": "gitbook",
|
||||||
"version": "2.3.1",
|
"version": "2.4.2",
|
||||||
"homepage": "https://www.gitbook.com",
|
"homepage": "https://www.gitbook.com",
|
||||||
"description": "Library and cmd utility to generate GitBooks",
|
"description": "Library and cmd utility to generate GitBooks",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"q": "1.0.1",
|
"q": "1.0.1",
|
||||||
"lunr": "0.5.7",
|
"lunr": "0.5.12",
|
||||||
"lodash": "3.5.0",
|
"lodash": "3.10.1",
|
||||||
"graceful-fs": "3.0.5",
|
"graceful-fs": "3.0.5",
|
||||||
"resolve": "0.6.3",
|
"resolve": "0.6.3",
|
||||||
"fs-extra": "0.16.5",
|
"fs-extra": "0.16.5",
|
||||||
"fstream-ignore": "1.0.2",
|
"fstream-ignore": "1.0.2",
|
||||||
"gitbook-parsers": "0.8.1",
|
"gitbook-parsers": "0.8.2",
|
||||||
"nunjucks": "mozilla/nunjucks#b4351ec0752b102ebd02c5e2cbc2898a6e0e4839",
|
"gitbook-plugin-highlight": "1.0.3",
|
||||||
|
"nunjucks": "mozilla/nunjucks#dc89bf91611a2101731c2c06afcf5c32160b4dc9",
|
||||||
"nunjucks-autoescape": "1.0.0",
|
"nunjucks-autoescape": "1.0.0",
|
||||||
"nunjucks-filter": "1.0.0",
|
"nunjucks-filter": "1.0.0",
|
||||||
"i18n": "0.5.0",
|
"i18n": "0.5.0",
|
||||||
@@ -32,12 +33,11 @@
|
|||||||
"npm": "2.4.1",
|
"npm": "2.4.1",
|
||||||
"dom-serializer": "0.1.0",
|
"dom-serializer": "0.1.0",
|
||||||
"spawn-cmd": "0.0.2",
|
"spawn-cmd": "0.0.2",
|
||||||
"highlight.js": "8.8.0",
|
|
||||||
"escape-string-regexp": "1.0.3"
|
"escape-string-regexp": "1.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"mocha": "2.2.1",
|
"mocha": "2.3.2",
|
||||||
"should": "5.2.0",
|
"should": "7.1.0",
|
||||||
"grunt": "~0.4.2",
|
"grunt": "~0.4.2",
|
||||||
"grunt-cli": "0.1.11",
|
"grunt-cli": "0.1.11",
|
||||||
"grunt-contrib-copy": "0.5.0",
|
"grunt-contrib-copy": "0.5.0",
|
||||||
|
|||||||
+29
-16
@@ -1,39 +1,52 @@
|
|||||||
var _ = require('lodash');
|
var _ = require("lodash");
|
||||||
var fs = require('fs');
|
var fs = require("fs");
|
||||||
var path = require('path');
|
var path = require("path");
|
||||||
var should = require('should');
|
var should = require("should");
|
||||||
var cheerio = require('cheerio');
|
var cheerio = require("cheerio");
|
||||||
|
|
||||||
should.Assertion.add('file', function(file, description) {
|
should.Assertion.add("file", function(file, description) {
|
||||||
this.params = { actual: this.obj.toString(), operator: 'have file ' + file, message: description };
|
this.params = { actual: this.obj.toString(), operator: "have file " + file, message: description };
|
||||||
|
|
||||||
this.obj.should.have.property('options').which.is.an.Object;
|
this.obj.should.have.property("options").which.is.an.Object();
|
||||||
this.obj.options.should.have.property('output').which.is.a.String;
|
this.obj.options.should.have.property("output").which.is.a.String();
|
||||||
this.assert(fs.existsSync(path.resolve(this.obj.options.output, file)));
|
this.assert(fs.existsSync(path.resolve(this.obj.options.output, file)));
|
||||||
});
|
});
|
||||||
|
|
||||||
should.Assertion.add('jsonfile', function(file, description) {
|
should.Assertion.add("jsonfile", function(file, description) {
|
||||||
this.params = { actual: this.obj.toString(), operator: 'have valid jsonfile ' + file, message: description };
|
this.params = { actual: this.obj.toString(), operator: "have valid jsonfile " + file, message: description };
|
||||||
|
|
||||||
this.obj.should.have.property('options').which.is.an.Object;
|
this.obj.should.have.property("options").which.is.an.Object();
|
||||||
this.obj.options.should.have.property('output').which.is.a.String;
|
this.obj.options.should.have.property("output").which.is.a.String();
|
||||||
this.assert(JSON.parse(fs.readFileSync(path.resolve(this.obj.options.output, file), { encoding: "utf-8" })));
|
this.assert(JSON.parse(fs.readFileSync(path.resolve(this.obj.options.output, file), { encoding: "utf-8" })));
|
||||||
});
|
});
|
||||||
|
|
||||||
should.Assertion.add('html', function(rules, description) {
|
should.Assertion.add("html", function(rules, description) {
|
||||||
this.params = { actual: "HTML string", operator: 'valid html', message: description };
|
this.params = { actual: "HTML string", operator: "valid html", message: description };
|
||||||
var $ = cheerio.load(this.obj);
|
var $ = cheerio.load(this.obj);
|
||||||
|
|
||||||
_.each(rules, function(validations, query) {
|
_.each(rules, function(validations, query) {
|
||||||
validations = _.defaults(validations || {}, {
|
validations = _.defaults(validations || {}, {
|
||||||
|
// Select a specific element in the list of matched elements
|
||||||
|
index: null,
|
||||||
|
|
||||||
|
// Check that there is the correct count of elements
|
||||||
count: 1,
|
count: 1,
|
||||||
|
|
||||||
|
// Check attribute values
|
||||||
attributes: {},
|
attributes: {},
|
||||||
|
|
||||||
|
// Trim inner text
|
||||||
trim: false,
|
trim: false,
|
||||||
|
|
||||||
|
// Check inner text
|
||||||
text: undefined
|
text: undefined
|
||||||
});
|
});
|
||||||
|
|
||||||
var $el = $(query);
|
var $el = $(query);
|
||||||
|
|
||||||
|
// Select correct element
|
||||||
|
if (_.isNumber(validations.index)) $el = $($el.get(validations.index));
|
||||||
|
|
||||||
// Test number of elements
|
// Test number of elements
|
||||||
$el.length.should.be.equal(validations.count);
|
$el.length.should.be.equal(validations.count);
|
||||||
|
|
||||||
@@ -47,7 +60,7 @@ should.Assertion.add('html', function(rules, description) {
|
|||||||
// Test attributes
|
// Test attributes
|
||||||
_.each(validations.attributes, function(value, name) {
|
_.each(validations.attributes, function(value, name) {
|
||||||
var attr = $el.attr(name);
|
var attr = $el.attr(name);
|
||||||
should(attr).be.ok;
|
should(attr).be.ok();
|
||||||
attr.should.be.equal(value);
|
attr.should.be.equal(value);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
### Relative
|
### Relative
|
||||||
|
|
||||||
<p id="t1">{% include "./hello.md" %}</p>
|
<p id="t1">{% include "./hello.md" %}</p>
|
||||||
|
<p id="t2">{% include "/hello.md" %}</p>
|
||||||
|
|
||||||
### Git
|
### Git
|
||||||
|
|
||||||
<p id="t2">{% include "git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test.md" %}</p>
|
<p id="t3">{% include "git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test.md" %}</p>
|
||||||
<p id="t3">{% include "git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test2.md" %}</p>
|
<p id="t4">{% include "git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test2.md" %}</p>
|
||||||
|
<p id="t5">{% include "git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test3.md" %}</p>
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
# Readme
|
||||||
|
|
||||||
|
Block without language
|
||||||
|
|
||||||
|
```
|
||||||
|
test 1
|
||||||
|
```
|
||||||
|
|
||||||
|
Block with a language
|
||||||
|
|
||||||
|
```lang
|
||||||
|
test 2
|
||||||
|
```
|
||||||
|
|
||||||
|
Inline code: `test 3`
|
||||||
|
Inline code with html: `<test>`
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
# Summary
|
||||||
@@ -4,3 +4,6 @@
|
|||||||
* [Hello 2](hello2.md)
|
* [Hello 2](hello2.md)
|
||||||
* Hello 3
|
* Hello 3
|
||||||
* [Hello 4](hello3/hello4.md)
|
* [Hello 4](hello3/hello4.md)
|
||||||
|
* Hello 5
|
||||||
|
* [Hello 6](hello3/hello5/hello6.md)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
var path = require("path");
|
||||||
|
var fs = require("fs");
|
||||||
|
|
||||||
|
var Plugin = require("../lib/plugin");
|
||||||
|
var PLUGINS_ROOT = path.resolve(__dirname, "plugins");
|
||||||
|
|
||||||
|
describe("Code Highlighting", function () {
|
||||||
|
var book, PAGE;
|
||||||
|
|
||||||
|
before(function() {
|
||||||
|
return books.generate("highlight", "website", {
|
||||||
|
prepare: function(_book) {
|
||||||
|
book = _book;
|
||||||
|
|
||||||
|
var plugin = new Plugin(book, "replace_highlight");
|
||||||
|
plugin.load("./replace_highlight", PLUGINS_ROOT);
|
||||||
|
|
||||||
|
book.plugins.load(plugin);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(function() {
|
||||||
|
PAGE = fs.readFileSync(
|
||||||
|
path.join(book.options.output, "index.html"),
|
||||||
|
{ encoding: "utf-8" }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should correctly replace highlighting", function() {
|
||||||
|
PAGE.should.be.html({
|
||||||
|
"code": {
|
||||||
|
index: 0,
|
||||||
|
text: "code_test 1\n_code"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should correctly replace highlighting with language", function() {
|
||||||
|
PAGE.should.be.html({
|
||||||
|
"code": {
|
||||||
|
index: 1,
|
||||||
|
text: "lang_test 2\n_lang"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should correctly replace highlighting for inline code", function() {
|
||||||
|
PAGE.should.be.html({
|
||||||
|
"code": {
|
||||||
|
index: 2,
|
||||||
|
text: "code_test 3_code"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should correctly replace highlighting for inline code with html tags", function() {
|
||||||
|
PAGE.should.be.html({
|
||||||
|
"code": {
|
||||||
|
index: 3,
|
||||||
|
text: "code_<test>_code"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
+13
-8
@@ -1,32 +1,37 @@
|
|||||||
var fs = require('fs');
|
describe("Configuration", function () {
|
||||||
var path = require('path');
|
it("should extract default title from README", function() {
|
||||||
|
|
||||||
describe('Configuration', function () {
|
|
||||||
it('should extract default title from README', function() {
|
|
||||||
return books.parse("basic")
|
return books.parse("basic")
|
||||||
.then(function(book) {
|
.then(function(book) {
|
||||||
book.options.title.should.be.equal("Readme");
|
book.options.title.should.be.equal("Readme");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should extract default description from README', function() {
|
it("should extract default description from README", function() {
|
||||||
return books.parse("basic")
|
return books.parse("basic")
|
||||||
.then(function(book) {
|
.then(function(book) {
|
||||||
book.options.description.should.be.equal("Default description for the book.");
|
book.options.description.should.be.equal("Default description for the book.");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly load from json (book.json)', function() {
|
it("should correctly load from json (book.json)", function() {
|
||||||
return books.parse("config-json")
|
return books.parse("config-json")
|
||||||
.then(function(book) {
|
.then(function(book) {
|
||||||
book.options.title.should.be.equal("json-config");
|
book.options.title.should.be.equal("json-config");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly load from JavaScript (book.js)', function() {
|
it("should correctly load from JavaScript (book.js)", function() {
|
||||||
return books.parse("config-js")
|
return books.parse("config-js")
|
||||||
.then(function(book) {
|
.then(function(book) {
|
||||||
book.options.title.should.be.equal("js-config");
|
book.options.title.should.be.equal("js-config");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should provide configuration on book.config.get", function() {
|
||||||
|
return books.parse("basic")
|
||||||
|
.then(function(book) {
|
||||||
|
book.config.get("description").should.be.equal("Default description for the book.");
|
||||||
|
book.getConfig("description").should.be.equal("Default description for the book.");
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+32
-7
@@ -1,7 +1,7 @@
|
|||||||
var fs = require('fs');
|
var fs = require("fs");
|
||||||
var path = require('path');
|
var path = require("path");
|
||||||
|
|
||||||
describe('ConRefs', function () {
|
describe("ConRefs", function () {
|
||||||
var book, readme;
|
var book, readme;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -16,7 +16,7 @@ describe('ConRefs', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle local references', function() {
|
it("should handle local references", function() {
|
||||||
readme.should.be.html({
|
readme.should.be.html({
|
||||||
".page-inner p#t1": {
|
".page-inner p#t1": {
|
||||||
count: 1,
|
count: 1,
|
||||||
@@ -26,14 +26,39 @@ describe('ConRefs', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle git references', function() {
|
it("should handle local references with absolute paths", function() {
|
||||||
readme.should.be.html({
|
readme.should.be.html({
|
||||||
".page-inner p#t2": {
|
".page-inner p#t2": {
|
||||||
|
count: 1,
|
||||||
|
text: "Hello World",
|
||||||
|
trim: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should correctly include file from git reference", function() {
|
||||||
|
readme.should.be.html({
|
||||||
|
".page-inner p#t3": {
|
||||||
count: 1,
|
count: 1,
|
||||||
text: "Hello from git",
|
text: "Hello from git",
|
||||||
trim: true
|
trim: true
|
||||||
},
|
}
|
||||||
".page-inner p#t3": {
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should correctly handle deep include in git reference", function() {
|
||||||
|
readme.should.be.html({
|
||||||
|
".page-inner p#t4": {
|
||||||
|
count: 1,
|
||||||
|
text: "First Hello. Hello from git",
|
||||||
|
trim: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should correctly handle absolute include in git reference", function() {
|
||||||
|
readme.should.be.html({
|
||||||
|
".page-inner p#t5": {
|
||||||
count: 1,
|
count: 1,
|
||||||
text: "First Hello. Hello from git",
|
text: "First Hello. Hello from git",
|
||||||
trim: true
|
trim: true
|
||||||
|
|||||||
+25
-14
@@ -1,8 +1,8 @@
|
|||||||
var fs = require('fs');
|
var fs = require("fs");
|
||||||
var path = require('path');
|
var path = require("path");
|
||||||
|
|
||||||
describe('eBook generator', function () {
|
describe("eBook generator", function () {
|
||||||
describe('Basic Book', function() {
|
describe("Basic Book", function() {
|
||||||
var book;
|
var book;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -12,17 +12,17 @@ describe('eBook generator', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly output a SUMMARY.html', function() {
|
it("should correctly output a SUMMARY.html", function() {
|
||||||
book.should.have.file("SUMMARY.html");
|
book.should.have.file("SUMMARY.html");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly copy assets', function() {
|
it("should correctly copy assets", function() {
|
||||||
book.should.have.file("gitbook");
|
book.should.have.file("gitbook");
|
||||||
book.should.have.file("gitbook/style.css");
|
book.should.have.file("gitbook/style.css");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Custom styles', function() {
|
describe("Custom styles", function() {
|
||||||
var book;
|
var book;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -32,24 +32,35 @@ describe('eBook generator', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should remove default print.css', function() {
|
it("should remove default print.css", function() {
|
||||||
var PAGE = fs.readFileSync(
|
var PAGE = fs.readFileSync(
|
||||||
path.join(book.options.output, "index.html"),
|
path.join(book.options.output, "index.html"),
|
||||||
{ encoding: "utf-8" }
|
{ encoding: "utf-8" }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// There are 2 styles (one from plugin-highlight and the new style)
|
||||||
PAGE.should.be.html({
|
PAGE.should.be.html({
|
||||||
"link": {
|
"link": {
|
||||||
count: 1,
|
count: 2
|
||||||
attributes: {
|
}
|
||||||
href: "./styles/print.css"
|
});
|
||||||
}
|
|
||||||
|
PAGE.should.be.html({
|
||||||
|
"link[href=\"./styles/print.css\"]": {
|
||||||
|
count: 1
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
PAGE.should.be.html({
|
||||||
|
"link[href=\"gitbook/plugins/gitbook-plugin-highlight/ebook.css\"]": {
|
||||||
|
count: 1
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly print.css', function() {
|
it("should correctly print.css", function() {
|
||||||
book.should.have.file("styles");
|
book.should.have.file("styles");
|
||||||
book.should.have.file("styles/print.css");
|
book.should.have.file("styles/print.css");
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+6
-6
@@ -1,8 +1,8 @@
|
|||||||
var should = require('should');
|
var should = require("should");
|
||||||
var git = require('../lib/utils/git');
|
var git = require("../lib/utils/git");
|
||||||
|
|
||||||
describe('GIT parser and getter', function () {
|
describe("GIT parser and getter", function () {
|
||||||
it('should correctly parse an https url', function() {
|
it("should correctly parse an https url", function() {
|
||||||
var parts = git.parseUrl("git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test.md");
|
var parts = git.parseUrl("git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test.md");
|
||||||
|
|
||||||
should.exist(parts);
|
should.exist(parts);
|
||||||
@@ -11,7 +11,7 @@ describe('GIT parser and getter', function () {
|
|||||||
parts.filepath.should.be.equal("test.md");
|
parts.filepath.should.be.equal("test.md");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly parse an https url with a reference', function() {
|
it("should correctly parse an https url with a reference", function() {
|
||||||
var parts = git.parseUrl("git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test.md#0.1.2");
|
var parts = git.parseUrl("git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test.md#0.1.2");
|
||||||
|
|
||||||
should.exist(parts);
|
should.exist(parts);
|
||||||
@@ -20,7 +20,7 @@ describe('GIT parser and getter', function () {
|
|||||||
parts.filepath.should.be.equal("test.md");
|
parts.filepath.should.be.equal("test.md");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly parse an ssh url', function() {
|
it("should correctly parse an ssh url", function() {
|
||||||
var parts = git.parseUrl("git+git@github.com:GitbookIO/gitbook.git/directory/README.md#e1594cde2c32e4ff48f6c4eff3d3d461743d74e1");
|
var parts = git.parseUrl("git+git@github.com:GitbookIO/gitbook.git/directory/README.md#e1594cde2c32e4ff48f6c4eff3d3d461743d74e1");
|
||||||
|
|
||||||
should.exist(parts);
|
should.exist(parts);
|
||||||
|
|||||||
+15
-15
@@ -1,8 +1,8 @@
|
|||||||
var fs = require('fs');
|
var fs = require("fs");
|
||||||
var path = require('path');
|
var path = require("path");
|
||||||
|
|
||||||
describe('Glossary', function () {
|
describe("Glossary", function () {
|
||||||
describe('Parsing', function() {
|
describe("Parsing", function() {
|
||||||
var book;
|
var book;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -12,13 +12,13 @@ describe('Glossary', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly list items', function() {
|
it("should correctly list items", function() {
|
||||||
book.should.have.property("glossary");
|
book.should.have.property("glossary");
|
||||||
book.glossary.should.have.lengthOf(3);
|
book.glossary.should.have.lengthOf(3);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Generation', function() {
|
describe("Generation", function() {
|
||||||
var book;
|
var book;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -28,11 +28,11 @@ describe('Glossary', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly generate a GLOSSARY.html', function() {
|
it("should correctly generate a GLOSSARY.html", function() {
|
||||||
book.should.have.file("GLOSSARY.html");
|
book.should.have.file("GLOSSARY.html");
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Page Integration', function() {
|
describe("Page Integration", function() {
|
||||||
var readme, page;
|
var readme, page;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -46,9 +46,9 @@ describe('Glossary', function () {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly replaced terms by links', function() {
|
it("should correctly replaced terms by links", function() {
|
||||||
readme.should.be.html({
|
readme.should.be.html({
|
||||||
".page-inner a[href='GLOSSARY.html#test']": {
|
".page-inner a[href=\"GLOSSARY.html#test\"]": {
|
||||||
count: 1,
|
count: 1,
|
||||||
text: "test",
|
text: "test",
|
||||||
attributes: {
|
attributes: {
|
||||||
@@ -58,15 +58,15 @@ describe('Glossary', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly replaced terms by links (relative)', function() {
|
it("should correctly replaced terms by links (relative)", function() {
|
||||||
page.should.be.html({
|
page.should.be.html({
|
||||||
".page-inner a[href='../GLOSSARY.html#test']": {
|
".page-inner a[href=\"../GLOSSARY.html#test\"]": {
|
||||||
count: 1
|
count: 1
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not replace terms in codeblocks', function() {
|
it("should not replace terms in codeblocks", function() {
|
||||||
readme.should.be.html({
|
readme.should.be.html({
|
||||||
".page-inner code a": {
|
".page-inner code a": {
|
||||||
count: 0
|
count: 0
|
||||||
@@ -74,9 +74,9 @@ describe('Glossary', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly select the longest term', function() {
|
it("should correctly select the longest term", function() {
|
||||||
readme.should.be.html({
|
readme.should.be.html({
|
||||||
".page-inner a[href='GLOSSARY.html#test_long']": {
|
".page-inner a[href=\"GLOSSARY.html#test_long\"]": {
|
||||||
count: 1,
|
count: 1,
|
||||||
text: "test long"
|
text: "test long"
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-15
@@ -1,13 +1,11 @@
|
|||||||
var os = require('os');
|
var os = require("os");
|
||||||
var path = require('path');
|
var path = require("path");
|
||||||
var Q = require('q');
|
var Q = require("q");
|
||||||
var fs = require('fs');
|
var _ = require("lodash");
|
||||||
var _ = require('lodash');
|
|
||||||
var should = require('should');
|
|
||||||
|
|
||||||
var fsUtil = require('../lib/utils/fs');
|
var fsUtil = require("../lib/utils/fs");
|
||||||
var Book = require('../').Book;
|
var Book = require("../").Book;
|
||||||
var LOG_LEVELS = require('../').LOG_LEVELS;
|
var LOG_LEVELS = require("../").LOG_LEVELS;
|
||||||
|
|
||||||
require("./assertions");
|
require("./assertions");
|
||||||
|
|
||||||
@@ -17,10 +15,18 @@ var TMPDIR = os.tmpdir();
|
|||||||
|
|
||||||
|
|
||||||
// Generate and return a book
|
// Generate and return a book
|
||||||
function generateBook(bookId, test) {
|
function generateBook(bookId, test, opts) {
|
||||||
|
opts = _.defaults(opts || {}, {
|
||||||
|
prepare: function() {}
|
||||||
|
});
|
||||||
|
|
||||||
return parseBook(bookId, test)
|
return parseBook(bookId, test)
|
||||||
.then(function(book) {
|
.then(function(book) {
|
||||||
return book.generate(test)
|
|
||||||
|
return Q(opts.prepare(book))
|
||||||
|
.then(function() {
|
||||||
|
return book.generate(test);
|
||||||
|
})
|
||||||
.thenResolve(book);
|
.thenResolve(book);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -53,16 +59,14 @@ global.books = {
|
|||||||
// Cleanup all tests
|
// Cleanup all tests
|
||||||
after(function() {
|
after(function() {
|
||||||
return _.chain(BOOKS)
|
return _.chain(BOOKS)
|
||||||
.map(function(types, bookId) {
|
.map(function(types) {
|
||||||
return _.values(types);
|
return _.values(types);
|
||||||
})
|
})
|
||||||
.flatten()
|
.flatten()
|
||||||
.reduce(function(prev, book) {
|
.reduce(function(prev, book) {
|
||||||
return prev.then(function() {
|
return prev.then(function() {
|
||||||
return fsUtil.remove(book.options.output);
|
return fsUtil.remove(book.options.output);
|
||||||
})
|
});
|
||||||
}, Q())
|
}, Q())
|
||||||
.value();
|
.value();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+14
-12
@@ -1,9 +1,9 @@
|
|||||||
var fs = require('fs');
|
var fs = require("fs");
|
||||||
var _ = require('lodash');
|
var _ = require("lodash");
|
||||||
var path = require('path');
|
var path = require("path");
|
||||||
var cheerio = require('cheerio');
|
var cheerio = require("cheerio");
|
||||||
|
|
||||||
describe('Images', function () {
|
describe("Images", function () {
|
||||||
var book, readme, $, $img, srcs;
|
var book, readme, $, $img, srcs;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -17,38 +17,40 @@ describe('Images', function () {
|
|||||||
);
|
);
|
||||||
$ = cheerio.load(readme);
|
$ = cheerio.load(readme);
|
||||||
$img = $("img");
|
$img = $("img");
|
||||||
srcs = $img.map(function() { return $(this).attr("src"); })
|
srcs = $img.map(function() {
|
||||||
|
return $(this).attr("src");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should detect all images', function() {
|
it("should detect all images", function() {
|
||||||
_.uniq(srcs).should.have.lengthOf(4);
|
_.uniq(srcs).should.have.lengthOf(4);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should keep image tags', function() {
|
it("should keep image tags", function() {
|
||||||
srcs.should.have.lengthOf(5);
|
srcs.should.have.lengthOf(5);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not have .svg files', function() {
|
it("should not have .svg files", function() {
|
||||||
_.each(srcs, function(src) {
|
_.each(srcs, function(src) {
|
||||||
path.extname(src).should.not.equal(".svg");
|
path.extname(src).should.not.equal(".svg");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly convert svg images to png', function() {
|
it("should correctly convert svg images to png", function() {
|
||||||
_.each(srcs, function(src) {
|
_.each(srcs, function(src) {
|
||||||
book.should.have.file(src);
|
book.should.have.file(src);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle relative paths', function() {
|
it("should handle relative paths", function() {
|
||||||
var PAGE = fs.readFileSync(
|
var PAGE = fs.readFileSync(
|
||||||
path.join(book.options.output, "folder/PAGE.html"),
|
path.join(book.options.output, "folder/PAGE.html"),
|
||||||
{ encoding: "utf-8" }
|
{ encoding: "utf-8" }
|
||||||
);
|
);
|
||||||
|
|
||||||
PAGE.should.be.html({
|
PAGE.should.be.html({
|
||||||
"img[src='../test.png']": {
|
"img[src=\"../test.png\"]": {
|
||||||
count: 1
|
count: 1
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
+11
-10
@@ -1,11 +1,11 @@
|
|||||||
var fs = require('fs');
|
var fs = require("fs");
|
||||||
var path = require('path');
|
var path = require("path");
|
||||||
var should = require('should');
|
var should = require("should");
|
||||||
|
|
||||||
var Book = require('../').Book;
|
var Book = require("../").Book;
|
||||||
var LOG_LEVELS = require('../').LOG_LEVELS;
|
var LOG_LEVELS = require("../").LOG_LEVELS;
|
||||||
|
|
||||||
describe('Init Books', function () {
|
describe("Init Books", function () {
|
||||||
var initRoot;
|
var initRoot;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -15,9 +15,10 @@ describe('Init Books', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create all chapters', function() {
|
it("should create all chapters", function() {
|
||||||
should(fs.existsSync(path.resolve(initRoot, "hello.md"))).be.ok;
|
should(fs.existsSync(path.resolve(initRoot, "hello.md"))).be.ok();
|
||||||
should(fs.existsSync(path.resolve(initRoot, "hello2.md"))).be.ok;
|
should(fs.existsSync(path.resolve(initRoot, "hello2.md"))).be.ok();
|
||||||
should(fs.existsSync(path.resolve(initRoot, "hello3/hello4.md"))).be.ok;
|
should(fs.existsSync(path.resolve(initRoot, "hello3/hello4.md"))).be.ok();
|
||||||
|
should(fs.existsSync(path.resolve(initRoot, "hello3/hello5/hello6.md"))).be.ok();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+17
-17
@@ -1,8 +1,8 @@
|
|||||||
var fs = require('fs');
|
var fs = require("fs");
|
||||||
var path = require('path');
|
var path = require("path");
|
||||||
|
|
||||||
describe('JSON generator', function () {
|
describe("JSON generator", function () {
|
||||||
describe('Basic Book', function() {
|
describe("Basic Book", function() {
|
||||||
var book;
|
var book;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -12,15 +12,15 @@ describe('JSON generator', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly output a README.json', function() {
|
it("should correctly output a README.json", function() {
|
||||||
book.should.have.file("README.json");
|
book.should.have.file("README.json");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should output a valid json', function() {
|
it("should output a valid json", function() {
|
||||||
book.should.have.jsonfile("README.json");
|
book.should.have.jsonfile("README.json");
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Page Format', function() {
|
describe("Page Format", function() {
|
||||||
var page;
|
var page;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -32,25 +32,25 @@ describe('JSON generator', function () {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should contains valid section', function() {
|
it("should contains valid section", function() {
|
||||||
page.should.have.property("sections").with.lengthOf(1);
|
page.should.have.property("sections").with.lengthOf(1);
|
||||||
page.sections[0].should.have.property("content").which.is.a.String;
|
page.sections[0].should.have.property("content").which.is.a.String();
|
||||||
page.sections[0].should.have.property("type").which.is.a.String.which.equal("normal");
|
page.sections[0].should.have.property("type", "normal");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should contains valid progress', function() {
|
it("should contains valid progress", function() {
|
||||||
page.should.have.property("progress");
|
page.should.have.property("progress");
|
||||||
page.progress.should.have.property("chapters").with.lengthOf(1);
|
page.progress.should.have.property("chapters").with.lengthOf(1);
|
||||||
page.progress.should.have.property("current");
|
page.progress.should.have.property("current");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should contains no languages', function() {
|
it("should contains no languages", function() {
|
||||||
page.should.have.property("langs").with.lengthOf(0);
|
page.should.have.property("langs").with.lengthOf(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Multilingual Book', function() {
|
describe("Multilingual Book", function() {
|
||||||
var book;
|
var book;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -60,19 +60,19 @@ describe('JSON generator', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly output READMEs', function() {
|
it("should correctly output READMEs", function() {
|
||||||
book.should.have.file("README.json");
|
book.should.have.file("README.json");
|
||||||
book.should.have.file("en/README.json");
|
book.should.have.file("en/README.json");
|
||||||
book.should.have.file("fr/README.json");
|
book.should.have.file("fr/README.json");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should output valid json', function() {
|
it("should output valid json", function() {
|
||||||
book.should.have.jsonfile("README.json");
|
book.should.have.jsonfile("README.json");
|
||||||
book.should.have.jsonfile("en/README.json");
|
book.should.have.jsonfile("en/README.json");
|
||||||
book.should.have.jsonfile("fr/README.json");
|
book.should.have.jsonfile("fr/README.json");
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Page Format', function() {
|
describe("Page Format", function() {
|
||||||
var page;
|
var page;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -84,7 +84,7 @@ describe('JSON generator', function () {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should contains no languages', function() {
|
it("should contains no languages", function() {
|
||||||
page.should.have.property("langs").with.lengthOf(2);
|
page.should.have.property("langs").with.lengthOf(2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+5
-8
@@ -1,8 +1,5 @@
|
|||||||
var fs = require('fs');
|
describe("Languages", function () {
|
||||||
var path = require('path');
|
describe("Parsing", function() {
|
||||||
|
|
||||||
describe('Languages', function () {
|
|
||||||
describe('Parsing', function() {
|
|
||||||
var book;
|
var book;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -12,7 +9,7 @@ describe('Languages', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly list languages', function() {
|
it("should correctly list languages", function() {
|
||||||
book.should.have.property("books");
|
book.should.have.property("books");
|
||||||
book.books.should.have.lengthOf(2);
|
book.books.should.have.lengthOf(2);
|
||||||
|
|
||||||
@@ -21,7 +18,7 @@ describe('Languages', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Generation', function() {
|
describe("Generation", function() {
|
||||||
var book;
|
var book;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -31,7 +28,7 @@ describe('Languages', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly create books', function() {
|
it("should correctly create books", function() {
|
||||||
book.should.have.file("index.html");
|
book.should.have.file("index.html");
|
||||||
book.should.have.file("en/index.html");
|
book.should.have.file("en/index.html");
|
||||||
book.should.have.file("fr/index.html");
|
book.should.have.file("fr/index.html");
|
||||||
|
|||||||
+14
-16
@@ -1,13 +1,11 @@
|
|||||||
var should = require('should');
|
var fs = require("fs");
|
||||||
var fs = require('fs');
|
var path = require("path");
|
||||||
var _ = require('lodash');
|
var cheerio = require("cheerio");
|
||||||
var path = require('path');
|
|
||||||
var cheerio = require('cheerio');
|
|
||||||
|
|
||||||
var links = require("../lib/utils/links");
|
var links = require("../lib/utils/links");
|
||||||
|
|
||||||
describe('Links', function () {
|
describe("Links", function () {
|
||||||
it('should correctly test external links', function() {
|
it("should correctly test external links", function() {
|
||||||
links.isExternal("http://google.fr").should.be.exactly(true);
|
links.isExternal("http://google.fr").should.be.exactly(true);
|
||||||
links.isExternal("https://google.fr").should.be.exactly(true);
|
links.isExternal("https://google.fr").should.be.exactly(true);
|
||||||
links.isExternal("test.md").should.be.exactly(false);
|
links.isExternal("test.md").should.be.exactly(false);
|
||||||
@@ -15,32 +13,32 @@ describe('Links', function () {
|
|||||||
links.isExternal("/folder/test.md").should.be.exactly(false);
|
links.isExternal("/folder/test.md").should.be.exactly(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly detect anchor links', function() {
|
it("should correctly detect anchor links", function() {
|
||||||
links.isAnchor("#test").should.be.exactly(true);
|
links.isAnchor("#test").should.be.exactly(true);
|
||||||
links.isAnchor(" #test").should.be.exactly(true);
|
links.isAnchor(" #test").should.be.exactly(true);
|
||||||
links.isAnchor("https://google.fr#test").should.be.exactly(false);
|
links.isAnchor("https://google.fr#test").should.be.exactly(false);
|
||||||
links.isAnchor("test.md#test").should.be.exactly(false);
|
links.isAnchor("test.md#test").should.be.exactly(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('toAbsolute', function() {
|
describe("toAbsolute", function() {
|
||||||
it('should correctly transform as absolute', function() {
|
it("should correctly transform as absolute", function() {
|
||||||
links.toAbsolute("http://google.fr").should.be.equal("http://google.fr");
|
links.toAbsolute("http://google.fr").should.be.equal("http://google.fr");
|
||||||
links.toAbsolute("test.md", "./", "./").should.be.equal("test.md");
|
links.toAbsolute("test.md", "./", "./").should.be.equal("test.md");
|
||||||
links.toAbsolute("folder/test.md", "./", "./").should.be.equal("folder/test.md");
|
links.toAbsolute("folder/test.md", "./", "./").should.be.equal("folder/test.md");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly handle windows path', function() {
|
it("should correctly handle windows path", function() {
|
||||||
links.toAbsolute("folder\\test.md", "./", "./").should.be.equal("folder/test.md");
|
links.toAbsolute("folder\\test.md", "./", "./").should.be.equal("folder/test.md");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly handle absolute path', function() {
|
it("should correctly handle absolute path", function() {
|
||||||
links.toAbsolute("/test.md", "./", "./").should.be.equal("test.md");
|
links.toAbsolute("/test.md", "./", "./").should.be.equal("test.md");
|
||||||
links.toAbsolute("/test.md", "test", "test").should.be.equal("../test.md");
|
links.toAbsolute("/test.md", "test", "test").should.be.equal("../test.md");
|
||||||
links.toAbsolute("/sub/test.md", "test", "test").should.be.equal("../sub/test.md");
|
links.toAbsolute("/sub/test.md", "test", "test").should.be.equal("../sub/test.md");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('page', function() {
|
describe("page", function() {
|
||||||
var book;
|
var book;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -50,7 +48,7 @@ describe('Links', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly replace relative links', function() {
|
it("should correctly replace relative links", function() {
|
||||||
var readme = fs.readFileSync(
|
var readme = fs.readFileSync(
|
||||||
path.join(book.options.output, "folder1/index.html"),
|
path.join(book.options.output, "folder1/index.html"),
|
||||||
{ encoding: "utf-8" }
|
{ encoding: "utf-8" }
|
||||||
@@ -58,8 +56,8 @@ describe('Links', function () {
|
|||||||
var $ = cheerio.load(readme);
|
var $ = cheerio.load(readme);
|
||||||
var $a = $(".page-inner a");
|
var $a = $(".page-inner a");
|
||||||
|
|
||||||
$a.attr('href').should.be.exactly("../folder2/index.html");
|
$a.attr("href").should.be.exactly("../folder2/index.html");
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
var should = require("should");
|
||||||
|
|
||||||
|
describe("Navigation", function () {
|
||||||
|
var book;
|
||||||
|
|
||||||
|
before(function() {
|
||||||
|
return books.parse("summary")
|
||||||
|
.then(function(_book) {
|
||||||
|
book = _book;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should correctly parse navigation as a map", function() {
|
||||||
|
book.should.have.property("navigation");
|
||||||
|
book.navigation.should.have.property("README.md");
|
||||||
|
book.navigation.should.have.property("README.md");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should correctly include filenames", function() {
|
||||||
|
book.navigation.should.have.property("README.md");
|
||||||
|
book.navigation.should.have.property("PAGE1.md");
|
||||||
|
book.navigation.should.have.property("folder/PAGE2.md");
|
||||||
|
book.navigation.should.not.have.property("NOTFOUND.md");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should correctly detect next/prev for README", function() {
|
||||||
|
var README = book.navigation["README.md"];
|
||||||
|
|
||||||
|
README.index.should.equal(0);
|
||||||
|
README.should.have.property("next");
|
||||||
|
should(README.prev).not.be.ok();
|
||||||
|
|
||||||
|
README.next.should.have.property("path");
|
||||||
|
README.next.path.should.equal("PAGE1.md");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should correctly detect next/prev a page", function() {
|
||||||
|
var PAGE = book.navigation["PAGE1.md"];
|
||||||
|
|
||||||
|
PAGE.index.should.equal(1);
|
||||||
|
PAGE.should.have.property("next");
|
||||||
|
PAGE.should.have.property("prev");
|
||||||
|
|
||||||
|
PAGE.prev.should.have.property("path");
|
||||||
|
PAGE.prev.path.should.equal("README.md");
|
||||||
|
|
||||||
|
PAGE.next.should.have.property("path");
|
||||||
|
PAGE.next.path.should.equal("folder/PAGE2.md");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should correctly detect next/prev for last page", function() {
|
||||||
|
var PAGE = book.navigation["folder/PAGE2.md"];
|
||||||
|
|
||||||
|
PAGE.index.should.equal(2);
|
||||||
|
PAGE.should.have.property("prev");
|
||||||
|
should(PAGE.next).not.be.ok();
|
||||||
|
|
||||||
|
PAGE.prev.should.have.property("path");
|
||||||
|
PAGE.prev.path.should.equal("PAGE1.md");
|
||||||
|
});
|
||||||
|
});
|
||||||
+107
-47
@@ -1,11 +1,12 @@
|
|||||||
var _ = require('lodash');
|
var _ = require("lodash");
|
||||||
var should = require('should');
|
var should = require("should");
|
||||||
var path = require('path');
|
var path = require("path");
|
||||||
|
|
||||||
var Plugin = require('../lib/plugin');
|
var Plugin = require("../lib/plugin");
|
||||||
var PLUGINS_ROOT = path.resolve(__dirname, 'plugins');
|
var parsers = require("gitbook-parsers");
|
||||||
|
var PLUGINS_ROOT = path.resolve(__dirname, "plugins");
|
||||||
|
|
||||||
describe('Plugins', function () {
|
describe("Plugins", function () {
|
||||||
var book;
|
var book;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -15,7 +16,7 @@ describe('Plugins', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Invalid', function() {
|
describe("Invalid", function() {
|
||||||
var plugin;
|
var plugin;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -23,12 +24,12 @@ describe('Plugins', function () {
|
|||||||
plugin.load("./invalid", PLUGINS_ROOT);
|
plugin.load("./invalid", PLUGINS_ROOT);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be detected', function() {
|
it("should be detected", function() {
|
||||||
should(plugin.isValid()).be.exactly(false);
|
should(plugin.isValid()).be.exactly(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Empty', function() {
|
describe("Empty", function() {
|
||||||
var plugin;
|
var plugin;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -36,11 +37,11 @@ describe('Plugins', function () {
|
|||||||
plugin.load("./empty", PLUGINS_ROOT);
|
plugin.load("./empty", PLUGINS_ROOT);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should valid a plugin', function() {
|
it("should valid a plugin", function() {
|
||||||
should(plugin.isValid()).be.exactly(true);
|
should(plugin.isValid()).be.exactly(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return an empty list of resources', function() {
|
it("should return an empty list of resources", function() {
|
||||||
return plugin.getResources()
|
return plugin.getResources()
|
||||||
.then(function(resources) {
|
.then(function(resources) {
|
||||||
_.each(Plugin.RESOURCES, function(resName) {
|
_.each(Plugin.RESOURCES, function(resName) {
|
||||||
@@ -50,7 +51,7 @@ describe('Plugins', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Resources', function() {
|
describe("Resources", function() {
|
||||||
var plugin;
|
var plugin;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -60,40 +61,45 @@ describe('Plugins', function () {
|
|||||||
return book.plugins.load(plugin);
|
return book.plugins.load(plugin);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should valid a plugin', function() {
|
it("should valid a plugin", function() {
|
||||||
should(plugin.isValid()).be.exactly(true);
|
should(plugin.isValid()).be.exactly(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Website', function() {
|
describe("Website", function() {
|
||||||
it('should return a valid list of resources', function() {
|
it("should return a valid list of resources", function() {
|
||||||
return plugin.getResources("website")
|
return plugin.getResources("website")
|
||||||
.then(function(resources) {
|
.then(function(resources) {
|
||||||
resources["js"].should.have.lengthOf(1);
|
resources.js.should.have.lengthOf(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should extend books plugins', function() {
|
it("should extend books plugins", function() {
|
||||||
var resources = book.plugins.resources("website");
|
var resources = book.plugins.resources("website");
|
||||||
resources["js"].should.have.lengthOf(1);
|
resources.js.should.have.lengthOf(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('eBook', function() {
|
describe("eBook", function() {
|
||||||
it('should return a valid list of resources', function() {
|
it("should return a valid list of resources", function() {
|
||||||
return plugin.getResources("ebook")
|
return plugin.getResources("ebook")
|
||||||
.then(function(resources) {
|
.then(function(resources) {
|
||||||
resources["css"].should.have.lengthOf(1);
|
resources.css.should.have.lengthOf(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should extend books plugins', function() {
|
it("should extend books plugins", function() {
|
||||||
var resources = book.plugins.resources("ebook");
|
var resources = book.plugins.resources("ebook");
|
||||||
resources["css"].should.have.lengthOf(1);
|
|
||||||
|
// There is resources from highlight plugin and this plugin
|
||||||
|
resources.css.should.have.lengthOf(2);
|
||||||
|
should.exist(_.find(resources.css, {
|
||||||
|
path: "./resources/test"
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Filters', function() {
|
describe("Filters", function() {
|
||||||
var plugin;
|
var plugin;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -103,11 +109,11 @@ describe('Plugins', function () {
|
|||||||
return book.plugins.load(plugin);
|
return book.plugins.load(plugin);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should valid a plugin', function() {
|
it("should valid a plugin", function() {
|
||||||
should(plugin.isValid()).be.exactly(true);
|
should(plugin.isValid()).be.exactly(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return a map of filters', function() {
|
it("should return a map of filters", function() {
|
||||||
var filters = plugin.getFilters();
|
var filters = plugin.getFilters();
|
||||||
|
|
||||||
_.size(filters).should.equal(2);
|
_.size(filters).should.equal(2);
|
||||||
@@ -115,22 +121,22 @@ describe('Plugins', function () {
|
|||||||
filters.should.have.property("helloCtx");
|
filters.should.have.property("helloCtx");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly extend template filters', function() {
|
it("should correctly extend template filters", function() {
|
||||||
return book.template.renderString('{{ "World"|hello }}')
|
return book.template.renderString("{{ \"World\"|hello }}")
|
||||||
.then(function(content) {
|
.then(function(content) {
|
||||||
content.should.equal("Hello World");
|
content.should.equal("Hello World");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly set book as context', function() {
|
it("should correctly set book as context", function() {
|
||||||
return book.template.renderString('{{ "root"|helloCtx }}')
|
return book.template.renderString("{{ \"root\"|helloCtx }}")
|
||||||
.then(function(content) {
|
.then(function(content) {
|
||||||
content.should.equal("root:"+book.root);
|
content.should.equal("root:"+book.root);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Blocks', function() {
|
describe("Blocks", function() {
|
||||||
var plugin;
|
var plugin;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -142,22 +148,22 @@ describe('Plugins', function () {
|
|||||||
|
|
||||||
var testTpl = function(str, args, options) {
|
var testTpl = function(str, args, options) {
|
||||||
return book.template.renderString(str, args, options)
|
return book.template.renderString(str, args, options)
|
||||||
.then(book.template.postProcess)
|
.then(book.template.postProcess);
|
||||||
};
|
};
|
||||||
|
|
||||||
it('should valid a plugin', function() {
|
it("should valid a plugin", function() {
|
||||||
should(plugin.isValid()).be.exactly(true);
|
should(plugin.isValid()).be.exactly(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly extend template blocks', function() {
|
it("should correctly extend template blocks", function() {
|
||||||
return testTpl('{% test %}hello{% endtest %}')
|
return testTpl("{% test %}hello{% endtest %}")
|
||||||
.then(function(content) {
|
.then(function(content) {
|
||||||
content.should.equal("testhellotest");
|
content.should.equal("testhellotest");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly accept shortcuts', function() {
|
it("should correctly accept shortcuts", function() {
|
||||||
return testTpl('$$hello$$', {}, {
|
return testTpl("$$hello$$", {}, {
|
||||||
type: "markdown"
|
type: "markdown"
|
||||||
})
|
})
|
||||||
.then(function(content) {
|
.then(function(content) {
|
||||||
@@ -165,40 +171,94 @@ describe('Plugins', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly extend template blocks with defined end', function() {
|
it("should correctly extend template blocks with defined end", function() {
|
||||||
return testTpl('{% test2 %}hello{% endtest2end %}')
|
return testTpl("{% test2 %}hello{% endtest2end %}")
|
||||||
.then(function(content) {
|
.then(function(content) {
|
||||||
content.should.equal("test2hellotest2");
|
content.should.equal("test2hellotest2");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly extend template blocks with sub-blocks', function() {
|
it("should correctly extend template blocks with sub-blocks", function() {
|
||||||
return testTpl('{% test3join separator=";" %}hello{% also %}world{% endtest3join %}')
|
return testTpl("{% test3join separator=\";\" %}hello{% also %}world{% endtest3join %}")
|
||||||
.then(function(content) {
|
.then(function(content) {
|
||||||
content.should.equal("hello;world");
|
content.should.equal("hello;world");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly extend template blocks with different sub-blocks', function() {
|
it("should correctly extend template blocks with different sub-blocks", function() {
|
||||||
return testTpl('{% test4join separator=";" %}hello{% also %}the{% finally %}world{% endtest4join %}')
|
return testTpl("{% test4join separator=\";\" %}hello{% also %}the{% finally %}world{% endtest4join %}")
|
||||||
.then(function(content) {
|
.then(function(content) {
|
||||||
content.should.equal("hello;the;world");
|
content.should.equal("hello;the;world");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly extend template blocks with arguments', function() {
|
it("should correctly extend template blocks with arguments (1)", function() {
|
||||||
return testTpl('{% test5args "a", "b", "c" %}{% endtest5args %}')
|
return testTpl("{% test5args \"a\" %}{% endtest5args %}")
|
||||||
|
.then(function(content) {
|
||||||
|
content.should.equal("test5atest5");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should correctly extend template blocks with arguments (2)", function() {
|
||||||
|
return testTpl("{% test5args 'a', 'b' %}{% endtest5args %}")
|
||||||
|
.then(function(content) {
|
||||||
|
content.should.equal("test5a,btest5");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should correctly extend template blocks with arguments (3)", function() {
|
||||||
|
return testTpl("{% test5args 'a', 'b', 'c' %}{% endtest5args %}")
|
||||||
.then(function(content) {
|
.then(function(content) {
|
||||||
content.should.equal("test5a,b,ctest5");
|
content.should.equal("test5a,b,ctest5");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly extend template blocks with args and kwargs', function() {
|
it("should correctly extend template blocks with args and kwargs", function() {
|
||||||
return testTpl('{% test5kwargs "a", "b", "c", d="test", e="test2" %}{% endtest5kwargs %}')
|
return testTpl("{% test5kwargs 'a', 'b', 'c', d='test', e='test2' %}{% endtest5kwargs %}")
|
||||||
.then(function(content) {
|
.then(function(content) {
|
||||||
content.should.equal("test5a,b,c,d:test,e:test2,__keywords:truetest5");
|
content.should.equal("test5a,b,c,d:test,e:test2,__keywords:truetest5");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should correctly extend template blocks with access to context", function() {
|
||||||
|
return testTpl("{% set name = 'john' %}{% test6context %}{% endtest6context %}", {})
|
||||||
|
.then(function(content) {
|
||||||
|
content.should.equal("test6johntest6");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Blocks without parsing", function() {
|
||||||
|
var plugin;
|
||||||
|
|
||||||
|
before(function() {
|
||||||
|
plugin = new Plugin(book, "blocks");
|
||||||
|
plugin.load("./blocks", PLUGINS_ROOT);
|
||||||
|
|
||||||
|
return book.plugins.load(plugin);
|
||||||
|
});
|
||||||
|
|
||||||
|
var testTpl = function(markup, str, args, options) {
|
||||||
|
var filetype = parsers.get(markup);
|
||||||
|
|
||||||
|
return book.template.renderString(str, args, options)
|
||||||
|
.then(filetype.page).get("sections").get(0).get("content")
|
||||||
|
.then(book.template.postProcess);
|
||||||
|
};
|
||||||
|
|
||||||
|
it("should correctly process unparsable for markdown", function() {
|
||||||
|
return testTpl(".md", "{% test %}**hello**{% endtest %}")
|
||||||
|
.then(function(content) {
|
||||||
|
content.should.equal("<p>test**hello**test</p>\n");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should correctly process unparsable for asciidoc", function() {
|
||||||
|
return testTpl(".adoc", "{% test %}**hello**{% endtest %}")
|
||||||
|
.then(function(content) {
|
||||||
|
content.should.equal("<div class=\"paragraph\">\n<p>test**hello**test</p>\n</div>");
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -39,18 +39,23 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
"test5args": {
|
"test5args": {
|
||||||
process: function(blk) {
|
process: function(blk) {
|
||||||
return "test5"+blk.args.join(',')+"test5";
|
return "test5"+blk.args.join(",")+"test5";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"test5kwargs": {
|
"test5kwargs": {
|
||||||
process: function(blk) {
|
process: function(blk) {
|
||||||
var s = blk.args.join(',');
|
var s = blk.args.join(",");
|
||||||
for (var key in blk.kwargs) {
|
for (var key in blk.kwargs) {
|
||||||
s = s + ','+key+':'+blk.kwargs[key];
|
s = s + ","+key+":"+blk.kwargs[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
return "test5"+s+"test5";
|
return "test5"+s+"test5";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"test6context": {
|
||||||
|
process: function() {
|
||||||
|
return "test6"+(this.ctx.name)+"test6";
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
module.exports = {
|
||||||
|
blocks: {
|
||||||
|
"code": {
|
||||||
|
process: function(blk) {
|
||||||
|
var lang = blk.kwargs.language || "code";
|
||||||
|
|
||||||
|
return {
|
||||||
|
body: lang+"_"+blk.body+"_"+lang,
|
||||||
|
html: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"name": "gitbook-plugin-replace_highlight",
|
||||||
|
"description": "Test replacing default code highlighter",
|
||||||
|
"main": "index.js",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"engines": {
|
||||||
|
"gitbook": "*"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
var path = require("path");
|
||||||
|
|
||||||
|
describe("Resolve Files", function () {
|
||||||
|
var book;
|
||||||
|
|
||||||
|
before(function() {
|
||||||
|
return books.parse("basic")
|
||||||
|
.then(function(_book) {
|
||||||
|
book = _book;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("book.fileIsInBook", function() {
|
||||||
|
it("should return true for correct paths", function() {
|
||||||
|
book.fileIsInBook(path.join(book.root, "README.md")).should.equal(true);
|
||||||
|
book.fileIsInBook(path.join(book.root, "styles/website.css")).should.equal(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return true for root folder", function() {
|
||||||
|
book.fileIsInBook(path.join(book.root, "./")).should.equal(true);
|
||||||
|
book.fileIsInBook(book.root).should.equal(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return false for files out of scope", function() {
|
||||||
|
book.fileIsInBook(path.join(book.root, "../")).should.equal(false);
|
||||||
|
book.fileIsInBook("README.md").should.equal(false);
|
||||||
|
book.fileIsInBook(path.resolve(book.root, "../README.md")).should.equal(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should correctly handle windows paths", function() {
|
||||||
|
book.fileIsInBook(path.join(book.root, "\\styles\\website.css")).should.equal(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("book.resolve", function() {
|
||||||
|
it("should resolve a file to its absolute path", function() {
|
||||||
|
book.resolve("README.md").should.equal(path.resolve(book.root, "README.md"));
|
||||||
|
book.resolve("website/README.md").should.equal(path.resolve(book.root, "website/README.md"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should correctly handle windows paths", function() {
|
||||||
|
book.resolve("styles\\website.css").should.equal(path.resolve(book.root, "styles\\website.css"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should correctly resolve all arguments", function() {
|
||||||
|
book.resolve("test", "hello", "..", "README.md").should.equal(path.resolve(book.root, "test/README.md"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should correctly resolve to root folder", function() {
|
||||||
|
book.resolve("test", "/README.md").should.equal(path.resolve(book.root, "README.md"));
|
||||||
|
book.resolve("test", "\\README.md").should.equal(path.resolve(book.root, "README.md"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should throw an error for file out of book", function() {
|
||||||
|
(function() {
|
||||||
|
return book.resolve("../README.md");
|
||||||
|
}).should.throw();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
+12
-12
@@ -1,8 +1,8 @@
|
|||||||
var fs = require('fs');
|
var fs = require("fs");
|
||||||
var path = require('path');
|
var path = require("path");
|
||||||
|
|
||||||
describe('Summary', function () {
|
describe("Summary", function () {
|
||||||
describe('Parsing', function() {
|
describe("Parsing", function() {
|
||||||
var book;
|
var book;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -12,13 +12,13 @@ describe('Summary', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly list items', function() {
|
it("should correctly list items", function() {
|
||||||
book.should.have.property("summary");
|
book.should.have.property("summary");
|
||||||
book.summary.should.have.property("chapters");
|
book.summary.should.have.property("chapters");
|
||||||
book.summary.chapters.should.have.lengthOf(4);
|
book.summary.chapters.should.have.lengthOf(4);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly mark non-existant entries', function() {
|
it("should correctly mark non-existant entries", function() {
|
||||||
book.summary.chapters[0].exists.should.have.equal(true);
|
book.summary.chapters[0].exists.should.have.equal(true);
|
||||||
book.summary.chapters[1].exists.should.have.equal(true);
|
book.summary.chapters[1].exists.should.have.equal(true);
|
||||||
book.summary.chapters[2].exists.should.have.equal(true);
|
book.summary.chapters[2].exists.should.have.equal(true);
|
||||||
@@ -26,7 +26,7 @@ describe('Summary', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Generation', function() {
|
describe("Generation", function() {
|
||||||
var book;
|
var book;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -36,30 +36,30 @@ describe('Summary', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create files according to summary', function() {
|
it("should create files according to summary", function() {
|
||||||
book.should.have.file("index.html");
|
book.should.have.file("index.html");
|
||||||
book.should.have.file("PAGE1.html");
|
book.should.have.file("PAGE1.html");
|
||||||
book.should.have.file("folder/PAGE2.html");
|
book.should.have.file("folder/PAGE2.html");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly output summary', function() {
|
it("should correctly output summary", function() {
|
||||||
var PAGE = fs.readFileSync(
|
var PAGE = fs.readFileSync(
|
||||||
path.join(book.options.output, "index.html"),
|
path.join(book.options.output, "index.html"),
|
||||||
{ encoding: "utf-8" }
|
{ encoding: "utf-8" }
|
||||||
);
|
);
|
||||||
|
|
||||||
PAGE.should.be.html({
|
PAGE.should.be.html({
|
||||||
".book-summary .chapter[data-level='0'] a": {
|
".book-summary .chapter[data-level=\"0\"] a": {
|
||||||
attributes: {
|
attributes: {
|
||||||
href: "./index.html"
|
href: "./index.html"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
".book-summary .chapter[data-level='1'] a": {
|
".book-summary .chapter[data-level=\"1\"] a": {
|
||||||
attributes: {
|
attributes: {
|
||||||
href: "./PAGE1.html"
|
href: "./PAGE1.html"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
".book-summary .chapter[data-level='2'] a": {
|
".book-summary .chapter[data-level=\"2\"] a": {
|
||||||
attributes: {
|
attributes: {
|
||||||
href: "./folder/PAGE2.html"
|
href: "./folder/PAGE2.html"
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-7
@@ -1,6 +1,6 @@
|
|||||||
var pkg = require("../package.json");
|
var pkg = require("../package.json");
|
||||||
|
|
||||||
describe('Templating', function () {
|
describe("Templating", function () {
|
||||||
var book;
|
var book;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -12,19 +12,19 @@ describe('Templating', function () {
|
|||||||
|
|
||||||
var testTpl = function(str, args, options) {
|
var testTpl = function(str, args, options) {
|
||||||
return book.template.renderString(str, args, options)
|
return book.template.renderString(str, args, options)
|
||||||
.then(book.template.postProcess)
|
.then(book.template.postProcess);
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('Context', function() {
|
describe("Context", function() {
|
||||||
it('should correctly have access to generator', function() {
|
it("should correctly have access to generator", function() {
|
||||||
return testTpl('{{ gitbook.generator }}')
|
return testTpl("{{ gitbook.generator }}")
|
||||||
.then(function(content) {
|
.then(function(content) {
|
||||||
content.should.equal("website");
|
content.should.equal("website");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly have access to gitbook version', function() {
|
it("should correctly have access to gitbook version", function() {
|
||||||
return testTpl('{{ gitbook.version }}')
|
return testTpl("{{ gitbook.version }}")
|
||||||
.then(function(content) {
|
.then(function(content) {
|
||||||
content.should.equal(pkg.version.toString());
|
content.should.equal(pkg.version.toString());
|
||||||
});
|
});
|
||||||
|
|||||||
+4
-7
@@ -1,8 +1,5 @@
|
|||||||
var fs = require('fs');
|
describe("Website generator", function () {
|
||||||
var path = require('path');
|
describe("Basic Book", function() {
|
||||||
|
|
||||||
describe('Website generator', function () {
|
|
||||||
describe('Basic Book', function() {
|
|
||||||
var book;
|
var book;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@@ -12,11 +9,11 @@ describe('Website generator', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly output an index.html', function() {
|
it("should correctly output an index.html", function() {
|
||||||
book.should.have.file("index.html");
|
book.should.have.file("index.html");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly copy assets', function() {
|
it("should correctly copy assets", function() {
|
||||||
book.should.have.file("gitbook");
|
book.should.have.file("gitbook");
|
||||||
book.should.have.file("gitbook/app.js");
|
book.should.have.file("gitbook/app.js");
|
||||||
book.should.have.file("gitbook/style.css");
|
book.should.have.file("gitbook/style.css");
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -105,7 +105,19 @@ define([
|
|||||||
events.trigger("page.change");
|
events.trigger("page.change");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var isLeftClickEvent = function (e) {
|
||||||
|
return e.button === 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
var isModifiedEvent = function (e) {
|
||||||
|
return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
|
||||||
|
};
|
||||||
|
|
||||||
var handlePagination = function (e) {
|
var handlePagination = function (e) {
|
||||||
|
if (isModifiedEvent(e) || !isLeftClickEvent(e)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
@import "mixins.less";
|
@import "mixins.less";
|
||||||
|
|
||||||
@import "ebook/variables.less";
|
@import "ebook/variables.less";
|
||||||
@import "ebook/highlight.less";
|
|
||||||
|
|
||||||
.page {
|
.page {
|
||||||
&.page-toc {
|
&.page-toc {
|
||||||
|
|||||||
@@ -1,90 +0,0 @@
|
|||||||
/* http://jmblog.github.io/color-themes-for-highlightjs */
|
|
||||||
|
|
||||||
/* Tomorrow Comment */
|
|
||||||
.hljs-comment,
|
|
||||||
.hljs-title {
|
|
||||||
color: #8e908c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tomorrow Red */
|
|
||||||
.hljs-variable,
|
|
||||||
.hljs-attribute,
|
|
||||||
.hljs-tag,
|
|
||||||
.hljs-regexp,
|
|
||||||
.ruby .hljs-constant,
|
|
||||||
.xml .hljs-tag .hljs-title,
|
|
||||||
.xml .hljs-pi,
|
|
||||||
.xml .hljs-doctype,
|
|
||||||
.html .hljs-doctype,
|
|
||||||
.css .hljs-id,
|
|
||||||
.css .hljs-class,
|
|
||||||
.css .hljs-pseudo {
|
|
||||||
color: #c82829;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tomorrow Orange */
|
|
||||||
.hljs-number,
|
|
||||||
.hljs-preprocessor,
|
|
||||||
.hljs-pragma,
|
|
||||||
.hljs-built_in,
|
|
||||||
.hljs-literal,
|
|
||||||
.hljs-params,
|
|
||||||
.hljs-constant {
|
|
||||||
color: #f5871f;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tomorrow Yellow */
|
|
||||||
.ruby .hljs-class .hljs-title,
|
|
||||||
.css .hljs-rules .hljs-attribute {
|
|
||||||
color: #eab700;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tomorrow Green */
|
|
||||||
.hljs-string,
|
|
||||||
.hljs-value,
|
|
||||||
.hljs-inheritance,
|
|
||||||
.hljs-header,
|
|
||||||
.ruby .hljs-symbol,
|
|
||||||
.xml .hljs-cdata {
|
|
||||||
color: #718c00;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tomorrow Aqua */
|
|
||||||
.css .hljs-hexcolor {
|
|
||||||
color: #3e999f;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tomorrow Blue */
|
|
||||||
.hljs-function,
|
|
||||||
.python .hljs-decorator,
|
|
||||||
.python .hljs-title,
|
|
||||||
.ruby .hljs-function .hljs-title,
|
|
||||||
.ruby .hljs-title .hljs-keyword,
|
|
||||||
.perl .hljs-sub,
|
|
||||||
.javascript .hljs-title,
|
|
||||||
.coffeescript .hljs-title {
|
|
||||||
color: #4271ae;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tomorrow Purple */
|
|
||||||
.hljs-keyword,
|
|
||||||
.javascript .hljs-function {
|
|
||||||
color: #8959a8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs {
|
|
||||||
display: block;
|
|
||||||
background: white;
|
|
||||||
color: #4d4d4c;
|
|
||||||
padding: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.coffeescript .javascript,
|
|
||||||
.javascript .xml,
|
|
||||||
.tex .hljs-formula,
|
|
||||||
.xml .javascript,
|
|
||||||
.xml .vbscript,
|
|
||||||
.xml .css,
|
|
||||||
.xml .hljs-cdata {
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
/* Tomorrow Night Bright Theme */
|
|
||||||
/* Original theme - https://github.com/chriskempson/tomorrow-theme */
|
|
||||||
/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
|
|
||||||
|
|
||||||
/* Tomorrow Comment */
|
|
||||||
.hljs-comment,
|
|
||||||
.hljs-title {
|
|
||||||
color: #969896;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tomorrow Red */
|
|
||||||
.hljs-variable,
|
|
||||||
.hljs-attribute,
|
|
||||||
.hljs-tag,
|
|
||||||
.hljs-regexp,
|
|
||||||
.ruby .hljs-constant,
|
|
||||||
.xml .hljs-tag .hljs-title,
|
|
||||||
.xml .hljs-pi,
|
|
||||||
.xml .hljs-doctype,
|
|
||||||
.html .hljs-doctype,
|
|
||||||
.css .hljs-id,
|
|
||||||
.css .hljs-class,
|
|
||||||
.css .hljs-pseudo {
|
|
||||||
color: #d54e53;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tomorrow Orange */
|
|
||||||
.hljs-number,
|
|
||||||
.hljs-preprocessor,
|
|
||||||
.hljs-pragma,
|
|
||||||
.hljs-built_in,
|
|
||||||
.hljs-literal,
|
|
||||||
.hljs-params,
|
|
||||||
.hljs-constant {
|
|
||||||
color: #e78c45;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tomorrow Yellow */
|
|
||||||
.ruby .hljs-class .hljs-title,
|
|
||||||
.css .hljs-rules .hljs-attribute {
|
|
||||||
color: #e7c547;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tomorrow Green */
|
|
||||||
.hljs-string,
|
|
||||||
.hljs-value,
|
|
||||||
.hljs-inheritance,
|
|
||||||
.hljs-header,
|
|
||||||
.ruby .hljs-symbol,
|
|
||||||
.xml .hljs-cdata {
|
|
||||||
color: #b9ca4a;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tomorrow Aqua */
|
|
||||||
.css .hljs-hexcolor {
|
|
||||||
color: #70c0b1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tomorrow Blue */
|
|
||||||
.hljs-function,
|
|
||||||
.python .hljs-decorator,
|
|
||||||
.python .hljs-title,
|
|
||||||
.ruby .hljs-function .hljs-title,
|
|
||||||
.ruby .hljs-title .hljs-keyword,
|
|
||||||
.perl .hljs-sub,
|
|
||||||
.javascript .hljs-title,
|
|
||||||
.coffeescript .hljs-title {
|
|
||||||
color: #7aa6da;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tomorrow Purple */
|
|
||||||
.hljs-keyword,
|
|
||||||
.javascript .hljs-function {
|
|
||||||
color: #c397d8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs {
|
|
||||||
display: block;
|
|
||||||
background: black;
|
|
||||||
color: #eaeaea;
|
|
||||||
padding: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.coffeescript .javascript,
|
|
||||||
.javascript .xml,
|
|
||||||
.tex .hljs-formula,
|
|
||||||
.xml .javascript,
|
|
||||||
.xml .vbscript,
|
|
||||||
.xml .css,
|
|
||||||
.xml .hljs-cdata {
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Orginal Style from ethanschoonover.com/solarized (c) Jeremy Hull <sourdrums@gmail.com>
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
.hljs {
|
|
||||||
display: block;
|
|
||||||
padding: 0.5em;
|
|
||||||
background: #fdf6e3;
|
|
||||||
color: #657b83;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs-comment,
|
|
||||||
.hljs-template_comment,
|
|
||||||
.diff .hljs-header,
|
|
||||||
.hljs-doctype,
|
|
||||||
.hljs-pi,
|
|
||||||
.lisp .hljs-string,
|
|
||||||
.hljs-javadoc {
|
|
||||||
color: #93a1a1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Solarized Green */
|
|
||||||
.hljs-keyword,
|
|
||||||
.hljs-winutils,
|
|
||||||
.method,
|
|
||||||
.hljs-addition,
|
|
||||||
.css .hljs-tag,
|
|
||||||
.hljs-request,
|
|
||||||
.hljs-status,
|
|
||||||
.nginx .hljs-title {
|
|
||||||
color: #859900;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Solarized Cyan */
|
|
||||||
.hljs-number,
|
|
||||||
.hljs-command,
|
|
||||||
.hljs-string,
|
|
||||||
.hljs-tag .hljs-value,
|
|
||||||
.hljs-rules .hljs-value,
|
|
||||||
.hljs-phpdoc,
|
|
||||||
.tex .hljs-formula,
|
|
||||||
.hljs-regexp,
|
|
||||||
.hljs-hexcolor,
|
|
||||||
.hljs-link_url {
|
|
||||||
color: #2aa198;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Solarized Blue */
|
|
||||||
.hljs-title,
|
|
||||||
.hljs-localvars,
|
|
||||||
.hljs-chunk,
|
|
||||||
.hljs-decorator,
|
|
||||||
.hljs-built_in,
|
|
||||||
.hljs-identifier,
|
|
||||||
.vhdl .hljs-literal,
|
|
||||||
.hljs-id,
|
|
||||||
.css .hljs-function {
|
|
||||||
color: #268bd2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Solarized Yellow */
|
|
||||||
.hljs-attribute,
|
|
||||||
.hljs-variable,
|
|
||||||
.lisp .hljs-body,
|
|
||||||
.smalltalk .hljs-number,
|
|
||||||
.hljs-constant,
|
|
||||||
.hljs-class .hljs-title,
|
|
||||||
.hljs-parent,
|
|
||||||
.haskell .hljs-type,
|
|
||||||
.hljs-link_reference {
|
|
||||||
color: #b58900;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Solarized Orange */
|
|
||||||
.hljs-preprocessor,
|
|
||||||
.hljs-preprocessor .hljs-keyword,
|
|
||||||
.hljs-pragma,
|
|
||||||
.hljs-shebang,
|
|
||||||
.hljs-symbol,
|
|
||||||
.hljs-symbol .hljs-string,
|
|
||||||
.diff .hljs-change,
|
|
||||||
.hljs-special,
|
|
||||||
.hljs-attr_selector,
|
|
||||||
.hljs-subst,
|
|
||||||
.hljs-cdata,
|
|
||||||
.clojure .hljs-title,
|
|
||||||
.css .hljs-pseudo,
|
|
||||||
.hljs-header {
|
|
||||||
color: #cb4b16;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Solarized Red */
|
|
||||||
.hljs-deletion,
|
|
||||||
.hljs-important {
|
|
||||||
color: #dc322f;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Solarized Violet */
|
|
||||||
.hljs-link_label {
|
|
||||||
color: #6c71c4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tex .hljs-formula {
|
|
||||||
background: #eee8d5;
|
|
||||||
}
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
|
|
||||||
|
|
||||||
/* Tomorrow Comment */
|
|
||||||
.hljs-comment,
|
|
||||||
.hljs-title {
|
|
||||||
color: #8e908c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tomorrow Red */
|
|
||||||
.hljs-variable,
|
|
||||||
.hljs-attribute,
|
|
||||||
.hljs-tag,
|
|
||||||
.hljs-regexp,
|
|
||||||
.ruby .hljs-constant,
|
|
||||||
.xml .hljs-tag .hljs-title,
|
|
||||||
.xml .hljs-pi,
|
|
||||||
.xml .hljs-doctype,
|
|
||||||
.html .hljs-doctype,
|
|
||||||
.css .hljs-id,
|
|
||||||
.css .hljs-class,
|
|
||||||
.css .hljs-pseudo {
|
|
||||||
color: #c82829;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tomorrow Orange */
|
|
||||||
.hljs-number,
|
|
||||||
.hljs-preprocessor,
|
|
||||||
.hljs-pragma,
|
|
||||||
.hljs-built_in,
|
|
||||||
.hljs-literal,
|
|
||||||
.hljs-params,
|
|
||||||
.hljs-constant {
|
|
||||||
color: #f5871f;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tomorrow Yellow */
|
|
||||||
.ruby .hljs-class .hljs-title,
|
|
||||||
.css .hljs-rules .hljs-attribute {
|
|
||||||
color: #eab700;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tomorrow Green */
|
|
||||||
.hljs-string,
|
|
||||||
.hljs-value,
|
|
||||||
.hljs-inheritance,
|
|
||||||
.hljs-header,
|
|
||||||
.ruby .hljs-symbol,
|
|
||||||
.xml .hljs-cdata {
|
|
||||||
color: #718c00;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tomorrow Aqua */
|
|
||||||
.css .hljs-hexcolor {
|
|
||||||
color: #3e999f;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tomorrow Blue */
|
|
||||||
.hljs-function,
|
|
||||||
.python .hljs-decorator,
|
|
||||||
.python .hljs-title,
|
|
||||||
.ruby .hljs-function .hljs-title,
|
|
||||||
.ruby .hljs-title .hljs-keyword,
|
|
||||||
.perl .hljs-sub,
|
|
||||||
.javascript .hljs-title,
|
|
||||||
.coffeescript .hljs-title {
|
|
||||||
color: #4271ae;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tomorrow Purple */
|
|
||||||
.hljs-keyword,
|
|
||||||
.javascript .hljs-function {
|
|
||||||
color: #8959a8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs {
|
|
||||||
display: block;
|
|
||||||
background: white;
|
|
||||||
color: #4d4d4c;
|
|
||||||
padding: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.coffeescript .javascript,
|
|
||||||
.javascript .xml,
|
|
||||||
.tex .hljs-formula,
|
|
||||||
.xml .javascript,
|
|
||||||
.xml .vbscript,
|
|
||||||
.xml .css,
|
|
||||||
.xml .hljs-cdata {
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
@@ -5,10 +5,6 @@
|
|||||||
.book .book-body .page-wrapper .page-inner section.normal {
|
.book .book-body .page-wrapper .page-inner section.normal {
|
||||||
.markdown-content(@content-color, @content-line-height);
|
.markdown-content(@content-color, @content-line-height);
|
||||||
|
|
||||||
pre, code {
|
|
||||||
@import "./highlight/white.less";
|
|
||||||
}
|
|
||||||
|
|
||||||
.glossary-term {
|
.glossary-term {
|
||||||
cursor: help;
|
cursor: help;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
@@ -51,8 +47,6 @@
|
|||||||
background: @page-pre-background-1;
|
background: @page-pre-background-1;
|
||||||
color: @page-pre-color-1;
|
color: @page-pre-color-1;
|
||||||
border-color: @page-pre-border-color-1;
|
border-color: @page-pre-border-color-1;
|
||||||
|
|
||||||
@import "./highlight/sepia.less";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.highlight {
|
.highlight {
|
||||||
@@ -112,8 +106,6 @@
|
|||||||
color: @page-pre-color-2;
|
color: @page-pre-color-2;
|
||||||
background: @page-pre-background-2;
|
background: @page-pre-background-2;
|
||||||
border-color: @page-pre-border-color-2;
|
border-color: @page-pre-border-color-2;
|
||||||
|
|
||||||
@import "./highlight/night.less";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.highlight {
|
.highlight {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<div class="book-header">
|
<div class="book-header" role="navigation">
|
||||||
<!-- Actions Left -->
|
<!-- Actions Left -->
|
||||||
<a href="#" class="btn pull-left toggle-summary" aria-label="{{ __("SUMMARY_TOGGLE") }}"><i class="fa fa-align-justify"></i></a>
|
<a href="#" class="btn pull-left toggle-summary" aria-label="{{ __("SUMMARY_TOGGLE") }}"><i class="fa fa-align-justify"></i></a>
|
||||||
<a href="#" class="btn pull-left toggle-search" aria-label="{{ __("SEARCH_TOGGLE") }}"><i class="fa fa-search"></i></a>
|
<a href="#" class="btn pull-left toggle-search" aria-label="{{ __("SEARCH_TOGGLE") }}"><i class="fa fa-search"></i></a>
|
||||||
|
|||||||
@@ -26,33 +26,35 @@
|
|||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
<div class="book-summary">
|
<div class="book-summary">
|
||||||
<div class="book-search">
|
<div class="book-search" role="search">
|
||||||
<input type="text" placeholder="{{ __("SEARCH_PLACEHOLDER") }}" class="form-control" />
|
<input type="text" placeholder="{{ __("SEARCH_PLACEHOLDER") }}" class="form-control" />
|
||||||
</div>
|
</div>
|
||||||
<ul class="summary">
|
<nav role="navigation">
|
||||||
{% set _divider = false %}
|
<ul class="summary">
|
||||||
{% if options.links.sidebar %}
|
{% set _divider = false %}
|
||||||
{% for linkTitle, link in options.links.sidebar %}
|
{% if options.links.sidebar %}
|
||||||
{% set _divider = true %}
|
{% for linkTitle, link in options.links.sidebar %}
|
||||||
|
{% set _divider = true %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ link }}" target="blank" class="custom-link">{{ linkTitle }}</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if _divider %}
|
||||||
|
<li class="divider"></li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{{ articles(summary.chapters) }}
|
||||||
|
|
||||||
|
{% if options.links.gitbook != false %}
|
||||||
|
<li class="divider"></li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ link }}" target="blank" class="custom-link">{{ linkTitle }}</a>
|
<a href="https://www.gitbook.com" target="blank" class="gitbook-link">
|
||||||
|
{{ __("GITBOOK_LINK") }}
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endif %}
|
||||||
{% endif %}
|
</ul>
|
||||||
|
</nav>
|
||||||
{% if _divider %}
|
|
||||||
<li class="divider"></li>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{{ articles(summary.chapters) }}
|
|
||||||
|
|
||||||
{% if options.links.gitbook != false %}
|
|
||||||
<li class="divider"></li>
|
|
||||||
<li>
|
|
||||||
<a href="https://www.gitbook.com" target="blank" class="gitbook-link">
|
|
||||||
{{ __("GITBOOK_LINK") }}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="book-langs-index">
|
<div class="book-langs-index" role="navigation">
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<h3>{{ __("LANGS_CHOOSE") }}</h3>
|
<h3>{{ __("LANGS_CHOOSE") }}</h3>
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
<div class="book-body">
|
<div class="book-body">
|
||||||
<div class="body-inner">
|
<div class="body-inner">
|
||||||
{% include "includes/header.html" %}
|
{% include "includes/header.html" %}
|
||||||
<div class="page-wrapper" tabindex="-1">
|
<div class="page-wrapper" tabindex="-1" role="main">
|
||||||
<div class="page-inner">
|
<div class="page-inner">
|
||||||
{% block page_inner %}
|
{% block page_inner %}
|
||||||
{% for section in content %}
|
{% for section in content %}
|
||||||
|
|||||||
Reference in New Issue
Block a user