mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-27 12:39:08 +00:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 366e6ed105 | |||
| 52078eb666 | |||
| d9ddbff443 | |||
| 01b160f9a1 | |||
| 23fcb817a4 | |||
| f531a3f984 | |||
| c777023e9f | |||
| 62c99759c1 | |||
| 6951c21d19 | |||
| 3a8289483e | |||
| 4079de9587 | |||
| b86d171082 | |||
| 959b272e65 | |||
| 684440e2d1 | |||
| 4740cd3b06 | |||
| b3131d99d2 | |||
| b0fd2a67ea | |||
| 7c83869869 | |||
| 57d5c23eaf | |||
| 8d92b74e61 | |||
| 4e2cda99cc | |||
| 12a7a4c4cf |
+20
@@ -1,4 +1,24 @@
|
||||
# Release notes
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## 2.0.0-alpha.9
|
||||
- Fix links in sidebar
|
||||
- Fix normalization of html link (README to index)
|
||||
- Fix html snippets escaping
|
||||
|
||||
## 2.0.0-alpha.8
|
||||
- Improve locale detection for i18n
|
||||
- Fix chapter name for Glossary in pdf
|
||||
- Don't escape html in glossary items
|
||||
- Fix generation of multilingual book as ebook
|
||||
- Add "post" block attribute to post-process
|
||||
|
||||
## 2.0.0-alpha.7
|
||||
- Fix display of glossary in ebook formats
|
||||
- Add default footer and header to pdf
|
||||
- Fix generation of json format compatible with 1.x.x
|
||||
- Add Simplifiled Chinese and Traditional Chinese translations
|
||||
|
||||
## 2.0.0-alpha.6
|
||||
- Add es and pt translations
|
||||
|
||||
+6
-3
@@ -10,6 +10,7 @@ var fs = require("./utils/fs");
|
||||
var parseNavigation = require("./utils/navigation");
|
||||
var parseProgress = require("./utils/progress");
|
||||
var pageUtil = require("./utils/page");
|
||||
var batch = require("./utils/batch");
|
||||
var links = require("./utils/links");
|
||||
var logger = require("./utils/logger");
|
||||
|
||||
@@ -224,9 +225,11 @@ Book.prototype.generate = function(generator) {
|
||||
|
||||
// Finally let's generate content
|
||||
.then(function() {
|
||||
return _.reduce(ops["content"] || [], function(prev, file) {
|
||||
var nFiles = (ops["content"] || []).length;
|
||||
return _.reduce(ops["content"] || [], function(prev, file, i) {
|
||||
return prev.then(function() {
|
||||
that.log.debug.ln("converting", file);
|
||||
var p = ((i*100)/nFiles).toFixed(0)+"%";
|
||||
that.log.info.ln("processing", file, p);
|
||||
return Q(generator.convertFile(file));
|
||||
});
|
||||
}, Q());
|
||||
@@ -661,7 +664,7 @@ Book.prototype.resolve = function(p) {
|
||||
// Normalize a link to .html and convert README -> index
|
||||
Book.prototype.contentLink = function(link) {
|
||||
if (
|
||||
path.basename(link) == "README"
|
||||
path.basename(link, path.extname(link)) == "README"
|
||||
|| link == this.readmeFile
|
||||
) {
|
||||
link = path.join(path.dirname(link), "index"+path.extname(link));
|
||||
|
||||
@@ -44,10 +44,11 @@ Generator.prototype.writeSummary = function() {
|
||||
Generator.prototype.finish = function() {
|
||||
var that = this;
|
||||
|
||||
return BaseGenerator.prototype.finish.apply(this)
|
||||
.then(function() {
|
||||
return that.writeSummary();
|
||||
})
|
||||
return Q()
|
||||
.then(this.copyAssets)
|
||||
.then(this.copyCover)
|
||||
.then(this.writeGlossary)
|
||||
.then(this.writeSummary)
|
||||
.then(function() {
|
||||
if (!that.ebookFormat) return Q();
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ Generator.prototype.convertFile = function(input) {
|
||||
var basePath = path.relative(path.dirname(output), that.options.output) || ".";
|
||||
if (process.platform === 'win32') basePath = basePath.replace(/\\/g, '/');
|
||||
|
||||
that.book.log.info.ln("write parsed file", page.path, "to", relativeOutput);
|
||||
that.book.log.debug.ln("write parsed file", page.path, "to", relativeOutput);
|
||||
|
||||
return that._writeTemplate(that.templates["page"], {
|
||||
progress: page.progress,
|
||||
|
||||
+42
-19
@@ -6,6 +6,7 @@ var nunjucks = require("nunjucks");
|
||||
var git = require("./utils/git");
|
||||
var stringUtils = require("./utils/string");
|
||||
var fs = require("./utils/fs");
|
||||
var batch = require("./utils/batch");
|
||||
var pkg = require("../package.json");
|
||||
|
||||
|
||||
@@ -87,18 +88,21 @@ TemplateEngine.prototype.processBlock = function(blk) {
|
||||
if (_.isString(blk)) blk = { body: blk };
|
||||
|
||||
blk = _.defaults(blk, {
|
||||
parse: false
|
||||
parse: false,
|
||||
post: undefined
|
||||
});
|
||||
blk.id = _.uniqueId("blk");
|
||||
|
||||
var toAdd = (!blk.parse) || (blk.post != undefined);
|
||||
|
||||
// Add to global map
|
||||
if (toAdd) this.blocks[blk.id] = blk;
|
||||
|
||||
//Parsable block, just return it
|
||||
if (blk.parse) {
|
||||
return blk.body;
|
||||
}
|
||||
|
||||
// Add to global map
|
||||
this.blocks[blk.id] = blk;
|
||||
|
||||
// Return it as a macro
|
||||
return "%+%"+blk.id+"%+%";
|
||||
};
|
||||
@@ -114,9 +118,6 @@ TemplateEngine.prototype.replaceBlocks = function(content) {
|
||||
|
||||
var body = blk.body;
|
||||
|
||||
// Remove it from map
|
||||
delete that.blocks[key];
|
||||
|
||||
return body;
|
||||
});
|
||||
};
|
||||
@@ -239,21 +240,25 @@ TemplateEngine.prototype.addBlock = function(name, block) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
var callback = args.pop();
|
||||
|
||||
// Extract blocks body
|
||||
var _blocks = _.chain(block.blocks)
|
||||
.reverse()
|
||||
.map(function(blockName){
|
||||
return {
|
||||
name: blockName,
|
||||
body: args.pop()()
|
||||
};
|
||||
})
|
||||
.reverse()
|
||||
.value();
|
||||
// Extract blocks
|
||||
var blocks = args
|
||||
.concat([])
|
||||
.slice(-block.blocks.length);
|
||||
|
||||
// Eliminate blocks from list
|
||||
if (block.blocks.length > 0) args = args.slice(0, -block.blocks.length);
|
||||
|
||||
// Extract main body and kwargs
|
||||
var body = args.pop();
|
||||
var kwargs = args.pop() || {};
|
||||
|
||||
// Extract blocks body
|
||||
var _blocks = _.map(block.blocks, function(blockName, i){
|
||||
return {
|
||||
name: blockName,
|
||||
body: blocks[i]()
|
||||
};
|
||||
});
|
||||
|
||||
var func = that.bindContext(block.process);
|
||||
|
||||
@@ -363,8 +368,26 @@ TemplateEngine.prototype.renderPage = function(page) {
|
||||
|
||||
// Post process content
|
||||
TemplateEngine.prototype.postProcess = function(content) {
|
||||
var that = this;
|
||||
|
||||
return Q(content)
|
||||
.then(this.replaceBlocks);
|
||||
.then(that.replaceBlocks)
|
||||
.then(function(_content) {
|
||||
return batch.execEach(that.blocks, {
|
||||
max: 20,
|
||||
fn: function(blk, blkId) {
|
||||
return Q()
|
||||
.then(function() {
|
||||
if (!blk.post) return Q();
|
||||
return blk.post();
|
||||
})
|
||||
.then(function() {
|
||||
delete that.blocks[blkId];
|
||||
});
|
||||
}
|
||||
})
|
||||
.thenResolve(_content);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = TemplateEngine;
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
var Q = require("q");
|
||||
var _ = require("lodash");
|
||||
|
||||
// Execute a method for all element
|
||||
function execEach(items, options) {
|
||||
if (_.size(items) == 0) return Q();
|
||||
var concurrents = 0, d = Q.defer(), pending = [];
|
||||
|
||||
options = _.defaults(options || {}, {
|
||||
max: 100,
|
||||
fn: function(item) {}
|
||||
});
|
||||
|
||||
|
||||
function startItem(item, i) {
|
||||
if (concurrents >= options.max) {
|
||||
pending.push([item, i]);
|
||||
return;
|
||||
}
|
||||
|
||||
concurrents++;
|
||||
Q()
|
||||
.then(function() {
|
||||
return options.fn(item, i);
|
||||
})
|
||||
.then(function() {
|
||||
concurrents--;
|
||||
|
||||
// Next pending
|
||||
var next = pending.shift();
|
||||
|
||||
if (concurrents == 0 && !next) {
|
||||
d.resolve();
|
||||
} else if (next) {
|
||||
startItem.apply(null, next);
|
||||
}
|
||||
})
|
||||
.fail(function(err) {
|
||||
pending = [];
|
||||
d.reject(err);
|
||||
})
|
||||
}
|
||||
|
||||
_.each(items, startItem);
|
||||
|
||||
return d.promise;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
execEach: execEach
|
||||
};
|
||||
|
||||
@@ -29,10 +29,14 @@ var getByLanguage = function(lang) {
|
||||
|
||||
var compareLocales = function(lang, locale) {
|
||||
var langMain = _.first(lang.split("-"));
|
||||
var langSecond = _.last(lang.split("-"));
|
||||
|
||||
var localeMain = _.first(locale.split("-"));
|
||||
var localeSecond = _.last(locale.split("-"));
|
||||
|
||||
if (locale == lang) return 100;
|
||||
if (localeMain == langMain) return 50;
|
||||
if (localeSecond == langSecond) return 20;
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
+30
-24
@@ -9,6 +9,7 @@ var crc = require("crc");
|
||||
var links = require('./links');
|
||||
var imgUtils = require('./images');
|
||||
var fs = require('./fs');
|
||||
var batch = require('./batch');
|
||||
|
||||
// Render a cheerio dom as html
|
||||
var renderDom = function($, dom, options) {
|
||||
@@ -112,6 +113,7 @@ function normalizeHtml(src, options) {
|
||||
$("img").each(function() {
|
||||
var origin = undefined;
|
||||
var src = $(this).attr("src");
|
||||
if (!src) return;
|
||||
var isExternal = links.isExternal(src);
|
||||
|
||||
// Transform as relative to the bases
|
||||
@@ -182,6 +184,7 @@ function normalizeHtml(src, options) {
|
||||
|
||||
$("a").each(function() {
|
||||
var href = $(this).attr("href");
|
||||
if (!href) return;
|
||||
|
||||
if (links.isRelative(href)) {
|
||||
var absolutePath = path.join(options.base, href);
|
||||
@@ -212,7 +215,7 @@ function normalizeHtml(src, options) {
|
||||
term.files = term.files || [];
|
||||
term.files.push(options.navigation[options.input]);
|
||||
}
|
||||
return "<a href='"+links.toAbsolute("/GLOSSARY.html", options.base, options.output)+"#"+term.id+"' class='glossary-term' title='"+term.description+"'>"+match+"</a>";
|
||||
return "<a href='"+links.toAbsolute("/GLOSSARY.html", options.base, options.output)+"#"+term.id+"' class='glossary-term' title='"+_.escape(term.description)+"'>"+match+"</a>";
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -230,33 +233,36 @@ function convertImages(images, options) {
|
||||
var downloaded = [];
|
||||
options.book.log.debug.ln("convert ", images.length, "images to png");
|
||||
|
||||
return _.reduce(images, function(prev, image) {
|
||||
var imgin = path.resolve(options.book.options.output, image.source);
|
||||
return batch.execEach(images, {
|
||||
max: 100,
|
||||
fn: function(image) {
|
||||
var imgin = path.resolve(options.book.options.output, image.source);
|
||||
|
||||
return prev
|
||||
return Q()
|
||||
|
||||
// Write image if need to be download
|
||||
.then(function() {
|
||||
if (!image.origin && !_.contains(downloaded, image.origin)) return;
|
||||
options.book.log.debug("download image", image.origin, "...");
|
||||
downloaded.push(image.origin);
|
||||
return options.book.log.debug.promise(fs.writeStream(imgin, request(image.origin)));
|
||||
})
|
||||
// Write image if need to be download
|
||||
.then(function() {
|
||||
if (!image.origin && !_.contains(downloaded, image.origin)) return;
|
||||
options.book.log.debug("download image", image.origin, "...");
|
||||
downloaded.push(image.origin);
|
||||
return options.book.log.debug.promise(fs.writeStream(imgin, request(image.origin)));
|
||||
})
|
||||
|
||||
// Write svg if content
|
||||
.then(function() {
|
||||
if (!image.content) return;
|
||||
return fs.writeFile(imgin, image.content);
|
||||
})
|
||||
// Write svg if content
|
||||
.then(function() {
|
||||
if (!image.content) return;
|
||||
return fs.writeFile(imgin, image.content);
|
||||
})
|
||||
|
||||
// Convert
|
||||
.then(function() {
|
||||
if (!image.dest) return;
|
||||
var imgout = path.resolve(options.book.options.output, image.dest);
|
||||
options.book.log.debug("convert image", image.source, "to", image.dest, "...");
|
||||
return options.book.log.debug.promise(imgUtils.convertSVG(imgin, imgout));
|
||||
});
|
||||
}, Q())
|
||||
// Convert
|
||||
.then(function() {
|
||||
if (!image.dest) return;
|
||||
var imgout = path.resolve(options.book.options.output, image.dest);
|
||||
options.book.log.debug("convert image", image.source, "to", image.dest, "...");
|
||||
return options.book.log.debug.promise(imgUtils.convertSVG(imgin, imgout));
|
||||
});
|
||||
}
|
||||
})
|
||||
.then(function() {
|
||||
options.book.log.debug.ok(images.length+" images converted with success");
|
||||
});
|
||||
|
||||
+5
-5
@@ -1,20 +1,20 @@
|
||||
{
|
||||
"name": "gitbook",
|
||||
"version": "2.0.0-alpha.7",
|
||||
"version": "2.0.0-alpha.9",
|
||||
"homepage": "https://www.gitbook.com",
|
||||
"description": "Library and cmd utility to generate GitBooks",
|
||||
"main": "lib/index.js",
|
||||
"dependencies": {
|
||||
"q": "1.0.1",
|
||||
"lunr": "0.5.7",
|
||||
"lodash": "2.4.1",
|
||||
"lodash": "3.2.0",
|
||||
"graceful-fs": "3.0.5",
|
||||
"resolve": "0.6.3",
|
||||
"fs-extra": "0.16.3",
|
||||
"fstream-ignore": "1.0.2",
|
||||
"gitbook-parsers": "0.4.0",
|
||||
"nunjucks": "git+https://github.com/SamyPesse/nunjucks.git#4019d1b7379372336b86ce1b0bf84352a2029747",
|
||||
"nunjucks-autoescape": "0.1.0",
|
||||
"gitbook-parsers": "0.4.1",
|
||||
"nunjucks": "git+https://github.com/mozilla/nunjucks.git#42d2b9f5c0ad5db8ca3a1fdbba5bde9fc4cc2c45",
|
||||
"nunjucks-autoescape": "0.1.1",
|
||||
"nunjucks-filter": "0.1.0",
|
||||
"nunjucks-i18n": "1.0.0",
|
||||
"semver": "2.2.1",
|
||||
|
||||
@@ -4,17 +4,18 @@
|
||||
|
||||
{% block content %}
|
||||
<div class="page page-toc">
|
||||
<h1>Glossary</h1>
|
||||
{% for item in glossary %}
|
||||
<section class="normal glossary" id="{{ item.id }}">
|
||||
<h2><a href="#{{ item.id }}">{{ item.name }}</a></h2>
|
||||
<p>{{ item.description }}</p>
|
||||
<h1 class="book-chapter book-chapter-1">{% i18n "GLOSSARY" %}Glossary{% endi18n %}</h1>
|
||||
<h1>{% i18n "GLOSSARY" %}Glossary{% endi18n %}</h1>
|
||||
{% for item in glossary %}
|
||||
<section class="normal glossary" id="{{ item.id }}">
|
||||
<h2><a href="#{{ item.id }}">{{ item.name }}</a></h2>
|
||||
<p>{{ item.description|safe }}</p>
|
||||
<ul class="glossary-index">
|
||||
{% for file in item.files %}
|
||||
<li><a href="{{ basePath }}/{{ file.path|contentLink }}"><span class="level">{{ file.level }}.</span> {{ file.title }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</section>
|
||||
{% endfor %}
|
||||
</section>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<meta name="description" content="{% block description %}{% endblock %}">
|
||||
<meta name="generator" content="GitBook {{ gitbook.version }}">
|
||||
{% block head %}{% endblock %}
|
||||
{{ htmlSnippet("head:end")|default("") }}
|
||||
{{ htmlSnippet("head:end")|default("")|safe }}
|
||||
</head>
|
||||
<body>
|
||||
{{ htmlSnippet("body:start")|default("")|safe }}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
{% for item in glossary %}
|
||||
<section class="normal glossary" id="{{ item.id }}">
|
||||
<h2><a href="#{{ item.id }}">{{ item.name }}</a></h2>
|
||||
<p>{{ item.description }}</p>
|
||||
<p>{{ item.description|safe }}</p>
|
||||
<ul class="glossary-index">
|
||||
{% for file in item.files %}
|
||||
<li><a href="{{ basePath }}/{{ file.path|contentLink }}"><span class="level">{{ file.level }}.</span> {{ file.title }}</a></li>
|
||||
|
||||
@@ -38,10 +38,10 @@
|
||||
<ul class="summary">
|
||||
{% set _divider = false %}
|
||||
{% if options.links.sidebar %}
|
||||
{% for link in options.links.sidebar %}
|
||||
{% for linkTitle, link in options.links.sidebar %}
|
||||
{% set _divider = true %}
|
||||
<li>
|
||||
<a href="{{ options.links.sidebar[loop.key] }}" target="blank" class="custom-link">{{ loop.key }}</a>
|
||||
<a href="{{ link }}" target="blank" class="custom-link">{{ linkTitle }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<html lang="{{ language }}">
|
||||
{{ htmlSnippet("html:start")|default("")|safe }}
|
||||
<head>
|
||||
{{ htmlSnippet("head:start")|default("") }}
|
||||
{{ htmlSnippet("head:start")|default("")|safe }}
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=11; IE=10; IE=9; IE=8; IE=7; IE=EDGE" />
|
||||
<title>{% block title %}{% endblock %}</title>
|
||||
|
||||
Reference in New Issue
Block a user