summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/generate/fs.js3
-rw-r--r--lib/generate/index.js110
-rw-r--r--lib/parse/index.js1
-rw-r--r--lib/parse/lex.js2
-rw-r--r--lib/parse/page.js22
-rw-r--r--lib/parse/readme.js32
6 files changed, 146 insertions, 24 deletions
diff --git a/lib/generate/fs.js b/lib/generate/fs.js
index f5f74a5..f96efb3 100644
--- a/lib/generate/fs.js
+++ b/lib/generate/fs.js
@@ -16,7 +16,8 @@ var getFiles = function(path) {
// Add extra rules to ignore common folders
ig.addIgnoreRules([
- '.git/'
+ '.git/',
+ '.gitignore',
], '__custom_stuff');
// Push each file to our list
diff --git a/lib/generate/index.js b/lib/generate/index.js
index 4804548..33edc1f 100644
--- a/lib/generate/index.js
+++ b/lib/generate/index.js
@@ -1,8 +1,8 @@
var Q = require("q");
var _ = require("lodash");
-
var path = require("path");
var swig = require('swig');
+var tmp = require('tmp');
var fs = require("./fs");
var parse = require("../parse");
@@ -15,6 +15,12 @@ var generators = {
"json": require("./json")
};
+var defaultDescription = "Book generated using GitBook";
+
+/*
+ * Use a specific generator to convert a gitbook to a site/pdf/ebook/
+ * output is always a folder
+ */
var generate = function(options) {
var generator = null;
var files;
@@ -29,7 +35,7 @@ var generate = function(options) {
// Book title, keyword, description
title: null,
- description: "Book generated using GitBook",
+ description: null,
// Origin github repository id
github: null,
@@ -39,14 +45,16 @@ var generate = function(options) {
theme: path.resolve(__dirname, '../../theme')
});
- if (!options.title || !options.input || !options.output) {
- return Q.reject(new Error("Need options: title, input, output"));
+ if (!options.input) {
+ return Q.reject(new Error("Need option input (book input directory)"));
}
if (!generators[options.generator]) {
return Q.reject(new Error("Invalid generator (availables are: "+_.keys(generators).join(", ")));
}
+ options.output = options.output || path.join(options.input, "_book");
+
// Clean output folder
return fs.remove(options.output)
@@ -97,14 +105,37 @@ var generate = function(options) {
return Q.reject(new Error("Invalid gitbook repository, need SUMMARY.md and README.md"));
} else {
// Generate the book
- return fs.readFile(path.join(options.input, "SUMMARY.md"), "utf-8")
+ return Q()
+
+ // Read readme
+ .then(function() {
+ return fs.readFile(path.join(options.input, "README.md"), "utf-8")
+ .then(function(_readme) {
+ _readme = parse.readme(_readme);
+
+ options.title = options.title || _readme.title;
+ options.description = options.description || _readme.description || defaultDescription;
+ });
+ })
// Get summary
- .then(function(_summary) {
- options.summary = parse.summary(_summary);
+ .then(function() {
+ return fs.readFile(path.join(options.input, "SUMMARY.md"), "utf-8")
+ .then(function(_summary) {
+ options.summary = parse.summary(_summary);
+
+ // Parse navigation
+ options.navigation = parse.navigation(options.summary);
+ });
+ })
- // Parse navigation
- options.navigation = parse.navigation(options.summary);
+ // Skip processing some files
+ .then(function() {
+ files = _.filter(files, function (file) {
+ return !(
+ file === 'SUMMARY.md'
+ );
+ });
})
// Copy file and replace markdown file
@@ -142,7 +173,66 @@ var generate = function(options) {
});
};
+/*
+ * Extract files from generate output in a temporary folder
+ */
+var generateFile = function(options) {
+ options = _.defaults(options || {}, {
+ input: null,
+ output: null,
+ extension: null
+ });
+
+ return Q.nfcall(tmp.dir)
+ .then(function(tmpDir) {
+ return generate(
+ _.extend({},
+ options,
+ {
+ output: tmpDir
+ })
+ )
+ .then(function(_options) {
+ var ext = options.extension;
+ var outputFile = options.output || path.resolve(options.input, "book."+ext);
+
+ var copyFile = function(lang) {
+ var _outputFile = outputFile;
+ var _tmpDir = tmpDir;
+
+ if (lang) {
+ _outputFile = _outputFile.slice(0, -path.extname(_outputFile).length)+"_"+lang+path.extname(_outputFile);
+ _tmpDir = path.join(_tmpDir, lang);
+ }
+
+ return fs.copy(
+ path.join(_tmpDir, "index."+ext),
+ _outputFile
+ );
+ };
+
+ // Multi-langs book
+ return Q()
+ .then(function() {
+ if (_options.langsSummary) {
+ return Q.all(
+ _.map(_options.langsSummary.list, function(lang) {
+ return copyFile(lang.lang);
+ })
+ );
+ } else {
+ return copyFile();
+ }
+ })
+ .then(function() {
+ return fs.remove(tmpDir);
+ });
+ });
+ });
+};
+
module.exports = {
generators: generators,
- folder: generate
+ folder: generate,
+ file: generateFile
};
diff --git a/lib/parse/index.js b/lib/parse/index.js
index 0e333e4..0ebb03a 100644
--- a/lib/parse/index.js
+++ b/lib/parse/index.js
@@ -5,4 +5,5 @@ module.exports = {
lex: require('./lex'),
progress: require('./progress'),
navigation: require('./navigation'),
+ readme: require('./readme')
};
diff --git a/lib/parse/lex.js b/lib/parse/lex.js
index 813dd33..17eab69 100644
--- a/lib/parse/lex.js
+++ b/lib/parse/lex.js
@@ -56,7 +56,7 @@ function isQuiz(nodes) {
if(
// List of questions
- listIdx !== -1 && isQuizNode(quizNodes[listIdx + 1]) &&
+ listIdx !== -1 && isQuizNode(quizNodes[listIdx + 1]) ||
// Table of questions
(
diff --git a/lib/parse/page.js b/lib/parse/page.js
index eb118e4..efadf82 100644
--- a/lib/parse/page.js
+++ b/lib/parse/page.js
@@ -8,17 +8,6 @@ var renderer = require('./renderer');
var lnormalize = require('../utils/lang').normalize;
-// Synchronous highlighting with highlight.js
-marked.setOptions({
- highlight: function (code, lang) {
- try {
- return hljs.highlight(lang, code).value;
- } catch(e) {
- return hljs.highlightAuto(code).value;
- }
- }
-});
-
// Render a section using our custom renderer
function render(section, _options) {
@@ -30,7 +19,16 @@ function render(section, _options) {
// Build options using defaults and our custom renderer
var options = _.extend({}, marked.defaults, {
- renderer: renderer(null, _options)
+ renderer: renderer(null, _options),
+
+ // Synchronous highlighting with highlight.js
+ highlight: function (code, lang) {
+ try {
+ return hljs.highlight(lang, code).value;
+ } catch(e) {
+ return hljs.highlightAuto(code).value;
+ }
+ }
});
return marked.parser(section, options);
diff --git a/lib/parse/readme.js b/lib/parse/readme.js
new file mode 100644
index 0000000..aab094d
--- /dev/null
+++ b/lib/parse/readme.js
@@ -0,0 +1,32 @@
+var _ = require('lodash');
+var marked = require('marked');
+
+function extractFirstNode(nodes, nType) {
+ return _.chain(nodes)
+ .filter(function(node) {
+ return node.type == nType;
+ })
+ .pluck("text")
+ .first()
+ .value();
+}
+
+
+function parseReadme(src) {
+ var nodes, title, description;
+
+ // Parse content
+ nodes = marked.lexer(src);
+
+ var title = extractFirstNode(nodes, "heading");
+ var description = extractFirstNode(nodes, "paragraph");
+
+ return {
+ title: title,
+ description: description
+ };
+}
+
+
+// Exports
+module.exports = parseReadme;