Files
gitbook/lib/generators/website.js
T
2015-01-27 12:49:08 +01:00

279 lines
7.7 KiB
JavaScript

var util = require("util");
var path = require("path");
var Q = require("q");
var _ = require("lodash");
var nunjucks = require("nunjucks");
var AutoEscapeExtension = require("nunjucks-autoescape");
var FilterExtension = require("nunjucks-filter");
var I18nExtension = require("nunjucks-i18n");
var fs = require("../utils/fs");
var BaseGenerator = require("../generator");
var links = require("../utils/links");
var pageUtil = require("../utils/page");
var pkg = require("../../package.json");
var Generator = function() {
BaseGenerator.apply(this, arguments);
// revision
this.revision = new Date();
// Style to integrates in the output
this.styles = ["website"];
// Templates
this.templates = {};
};
util.inherits(Generator, BaseGenerator);
// Prepare the genertor
Generator.prototype.prepare = function() {
return BaseGenerator.prototype.prepare.apply(this)
.then(this.prepareStyles)
.then(this.prepareTemplates)
.then(this.prepareTemplateEngine);
};
// Prepare all styles
Generator.prototype.prepareStyles = function() {
var that = this;
this.styles = _.chain(this.styles)
.map(function(style) {
var stylePath = that.options.styles[style];
if (fs.existsSync(path.resolve(that.book.root, stylePath))) {
return stylePath;
}
return null;
})
.compact()
.value();
return Q();
};
// Prepare templates
Generator.prototype.prepareTemplates = function() {
this.templates["page"] = this.book.plugins.template("site:page") || path.resolve(this.options.theme, 'templates/website/page.html');
this.templates["langs"] = this.book.plugins.template("site:langs") || path.resolve(this.options.theme, 'templates/website/langs.html');
this.templates["glossary"] = this.book.plugins.template("site:glossary") || path.resolve(this.options.theme, 'templates/website/glossary.html');
return Q();
};
// Prepare template engine
Generator.prototype.prepareTemplateEngine = function() {
var that = this;
return fs.readdir(path.resolve(__dirname, "../../theme/i18n"))
.then(function(locales) {
var language = that.book.config.normalizeLanguage();
locales = _.chain(locales)
.map(function(local) {
local = path.basename(local, ".json");
return [local, require("../../theme/i18n/"+local)];
})
.object()
.value();
if (!_.contains(_.keys(locales), language) && language != "en") {
that.book.log.warn.ln("Language '"+language+"' is not available as a layout locales (en, "+_.keys(locales).join(", ")+")");
}
var folders = _.chain(that.templates)
.values()
.map(path.dirname)
.uniq()
.value();
that.env = new nunjucks.Environment(
new nunjucks.FileSystemLoader(folders),
{
autoescape: true
}
);
// Add filter
that.env.addFilter("contentLink", that.book.contentLink.bind(that.book));
that.env.addFilter('lvl', function(lvl) {
return lvl.split(".").length;
});
// Add extension
that.env.addExtension('AutoEscapeExtension', new AutoEscapeExtension(that.env));
that.env.addExtension('FilterExtension', new FilterExtension(that.env));
that.env.addExtension('I18nExtension', new I18nExtension({
env: that.env,
translations: locales,
locale: "language"
}));
});
};
// Finis generation
Generator.prototype.finish = function() {
return this.copyAssets()
.then(this.copyCover)
.then(this.writeGlossary)
.then(this.writeSearchIndex);
};
// Convert an input file
Generator.prototype.convertFile = function(input) {
var that = this;
return that.book.parsePage(input, {
interpolateTemplate: function(page) {
return that.callHook("page:before", page);
},
interpolateContent: function(page) {
return that.callHook("page", page);
}
})
.then(function(page) {
var relativeOutput = that.book.contentLink(page.path);
var output = path.join(that.options.output, relativeOutput);
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);
return that._writeTemplate(that.templates["page"], {
progress: page.progress,
_input: page.path,
content: page.sections,
basePath: basePath,
staticBase: links.join(basePath, "gitbook")
}, output);
});
};
// Write the index for langs
Generator.prototype.langsIndex = function(langs) {
var that = this;
return this._writeTemplate(this.templates["langs"], {
langs: langs
}, path.join(this.options.output, "index.html"));
};
// Write glossary
Generator.prototype.writeGlossary = function() {
var that = this;
// No glossary
if (this.book.glossary.length == 0) return Q();
return this._writeTemplate(this.templates["glossary"], {}, path.join(this.options.output, "GLOSSARY.html"));
};
// Write the search index
Generator.prototype.writeSearchIndex = function() {
var that = this;
return fs.writeFile(
path.join(this.options.output, "search_index.json"),
JSON.stringify(this.book.searchIndex)
);
};
// Convert a page into a normalized data set
Generator.prototype.normalizePage = function(page) {
var that = this;
var _callHook = function(name) {
return that.callHook(name, page)
.then(function(_page) {
page = _page;
return page;
});
};
return Q()
.then(function() {
return _callHook("page");
})
.then(function() {
return page;
});
};
// Generate a template
Generator.prototype._writeTemplate = function(tpl, options, output, interpolate) {
var that = this;
interpolate = interpolate || _.identity;
return Q()
.then(function(sections) {
return that.env.render(
tpl,
_.extend({
gitbook: {
version: pkg.version
},
styles: that.styles,
revision: that.revision,
title: that.options.title,
description: that.options.description,
language: that.book.config.normalizeLanguage(),
glossary: that.book.glossary,
summary: that.book.summary,
allNavigation: that.book.navigation,
plugins: that.book.plugins,
pluginsConfig: JSON.stringify(that.options.pluginsConfig),
htmlSnippet: _.partialRight(that.book.plugins.html, that, options),
options: that.options,
basePath: ".",
staticBase: path.join(".", "gitbook"),
}, options)
);
})
.then(interpolate)
.then(function(html) {
return fs.writeFile(
output,
html
);
});
};
// Copy assets
Generator.prototype.copyAssets = function() {
var that = this;
// Copy gitbook assets
return fs.copy(
path.join(that.options.theme, "assets"),
path.join(that.options.output, "gitbook")
)
// Copy plugins assets
.then(function() {
return Q.all(
_.map(that.book.plugins.list, function(plugin) {
var pluginAssets = path.join(that.options.output, "gitbook/plugins/", plugin.name);
return plugin.copyAssets(pluginAssets, {
base: "book"
});
})
);
});
};
module.exports = Generator;