Files
gitbook/lib/book.js
T
2015-01-19 15:26:31 +01:00

210 lines
4.4 KiB
JavaScript

var Q = require("q");
var _ = require("lodash");
var path = require("path");
var fs = require("./utils/fs");
var Configuration = require("./configuration");
var TemplateEngine = require("./template");
var parser = require("./parser");
var Book = function(root, options, parent) {
// Root folder of the book
this.root = root;
// Parent book
this.parent = parent;
// Configuration
this.config = new Configuration(this, options);
Object.defineProperty(this, "options", {
get: function () {
return this.config.options;
}
});
// Template
this.template = new TemplateEngine(this);
// Summary
this.summary = {};
// Glossary
this.glossary = [];
// Langs
this.langs = [];
};
// Initialize and parse the book: config, summary, glossary
Book.prototype.init = function() {
var that = this;
var multilingal = false;
return this.config.load()
.then(function() {
return that.parseLangs()
.then(function() {
multilingal = that.langs.length > 0;
// Sub-books that inherit from the current book configuration
that.books = _.map(that.langs, function(lang) {
return new Book(
path.join(that.root, lang.path),
_.extend({}, that.options, {
'output': path.join(that.options.output, lang.path),
'lang': lang.lang
}),
that
)
});
});
})
.then(function() {
if (multilingal) return;
return that.parseReadme();
})
.then(function() {
if (multilingal) return;
return that.parseSummary();
})
.then(function() {
if (multilingal) return;
return that.parseGlossary();
})
.thenResolve(this);
};
// Generate the output
Book.prototype.generate = function() {
var that = this;
return this.init()
.then(function() {
});
};
// Parse readme to extract defaults title and description
Book.prototype.parseReadme = function() {
var that = this;
return that.findFile(that.config.getStructure("readme"))
.then(function(readme) {
if (!readme) throw "No README file";
return that.template.renderFile(readme.path)
.then(function(content) {
return readme.parser.readme(content);
});
})
.then(function(readme) {
that.options.title = that.options.title || readme.title;
that.options.description = that.options.description || readme.description;
});
};
// Parse langs to extract list of sub-books
Book.prototype.parseLangs = function() {
var that = this;
return that.findFile(that.config.getStructure("langs"))
.then(function(langs) {
if (!langs) return [];
return that.template.renderFile(langs.path)
.then(function(content) {
return langs.parser.langs(content);
});
})
.then(function(langs) {
that.langs = langs;
});
};
// Parse summary to extract list of chapters
Book.prototype.parseSummary = function() {
var that = this;
return Q.all([
that.findFile(that.config.getStructure("summary")),
that.findFile(that.config.getStructure("readme"))
])
.spread(function(summary, readme) {
if (!summary) throw "No SUMMARY file";
return that.template.renderFile(summary.path)
.then(function(content) {
return summary.parser.summary(content, readme.path);
});
})
.then(function(summary) {
that.summary = summary;
});
};
// Parse glossary to extract terms
Book.prototype.parseGlossary = function() {
var that = this;
return that.findFile(that.config.getStructure("glossary"))
.then(function(glossary) {
if (!glossary) return {};
return that.template.renderFile(glossary.path)
.then(function(content) {
return glossary.parser.glossary(content);
});
})
.then(function(glossary) {
that.glossary = glossary;
});
};
// Find file that can be parsed with a specific filename
Book.prototype.findFile = function(filename) {
var that = this;
return _.reduce(parser.extensions, function(prev, ext) {
return prev.then(function(output) {
// Stop if already find a parser
if (output) return output;
var filepath = filename+ext;
return that.fileExists(filepath)
.then(function(exists) {
if (!exists) return null;
return {
parser: parser.get(ext).parser,
path: filepath
};
})
});
}, Q(null));
};
// Check if a file exists in the book
Book.prototype.fileExists = function(filename) {
return fs.exists(
path.join(this.root, filename)
);
};
// Read a file
Book.prototype.readFile = function(filename) {
return fs.readFile(
path.join(this.root, filename),
{ encoding: "utf8" }
);
};
// Return stat for a file
Book.prototype.statFile = function(filename) {
return fs.stat(path.join(this.root, filename));
};
module.exports= Book;