Compare commits

...

21 Commits

Author SHA1 Message Date
Samy Pessé 0feb672d70 Bump version to 1.3.0 2014-11-01 15:36:10 +01:00
Samy Pessé 2a4ef5bbf4 Fix dependency in renderer 2014-11-01 15:21:16 +01:00
Samy Pessé c4540332a7 Bundle gitbook parser as a client side library 2014-11-01 15:09:58 +01:00
Samy Pessé 2104404cb3 Remove dependency for path in parser 2014-11-01 15:09:41 +01:00
Samy Pessé 002d685ebb Adapt include in page parsing to works on clientside 2014-11-01 15:00:13 +01:00
Samy Pessé 1e4632080b Bump version to 1.2.0 2014-10-30 18:27:56 +01:00
Samy Pessé 5191106396 Update documentation in readme 2014-10-30 18:27:26 +01:00
Samy Pessé 6ab5cafaf3 Improve toc in ebook (Fixes #338, #322) 2014-10-30 18:14:06 +01:00
Samy Pessé d1c0cb9c71 Normalize template paths 2014-10-30 18:01:56 +01:00
Samy Pessé 38c750101c Fix #487: Use generated toc as base for ebook generation 2014-10-30 17:52:39 +01:00
Samy Pessé ba0f379a89 Add plugin infinitescroll 2014-10-30 16:19:19 +01:00
Samy Pessé 1d9509b3b6 Merge pull request #485 from citizenmatt/Nested_list_spacing
Fix bottom border on nested ul
2014-10-30 14:15:54 +01:00
Samy Pessé 3c8de4a8ab Add 'variables' to book.json doc 2014-10-29 17:20:30 +01:00
Samy Pessé 591d8fc9ee Use book.json to store variables 2014-10-29 17:19:19 +01:00
Samy Pessé d480e9cea4 Update highlight.js@8.3.0 2014-10-23 17:05:27 +02:00
Matt Ellis 32a71869da Fix bottom border on nested ul 2014-10-23 09:19:02 +01:00
Samy Pessé fdbfda64a6 Merge pull request #483 from dharmeshkakadia/patch-1
Corrected a small typo in Plugins description
2014-10-21 15:45:45 +02:00
Dharmesh Kakadia a6f48be39e Corrected a small typo in Plugins description 2014-10-21 00:47:37 +05:30
Aaron O'Mullan ce50b893e9 Merge pull request #482 from GitbookIO/feature/includes
Add include support, with variables and the whole shebang
2014-10-15 21:29:23 +02:00
Aaron O'Mullan 225ff27dd1 Fix small incompatibility mistake 2014-10-15 21:28:53 +02:00
Aaron O'Mullan 52e8361846 Add include support, with variables and the whole shebang
Fixes #462
2014-10-15 21:20:10 +02:00
37 changed files with 20954 additions and 95 deletions
+10
View File
@@ -1,5 +1,15 @@
# Release notes
## 1.3.0
- Bundle gitbook parsing library as a client side library in `gitbook.js` and `gitbook.min.js`
## 1.2.0
- Improvements on ebook generation
- Fix incorrect follow of links in ebook generation
- Move Table of Contents at the beginning of the ebook
- Update to last highlight.js (includes Swift)
- Includes of templates and variables (from book.json)
## 1.1.1
- Rewrite quiz logic to be more robust
- Improve integration of glossary
+34 -1
View File
@@ -6,6 +6,8 @@ module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-requirejs');
grunt.loadNpmTasks("grunt-bower-install-simple");
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-contrib-uglify');
// Init GRUNT configuraton
grunt.initConfig({
@@ -77,6 +79,30 @@ module.exports = function (grunt) {
}
]
}
},
browserify: {
dist: {
files: {
'gitbook.js': [
'./lib/parse/index.js'
],
},
options: {
postBundleCB: function (err, src, next) {
return next(null, '(function () { var define = undefined; '+src+'; })();')
},
browserifyOptions: {
'standalone': "gitbook"
}
}
}
},
uglify: {
dist: {
files: {
'gitbook.min.js': ['gitbook.js']
}
}
}
});
@@ -90,7 +116,14 @@ module.exports = function (grunt) {
'copy:vendors'
]);
// Bundle the library
grunt.registerTask('bundle', [
'bower-install',
'uglify'
]);
grunt.registerTask('default', [
'build'
'build',
'bundle'
]);
};
+5 -4
View File
@@ -74,6 +74,9 @@ Here are the options that can be stored in this file:
}
},
// Variables for templating
"variables": {},
// Links in template (null: default, false: remove, string: new value)
"links": {
// Custom links at top of sidebar
@@ -94,9 +97,6 @@ Here are the options that can be stored in this file:
// Options for PDF generation
"pdf": {
// Add toc at the end of the file
"toc": true,
// Add page numbers to the bottom of every page
"pageNumbers": false,
@@ -209,7 +209,7 @@ The platform [GitBook.io](https://www.gitbook.io/) is like an "Heroku for books"
#### Plugins
Plugins can used to extend your book's functionality. Read [GitbookIO/plugin](https://github.com/GitbookIO/plugin) for more information about how to build a plugin for GitBook.
Plugins can be used to extend your book's functionality. Read [GitbookIO/plugin](https://github.com/GitbookIO/plugin) for more information about how to build a plugin for GitBook.
##### Official plugins:
@@ -219,6 +219,7 @@ Plugins can used to extend your book's functionality. Read [GitbookIO/plugin](ht
| [quizzes](https://github.com/GitbookIO/plugin-quizzes) | Add interactive quizzes to your book. |
| [mathjax](https://github.com/GitbookIO/plugin-mathjax) | Displays mathematical notation in the book. |
| [mixpanel](https://github.com/GitbookIO/plugin-mixpanel) | Mixpanel tracking for your book |
| [infinitescroll](https://github.com/GitbookIO/gitbook-plugin-infinitescroll) | Infinite Scrolling |
##### Other plugins:
+20719
View File
File diff suppressed because one or more lines are too long
+10
View File
File diff suppressed because one or more lines are too long
+3
View File
@@ -38,6 +38,9 @@ var CONFIG = {
}
},
// Variables for templating
"variables": {},
// Set another theme with your own layout
// It's recommended to use plugins or add more options for default theme, though
// See https://github.com/GitbookIO/gitbook/issues/209
+3 -3
View File
@@ -39,7 +39,8 @@ Generator.prototype.finish = function() {
"--level2-toc": "descendant-or-self::*[contains(concat(' ', normalize-space(@class), ' '), ' book-chapter-2 ')]",
"--level3-toc": "descendant-or-self::*[contains(concat(' ', normalize-space(@class), ' '), ' book-chapter-3 ')]",
"--no-chapters-in-toc": true,
"--max-levels": "1000"
"--max-levels": "1",
"--breadth-first": true
};
if (format == "pdf") {
@@ -50,7 +51,6 @@ Generator.prototype.finish = function() {
"--margin-right": String(pdfOptions.margin.right),
"--margin-top": String(pdfOptions.margin.top),
"--margin-bottom": String(pdfOptions.margin.bottom),
"--pdf-add-toc": Boolean(pdfOptions.toc),
"--pdf-default-font-size": String(pdfOptions.fontSize),
"--pdf-mono-font-size": String(pdfOptions.fontSize),
"--paper-size": String(pdfOptions.paperSize),
@@ -62,7 +62,7 @@ Generator.prototype.finish = function() {
var command = [
"ebook-convert",
path.join(that.options.output, "index.html"),
path.join(that.options.output, "SUMMARY.html"),
path.join(that.options.output, "index."+format),
stringUtils.optionsToShellArgs(_options)
].join(" ");
+1
View File
@@ -74,4 +74,5 @@ module.exports = {
fs.exists(path, d.resolve);
return d.promise;
},
readFileSync: fs.readFileSync.bind(fs)
};
+5
View File
@@ -20,6 +20,11 @@ BaseGenerator.prototype.callHook = function(name, data) {
return this.plugins.hook(name, data);
};
// Sets up generator
BaseGenerator.prototype.load = function() {
return this.loadPlugins();
};
BaseGenerator.prototype.loadPlugins = function() {
var that = this;
+1 -1
View File
@@ -40,7 +40,7 @@ var loadGenerator = function(options) {
.then(function() {
var generator = new generators[options.generator](options);
return generator.loadPlugins()
return generator.load()
.then(_.constant(generator));
});
};
+21 -1
View File
@@ -21,8 +21,23 @@ util.inherits(Generator, BaseGenerator);
Generator.prototype.loadTemplates = function() {
this.template = swig.compileFile(
this.plugins.template("page") || path.resolve(this.options.theme, 'templates/page.html')
this.plugins.template("ebook:page") || path.resolve(this.options.theme, 'templates/ebook/page.html')
);
this.summaryTemplate = swig.compileFile(
this.plugins.template("ebook:sumary") || path.resolve(this.options.theme, 'templates/ebook/summary.html')
);
};
// Generate table of contents
Generator.prototype.writeToc = function() {
var that = this;
var basePath = ".";
return this._writeTemplate(this.summaryTemplate, {
toc: parse.progress(this.options.navigation, "README.md").chapters,
basePath: basePath,
staticBase: path.join(basePath, "gitbook"),
}, path.join(this.options.output, "SUMMARY.html"));
};
Generator.prototype.finish = function() {
@@ -34,6 +49,11 @@ Generator.prototype.finish = function() {
return Q()
// Write table of contents
.then(function() {
return that.writeToc();
})
// Copy cover
.then(function() {
return that.copyCover();
+27 -23
View File
@@ -23,29 +23,29 @@ var Generator = function() {
};
util.inherits(Generator, BaseGenerator);
// Load all templates
Generator.prototype.loadTemplates = function() {
this.template = swig.compileFile(
this.plugins.template("site") || path.resolve(this.options.theme, 'templates/site.html')
);
this.langsTemplate = swig.compileFile(
this.plugins.template("langs") || path.resolve(this.options.theme, 'templates/langs.html')
);
this.glossaryTemplate = swig.compileFile(
this.plugins.template("glossary") || path.resolve(this.options.theme, 'templates/glossary.html')
);
};
// Load plugins
Generator.prototype.loadPlugins = function() {
// Add template loading to load
Generator.prototype.load = function() {
var that = this;
return BaseGenerator.prototype.loadPlugins.apply(this)
return BaseGenerator.prototype.load.apply(this)
.then(function() {
return that.loadTemplates();
});
};
// Load all templates
Generator.prototype.loadTemplates = function() {
this.template = swig.compileFile(
this.plugins.template("site:page") || path.resolve(this.options.theme, 'templates/book/page.html')
);
this.langsTemplate = swig.compileFile(
this.plugins.template("site:langs") || path.resolve(this.options.theme, 'templates/book/langs.html')
);
this.glossaryTemplate = swig.compileFile(
this.plugins.template("site:glossary") || path.resolve(this.options.theme, 'templates/book/glossary.html')
);
};
// Generate a template
Generator.prototype._writeTemplate = function(tpl, options, output, interpolate) {
var that = this;
@@ -118,16 +118,20 @@ Generator.prototype.prepareFile = function(content, _input) {
return _callHook("page:before");
})
.then(function() {
// Lex page
return parse.lex(page.content);
})
.then(function(lexed) {
page.lexed = lexed;
// Lex, parse includes and get
// Get HTML generated sections
return parse.page(lexed, {
return parse.page(page.content, {
// Local files path
dir: path.dirname(_input) || '/',
// Output directory
outdir: path.dirname(_input) || '/',
// Includer for templating
includer: parse.includer(that.options.variables, [
path.dirname(_input) || '/',
path.join(that.options.input, '_includes'),
], path.join, fs.readFileSync)
});
})
.then(function(sections) {
-20
View File
@@ -1,20 +0,0 @@
var fs = require('graceful-fs');
var path = require('path');
module.exports = function(code, folder) {
folder = folder || '';
return code.replace(/{{([\s\S]+?)}}/g, function(match, filename) {
// Normalize filename
var fname = path.join(folder, filename.trim());
// Try including snippet from FS
try {
// Trim trailing newlines/space of imported snippets
return fs.readFileSync(fname, 'utf8').trimRight();
} catch(err) {}
// If fails leave content as is
return match;
});
};
+12
View File
@@ -0,0 +1,12 @@
var _ = require('lodash');
module.exports = function(markdown, includer) {
// Memoized include function (to cache lookups)
var _include = _.memoize(includer);
return markdown.replace(/{{([\s\S]+?)}}/g, function(match, key) {
// If fails leave content as is
key = key.trim();
return _include(key) || match;
});
};
+15
View File
@@ -0,0 +1,15 @@
// Return a fs inclduer
module.exports = function(ctx, folders, resolveFile, readFile) {
return function(name) {
return ctx[name] ||
folders.map(function(folder) {
// Try including snippet from FS
try {
var fname = resolveFile(folder, name);
// Trim trailing newlines/space of imported snippets
return readFile(fname, 'utf8').trimRight();
} catch(err) {}
})
.filter(Boolean)[0];
}
};
+2 -1
View File
@@ -6,5 +6,6 @@ module.exports = {
lex: require('./lex'),
progress: require('./progress'),
navigation: require('./navigation'),
readme: require('./readme')
readme: require('./readme'),
includer: require('./includer')
};
+5 -10
View File
@@ -5,7 +5,7 @@ var hljs = require('highlight.js');
var lex = require('./lex');
var renderer = require('./renderer');
var codeInclude = require('./code_include');
var include = require('./include');
var lnormalize = require('../utils/lang').normalize;
@@ -51,7 +51,7 @@ function parsePage(src, options) {
options = options || {};
// Lex if not already lexed
return (_.isArray(src) ? src : lex(src))
return (_.isArray(src) ? src : lex(include(src, options.includer || function() { return undefined; })))
.map(function(section) {
// Transform given type
if(section.type === 'exercise') {
@@ -74,20 +74,15 @@ function parsePage(src, options) {
// Main language
var lang = validLangs ? langs[0] : null;
// codeInclude shortcut
var ci = function(code) {
return codeInclude(code, options.dir);
};
return {
id: section.id,
type: section.type,
content: render(nonCodeNodes, options),
lang: lang,
code: {
base: ci(codeNodes[0].text),
solution: ci(codeNodes[1].text),
validation: ci(codeNodes[2].text),
base: codeNodes[0].text,
solution: codeNodes[1].text,
validation: codeNodes[2].text,
// Context is optional
context: codeNodes[3] ? codeNodes[3].text : null,
}
+4 -9
View File
@@ -1,11 +1,7 @@
var url = require('url');
var _ = require('lodash');
var inherits = require('util').inherits;
var links = require('../utils').links;
var codeInclude = require('./code_include');
var path = require('path');
var kramed = require('kramed');
var rendererId = 0;
@@ -52,11 +48,11 @@ GitBookRenderer.prototype.link = function(href, title, text) {
// Parsed version of the url
var parsed = url.parse(href);
var o = this._extra_options;
var extname = _.last(parsed.path.split("."));
// Relative link, rewrite it to point to github repo
if(links.isRelative(_href) && path.extname(parsed.path) == ".md") {
if(links.isRelative(_href) && extname == "md") {
_href = links.toAbsolute(_href, o.dir || "./", o.outdir || "./");
_href = _href.replace(".md", ".html");
}
@@ -130,8 +126,7 @@ GitBookRenderer.prototype.listitem = function(text) {
GitBookRenderer.prototype.code = function(code, lang, escaped) {
return GitBookRenderer.super_.prototype.code.call(
this,
// Import code snippets
codeInclude(code, this._extra_options.dir),
code,
lang,
escaped
);
+2 -2
View File
@@ -11,8 +11,8 @@ function escapeShellArg(arg) {
function optionsToShellArgs(options) {
return _.chain(options)
.map(function(value, key) {
if (value == null || value == false) return null;
if (value == true) return key;
if (value == null || value === false) return null;
if (value === true) return key;
return key+"="+escapeShellArg(value);
})
.compact()
+5 -3
View File
@@ -1,6 +1,6 @@
{
"name": "gitbook",
"version": "1.1.1",
"version": "1.3.0",
"homepage": "http://www.gitbook.io/",
"description": "Library and cmd utility to generate GitBooks",
"main": "lib/index.js",
@@ -16,7 +16,7 @@
"commander": "2.2.0",
"graceful-fs": "3.0.2",
"fs-extra": "0.10.0",
"highlight.js": "8.2.0",
"highlight.js": "8.3.0",
"tmp": "0.0.23",
"semver": "2.2.1",
"gaze": "~0.5.1",
@@ -35,7 +35,9 @@
"grunt-contrib-copy": "0.5.0",
"grunt-contrib-less": "~0.5.0",
"grunt-contrib-requirejs": "0.4.1",
"grunt-bower-install-simple": "0.9.2"
"grunt-bower-install-simple": "0.9.2",
"grunt-browserify": "3.1.0",
"grunt-contrib-uglify": "0.6.0"
},
"scripts": {
"test": "export TESTING=true; mocha --reporter list"
+4
View File
@@ -3,6 +3,7 @@ var path = require('path');
var assert = require('assert');
var page = require('../').parse.page;
var includer = require('../').parse.includer;
var FIXTURES_DIR = path.join(__dirname, './fixtures/');
@@ -16,6 +17,9 @@ describe('Code includes', function() {
var LEXED = loadPage('INCLUDES', {
'dir': FIXTURES_DIR,
'includer': includer({}, [
FIXTURES_DIR
], path.join, fs.readFileSync)
});
var INCLUDED_C = fs.readFileSync(path.join(FIXTURES_DIR, 'included.c'), 'utf8');
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -1
View File
@@ -256,7 +256,8 @@
}
ol ol,
ol ul {
ol ul,
ul ul {
margin-top: 0;
margin-bottom: 0;
}
+6
View File
@@ -4,6 +4,12 @@
@import "ebook/highlight.less";
.page {
&.page-toc {
ol {
margin: 0px;
}
}
.book-chapter {
display: none;
}
@@ -1,4 +1,4 @@
{% extends "site.html" %}
{% extends "page.html" %}
{% block title %}Glossary | {{ title }}{% endblock %}
@@ -1,4 +1,4 @@
{% extends "layout.html" %}
{% extends "../layout.html" %}
{% block title %}{{ title }}{% endblock %}
@@ -1,4 +1,4 @@
{% extends "layout.html" %}
{% extends "../layout.html" %}
{% block head %}
{% parent %}
@@ -15,10 +15,10 @@
{% block content %}
<div class="book" data-level="{{ progress.current.level }}" data-basepath="{{ basePath }}" data-revision="{{ revision }}">
{% include "includes/book/summary.html" %}
{% include "includes/summary.html" %}
<div class="book-body">
<div class="body-inner">
{% include "includes/book/header.html" %}
{% include "includes/header.html" %}
<div class="page-wrapper" tabindex="-1">
<div class="page-inner">
{% block page_inner %}
@@ -27,9 +27,9 @@
{% if section.type == "normal" %}
{% autoescape false %}{{ section.content }}{% endautoescape %}
{% elif section.type == "exercise" %}
{% include "./includes/book/exercise.html" with {section: section} %}
{% include "./includes/exercise.html" with {section: section} %}
{% elif section.type == "quiz" %}
{% include "./includes/book/quiz.html" with {section: section} %}
{% include "./includes/quiz.html" with {section: section} %}
{% endif %}
</section>
{% endfor %}
@@ -1,4 +1,4 @@
{% extends "layout.html" %}
{% extends "../layout.html" %}
{% block title %}{{ progress.current.title }} | {{ title }}{% endblock %}
@@ -21,16 +21,12 @@
{% if section.type == "normal" %}
{% autoescape false %}{{ section.content }}{% endautoescape %}
{% elif section.type == "exercise" %}
{% include "./includes/page/exercise.html" with {section: section} %}
{% include "./includes/exercise.html" with {section: section} %}
{% elif section.type == "quiz" %}
{% include "./includes/page/quiz.html" with {section: section} %}
{% include "./includes/quiz.html" with {section: section} %}
{% endif %}
</section>
{% endfor %}
{% if progress.current.next and progress.current.next.path %}
<a href="{{ basePath }}/{{ progress.current.next.path|mdLink }}" />
{% endif %}
</div>
{% endblock %}
+46
View File
@@ -0,0 +1,46 @@
{% extends "../layout.html" %}
{% block title %}Table of Contents | {{ title }}{% endblock %}
{% block style %}
<link rel="stylesheet" href="{{ staticBase }}/print.css">
{% for resource in plugins.resources.css %}
{% if resource.url %}
<link rel="stylesheet" href="{{ resource.url }}">
{% else %}
<link rel="stylesheet" href="{{ staticBase }}/plugins/{{ resource.path }}">
{% endif %}
{% endfor %}
{% endblock %}
{% macro articles(_articles) %}
{% for item in _articles %}
{% set externalLink = item.path|isExternalLink %}
<li>
{% if item.path %}
{% if !externalLink %}
<a href="{{ basePath }}/{{ item.path|mdLink }}">{{ item.title }}</a>
{% else %}
<a target="_blank" href="{{ item.path }}">{{ item.title }}</a>
{% endif %}
{% else %}
{{ item.title }}
{% endif %}
{% if item.articles.length > 0 %}
<ol>
{{ articles(item.articles) }}
</ol>
{% endif %}
</li>
{% endfor %}
{% endmacro %}
{% block content %}
<div class="page page-toc">
<h1>Table of Contents</h1>
<ol>
{{ articles(summary.chapters) }}
</ol>
</div>
{% endblock %}