Compare commits

...

38 Commits

Author SHA1 Message Date
Aaron O'Mullan 89ba17de84 Bump version to 0.4.7 2014-05-26 12:14:32 -07:00
Aaron O'Mullan 115fba837c Merge pull request #265 from GitbookIO/feature/levels
More than two section level in summary
2014-05-26 11:27:27 -07:00
Samy Pessé 4df51546b2 Remove command log in ebook convert 2014-05-26 18:02:32 +02:00
Samy Pessé f68aaf7ff9 Fix cover option for ebook 2014-05-26 18:02:09 +02:00
Samy Pessé e3d1746ba3 Fix use of cover.jpg in ebook 2014-05-26 17:58:08 +02:00
Samy Pessé a0d5646034 Adapt navigation parsing to third and more levels in summary 2014-05-26 17:42:05 +02:00
Samy Pessé 2f8af5f136 Improve design of summary for deep articles 2014-05-26 17:33:10 +02:00
Samy Pessé 8b7abbd6f4 Render articles of level > 2 in summary 2014-05-26 17:31:35 +02:00
Samy Pessé f228f646eb Remove useless method parseArticle 2014-05-26 17:23:19 +02:00
Samy Pessé 45891d80c7 Parse more than two level in summary 2014-05-26 17:21:23 +02:00
Samy Pessé ac900aa37f Merge pull request #263 from jpoesen/patch-1
Minor typo, grammar and style corrections.
2014-05-26 10:44:25 +02:00
Joeri Poesen 422cbed796 Minor typo, grammar and style corrections. 2014-05-26 08:13:35 +02:00
Samy Pessé 38cbbe46aa Fix cache manifest generation 2014-05-25 20:47:57 +02:00
Aaron O'Mullan c1b57a387b Bump version to 0.4.6 2014-05-23 16:35:44 -07:00
Samy Pessé aaa9ae8bb7 Fix loading button display on navigation 2014-05-24 01:32:39 +02:00
Samy Pessé 6340a64cff Fix #235: search after navigation to another page 2014-05-23 22:28:36 +02:00
Samy Pessé 96bcfa4e20 Fix #218: keep state of font settings 2014-05-23 22:20:36 +02:00
Samy Pessé af0f56b26b Change position of menu action in header 2014-05-23 21:49:11 +02:00
Samy Pessé aed5befa48 Fix display of divider in lateral menu 2014-05-23 21:48:04 +02:00
Samy Pessé 8e37da672d Minor css improvements 2014-05-23 21:43:47 +02:00
Samy Pessé c0f68c45e2 Fix #249: fix links.toAbsolute on windows 2014-05-23 21:10:58 +02:00
Samy Pessé 47fdd73791 Fix cache manifest in the html tag
Serve command disable cache
2014-05-23 17:45:46 +02:00
Samy Pessé 7c0b88cf2e Plugins can extend html 2014-05-23 17:00:37 +02:00
Samy Pessé bf21633b6c Support multi-languages book in json format 2014-05-23 16:35:34 +02:00
Samy Pessé ad9b1fd6f7 Fix order of progress for level superior to x.9
Related to GitbookIO/gitbook.io#23
2014-05-21 23:31:57 +02:00
Samy Pessé d245895085 Add link to documentation 2014-05-21 20:22:28 +02:00
Samy Pessé c7439d12f7 Add livereload as default plugins only for serve 2014-05-21 17:34:36 +02:00
Samy Pessé 8d6923ce2c Merge pull request #234 from davidagraf/livereload
Livereload
2014-05-21 17:17:08 +02:00
David Graf b21fb24a82 gitbook-plugin-livereload dependency to npm 2014-05-21 16:35:55 +02:00
David Graf e7be132194 Merge branch 'master' into livereload 2014-05-21 16:24:07 +02:00
Samy Pessé 0e1717f4bb Improve grammar (thanks to @theoutlander ) 2014-05-21 10:46:26 +02:00
Aaron O'Mullan 276dbe29c7 Bump version to 0.4.5 2014-05-20 23:29:39 -07:00
Aaron O'Mullan 21fd5924b8 Fix generate failing on README parsing
Failed if no title or description could be extracted
2014-05-20 23:29:06 -07:00
David Graf 7c65adc9b2 disable cache manifest import if cache is disabled 2014-05-15 12:07:51 +02:00
David Graf 9b96ef9bae added livereload dependency 2014-05-15 11:41:59 +02:00
David Graf e97d1941dc Introducing livereload server 2014-05-15 08:09:02 +02:00
David Graf 0b0ac46e34 Introducing option to disable cache manifest generation 2014-05-15 08:07:24 +02:00
David Graf 622bbcb8ea ignore vim swap files 2014-05-15 07:43:59 +02:00
36 changed files with 264 additions and 188 deletions
+4 -1
View File
@@ -24,4 +24,7 @@ build/Release
# see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git
node_modules
theme/javascript/vendors
theme/javascript/vendors
# vim swapfile
*.swp
+20 -20
View File
@@ -3,7 +3,7 @@ GitBook
[![Build Status](https://travis-ci.org/GitbookIO/gitbook.png?branch=master)](https://travis-ci.org/GitbookIO/gitbook)
GitBook is a command line tool (and Node.js library) for building beautiful books and exercises using GitHub/Git and Markdown. You can see an example: [Learn Javascript](https://www.gitbook.io/book/GitBookIO/javascript). An [editor](https://github.com/GitbookIO/editor) is available for Windows, Mac and Linux. You can follow [@GitBookIO](https://twitter.com/GitBookIO) on Twitter.
GitBook is a command line tool (and Node.js library) for building beautiful books and exercises using GitHub/Git and Markdown. You can see an example: [Learn Javascript](https://www.gitbook.io/book/GitBookIO/javascript). An [editor](https://github.com/GitbookIO/editor) is available for Windows, Mac and Linux. You can follow [@GitBookIO](https://twitter.com/GitBookIO) on Twitter. Complete documentation is available at [help.gitbook.io](http://help.gitbook.io/).
![Image](https://raw.github.com/GitbookIO/gitbook/master/preview.png)
@@ -35,23 +35,23 @@ Options for commands `build` and `serve` are:
--config <config file> Configuration file to use, defaults to book.json
```
GitBook load the default configuration from a `book.json` file in the repository if it exists.
GitBook loads the default configuration from a `book.json` file in the repository if it exists.
Here are the options that can be stored in this file:
```
{
// Folders to use for output (caution: it override the value from the command line)
// Folders to use for output (caution: it overrides the value from the command line)
"output": null,
// Generator to use for building (caution: it override the value from the command line)
// Generator to use for building (caution: it overrides the value from the command line)
"generator": "site",
// Book title and description (defaults are extracted from the README)
"title": null,
"description": null,
// GitHub informations (defaults are extracted using git)
// GitHub information (defaults are extracted using git)
"github": null,
"githubHost": "https://github.com/",
@@ -67,9 +67,9 @@ Here are the options that can be stored in this file:
}
},
// 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
// 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
"theme": "./localtheme",
// Links in template (null: default, false: remove, string: new value)
@@ -98,11 +98,11 @@ You can publish your books to our index by visiting [GitBook.io](http://www.gitb
GitBook can generate your book in the following formats:
* **Static Website**: This is the default format, it generates a complete interactive static website that can be for example hosted on GitHub Pages.
* **PDF**: A complete PDF book with exercise solutions at the end of the book. Generate to this format using: ```gitbook pdf ./myrepo```, you need to have [gitbook-pdf](https://github.com/GitbookIO/gitbook-pdf) installed.
* **eBook**: A complete eBook with exercise solutions at the end of the book. Generate to this format using: ```gitbook ebook ./myrepo```, you need to have [ebook-convert](http://manual.calibre-ebook.com/cli/ebook-convert.html) installed.
* **Single Page**: The book will be stored in a single printable HTML page, this format is used for conversion to PDF or eBook. Generate to this format using: ```gitbook build ./myrepo -f page```.
* **JSON**: This format is used for debugging or extracting metadata from a book. Generate to this format using: ```gitbook build ./myrepo -f json```.
* **Static Website**: This is the default format. It generates a complete interactive static website that can be, for example, hosted on GitHub Pages.
* **PDF**: A complete PDF book with exercise solutions at the end of the book. Generate this format using: ```gitbook pdf ./myrepo```. You need to have [gitbook-pdf](https://github.com/GitbookIO/gitbook-pdf) installed.
* **eBook**: A complete eBook with exercise solutions at the end of the book. Generate this format using: ```gitbook ebook ./myrepo```. You need to have [ebook-convert](http://manual.calibre-ebook.com/cli/ebook-convert.html) installed.
* **Single Page**: The book will be stored in a single printable HTML page. This format is used for conversion to PDF or eBook. Generate this format using: ```gitbook build ./myrepo -f page```.
* **JSON**: This format is used for debugging or extracting metadata from a book. Generate this format using: ```gitbook build ./myrepo -f json```.
## Book Format
@@ -110,7 +110,7 @@ A book is a Git repository containing at least 2 files: `README.md` and `SUMMARY
#### README.md
As usual, it should contains an introduction for your book. It will be automatically added to the final summary.
Typically, this should be the introduction for your book. It will be automatically added to the final summary.
#### SUMMARY.md
@@ -130,11 +130,11 @@ This is the summary of my book.
* [example 1](section2/example1.md)
```
Files that are not included in the `SUMMARY.md` will not be processed by `gitbook`.
Files that are not included in `SUMMARY.md` will not be processed by `gitbook`.
#### Exercises
A book can contain interactive exercises (currently only in Javascript but Python and Ruby are coming soon ;) ). An exercise is a code challenge provided to the reader, which is given a code editor to write a solution which is checked against the book author's validation code.
A book can contain interactive exercises (currently only in Javascript but Python and Ruby are coming soon ;) ). An exercise is a code challenge provided to the reader, who is given a code editor to write a solution which is checked against the book author's validation code.
An exercise is defined by 4 simple parts:
@@ -143,7 +143,7 @@ An exercise is defined by 4 simple parts:
* **Solution** code, being a correct solution to the exercise
* **Validation** code that tests the correctness of the user's input
Exercises need to start and finish with a separation bar (```---``` or ```***```). It should contain 3 code elements (**base**, **solution** and **validation**). It can contain a 4th element that provides **context** code (functions, imports of libraries etc ... that shouldn't be displayed to the user).
Exercises need to start and finish with a separation bar (```---``` or ```***```). It should contain 3 code elements (**base**, **solution** and **validation**). It can contain a 4th element that provides **context** code (functions, imports of libraries, etc which shouldn't be displayed to the user).
---
@@ -185,7 +185,7 @@ You can see a complete example with the [Learn Git](https://github.com/GitbookIO
#### Ignoring files & folders
GitBook will read the `.gitignore`, `.bookignore` and `.ignore` files to get a list of files and folders to skip. (The format inside those files, follows the same convention as `.gitignore`)
GitBook will read the `.gitignore`, `.bookignore` and `.ignore` files to get a list of files and folders to skip. (The format inside those files follows the same convention as `.gitignore`)
#### Cover
@@ -196,11 +196,11 @@ A small version of the cover can also be set by creating a file: **/cover_small.
#### Publish your book
The platform [GitBook.io](https://www.gitbook.io/) is like an "Heroku for books", you can create a book on it (public, paid, or private) and update it using **git push**.
The platform [GitBook.io](https://www.gitbook.io/) is like an "Heroku for books": you can create a book on it (public, paid, or private) and update it using **git push**.
#### 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 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.
##### Default plugins:
+22 -2
View File
@@ -4,6 +4,7 @@ var Q = require('q');
var _ = require('lodash');
var path = require('path');
var prog = require('commander');
var tinylr = require('tiny-lr-fork');
var pkg = require('../package.json');
var generators = require("../lib/generate").generators;
@@ -29,12 +30,24 @@ build.command(prog.command('serve [source_dir]'))
.action(function(dir, options) {
var server = new Server();
// init livereload server
var lrOptions = {port: 35729};
var lrServer = tinylr(lrOptions);
var lrPath = undefined;
lrServer.listen(lrOptions.port, function(err) {
if (err) { return console.log(err); }
console.log('Live reload server started on port: ' + lrOptions.port);
});
var generate = function() {
if (server.isRunning()) console.log("Stopping server");
server.stop()
.then(function() {
return build.folder(dir, options);
return build.folder(dir, _.extend(options || {}, {
cache: false,
defaultsPlugins: ["livereload"]
}));
})
.then(function(_options) {
console.log();
@@ -43,9 +56,16 @@ build.command(prog.command('serve [source_dir]'))
.then(function() {
console.log('Serving book on http://localhost:'+options.port);
if (lrPath) {
// trigger livereload
lrServer.changed({body:{files:[lrPath]}})
}
if (!options.watch) return;
return utils.watch(_options.input)
.then(function(filepath) {
// set livereload path
lrPath = filepath;
console.log("Restart after change in files");
console.log('');
return generate();
@@ -72,7 +92,7 @@ build.command(prog.command('pdf [source_dir]'))
build.command(prog.command('ebook [source_dir]'))
.description('Build a gitbook as a eBook')
.option('-c, --cover <path>', 'Cover image, default is cover.png if exists')
.option('-c, --cover <path>', 'Cover image, default is cover.jpg if exists')
.action(function(dir, options) {
var ext = options.output ? path.extname(options.output) : "epub";
+4 -4
View File
@@ -19,10 +19,6 @@ var Generator = function() {
this.options = _.defaults(this.options, {
extension: "epub"
});
if (!this.options.cover && fs.existsSync(path.join(this.options.input, "cover.png"))) {
this.options.cover = path.join(this.options.input, "cover.png")
}
};
util.inherits(Generator, BaseGenerator);
@@ -33,6 +29,10 @@ Generator.prototype.finish = function() {
.then(function() {
var d = Q.defer();
if (!that.options.cover && fs.existsSync(path.join(that.options.output, "cover.jpg"))) {
that.options.cover = path.join(that.options.output, "cover.jpg");
}
var _options = {
"--cover": that.options.cover
};
+1
View File
@@ -9,6 +9,7 @@ var BaseGenerator = function(options) {
this.options = options;
this.options.plugins = Plugin.normalizeNames(this.options.plugins);
this.options.plugins = _.union(this.options.plugins, this.options.defaultsPlugins);
this.plugins = [];
};
+17 -16
View File
@@ -64,6 +64,7 @@ var generate = function(options) {
// Plugins
"plugins": [],
"pluginsConfig": {},
"defaultsPlugins": [], // Default plugins that can't be set in book.json
// Links
"links": {
@@ -86,6 +87,21 @@ var generate = function(options) {
// Check files to get folder type (book, multilanguage book or neither)
return Q()
// Read config file
.then(function() {
return fs.readFile(path.resolve(options.input, options.configFile))
.then(function(_config) {
// Extend current config
_config = JSON.parse(_config);
_config = _.omit(_config, 'input', 'configFile', 'defaultsPlugins');
_.extend(options, _config);
}, function() {
// No config file: not a big deal
return Q();
});
})
// Read readme
.then(function() {
return fs.readFile(path.join(options.input, "README.md"), "utf-8")
@@ -177,21 +193,6 @@ var generateBook = function(options) {
}
})
// Read config file
.then(function() {
return fs.readFile(path.resolve(options.input, options.configFile))
.then(function(_config) {
// Extend current config
_config = JSON.parse(_config);
_config = _.omit(_config, 'input', 'configFile');
_.extend(options, _config);
}, function() {
// No config file: not a big deal
return Q();
});
})
// Clean output folder
.then(function() {
return fs.remove(options.output);
@@ -237,7 +238,7 @@ var generateBook = function(options) {
return loadGenerator(options);
})
// Detect multi-languages book
// Convert files
.then(function(generator) {
// Generate the book
return Q()
+17 -4
View File
@@ -1,6 +1,7 @@
var util = require("util");
var path = require("path");
var Q = require("q");
var _ = require("lodash");
var fs = require("../fs");
var parse = require("../../parse");
@@ -41,17 +42,29 @@ Generator.prototype.convertFile = function(content, input) {
};
// Generate languages index
// Contains the first languages readme and langs infos
Generator.prototype.langsIndex = function(langs) {
var that = this;
var json = {
langs: langs.list
};
if (langs.list.length == 0) return Q.reject("Need at least one language");
var mainLang = _.first(langs.list).lang;
console.log("Main language is", mainLang);
return Q()
.then(function() {
return fs.readFile(
path.join(that.options.output, mainLang, "README.json")
);
})
.then(function(content) {
var json = JSON.parse(content);
_.extend(json, {
langs: langs.list
});
return fs.writeFile(
path.join(that.options.output, "langs.json"),
path.join(that.options.output, "README.json"),
JSON.stringify(json, null, 4)
);
});
+16 -1
View File
@@ -160,6 +160,16 @@ Plugin.fromList = function(names, root) {
})
.object()
.value();
resources.html = {}
_.each(plugins, function(plugin) {
var html = plugin.infos.book.html || {};
_.each(html, function(code, key) {
if (!_.isFunction(code)) code = _.constant(code);
if (!resources.html[key]) resources.html[key] = [];
resources.html[key].push(code);
})
});
return Q({
'list': plugins,
@@ -179,6 +189,11 @@ Plugin.fromList = function(names, root) {
if (!withTpl) return null;
return withTpl.resolveFile(withTpl.infos.templates[name]);
},
'html': function(tag, context, options) {
return _.map(resources.html[tag] || [], function(code) {
return code.call(context, options);
}).join("\n");
}
});
};
@@ -189,4 +204,4 @@ Plugin.defaults = [
"mathjax"
];
module.exports = Plugin;
module.exports = Plugin;
+8 -3
View File
@@ -81,6 +81,7 @@ Generator.prototype._writeTemplate = function(tpl, options, output, interpolate)
plugins: that.plugins,
pluginsConfig: JSON.stringify(that.options.pluginsConfig),
htmlSnippet: _.partialRight(that.plugins.html, that, options),
options: that.options
}, options));
@@ -237,9 +238,13 @@ Generator.prototype.writeCacheManifest = function() {
};
Generator.prototype.finish = function() {
return this.copyAssets()
.then(this.writeSearchIndex)
.then(this.writeCacheManifest);
var deferred = this.copyAssets().then(this.writeSearchIndex);
if (this.options.cache !== false) {
deferred = deferred.then(this.writeCacheManifest);
}
return deferred;
};
module.exports = Generator;
+1 -1
View File
@@ -8,7 +8,7 @@ function clean(obj) {
function flattenChapters(chapters) {
return _.reduce(chapters, function(accu, chapter) {
return accu.concat([clean(chapter)].concat(chapter.articles));
return accu.concat([clean(chapter)].concat(flattenChapters(chapter.articles)));
}, []);
}
+2 -2
View File
@@ -12,7 +12,7 @@ var calculProgress = function(navigation, current) {
return nav;
})
.sortBy(function(nav) {
return nav.level;
return parseFloat(nav.level);
})
.map(function(nav, i) {
// Calcul percent
@@ -27,7 +27,7 @@ var calculProgress = function(navigation, current) {
} else if (done) {
prevPercent = nav.percent;
}
return nav;
})
.value();
+7 -5
View File
@@ -20,16 +20,18 @@ function parseReadme(src) {
// Parse content
nodes = marked.lexer(src);
var title = extractFirstNode(nodes, "heading");
var description = extractFirstNode(nodes, "paragraph");
title = extractFirstNode(nodes, "heading") || '';
description = extractFirstNode(nodes, "paragraph") || '';
var convert = _.compose(
function(text) {
return _.unescape(text.replace(/(\r\n|\n|\r)/gm, ""));
},
_.partialRight(marked, _.extend({}, marked.defaults, {
renderer: renderer
}))
function(text) {
return marked.parse(text, _.extend({}, marked.defaults, {
renderer: renderer
}));
}
);
return {
+8 -8
View File
@@ -86,13 +86,11 @@ function parseTitle(src, nums) {
};
}
function parseArticle(chapterNum, nodes, idx) {
return parseTitle(_.first(nodes).text, [chapterNum, idx+1]);
}
function parseChapter(nodes, idx) {
return _.extend(parseTitle(_.first(nodes).text, [idx+1]), {
articles: _.map(listSplit(filterList(nodes), 'list_item_start', 'list_item_end'), parseArticle.bind(null, idx+1))
function parseChapter(nodes, nums) {
return _.extend(parseTitle(_.first(nodes).text, nums), {
articles: _.map(listSplit(filterList(nodes), 'list_item_start', 'list_item_end'), function(nodes, i) {
return parseChapter(nodes, nums.concat(i + 1));
})
});
}
@@ -104,7 +102,9 @@ function parseSummary(src) {
// Split out chapter sections
var chapters = _.chain(listSplit(chapterList, 'list_item_start', 'list_item_end'))
.map(parseChapter)
.map(function(nodes, i) {
return parseChapter(nodes, [i + 1]);
})
.value();
return {
+4
View File
@@ -19,6 +19,10 @@ var toAbsolute = function(_href, dir, outdir) {
// make it relative to output
_href = path.relative(outdir, _href);
if (process.platform === 'win32') {
_href = _href.replace(/\\/g, '/');
}
return _href;
};
+4 -3
View File
@@ -1,6 +1,6 @@
{
"name": "gitbook",
"version": "0.4.4",
"version": "0.4.7",
"homepage": "http://www.gitbook.io/",
"description": "Library and cmd utility to generate GitBooks",
"main": "lib/index.js",
@@ -20,10 +20,11 @@
"semver": "2.2.1",
"gaze": "~0.5.1",
"resolve": "0.6.3",
"tiny-lr-fork": "0.0.5",
"gitbook-plugin": "0.0.2",
"gitbook-plugin-mixpanel": "0.0.2",
"gitbook-plugin-mathjax": "0.0.3"
"gitbook-plugin-mathjax": "0.0.3",
"gitbook-plugin-livereload": "0.0.1"
},
"devDependencies": {
"mocha": "1.18.2",
+2
View File
@@ -3,6 +3,8 @@
* [Chapter 1](chapter-1/README.md)
* [Article 1](chapter-1/ARTICLE1.md)
* [Article 2](chapter-1/ARTICLE2.md)
* [article 1.2.1](chapter-1/ARTICLE-1-2-1.md)
* [article 1.2.2](chapter-1/ARTICLE-1-2-2.md)
* [Chapter 2](chapter-2/README.md)
* [Chapter 3](chapter-3/README.md)
* [Chapter 4](chapter-4/README.md)
+12 -2
View File
@@ -18,6 +18,8 @@ describe('Summary navigation', function() {
'chapter-1/ARTICLE1.md',
'chapter-1/ARTICLE2.md',
'chapter-2/README.md',
'chapter-1/ARTICLE-1-2-1.md',
'chapter-1/ARTICLE-1-2-2.md'
]);
// Make sure it found the files we gave it
@@ -26,6 +28,8 @@ describe('Summary navigation', function() {
assert(nav['chapter-1/ARTICLE1.md']);
assert(nav['chapter-1/ARTICLE2.md']);
assert(nav['chapter-2/README.md']);
assert(nav['chapter-1/ARTICLE-1-2-1.md']);
assert(nav['chapter-1/ARTICLE-1-2-2.md']);
assert.equal(nav['README.md'].prev, null);
@@ -38,9 +42,15 @@ describe('Summary navigation', function() {
assert.equal(nav['chapter-1/ARTICLE1.md'].next.path, 'chapter-1/ARTICLE2.md');
assert.equal(nav['chapter-1/ARTICLE2.md'].prev.path, 'chapter-1/ARTICLE1.md');
assert.equal(nav['chapter-1/ARTICLE2.md'].next.path, 'chapter-2/README.md');
assert.equal(nav['chapter-1/ARTICLE2.md'].next.path, 'chapter-1/ARTICLE-1-2-1.md');
assert.equal(nav['chapter-2/README.md'].prev.path, 'chapter-1/ARTICLE2.md');
assert.equal(nav['chapter-1/ARTICLE-1-2-1.md'].prev.path, 'chapter-1/ARTICLE2.md');
assert.equal(nav['chapter-1/ARTICLE-1-2-1.md'].next.path, 'chapter-1/ARTICLE-1-2-2.md');
assert.equal(nav['chapter-1/ARTICLE-1-2-2.md'].prev.path, 'chapter-1/ARTICLE-1-2-1.md');
assert.equal(nav['chapter-1/ARTICLE-1-2-2.md'].next.path, 'chapter-2/README.md');
assert.equal(nav['chapter-2/README.md'].prev.path, 'chapter-1/ARTICLE-1-2-2.md');
assert.equal(nav['chapter-2/README.md'].next.path, 'chapter-3/README.md');
});
+1
View File
@@ -50,5 +50,6 @@ describe('Summary parsing', function () {
assert.equal(c[0].articles[0].level, '1.1');
assert.equal(c[0].articles[1].level, '1.2');
assert.equal(c[0].articles[1].articles[0].level, '1.2.1');
});
});
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+20 -25
View File
@@ -30,40 +30,23 @@ define([
};
var enlargeFontSize = function(e){
var $bookBody = $(".book-body");
if (fontState.size < 4){
$bookBody.toggleClass("font-size-"+fontState.size, false);
fontState.size++;
$bookBody.toggleClass("font-size-"+fontState.size, true);
fontState.save();
}
};
var reduceFontSize = function(e){
var $bookBody = $(".book-body");
if (fontState.size > 0){
$bookBody.toggleClass("font-size-"+fontState.size);
fontState.size--;
$bookBody.toggleClass("font-size-"+fontState.size);
fontState.save();
}
};
var changeFontFamily = function(){
var $bookBody = $(".book-body");
var index = $(this).data("font");
$bookBody.toggleClass("font-family-"+fontState.family);
$(".font-settings .font-family-list li:nth-child("+(fontState.family+1)+")")
.removeClass("active");
fontState.family = index;
$bookBody.toggleClass("font-family-"+fontState.family);
$(this).addClass("active");
fontState.save();
};
@@ -81,6 +64,22 @@ define([
fontState.save();
};
var update = function() {
var $book = $(".book");
$(".font-settings .font-family-list li").removeClass("active");
$(".font-settings .font-family-list li:nth-child("+(fontState.family+1)+")").addClass("active");
$book[0].className = $book[0].className.replace(/\bfont-\S+/g, '');
$book.addClass("font-size-"+fontState.size);
$book.addClass("font-family-"+fontState.family);
if(fontState.theme !== 0) {
$book[0].className = $book[0].className.replace(/\bcolor-theme-\S+/g, '');
$book.addClass("color-theme-"+fontState.theme);
}
};
var init = function(config) {
var $toggle, $bookBody, $dropdown, $book;
@@ -98,15 +97,10 @@ define([
});
fontState.save = function(){
storage.set("fontState",fontState);
update();
};
$bookBody.addClass("font-size-"+fontState.size);
$bookBody.addClass("font-family-"+fontState.family);
$(".font-settings .font-family-list li:nth-child("+(fontState.family+1)+")").addClass("active");
if(fontState.theme !== 0)
$book.addClass("color-theme-"+fontState.theme);
update();
//Add event listeners
$(document).on('click', "#enlarge-font-size", enlargeFontSize);
@@ -121,6 +115,7 @@ define([
};
return {
init: init
init: init,
update: update
}
});
+2 -4
View File
@@ -2,11 +2,9 @@ define([
"jQuery"
], function($) {
var showLoading = function(p) {
var $book = $(".book");
$book.addClass("is-loading");
$(".book").addClass("is-loading");
p.always(function() {
$book.removeClass("is-loading");
$(".book").removeClass("is-loading");
});
return p;
+3 -5
View File
@@ -3,12 +3,11 @@ define([
"utils/url",
"core/events",
"core/state",
"core/search",
"core/progress",
"core/exercise",
"core/quiz",
"core/loading"
], function($, URL, events, state, search, progress, exercises, quiz, loading) {
], function($, URL, events, state, progress, exercises, quiz, loading) {
var prev, next;
var githubCountStars, githubCountWatch;
@@ -47,10 +46,12 @@ define([
$("head").html(headContent);
// Merge body
var bodyClass = $(".book").attr("class");
var scrollPosition = $('.book-summary .summary').scrollTop();
$pageBody.toggleClass("with-summary", $(".book").hasClass("with-summary"))
$(".book").replaceWith($pageBody);
$(".book").attr("class", bodyClass);
$('.book-summary .summary').scrollTop(scrollPosition);
// Update state
@@ -94,9 +95,6 @@ define([
// Focus on content
$pageWrapper.focus();
// Prepare search bar
search.prepare();
// Update GitHub count
if (state.githubId) {
if (githubCountStars) {
+5 -8
View File
@@ -67,12 +67,10 @@ define([
e.preventDefault();
toggleSearch();
});
};
var prepare = function() {
var $searchInput = $(".book-search input");
$searchInput.keyup(function(e) {
// Type in search bar
$(document).on("keyup", ".book-search input", function(e) {
var key = (e.keyCode ? e.keyCode : e.which);
var q = $(this).val();
@@ -89,13 +87,12 @@ define([
_.pluck(results, "path")
);
}
});
}
})
};
return {
init: init,
search: search,
toggle: toggleSearch,
prepare: prepare
toggle: toggleSearch
};
});
+4 -4
View File
@@ -1,11 +1,10 @@
define([
"jQuery",
"lodash",
"utils/storage",
"utils/platform",
"core/state"
], function(_, storage, platform, state) {
var $summary = state.$book.find(".book-summary");
], function($, _, storage, platform, state) {
// Toggle sidebar with or withour animation
var toggleSidebar = function(_state, animation) {
if (state != null && isOpen() == _state) return;
@@ -38,6 +37,8 @@ define([
// Filter summary with a list of path
var filterSummary = function(paths) {
var $summary = $(".book-summary");
$summary.find("li").each(function() {
var path = $(this).data("path");
var st = paths == null || _.contains(paths, path);
@@ -48,7 +49,6 @@ define([
};
return {
$el: $summary,
init: init,
toggle: toggleSidebar,
filter: filterSummary
+33 -22
View File
@@ -59,28 +59,6 @@
min-height: calc(~"100% - 57px")
}
}
&.font-size-0{
font-size:@s-font-size;
}
&.font-size-1{
font-size:@m-font-size;
}
&.font-size-2{
font-size:@l-font-size;
}
&.font-size-3{
font-size:@xl-font-size;
}
&.font-size-4{
font-size:@xxl-font-size;
}
&.font-family-0{
font-family: @font-family-serif;
}
&.font-family-1{
font-family: @font-family-sans;
}
}
&.with-summary {
@@ -122,4 +100,37 @@
}
}
}
&.font-size-0 {
.book-body {
font-size:@s-font-size;
}
}
&.font-size-1 {
.book-body {
font-size:@m-font-size;
}
}
&.font-size-2 {
.book-body {
font-size:@l-font-size;
}
}
&.font-size-3 {
.book-body {
font-size:@xl-font-size;
}
}
&.font-size-4 {
.book-body {
font-size:@xxl-font-size;
}
}
&.font-family-0{
font-family: @font-family-serif;
}
&.font-family-1{
font-family: @font-family-sans;
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
.book .book-body .page-wrapper .page-inner {
section.exercise {
padding: 0px;
margin: 20px 0px;
margin: 20px 15px;
border: 3px solid #2f8cde;
.header {
+1
View File
@@ -24,6 +24,7 @@
padding-bottom: 25px;
padding-top: 15px;
color:@page-color;
letter-spacing: 0.01rem;
& > *:first-child {
margin-top: 0 !important; }
+2 -4
View File
@@ -13,15 +13,15 @@
flex-direction: column;
font-size: 40px;
color: rgba(0,0,0,0.5);
color: rgba(0,0,0,0.4);
text-align: center;
.transition(all 350ms ease);
&:hover {
background-color: @body-pagination-background;
text-decoration: none;
color: rgba(0,0,0,0.6);
}
&.navigation-next {
@@ -50,11 +50,9 @@
}
.book.color-theme-1 .book-body {
.navigation:hover{
background-color: @body-pagination-background-1;
}
}
.book.color-theme-2 .book-body {
.navigation:hover{
background-color: @body-pagination-background-2;
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
.book .book-body .page-wrapper .page-inner {
section.quiz {
padding: 0px;
margin: 20px 0px;
margin: 20px 15px;
border: 3px solid #2f8cde;
.header {
-1
View File
@@ -90,7 +90,6 @@
overflow: hidden;
white-space: nowrap;
position: relative;
padding-left: 25px;
}
span {
+7 -10
View File
@@ -13,7 +13,6 @@
// Body
@body-background: white;
@body-pagination-background: hsl(207, 15%, 95%);
// Sidebar
@sidebar-width: 250px;
@@ -21,7 +20,7 @@
@sidebar-color: hsl(207, 15%, 80%);
@sidebar-background: hsl(207, 15%, 95%);
@sidebar-nested-padding: 10px;
@sidebar-nested-padding: 20px;
@sidebar-search-padding: 6px;
@sidebar-search-background: transparent;
@@ -91,12 +90,12 @@
@xl-font-size: 2.2rem;
@xxl-font-size: 4.0rem;
/*
,--------.,--.
'--. .--'| ,---. ,---. ,--,--,--. ,---. ,---. .--.
| | | .-. || .-. :| || .-. :( .-' '--'
| | | | | |\ --.| | | |\ --..-' `).--.
`--' `--' `--' `----'`--`--`--' `----'`----' '--'
/*
,--------.,--.
'--. .--'| ,---. ,---. ,--,--,--. ,---. ,---. .--.
| | | .-. || .-. :| || .-. :( .-' '--'
| | | | | |\ --.| | | |\ --..-' `).--.
`--' `--' `--' `----'`--`--`--' `----'`----' '--'
*/
// Header
@header-color-1: #AFA790;
@@ -113,8 +112,6 @@
// Body
@body-background-1: #F3EACB;
@body-background-2: #1d1f21;
@body-pagination-background-1: #FFFAEA;
@body-pagination-background-2: #33404D;
// Sidebar
@sidebar-color-1: #AFA790;
+1 -1
View File
@@ -1,9 +1,9 @@
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
{% if options.links.home !== false and (options.links.home != null or githubId) %}
<a href="{{ options.links.home|default(githubHost+githubId) }}" target="_blank" class="btn pull-left home-bookmark" aria-label="GitHub home"><i class="fa fa-bookmark-o"></i></a>
{% endif %}
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
<a href="#" class="btn pull-left toggle-search" aria-label="Toggle search"><i class="fa fa-search"></i></a>
<span id="font-settings-wrapper">
<a href="#" class="btn pull-left toggle-font-settings" aria-label="Toggle font settings"><i class="fa fa-font"></i>
+25 -27
View File
@@ -1,59 +1,57 @@
{% macro articles(_articles) %}
{% for item in _articles %}
<li class="chapter {% if item._path == _input %}active{% endif %}" data-level="{{ item.level }}" {% if item.path %}data-path="{{ item.path|mdLink }}"{% endif %}>
{% if item.path %}
<a href="{{ basePath }}/{{ item.path|mdLink }}">
<i class="fa fa-check"></i> <b>{{ item.level }}.</b> {{ item.title }}
</a>
{% else %}
<span><b>{{ item.level }}.</b> {{ item.title }}</span>
{% endif %}
{% if item.articles.length > 0 %}
<ul class="articles">
{{ articles(item.articles) }}
</ul>
{% endif %}
</li>
{% endfor %}
{% endmacro %}
<div class="book-summary">
<div class="book-search">
<input type="text" placeholder="Search" class="form-control" />
</div>
<ul class="summary">
{% set _divider = false %}
{% if options.links.about !== false && (options.links.about || githubId) %}
{% set _divider = true %}
<li>
<a href="{{ options.links.about|default(githubHost+githubAuthor) }}" target="blank" class="author-link">About the author</a>
</li>
{% endif %}
{% if options.links.issues !== false && (options.links.issues || githubId) %}
{% set _divider = true %}
<li>
<a href="{{ options.links.issues|default(githubHost+githubId+"/issues") }}" target="blank"class="issues-link">Questions and Issues</a>
</li>
{% endif %}
{% if options.links.contribute !== false && (options.links.contribute || githubId) %}
{% set _divider = true %}
<li>
<a href="{{ options.links.contribute|default(githubHost+githubId+"/edit/master/"+_input) }}" target="blank" class="contribute-link">Edit and Contribute</a>
</li>
{% endif %}
{% if options.links.contribute || options.links.issues || options.links.about %}
{% if _divider %}
<li class="divider"></li>
{% endif %}
<li data-level="0" data-path="index.html">
<a href="{{ basePath }}/"><i class="fa fa-check"></i> Introduction</a>
</li>
{% for item in summary.chapters %}
<li class="chapter {% if item._path == _input %}active{% endif %}" data-level="{{ item.level }}" {% if item.path %}data-path="{{ item.path|mdLink }}"{% endif %}>
{% if item.path %}
<a href="{{ basePath }}/{{ item.path|mdLink }}">
<i class="fa fa-check"></i> <b>{{ item.level }}.</b> {{ item.title }}
</a>
{% else %}
<span><b>{{ item.level }}.</b> {{ item.title }}</span>
{% endif %}
{% if item.articles.length > 0 %}
<ul class="articles">
{% for article in item.articles %}
<li {% if article._path == _input %}class="active"{% endif %} data-level="{{ article.level }}" {% if article.path %}data-path="{{ article.path|mdLink }}"{% endif %}>
{% if article.path %}
<a href="{{ basePath }}/{{ article.path|mdLink }}">
<i class="fa fa-check"></i> <b>{{ article.level }}.</b> {{ article.title }}
</a>
{% else %}
<span><b>{{ article.level }}.</b> {{ article.title }}</span>
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
</li>
{% endfor %}
{{ articles(summary.chapters) }}
{% if options.links.gitbook !== false %}
<li class="divider"></li>
+6
View File
@@ -1,6 +1,8 @@
<!DOCTYPE HTML>
<html lang="en-US" {% block htmlTag %}{% endblock %}>
{{ htmlSnippet("html:start")|default("") }}
<head prefix="og: http://ogp.me/ns# book: http://ogp.me/ns/book#">
{{ htmlSnippet("head:start")|default("") }}
{% block head %}
<meta charset="UTF-8">
<title>{% block title %} | {{ title }}{% endblock %}</title>
@@ -33,8 +35,10 @@
<link rel="shortcut icon" href="{{ staticBase }}/images/favicon.ico" type="image/x-icon">
{% endblock %}
{{ htmlSnippet("head:end")|default("") }}
</head>
<body>
{{ htmlSnippet("body:start")|default("") }}
{% block style %}
<link rel="stylesheet" href="{{ staticBase }}/style.css">
{% endblock %}
@@ -45,5 +49,7 @@
<script src="{{ staticBase }}/jsrepl/jsrepl.js" id="jsrepl-script"></script>
<script src="{{ staticBase }}/app.js"></script>
{% endblock %}
{{ htmlSnippet("body:end")|default("") }}
</body>
{{ htmlSnippet("html:end")|default("") }}
</html>
+1 -1
View File
@@ -1,6 +1,6 @@
{% extends "layout.html" %}
{% block htmlTag %}manifest="{{ basePath }}/manifest.appcache"{% endblock %}
{% block htmlTag %}{% if options.cache !== false %}manifest="{{ basePath }}/manifest.appcache"{% endif %}{% endblock %}
{% block title %}{{ progress.current.title }}{% parent %}{% endblock %}
{% block content %}
<div class="book" {% if githubId %}data-github="{{ githubId }}"{% endif %} data-level="{{ progress.current.level }}" data-basepath="{{ basePath }}" data-revision="{{ revision }}">