Compare commits

...

37 Commits

Author SHA1 Message Date
Samy Pessé 65319e8fd6 Bump version to 0.5.0 2014-06-03 22:30:42 +02:00
Samy Pessé 55db44a3b4 Fix #289: center images on ebook 2014-06-03 22:20:51 +02:00
Samy Pessé 13b6045300 Font Merriweather 600 doesn't exists 2014-06-03 20:45:55 +02:00
Samy Pessé b7ff879c31 Remove fonts Anonymous Pro and EB Garamond 2014-06-03 20:43:47 +02:00
Samy Pessé 57ade87fe1 Fix #275: fix emphasized font path 2014-06-03 20:30:04 +02:00
Samy Pessé 907e9ea5a7 Improve font on title
Set sans-serif as default
2014-06-03 20:14:44 +02:00
Samy Pessé 215488dc45 Improve design (more flat) 2014-06-03 18:43:13 +02:00
Samy Pessé a195b3eac2 Improve less files organisation 2014-06-03 18:11:03 +02:00
Samy Pessé 77c6f0e967 Merge pull request #291 from bebraw/book.js
Allow book.js to be used in addition to book.json
2014-06-03 17:20:26 +02:00
Juho Vepsalainen f0e18afec1 In case there's no config file, do not fail 2014-06-03 17:59:26 +03:00
Juho Vepsalainen b6d11d88b7 Allow book.js to be used in addition to book.json
Now it's possible to comment configuration properly and do some dynamic
things if needed.

