Compare commits

...

10 Commits

Author SHA1 Message Date
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
13 changed files with 147 additions and 262 deletions
+3 -3
View File
@@ -31,7 +31,7 @@ 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
-f, --format <name> Change generation format, defaults to site, availables are: site, page, pdf, json, mobi, epub
--config <config file> Configuration file to use, defaults to book.json
```
@@ -99,8 +99,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 +216,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
+7 -1
View File
@@ -16,6 +16,11 @@ var buildCommand = function(command) {
};
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();
@@ -43,5 +48,6 @@ var makeBuildFunc = function(converter) {
module.exports = {
folder: makeBuildFunc(generate.folder),
file: makeBuildFunc(generate.file),
command: buildCommand
command: buildCommand,
commandEbook: buildEbookCommand
};
+29 -13
View File
@@ -80,19 +80,8 @@ build.command(prog.command('serve [source_dir]'))
generate();
});
build.command(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"
}));
});
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('ebook [source_dir]'))
.description('Build a gitbook as a eBook (format detected according to the extension)')
.action(function(dir, options) {
var ext = options.output ? path.extname(options.output) : "epub";
@@ -102,6 +91,33 @@ build.command(prog.command('ebook [source_dir]'))
}));
});
build.commandEbook(prog.command('pdf [source_dir]'))
.description('Build a gitbook as a PDF')
.action(function(dir, options) {
build.file(dir, _.extend(options, {
extension: "pdf",
format: "ebook"
}));
});
build.commandEbook(prog.command('epub [source_dir]'))
.description('Build a gitbook as a ePub book')
.action(function(dir, options) {
build.file(dir, _.extend(options, {
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"
}));
});
prog
.command('init [source_dir]')
.description('Create files and folders based on contents of SUMMARY.md')
+22 -9
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
@@ -28,27 +29,39 @@ 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);
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") {
_.extend(_options, {
"--margin-left": "62",
"--margin-right": "62",
"--margin-top": "36",
"--margin-bottom": "36",
"--pdf-add-toc": true,
"--pdf-default-font-size": "12",
"--paper-size": "a4",
});
}
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(" ")
stringUtils.optionsToShellArgs(_options)
].join(" ");
exec(command, function (error, stdout, stderr) {
-1
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")
};
+8
View File
@@ -18,6 +18,11 @@ swig.setFilter('code', function(code, lang) {
}
});
// Convert a level into a deep level
swig.setFilter('lvl', function(lvl) {
return lvl.split(".").length;
});
/*
* This generator will generate a simple index.html which can be converted as a PDF
@@ -66,11 +71,14 @@ Generator.prototype.finish = function() {
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
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) return null;
if (value == true) return key;
return key+"="+escapeShellArg(value);
})
.compact()
.value()
.join(" ");
}
module.exports = {
escapeShellArg: escapeShellArg,
optionsToShellArgs: optionsToShellArgs
};
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "gitbook",
"version": "0.4.7",
"version": "0.4.8",
"homepage": "http://www.gitbook.io/",
"description": "Library and cmd utility to generate GitBooks",
"main": "lib/index.js",
File diff suppressed because one or more lines are too long
+15 -82
View File
@@ -1,38 +1,19 @@
@import "vendors/bootstrap/bootstrap.less";
@import "vendors/fontawesome/font-awesome.less";
@import "mixins.less";
@import "variables.less";
@import "fonts.less";
/*@import "variables.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;
.book-chapter {
display: none;
}
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;
article {
page-break-after: always;
}
h1 { font-size: floor(@font-size-base * 2.15); }
@@ -52,64 +33,16 @@ img {
page-break-inside: avoid;
}
section {
page-break-after: always;
.exercise {
margin: 1cm 0cm;
padding: 0.4cm;
page-break-inside: avoid;
&#cover {
padding: 3cm 0cm;
text-align: center;
border: 3px solid #ddd;
h1 {
font-size: 1.5cm;
}
.exercise-header {
margin-bottom: 0.4cm;
padding-bottom: 0.2cm;
border-bottom: 1px solid #ddd;
}
&#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;
}
}
}
}
}
+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 %}