Compare commits

...

24 Commits

Author SHA1 Message Date
Samy Pessé 99253eecea Bump version to 3.0.0-pre.8 2016-04-14 15:02:49 +02:00
Samy Pessé 916a02cb36 Update plugins search@2.0.0 and theme-default@1.0.0-pre.7 2016-04-14 15:00:25 +02:00
Samy Pessé 114c4abcd1 Add method for theme: template.getJSContext 2016-04-14 14:51:42 +02:00
Samy Pessé e1e3d11932 Add lunr as default plugin 2016-04-14 14:51:22 +02:00
Samy Pessé df46217c78 Improve description extraction and adapt unit tests 2016-04-14 10:07:51 +02:00
Samy Pessé d18cc92396 Pass template to block's context 2016-04-14 09:51:56 +02:00
Samy Pessé 8f63b4b790 Remove unused variable 2016-04-13 17:32:01 +02:00
Samy Pessé ce7de93936 Improve block parsing to handle args/kwargs on subblocks 2016-04-13 16:22:53 +02:00
Johan Preynat ef2a24fe6f Add trailing dots to page.description when longer than 300 characters 2016-04-13 16:00:16 +02:00
Samy Pessé 038cd0155b Add filter "getArticleByPath" for theme templates 2016-04-13 11:48:29 +02:00
Samy Pessé fb430ac1ed Increase size of extracted description 2016-04-13 10:55:32 +02:00
Johan Preynat 53cfa3703b Update page context for plugins hooks 2016-04-13 09:33:26 +02:00
Johan Preynat 7ed9e8d145 Update plugin-fontsettings@1.0.3 / plugin-sharing@1.0.2 2016-04-12 17:05:32 +02:00
Samy Pessé 93e0b0cbea Watch _layouts when serving 2016-04-12 13:53:58 +02:00
Samy Pessé 0118bd3168 Cleanup code to list plugins 2016-04-11 12:29:53 +02:00
Samy Pessé 07d5245a5f Bump version to 3.0.0-pre.7 2016-04-11 09:59:58 +02:00
Samy Pessé 6b844213ec Update theme-default@1.0.0-pre.6 2016-04-11 09:59:18 +02:00
Samy Pessé dabdeb8a80 Fix #1195: fix external images and fix test for it 2016-04-11 09:56:13 +02:00
Samy Pessé ecd56315e6 Merge pull request #1220 from seanlane/patch-1
Fix minor spelling error.
2016-04-11 09:34:15 +02:00
Sean Lane 15b9e839e9 Fix minor spelling error. 2016-04-10 14:31:49 -06:00
Samy Pesse d7f7dcd47b Switch to ignore@3.1.1 2016-04-10 22:28:29 +02:00
Samy Pessé b1981e09b8 Fix generator deprecation warning being shown for each call 2016-04-10 18:20:51 +02:00
Samy Pessé c9edd0a795 Load plugins from book parent in multilingual book 2016-04-09 12:16:17 +02:00
Samy Pesse d83e0716bb Add test for main language in json output 2016-04-08 23:58:42 +02:00
13 changed files with 150 additions and 87 deletions
+1 -1
View File
@@ -25,7 +25,7 @@ Each chapter has a dedicated page (`part#/README.md`) and is split into subchapt
##### Anchors
Chaptersi n the Table of Contents can be pointing to specific part of a file using anchor.
Chapters in the Table of Contents can be pointing to specific part of a file using anchor.
```markdown
# Summary
+1 -1
View File
@@ -11,7 +11,7 @@ function watch(dir) {
dir = path.resolve(dir);
var toWatch = [
'book.json', 'book.js'
'book.json', 'book.js', '_layouts/**'
];
// Watch all parsable files
+1 -1
View File
@@ -1,7 +1,7 @@
var _ = require('lodash');
// Default plugins added to each books
var DEFAULT_PLUGINS = ['highlight', 'search', 'sharing', 'fontsettings', 'theme-default'];
var DEFAULT_PLUGINS = ['highlight', 'search', 'lunr', 'sharing', 'fontsettings', 'theme-default'];
// Return true if a plugin is a default plugin
function isDefaultPlugin(name, version) {
+6 -4
View File
@@ -38,10 +38,8 @@ function Output(book, opts, parent) {
// Files to ignore in output
this.ignore = Ignore();
// Hack to inherits from rules of the book:
// Waiting for https://github.com/kaelzhang/node-ignore/pull/19 to be merged
this.ignore._rules = this.ignore._rules.concat(this.book.ignore._rules);
this.ignore._cache = {};
// Hack to inherits from rules of the book
this.ignore.add(this.book.ignore);
}
// Default name for generator
@@ -209,6 +207,10 @@ Output.prototype.onOutputSVG = function(page, svg) {
// Output an image as a file
// Normalize the relative link
Output.prototype.onOutputImage = function(page, imgFile) {
if (location.isExternal(imgFile)) {
return imgFile;
}
imgFile = page.resolveLocal(imgFile);
return page.relative(imgFile);
};
+22 -1
View File
@@ -96,6 +96,14 @@ WebsiteOutput.prototype.prepare = function() {
return that.toURL(s);
});
// Get an article using its path
that.env.addFilter('getArticleByPath', function(s) {
var article = that.book.summary.getArticle(s);
if (!article) return undefined;
return article.getContext();
});
// Relase path to an asset
that.env.addFilter('resolveAsset', function(href) {
href = path.join('gitbook', href);
@@ -208,11 +216,24 @@ WebsiteOutput.prototype.outputMultilingualIndex = function() {
// Render a template using nunjucks
// Templates are stored in `_layouts` folders
WebsiteOutput.prototype.render = function(tpl, context) {
var that = this;
var filename = this.templateName(tpl);
context = _.extend(context, {
template: {
self: filename
self: filename,
getJSContext: function() {
return {
page: _.omit(context.page, 'content'),
config: context.config,
file: context.file,
gitbook: context.gitbook,
basePath: location.normalize(that.resolveForPage(context.file.path, './')),
book: {
language: context.book.language
}
};
}
},
plugins: {
+12 -2
View File
@@ -184,8 +184,18 @@ HTMLPipeline.prototype.applyAnnotations = function() {
// Extract page description from html
// This can totally be improved
HTMLPipeline.prototype.extractDescription = function() {
var $p = this.$('p').first();
var description = $p.text().trim().slice(0, 155);
var $ = this.$;
var $p = $('p').first();
var $next = $p.nextUntil('h1,h2,h3,h4,h5,h6,pre,blockquote,ul,ol,div');
var description = $p.text().trim();
$next.each(function() {
description += ' ' + $(this).text().trim();
});
// Truncate description
description = _.trunc(description, 300);
this.opts.onDescription(description);
};
-1
View File
@@ -7,7 +7,6 @@ var error = require('../utils/error');
var pathUtil = require('../utils/path');
var location = require('../utils/location');
var parsers = require('../parsers');
var gitbook = require('../gitbook');
var pluginCompatibility = require('../plugins/compatibility');
var HTMLPipeline = require('./html');
+7 -6
View File
@@ -14,12 +14,13 @@ function pluginCtx(plugin) {
// Call a function "fn" with a context of page similar to the one in GitBook v2
function pageHook(page, fn) {
var ctx = {
type: page.type,
content: page.content,
path: page.path,
rawPath: page.rawPath
};
// Get page context
var ctx = page.getContext().page;
// Add other informations
ctx.type = page.type;
ctx.rawPath = page.rawPath;
ctx.path = page.path;
// Deprecate sections
error.deprecateField(ctx, 'sections', [
+9 -3
View File
@@ -144,10 +144,16 @@ function listInstalled(folder) {
function listPlugins(book) {
return Promise.all([
listInstalled(path.resolve(__dirname, '../..')),
listInstalled(book.root)
listInstalled(book.root),
book.isLanguageBook()? listInstalled(book.parent.root) : Promise([])
])
.spread(function(defaultPlugins, plugins) {
var results = plugins.concat(defaultPlugins);
.spread(function() {
var args = _.toArray(arguments);
var results = _.reduce(args, function(out, a) {
return out.concat(a);
}, []);
return _.uniq(results, 'name');
});
}
+79 -57
View File
@@ -10,6 +10,8 @@ var defaultBlocks = require('./blocks');
var defaultFilters = require('./filters');
var Loader = require('./loader');
var NODE_ENDARGS = '%%endargs%%';
// Return extension name for a specific block
function blockExtName(name) {
return 'Block'+name+'Extension';
@@ -21,6 +23,12 @@ function normBlockResult(blk) {
return blk;
}
// Extract kwargs from an arguments array
function extractKwargs(args) {
var last = _.last(args);
return (_.isObject(last) && last.__keywords)? args.pop() : {};
}
function TemplateEngine(output) {
this.output = output;
this.book = output.book;
@@ -63,6 +71,14 @@ function TemplateEngine(output) {
// Add default blocks and filters
this.addBlocks(defaultBlocks);
this.addFilters(defaultFilters);
// Build context for this book with depreacted fields
this.ctx = {
template: this,
book: this.book,
output: this.output
};
error.deprecateField(this.ctx, 'generator', this.output.name, '"generator" property is deprecated, use "output.generator" instead');
}
// Bind a function to a context
@@ -71,12 +87,9 @@ TemplateEngine.prototype.bindContext = function(func) {
var that = this;
return function() {
var ctx = {
ctx: this.ctx,
book: that.book,
output: that.output
};
error.deprecateField(ctx, 'generator', that.output.name, '"generator" property is deprecated, use "output.generator" instead');
var ctx = _.extend({
ctx: this.ctx
}, that.ctx);
return func.apply(ctx, arguments);
};
@@ -174,91 +187,100 @@ TemplateEngine.prototype.addBlock = function(name, block) {
this.tags = [name];
this.parse = function(parser, nodes) {
var body = null;
var lastBlockName = null;
var lastBlockArgs = null;
var allBlocks = block.blocks.concat([block.end]);
var subbodies = {};
// Parse first block
var tok = parser.nextToken();
var args = parser.parseSignature(null, true);
lastBlockArgs = parser.parseSignature(null, true);
parser.advanceAfterBlockEnd(tok.value);
var args = new nodes.NodeList();
var bodies = [];
var blockNamesNode = new nodes.Array(tok.lineno, tok.colno);
var blockArgCounts = new nodes.Array(tok.lineno, tok.colno);
// Parse while we found "end<block>"
do {
// Read body
var currentBody = parser.parseUntilBlocks.apply(parser, allBlocks);
// Handle body with previous block name and args
if (lastBlockName) {
subbodies[lastBlockName] = subbodies[lastBlockName] || [];
subbodies[lastBlockName].push({
body: currentBody,
args: lastBlockArgs
});
} else {
body = currentBody;
}
blockNamesNode.addChild(new nodes.Literal(args.lineno, args.colno, lastBlockName));
blockArgCounts.addChild(new nodes.Literal(args.lineno, args.colno, lastBlockArgs.children.length));
bodies.push(currentBody);
// Append arguments of this block as arguments of the run function
_.each(lastBlockArgs.children, function(child) {
args.addChild(child);
});
// Read new block
lastBlockName = parser.peekToken().value;
lastBlockName = parser.nextToken().value;
// Parse signature and move to the end of the block
if (lastBlockName != block.end) {
lastBlockArgs = parser.parseSignature(null, true);
parser.advanceAfterBlockEnd(lastBlockName);
}
parser.advanceAfterBlockEnd(lastBlockName);
} while (lastBlockName != block.end);
parser.advanceAfterBlockEnd();
var bodies = [body];
_.each(block.blocks, function(blockName) {
subbodies[blockName] = subbodies[blockName] || [];
if (subbodies[blockName].length === 0) {
subbodies[blockName].push({
args: new nodes.NodeList(),
body: new nodes.NodeList()
});
}
bodies.push(subbodies[blockName][0].body);
});
args.addChild(blockNamesNode);
args.addChild(blockArgCounts);
args.addChild(new nodes.Literal(args.lineno, args.colno, NODE_ENDARGS));
return new nodes.CallExtensionAsync(this, 'run', args, bodies);
};
this.run = function(context) {
var args = Array.prototype.slice.call(arguments, 1);
var callback = args.pop();
var fnArgs = Array.prototype.slice.call(arguments, 1);
// Extract blocks
var blocks = args
.concat([])
.slice(-block.blocks.length);
var args;
var blocks = [];
var bodies = [];
var blockNames;
var blockArgCounts;
var callback;
// Eliminate blocks from list
if (block.blocks.length > 0) args = args.slice(0, -block.blocks.length);
// Extract callback
callback = fnArgs.pop();
// Extract main body and kwargs
var body = args.pop();
var kwargs = _.isObject(_.last(args))? args.pop() : {};
// Detect end of arguments
var endArgIndex = fnArgs.indexOf(NODE_ENDARGS);
// Extract blocks body
var _blocks = _.map(block.blocks, function(blockName, i){
return {
name: blockName,
body: blocks[i]()
};
// Extract arguments and bodies
args = fnArgs.slice(0, endArgIndex);
bodies = fnArgs.slice(endArgIndex + 1);
// Extract block counts
blockArgCounts = args.pop();
blockNames = args.pop();
// Recreate list of blocks
_.each(blockNames, function(name, i) {
var countArgs = blockArgCounts[i];
var blockBody = bodies.shift();
var blockArgs = countArgs > 0? args.slice(0, countArgs) : [];
args = args.slice(countArgs);
var blockKwargs = extractKwargs(blockArgs);
blocks.push({
name: name,
body: blockBody(),
args: blockArgs,
kwargs: blockKwargs
});
});
var mainBlock = blocks.shift();
mainBlock.blocks = blocks;
Promise()
.then(function() {
return that.applyBlock(name, {
body: body(),
args: args,
kwargs: kwargs,
blocks: _blocks
}, context);
return that.applyBlock(name, mainBlock, context);
})
// Process the block returned
+7 -6
View File
@@ -1,6 +1,6 @@
{
"name": "gitbook",
"version": "3.0.0-pre.6",
"version": "3.0.0-pre.8",
"homepage": "https://www.gitbook.com",
"description": "Library and cmd utility to generate GitBooks",
"main": "lib/index.js",
@@ -21,16 +21,17 @@
"front-matter": "2.0.7",
"gitbook-asciidoc": "1.1.0",
"gitbook-markdown": "1.2.0",
"gitbook-plugin-fontsettings": "1.0.2",
"gitbook-plugin-fontsettings": "1.0.3",
"gitbook-plugin-highlight": "2.0.2",
"gitbook-plugin-livereload": "0.0.1",
"gitbook-plugin-search": "1.2.0",
"gitbook-plugin-sharing": "1.0.1",
"gitbook-plugin-theme-default": "1.0.0-pre.5",
"gitbook-plugin-search": "2.0.0",
"gitbook-plugin-lunr": "1.0.0",
"gitbook-plugin-theme-default": "1.0.0-pre.7",
"gitbook-plugin-sharing": "1.0.2",
"github-slugid": "1.0.1",
"graceful-fs": "4.1.3",
"i18n-t": "1.0.0",
"ignore": "3.0.14",
"ignore": "3.1.1",
"json-schema-defaults": "0.1.1",
"jsonschema": "1.1.0",
"juice": "1.10.0",
+2 -1
View File
@@ -53,9 +53,10 @@ describe('JSON Output', function() {
it('should correctly generate a README.json for the whole book', function() {
output.should.have.file('README.json');
var json = require(output.resolve('README.json'));
json.book.language.should.equal('en');
json.should.have.property('languages')
.with.property('list').with.lengthOf(2);
});
+3 -3
View File
@@ -8,7 +8,7 @@ describe('Page', function() {
return mock.setupDefaultBook({
'README.md': ' # Hello World\n\nThis is a description',
'heading.md': '# Hello\n\n## World',
'description.md': '# This is a title\n\nThis is the short description.\n\nNot this one.',
'description.md': '# This is a title\n\nThis is the short description.\n\nAnd the rest of the description.\n\n# Heading\n\nThis is not in the description',
'frontmatter/description.md': '---\ndescription: Hello World\n---\n\n# This is a title\n\nThis is not the description',
'frontmatter/var.md': '---\ntest: Hello World\n---\n\n{{ page.test }}',
@@ -141,7 +141,7 @@ describe('Page', function() {
return page.toHTML(output)
.then(function() {
page.attributes.description.should.equal('This is the short description.');
page.attributes.description.should.equal('This is the short description. And the rest of the description.');
});
});
});
@@ -289,7 +289,7 @@ describe('Page', function() {
it('should keep external images path', function() {
page.content.should.be.html({
'img[src="https:/upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png"]': {
'img[src="https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png"]': {
count: 1
}
});