Closes #287.
2014-06-03 17:42:30 +03:00
Samy Pessé c803270af8 Add option pdf.pageNumber
Fix GitbookIO/editor#38
2014-06-03 16:24:35 +02:00
Samy Pessé 5d51263a58 Remove mixpanel as a default addon 2014-06-03 15:29:15 +02:00
Samy Pessé 7e30720b2c Merge pull request #292 from bebraw/typofix
Fix build success message typo
2014-06-03 15:07:29 +02:00
Juho Vepsalainen 771c5e8b68 Fix build success message typo 2014-06-03 15:58:22 +03:00
Samy Pessé 8f53afab6b Fix #286: fix doc about formats 2014-06-02 20:12:56 +02:00
Samy Pessé 0ad0403d41 Merge pull request #283 from GitbookIO/feature/pdfoptions
Add more options for PDF
2014-06-02 18:22:07 +02:00
Samy Pessé 2515c1dd73 Remove useless command "gitbook ebook" 2014-06-02 18:17:02 +02:00
Samy Pessé 7dfcd102dd Fix calcul of output format for ebook 2014-06-02 18:16:44 +02:00
Samy Pessé a91245d575 Add options paperSize and margin for pdf 2014-06-02 17:57:47 +02:00
Samy Pessé 5f207f5e14 Add options pdf.toc and pdf.fontSize 2014-06-02 17:49:05 +02:00
Samy Pessé 718692de3b Langs index page now use direct link to html file 2014-06-02 14:49:40 +02:00
Samy Pessé 9856a51255 Fix #282: stop generation of langs index for page format 2014-06-02 14:13:52 +02:00
Samy Pessé 58eaaf5514 Fix error when plugin don't extend book 2014-06-02 12:51:22 +02:00
Samy Pessé c0ae0138f8 Improve documentation about book.json 2014-06-02 11:41:16 +02:00
Samy Pessé b1b9dc5b0a Fix error during generation 2014-06-02 11:37:25 +02:00
Samy Pessé f85c5a6498 Add error message when generator is invalid
Fixes #276, #277
2014-06-02 11:32:09 +02:00
Aaron O'Mullan 32eafefc45 Bump version to 0.4.8 2014-05-29 16:36:56 -07:00
Aaron O'Mullan 336999a34e Set default pdf font size to 12 2014-05-29 15:57:56 -07:00
Samy Pessé 1bf5f3b984 Force paper format to A4 fro pdf 2014-05-30 00:33:35 +02:00
Samy Pessé c76d070237 Merge pull request #274 from emmanuel-keller/patch-1
Adding a new plugin (Piwik Open Analytics plugin)
2014-05-30 00:11:38 +02:00
Emmanuel Keller 8c7da1351f Adding a new plugin.
I Just published a first version of the Piwik Open Analytics plugin, on both GIT and NPM.
2014-05-29 23:31:38 +02:00
Samy Pessé 34588c6092 Add margin on pdf output 2014-05-29 18:53:08 +02:00
Samy Pessé 9f00bf8060 Add toc at the end of pdf 2014-05-29 18:33:05 +02:00
Samy Pessé f4a17b182f Improve ebook generation (toc, ...) 2014-05-29 18:28:09 +02:00
Samy Pessé 5c3b345fa6 Generate valid first level table of content for ebook 2014-05-29 17:28:18 +02:00
Samy Pessé 46321fffd9 Use ebook-convert for pdf generation 2014-05-29 17:07:03 +02:00
45 changed files with 311 additions and 425 deletions
+2 -2
View File
@@ -24,8 +24,8 @@ module.exports = function (grunt) {
optimization: 2
},
files: {
"theme/assets/style.css": "theme/stylesheets/main.less",
"theme/assets/print.css": "theme/stylesheets/print.less"
"theme/assets/style.css": "theme/stylesheets/website.less",
"theme/assets/print.css": "theme/stylesheets/ebook.less"
}
}
},
+43 -7
View File
@@ -31,26 +31,36 @@ Options for commands `build` and `serve` are:
```
-o, --output <directory> Path to output directory, defaults to ./_book
-f, --format <name> Change generation format, defaults to site, availables are: site, page, pdf, json
--config <config file> Configuration file to use, defaults to book.json
-f, --format <name> Change generation format, defaults to site, availables are: site, page, ebook, json
--config <config file> Configuration file to use, defaults to book.js or book.json
```
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:
```
```js
{
// Folders to use for output (caution: it overrides the value from the command line)
// Folders to use for output
// Caution: it overrides the value from the command line
// It's not advised this option in the book.json
"output": null,
// Generator to use for building (caution: it overrides the value from the command line)
// Generator to use for building
// Caution: it overrides the value from the command line
// It's not advised this option in the book.json
"generator": "site",
// Book title and description (defaults are extracted from the README)
"title": null,
"description": null,
// For ebook format, the extension to use for generation (default is detected from output extension)
// "epub", "pdf", "mobi"
// Caution: it overrides the value from the command line
// It's not advised this option in the book.json
"extension": null,
// GitHub information (defaults are extracted using git)
"github": null,
"githubHost": "https://github.com/",
@@ -88,6 +98,32 @@ Here are the options that can be stored in this file:
"facebook": null,
"twitter": null
}
},
// 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,
// Font size for the fiel content
"fontSize": 12,
// Paper size for the pdf
// Choices are [u’a0’, u’a1’, u’a2’, u’a3’, u’a4’, u’a5’, u’a6’, u’b0’, u’b1’, u’b2’, u’b3’, u’b4’, u’b5’, u’b6’, u’legal’, u’letter’]
"paperSize": "a4",
// Margin (in pts)
// Note: 72 pts equals 1 inch
"margin": {
"right": 62,
"left": 62,
"top": 36,
"bottom": 36
}
}
}
```
@@ -99,8 +135,7 @@ 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 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.
* **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. The output format could be **PDF**, **ePub** or **MOBI**.
* **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```.
@@ -217,3 +252,4 @@ Plugins can used to extend your book's functionality. Read [GitbookIO/plugin](ht
* [Revealable sections](https://github.com/mrpotes/gitbook-plugin-reveal): Reveal sections of the page using buttons made from the first title in each section
* [Markdown within HTML](https://github.com/mrpotes/gitbook-plugin-nestedmd): Process markdown within HTML blocks - allows custom layout options for individual pages
* [Bootstrap JavaScript plugins](https://github.com/mrpotes/gitbook-plugin-bootstrapjs): Use the [Bootstrap JavaScript plugins](http://getbootstrap.com/javascript) in your online GitBook
* [Piwik Open Analytics](https://github.com/emmanuel-keller/gitbook-plugin-piwik): Piwik Open Analytics tracking for your book
+9 -3
View File
@@ -12,10 +12,15 @@ var buildCommand = function(command) {
return command
.option('-o, --output <directory>', 'Path to output directory, defaults to ./_book')
.option('-f, --format <name>', 'Change generation format, defaults to site, availables are: '+_.keys(generators).join(", "))
.option('--config <config file>', 'Configuration file to use, defualt to book.json')
.option('--config <config file>', 'Configuration file to use, defaults to book.js or book.json')
};
var buildEbookCommand = function(command) {
return buildCommand(command)
.option('-c, --cover <path>', 'Cover image, default is cover.jpg if exists');
};
var makeBuildFunc = function(converter) {
return function(dir, options) {
dir = dir || process.cwd();
@@ -31,7 +36,7 @@ var makeBuildFunc = function(converter) {
})
)
.then(function(output) {
console.log("Successfuly built !");
console.log("Successfully built!");
return output;
}, utils.logError)
.fail(function() {
@@ -43,5 +48,6 @@ var makeBuildFunc = function(converter) {
module.exports = {
folder: makeBuildFunc(generate.folder),
file: makeBuildFunc(generate.file),
command: buildCommand
command: buildCommand,
commandEbook: buildEbookCommand
};
+14 -9
View File
@@ -80,24 +80,29 @@ build.command(prog.command('serve [source_dir]'))
generate();
});
build.command(prog.command('pdf [source_dir]'))
build.commandEbook(prog.command('pdf [source_dir]'))
.description('Build a gitbook as a PDF')
.option('-pf, --paperformat <format>', 'PDF paper format (default is A4): "5in*7.5in", "10cm*20cm", "A4", "Letter"')
.action(function(dir, options) {
build.file(dir, _.extend(options, {
extension: "pdf",
format: "pdf"
format: "ebook"
}));
});
build.command(prog.command('ebook [source_dir]'))
.description('Build a gitbook as a eBook')
.option('-c, --cover <path>', 'Cover image, default is cover.jpg if exists')
build.commandEbook(prog.command('epub [source_dir]'))
.description('Build a gitbook as a ePub book')
.action(function(dir, options) {
var ext = options.output ? path.extname(options.output) : "epub";
build.file(dir, _.extend(options, {
extension: ext,
extension: "epub",
format: "ebook"
}));
});
build.commandEbook(prog.command('mobi [source_dir]'))
.description('Build a gitbook as a Mobi book')
.action(function(dir, options) {
build.file(dir, _.extend(options, {
extension: "mobi",
format: "ebook"
}));
});
+37 -15
View File
@@ -7,6 +7,7 @@ var exec = require('child_process').exec;
var fs = require("fs");
var parse = require("../../parse");
var BaseGenerator = require("../page");
var stringUtils = require("../../utils/string");
/*
* This generator inherits from the single page generator
@@ -14,11 +15,6 @@ var BaseGenerator = require("../page");
*/
var Generator = function() {
BaseGenerator.apply(this, arguments);
// Options for eBook generation
this.options = _.defaults(this.options, {
extension: "epub"
});
};
util.inherits(Generator, BaseGenerator);
@@ -28,27 +24,53 @@ Generator.prototype.finish = function() {
return BaseGenerator.prototype.finish.apply(this)
.then(function() {
var d = Q.defer();
var format = that.options.extension || path.extname(that.options.output).replace("\.", "") || "pdf";
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
"--cover": that.options.cover,
"--title": that.options.title,
"--comments": that.options.description,
"--authors": that.options.author,
"--level1-toc": "descendant-or-self::*[contains(concat(' ', normalize-space(@class), ' '), ' book-chapter-1 ')]",
"--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 ')]"
};
if (format == "pdf") {
var pdfOptions = _.defaults(that.options.pdf || {}, {
"fontSize": 12,
"toc": true,
"pageNumbers": false,
"paperSize": "a4",
"margin": {
"right": 62,
"left": 62,
"top": 36,
"bottom": 36
}
});
_.extend(_options, {
"--margin-left": String(pdfOptions.margin.left),
"--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),
"--paper-size": String(pdfOptions.paperSize),
"--pdf-page-numbers": Boolean(pdfOptions.pageNumbers)
});
}
var command = [
"ebook-convert",
path.join(that.options.output, "index.html"),
path.join(that.options.output, "index."+that.options.extension),
_.chain(_options)
.map(function(value, key) {
if (value == null) return null;
return key+"="+value;
})
.compact()
.value()
.join(" ")
path.join(that.options.output, "index."+format),
stringUtils.optionsToShellArgs(_options)
].join(" ");
exec(command, function (error, stdout, stderr) {
+26 -20
View File
@@ -11,7 +11,6 @@ var Plugin = require("./plugin");
var generators = {
"site": require("./site"),
"page": require("./page"),
"pdf": require("./pdf"),
"ebook": require("./ebook"),
"json": require("./json")
};
@@ -26,13 +25,23 @@ var containsFiles = function(dir, files) {
.then(_.all);
};
// TEst if generator exists
var checkGenerator = function(options) {
if (!generators[options.generator]) {
return Q.reject(new Error("Invalid generator (availables are: "+_.keys(generators).join(", ")+")"));
}
return Q();
};
// Create the generator and load plugins
var loadGenerator = function(options) {
var generator = new generators[options.generator](options);
return checkGenerator(options)
.then(function() {
var generator = new generators[options.generator](options);
return generator.loadPlugins()
.then(_.constant(generator));
return generator.loadPlugins()
.then(_.constant(generator));
});
};
@@ -45,7 +54,7 @@ var generate = function(options) {
"output": null,
// Config file (relative to input)
"configFile": "book.json",
"configFile": "book",
// Output generator
"generator": "site",
@@ -79,27 +88,20 @@ var generate = function(options) {
return Q.reject(new Error("Need option input (book input directory)"));
}
// Ensure generator exists
if (!generators[options.generator]) {
return Q.reject(new Error("Invalid generator (availables are: "+_.keys(generators).join(", ")));
}
// Check files to get folder type (book, multilanguage book or neither)
return Q()
return checkGenerator(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', 'defaultsPlugins');
try {
var _config = require(path.resolve(options.input, options.configFile));
_.extend(options, _config);
}, function() {
_.extend(options, _.omit(_config, 'input', 'configFile', 'defaultsPlugins'));
}
catch(err) {
// No config file: not a big deal
return Q();
});
}
})
// Read readme
@@ -134,8 +136,12 @@ var generateMultiLang = function(options) {
var langsSummary;
options.output = options.output || path.join(options.input, "_book");
return checkGenerator(options)
// Multi-languages book
return fs.readFile(path.join(options.input, "LANGS.md"), "utf-8")
.then(function() {
return fs.readFile(path.join(options.input, "LANGS.md"), "utf-8")
})
// Clean output folder
.then(function(_langsSummary) {
+18
View File
@@ -18,6 +18,16 @@ swig.setFilter('code', function(code, lang) {
}
});
// Convert a level into a deep level
swig.setFilter('lvl', function(lvl) {
return lvl.split(".").length;
});
// Join path
swig.setFilter('pathJoin', function(base, _path) {
return path.join(base, _path);
});
/*
* This generator will generate a simple index.html which can be converted as a PDF
@@ -61,16 +71,24 @@ Generator.prototype.convertFile = function(content, input) {
});
};
// Generate languages index
Generator.prototype.langsIndex = function(langs) {
return Q();
};
Generator.prototype.finish = function() {
var that = this;
var basePath = ".";
var output = path.join(this.options.output, "index.html");
var progress = parse.progress(this.options.navigation, "README.md");
return Q()
// Generate html
.then(function(pages) {
return that._writeTemplate(that.template, {
pages: that.pages,
progress: progress,
basePath: basePath,
staticBase: path.join(basePath, "gitbook"),
-56
View File
@@ -1,56 +0,0 @@
var util = require("util");
var path = require("path");
var Q = require("q");
var _ = require("lodash");
var exec = require('child_process').exec;
var fs = require("../fs");
var parse = require("../../parse");
var BaseGenerator = require("../page");
/*
* This generator inherits from the single page generator
* and convert the page output to pdf using gitbook-pdf
*/
var Generator = function() {
BaseGenerator.apply(this, arguments);
// Options for PDF generation
this.options = _.defaults(this.options, {
paperformat: "A4"
});
};
util.inherits(Generator, BaseGenerator);
Generator.prototype.finish = function() {
var that = this;
return BaseGenerator.prototype.finish.apply(this)
.then(function() {
var d = Q.defer();
var command = [
"gitbook-pdf",
"generate",
path.join(that.options.output, "index.html"),
path.join(that.options.output, "index.pdf"),
"--format="+that.options.paperformat
].join(" ");
exec(command, function (error, stdout, stderr) {
if (error) {
if (error.code == 127) {
error.message = "Need to install gitbook-pdf using: npm install gitbook-pdf -g";
} else {
error.message = error.message + " "+stdout;
}
return d.reject(error);
}
d.resolve();
});
return d.promise;
});
};
module.exports = Generator;
+1 -1
View File
@@ -163,6 +163,7 @@ Plugin.fromList = function(names, root) {
resources.html = {}
_.each(plugins, function(plugin) {
if (!plugin.infos.book || !plugin.infos.book.html) return;
var html = plugin.infos.book.html || {};
_.each(html, function(code, key) {
if (!_.isFunction(code)) code = _.constant(code);
@@ -200,7 +201,6 @@ Plugin.fromList = function(names, root) {
// Default plugins
Plugin.defaults = [
"mixpanel",
"mathjax"
];
-1
View File
@@ -63,7 +63,6 @@ Generator.prototype._writeTemplate = function(tpl, options, output, interpolate)
var that = this;
interpolate = interpolate || _.identity;
return Q()
.then(function(sections) {
return tpl(_.extend({
+26
View File
@@ -0,0 +1,26 @@
var _ = require("lodash");
function escapeShellArg(arg) {
var ret = '';
ret = arg.replace(/"/g, '\\"');
return "\"" + ret + "\"";
}
function optionsToShellArgs(options) {
return _.chain(options)
.map(function(value, key) {
if (value == null || value == false) return null;
if (value == true) return key;
return key+"="+escapeShellArg(value);
})
.compact()
.value()
.join(" ");
}
module.exports = {
escapeShellArg: escapeShellArg,
optionsToShellArgs: optionsToShellArgs
};
+1 -2
View File
@@ -1,6 +1,6 @@
{
"name": "gitbook",
"version": "0.4.7",
"version": "0.5.0",
"homepage": "http://www.gitbook.io/",
"description": "Library and cmd utility to generate GitBooks",
"main": "lib/index.js",
@@ -22,7 +22,6 @@
"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-livereload": "0.0.1"
},
+1 -1
View File
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -92,7 +92,7 @@ define([
// Instantiate font state object
fontState = storage.get("fontState", {
size: config.size || 1,
family: FAMILY[config.family || "serif"],
family: FAMILY[config.family || "sans"],
theme: THEMES[config.theme || "white"]
});
fontState.save = function(){
+45
View File
@@ -0,0 +1,45 @@
@import "vendors/bootstrap/bootstrap.less";
@import "mixins.less";
@import "ebook/variables.less";
@import "ebook/highlight.less";
.book-chapter {
display: none;
}
article {
page-break-after: always;
}
h1 { font-size: floor(@font-size-base * 2.15); }
h2 { font-size: floor(@font-size-base * 1.70); }
h3 { font-size: ceil(@font-size-base * 1.25); }
h4 { font-size: ceil(@font-size-base * 1); }
h5 { font-size: ceil(@font-size-base * 0.85); }
h6 { font-size: ceil(@font-size-base * 0.65); }
pre, blockquote {
border: 1px solid #999;
page-break-inside: avoid;
}
img {
max-width: 100% !important;
page-break-inside: avoid;
margin: 0px auto;
}
.exercise {
margin: 1cm 0cm;
padding: 0.4cm;
page-break-inside: avoid;
border: 3px solid #ddd;
.exercise-header {
margin-bottom: 0.4cm;
padding-bottom: 0.2cm;
border-bottom: 1px solid #ddd;
}
}
+1
View File
@@ -0,0 +1 @@
@font-size-base: 13px;
+1 -1
View File
@@ -4,4 +4,4 @@
&:hover, &:focus {
color: inherit;
}
}
}
-115
View File
@@ -1,115 +0,0 @@
@import "vendors/bootstrap/bootstrap.less";
@import "vendors/fontawesome/font-awesome.less";
@import "mixins.less";
@import "variables.less";
@import "fonts.less";
@import "page/highlight.less";
@font-size-base: 13px;
* {
-webkit-overflow-scrolling: touch;
-webkit-tap-highlight-color: transparent;
-webkit-text-size-adjust: none;
-webkit-touch-callout: none;
-webkit-font-smoothing: antialiased;
}
html, body {
height: 100%;
}
body {
text-rendering: optimizeLegibility;
font-smoothing: antialiased;
font-family: @font-family-base;
}
h1, h2, h3 {
page-break-after: avoid;
page-break-before: auto;
}
h1 { font-size: floor(@font-size-base * 2.15); }
h2 { font-size: floor(@font-size-base * 1.70); }
h3 { font-size: ceil(@font-size-base * 1.25); }
h4 { font-size: ceil(@font-size-base * 1); }
h5 { font-size: ceil(@font-size-base * 0.85); }
h6 { font-size: ceil(@font-size-base * 0.65); }
pre, blockquote {
border: 1px solid #999;
page-break-inside: avoid;
}
img {
max-width: 100% !important;
page-break-inside: avoid;
}
section {
page-break-after: always;
&#cover {
padding: 3cm 0cm;
text-align: center;
h1 {
font-size: 1.5cm;
}
}
&#summary {
margin: 1.5cm;
h1 {
text-align: center;
}
ol {
list-style: none;
padding: 0px;
margin: 0px;
margin-left: 1cm;
}
> ol {
> li {
}
}
}
article {
margin-bottom: 1.5cm;
&.new-chapter {
page-break-after: always;
font-size: 0.6cm;
text-align: center;
padding: 3cm 0cm;
h1 {
font-size: floor(@font-size-base * 2.7);
}
}
.exercise {
margin: 1cm 0cm;
padding: 0.4cm;
page-break-inside: avoid;
border: 3px solid #ddd;
.exercise-header {
margin-bottom: 0.4cm;
padding-bottom: 0.2cm;
border-bottom: 1px solid #ddd;
}
}
}
}
@@ -2,19 +2,19 @@
@import "vendors/fontawesome/font-awesome.less";
@import "mixins.less";
@import "variables.less";
@import "fonts.less";
@import "book/languages.less";
@import "book/header.less";
@import "book/summary.less";
@import "book/font-settings.less";
@import "book/body.less";
@import "book/exercise.less";
@import "book/quiz.less";
@import "book/markdown.less";
@import "book/progress.less";
@import "book/navigation.less";
@import "website/fonts.less";
@import "website/variables.less";
@import "website/languages.less";
@import "website/header.less";
@import "website/summary.less";
@import "website/font-settings.less";
@import "website/body.less";
@import "website/exercise.less";
@import "website/quiz.less";
@import "website/markdown.less";
@import "website/progress.less";
@import "website/navigation.less";
* {
-webkit-overflow-scrolling: touch;
+8 -56
View File
@@ -1,15 +1,3 @@
@font-face {
font-family: 'EB Garamond';
font-style: normal;
font-weight: 400;
src: local('EB Garamond 12 Regular'),url('@{FontPath}/ebgaramond/400.woff') format('woff');
}
@font-face {
font-family: 'EB Garamond';
font-style: italic;
font-weight: 400i;
src: local('EB Garamond 12 Italic'),url('@{FontPath}/ebgaramond/400i.woff') format('woff');
}
@font-face {
font-family: 'Merriweather';
font-style: normal;
@@ -19,7 +7,7 @@
@font-face {
font-family: 'Merriweather';
font-style: italic;
font-weight: 250i;
font-weight: 250;
src: local('Merriweather Light Italic'),url('@{FontPath}/merriweather/250i.woff') format('woff');
}
@font-face {
@@ -31,21 +19,9 @@
@font-face {
font-family: 'Merriweather';
font-style: italic;
font-weight: 400i;
font-weight: 400;
src: local('Merriweather Italic'),url('@{FontPath}/merriweather/400i.woff') format('woff');
}
@font-face {
font-family: 'Merriweather';
font-style: normal;
font-weight: 600;
src: local(''),url('@{FontPath}/merriweather/600.woff') format('woff');
}
/*@font-face {
font-family: 'Merriweather';
font-style: italic;
font-weight: 600i;
src: local(''),url('@{FontPath}/merriweather/600i.woff') format('woff');
}*/
@font-face {
font-family: 'Merriweather';
font-style: normal;
@@ -55,7 +31,7 @@
@font-face {
font-family: 'Merriweather';
font-style: italic;
font-weight: 700i;
font-weight: 700;
src: local('Merriweather Bold Italic'),url('@{FontPath}/merriweather/700i.woff') format('woff');
}
@font-face {
@@ -67,33 +43,9 @@
@font-face {
font-family: 'Merriweather';
font-style: italic;
font-weight: 900i;
font-weight: 900;
src: local('Merriweather Heavy Italic'),url('@{FontPath}/merriweather/900i.woff') format('woff');
}
@font-face {
font-family: 'Anonymous Pro';
font-style: normal;
font-weight: 400;
src: local('Anonymous Pro'),url('@{FontPath}/anonymouspro/400.woff') format('woff');
}
@font-face {
font-family: 'Anonymous Pro';
font-style: italic;
font-weight: 400i;
src: local('Anonymous Pro Italic'),url('@{FontPath}/anonymouspro/400i.woff') format('woff');
}
@font-face {
font-family: 'Anonymous Pro';
font-style: normal;
font-weight: 700;
src: local('Anonymous Pro Bold'),url('@{FontPath}/anonymouspro/700.woff') format('woff');
}
@font-face {
font-family: 'Anonymous Pro';
font-style: italic;
font-weight: 700i;
src: local('Anonymous Pro Bold Italic'),url('@{FontPath}/anonymouspro/700i.woff') format('woff');
}
@font-face {
font-family: 'Open Sans';
font-style: normal;
@@ -103,7 +55,7 @@
@font-face {
font-family: 'Open Sans';
font-style: italic;
font-weight: 300i;
font-weight: 300;
src: local('Open Sans Light Italic'),url('@{FontPath}/opensans/300i.woff') format('woff');
}
@font-face {
@@ -115,7 +67,7 @@
@font-face {
font-family: 'Open Sans';
font-style: italic;
font-weight: 400i;
font-weight: 400;
src: local('Open Sans Italic'),url('@{FontPath}/opensans/400i.woff') format('woff');
}
@font-face {
@@ -127,7 +79,7 @@
@font-face {
font-family: 'Open Sans';
font-style: italic;
font-weight: 600i;
font-weight: 600;
src: local('Open Sans Semibold Italic'),url('@{FontPath}/opensans/600i.woff') format('woff');
}
@font-face {
@@ -139,6 +91,6 @@
@font-face {
font-family: 'Open Sans';
font-style: italic;
font-weight: 700i;
font-weight: 700;
src: local('Open Sans Bold Italic'),url('@{FontPath}/opensans/700i.woff') format('woff');
}
@@ -13,7 +13,7 @@
font-size: 0.85em;
color: @header-color;
background: @header-background;
box-shadow: 0 1px 2px hsla(200,10%,80%,0.6);
border-bottom: 1px solid @header-border;
.btn {
display: block;
@@ -11,7 +11,7 @@
width: @sidebar-width;
color: @sidebar-color;
background: @sidebar-background;
box-shadow: inset -1px 0 5px hsla(0, 0%, 0%, 0.1);
border-right: 1px solid @sidebar-border;
.transition(all 0.5s ease);
@@ -57,7 +57,6 @@
margin: 7px 0;
overflow: hidden;
background: @sidebar-divider-color;
box-shadow: 0 1px rgba(255,255,255,0.7);
}
i.fa-check {
+25 -23
View File
@@ -7,6 +7,7 @@
@header-height: 50px;
@header-color: hsl(194, 5%, 52%);
@header-background: white;
@header-border: rgba(0, 0, 0, 0.07);
@header-button-color: hsl(194, 5%, 52%);
@header-button-hover-color: #151515;
@header-button-hover-background: hsl(207, 15%, 95%);
@@ -18,28 +19,29 @@
@sidebar-width: 250px;
@sidebar-breakpoint: 600px;
@sidebar-color: hsl(207, 15%, 80%);
@sidebar-background: hsl(207, 15%, 95%);
@sidebar-background: @body-background;
@sidebar-border: @header-border;
@sidebar-nested-padding: 20px;
@sidebar-search-padding: 6px;
@sidebar-search-background: transparent;
@sidebar-search-input-border-color: hsl(207, 15%, 80%);
@sidebar-search-input-border-color: @sidebar-border;
@sidebar-divider-color: hsl(207, 15%, 85%);
@sidebar-divider-color: @sidebar-border;
@sidebar-link-color: hsl(207, 15%, 50%);
@sidebar-link-color: hsl(207, 15%, 25%);
@sidebar-link-background: transparent;
@sidebar-link-hover-color: hsl(207, 100%, 50%);
@sidebar-link-hover-background: transparent;
@sidebar-icon-color: @bar-progress-background;
@sidebar-link-completed: hsl(207, 15%, 25%);
@sidebar-link-completed: @sidebar-link-color;
@sidebar-link-completed-weight: normal;
// Page
@page-color: black;
@page-background: white;
@page-color: black;
@page-background: @body-background;
// Progress Bar
@chapter-display: none;
@@ -76,19 +78,19 @@
@border-radius-small: 1px;
// Fonts
@font-family-serif: Merriweather, "EB Garamond", Georgia, serif;
@font-family-serif: "Merriweather", Georgia, serif;
@font-family-sans: "Open Sans", "Clear Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
@font-family-base: @font-family-serif;
@font-family-base: @font-family-sans;
@headings-font-family: inherit;
@FontPath: '@{staticPath}/fonts';
@fa-font-path: "@{FontPath}/fontawesome";
@s-font-size: 1.2rem;
@m-font-size: 1.4rem;
@l-font-size: 1.6rem;
@xl-font-size: 2.2rem;
@xxl-font-size: 4.0rem;
@s-font-size: 1.2rem;
@m-font-size: 1.4rem;
@l-font-size: 1.6rem;
@xl-font-size: 2.2rem;
@xxl-font-size: 4.0rem;
/*
,--------.,--.
@@ -116,15 +118,15 @@
// Sidebar
@sidebar-color-1: #AFA790;
@sidebar-color-2: hsl(207, 15%, 80%);
@sidebar-background-1: #F3EACB;
@sidebar-background-2: #111111;
@sidebar-background-1: @body-background-1;
@sidebar-background-2: @body-background-2;
@sidebar-search-background-1: transparent;
@sidebar-search-background-2: transparent;
@sidebar-search-input-border-color-1: #D6CFBA;
@sidebar-search-input-border-color-2: #c4cdd4;
@sidebar-search-input-border-color-2: #000;
@sidebar-divider-color-1: hsl(207, 15%, 85%);
@sidebar-divider-color-1: @sidebar-divider-color;
@sidebar-divider-color-2: #1d1f21;
@sidebar-link-color-1: #877F6A;
@@ -138,14 +140,14 @@
@sidebar-icon-color-1: @bar-progress-background;
@sidebar-icon-color-2: @bar-progress-background;
@sidebar-link-completed-1: hsl(207, 15%, 25%);
@sidebar-link-completed-2: hsl(207, 15%, 25%);
@sidebar-link-completed-1: @sidebar-link-color-1;
@sidebar-link-completed-2: @sidebar-link-color-2;
@sidebar-link-completed-weight-1: normal;
@sidebar-link-completed-weight-2: normal;
// Page
@page-color-1: #704214;
@page-color-2: #a4b1b1;
@page-color-1: #704214;
@page-color-2: #a4b1b1;
@page-background-1: #F3EACB;
@page-background-2: #1d1f21;
+1 -1
View File
@@ -10,7 +10,7 @@
<ul class="languages">
{% for lang in langs %}
<li>
<a href="{{ basePath}}/{{ lang.path }}">{{ lang.title }}</a>
<a href="{{ basePath}}/{{ lang.path|pathJoin("/index.html") }}">{{ lang.title }}</a>
</li>
{% endfor %}
</ul>
+35 -94
View File
@@ -20,10 +20,10 @@
</div>
{% elif section.type == "quiz" %}
<div class="quiz">
<div class="exercise-header">Exercise #{{ exercise }}</div>
{% autoescape false %}{{ section.content }}{% endautoescape %}
{% autoescape false %}{{ section.quiz.base }}{% endautoescape %}
{% set exercise = exercise + 1 %}
<div class="exercise-header">Exercise #{{ exercise }}</div>
{% autoescape false %}{{ section.content }}{% endautoescape %}
{% autoescape false %}{{ section.quiz.base }}{% endautoescape %}
{% set exercise = exercise + 1 %}
</div>
{% endif %}
{% endfor %}
@@ -31,104 +31,45 @@
{% set exercise = 1 %}
{% block content %}
{# Cover #}
<section id="cover">
<h1>{{ title }}</h1>
{% if githubId %}
<h2>By <a href="{{ githubHost }}{{ githubAuthor }}">@{{ githubAuthor }}</a></h2>
{% endif %}
</section>
{# Summary #}
<section id="summary">
<h1>Table of Contents</h1>
<ol>
<li>
<a href="#README.md">
<h2>Introduction</h2>
</a>
</li>
{% for item in summary.chapters %}
<li>
<h2><span>{{ item.level }}.</span> <a href="#{{ item.path }}">{{ item.title }}</a></h2>
{% if item.articles.length > 0 %}
<ol>
{% for article in item.articles %}
<li>
<span>{{ article.level }}</span> <a href="#{{ article.path }}">{{ article.title }}</a>
</li>
{% endfor %}
</ol>
{% endif %}
</li>
{% endfor %}
</ol>
</section>
{# Pages content #}
<section>
<article id="README.md">
{{ articleContent(pages["README.md"].content) }}
</article>
</section>
{% for item in summary.chapters %}
<section>
<article id="{{ item.path }}" class="new-chapter">
<h1>{{ item.title }}</h1>
</article>
{% if pages[item.path] %}
<article>
{{ articleContent(pages[item.path].content) }}
</article>
{% endif %}
{% if item.articles.length > 0 %}
{% for article in item.articles %}
{% if pages[article.path] %}
<article id="{{ article.path }}">
{{ articleContent(pages[article.path].content) }}
</article>
{% endif %}
{% endfor %}
{% endif %}
</section>
{% for item in progress.chapters %}
<article id="{{ article.path }}">
<h1 class="book-chapter book-chapter-{{ item.level|lvl }}">{{ item.title }}</h1>
{% if pages[item.path] %}
{{ articleContent(pages[item.path].content) }}
{% endif %}
</article>
{% endfor %}
{# Exercise solutions #}
{% if exercise > 1 %}
{% set exercise = 1 %}
<section>
<article class="new-chapter">
<h1>Exercise Solutions</h1>
</article>
<article>
{% for item in summary.chapters %}
{% for article in item.articles %}
{% if pages[article.path] %}
{% for section in pages[article.path].content %}
{% if section.type == "exercise" %}
<div class="exercise">
<div class="exercise-header">Exercise #{{ exercise }}</div>
{% autoescape false %}{{ section.content }}{% endautoescape %}
<pre><code>{% autoescape false %}{{ section.code.solution|code }}{% endautoescape %}</code></pre>
{% set exercise = exercise + 1 %}
</div>
{% elif section.type == "quiz" %}
<div class="quiz">
<div class="exercise-header">Exercise #{{ exercise }}</div>
{% autoescape false %}{{ section.content }}{% endautoescape %}
{% autoescape false %}{{ section.quiz.solution }}{% endautoescape %}
{% set exercise = exercise + 1 %}
</div>
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
<article>
<h1 class="book-chapter book-chapter-1">Exercise Solutions</h1>
{% for item in progress.chapters %}
{% if pages[item.path] %}
{% for section in pages[item.path].content %}
{% if section.type == "exercise" %}
<div class="exercise">
<div class="exercise-header">Exercise #{{ exercise }}</div>
{% autoescape false %}{{ section.content }}{% endautoescape %}
<pre><code>{% autoescape false %}{{ section.code.solution|code }}{% endautoescape %}</code></pre>
{% set exercise = exercise + 1 %}
</div>
{% elif section.type == "quiz" %}
<div class="quiz">
<div class="exercise-header">Exercise #{{ exercise }}</div>
{% autoescape false %}{{ section.content }}{% endautoescape %}
{% autoescape false %}{{ section.quiz.solution }}{% endautoescape %}
{% set exercise = exercise + 1 %}
</div>
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
</article>
</section>
</article>
{% endif %}
{% endblock %}