summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/book.js11
-rw-r--r--lib/generators/ebook.js3
-rw-r--r--lib/generators/website.js4
-rw-r--r--lib/utils/fs.js22
-rw-r--r--lib/utils/images.js29
-rw-r--r--lib/utils/page.js75
6 files changed, 138 insertions, 6 deletions
diff --git a/lib/book.js b/lib/book.js
index cadc9f5..4e4279a 100644
--- a/lib/book.js
+++ b/lib/book.js
@@ -456,6 +456,9 @@ Book.prototype.parseGlossary = function() {
Book.prototype.parsePage = function(filename, options) {
var that = this, page = {};
options = _.defaults(options || {}, {
+ // Transform svg images
+ convertImages: false,
+
// Interpolate before templating
interpolateTemplate: _.identity,
@@ -514,14 +517,20 @@ Book.prototype.parsePage = function(filename, options) {
// Prepare html
.then(function(_page) {
- page.sections = pageUtil.normalize(_page.sections, {
+ return pageUtil.normalize(_page.sections, {
+ book: that,
+ convertImages: options.convertImages,
input: filename,
navigation: that.navigation,
base: path.dirname(filename) || './',
output: path.dirname(filename) || './',
glossary: that.glossary
});
+ })
+ // Interpolate output
+ .then(function(_sections) {
+ page.sections = _sections;
return interpolate(options.interpolateContent);
})
diff --git a/lib/generators/ebook.js b/lib/generators/ebook.js
index 237e22e..b63c6b0 100644
--- a/lib/generators/ebook.js
+++ b/lib/generators/ebook.js
@@ -16,6 +16,9 @@ var Generator = function(book, format) {
// Styles to use
this.styles = _.compact(["ebook", this.ebookFormat]);
+
+ // Convert images (svg -> png)
+ this.convertImages = true;
};
util.inherits(Generator, BaseGenerator);
diff --git a/lib/generators/website.js b/lib/generators/website.js
index 480e56b..0187416 100644
--- a/lib/generators/website.js
+++ b/lib/generators/website.js
@@ -24,6 +24,9 @@ var Generator = function() {
// Style to integrates in the output
this.styles = ["website"];
+ // Convert images (svg -> png)
+ this.convertImages = false;
+
// Templates
this.templates = {};
};
@@ -127,6 +130,7 @@ Generator.prototype.convertFile = function(input) {
var that = this;
return that.book.parsePage(input, {
+ convertImages: that.convertImages,
interpolateTemplate: function(page) {
return that.callHook("page:before", page);
},
diff --git a/lib/utils/fs.js b/lib/utils/fs.js
index 8d8c189..e434953 100644
--- a/lib/utils/fs.js
+++ b/lib/utils/fs.js
@@ -43,9 +43,27 @@ var fsUtils = {
},
existsSync: fs.existsSync.bind(fs),
readFileSync: fs.readFileSync.bind(fs),
- clean: cleanFolder
+ clean: cleanFolder,
+ getUniqueFilename: getUniqueFilename
}
+// Find a filename available
+function getUniqueFilename(base) {
+ var ext = path.extname(base);
+ base = path.join(path.dirname(base), path.basename(base, ext));
+
+ var filename = base+ext;
+
+ var i = 0;
+ while (1) {
+ if (!fs.existsSync(filename)) break;
+ filename = base+"_"+i+ext;
+ i = i + 1;
+ }
+
+ return filename;
+};
+
// List files in a directory
function listFiles(root, options) {
@@ -112,7 +130,7 @@ function cleanFolder(root) {
var _file = path.join(root, file);
d.notify({
- i: i,
+ i: i+1,
count: files.length,
file: _file
});
diff --git a/lib/utils/images.js b/lib/utils/images.js
new file mode 100644
index 0000000..5a39927
--- /dev/null
+++ b/lib/utils/images.js
@@ -0,0 +1,29 @@
+var _ = require("lodash");
+var Q = require("q");
+var fs = require("fs");
+var gm = require("gm");
+
+
+var convert = function(source, dest, options) {
+ var d = Q.defer();
+ options = _.defaults(options || {}, {
+ resize: null
+ });
+
+ var img = gm(source)
+ .options({
+ imageMagick: true
+ });
+
+ if (options.resize) img = img.resize(options.resize.w, options.resize.h);
+
+ img.noProfile()
+ .write(dest, d.makeNodeResolver());
+
+ return d.promise;
+};
+
+module.exports = {
+ convert: convert,
+ INVALID: [".svg"]
+};
diff --git a/lib/utils/page.js b/lib/utils/page.js
index 525722e..e526afb 100644
--- a/lib/utils/page.js
+++ b/lib/utils/page.js
@@ -1,8 +1,11 @@
+var Q = require('q');
var _ = require('lodash');
var path = require('path');
var cheerio = require('cheerio');
var links = require('./links');
+var imgUtils = require('./images');
+var fs = require('./fs');
function replaceText($, el, search, replace, text_only ) {
return $(el).each(function(){
@@ -61,6 +64,7 @@ function pregQuote( str ) {
// Adapt an html snippet to be relative to a base folder
function normalizeHtml(src, options) {
var $ = cheerio.load(src);
+ var toConvert = [];
$("img").each(function() {
var src = $(this).attr("src");
@@ -70,6 +74,31 @@ function normalizeHtml(src, options) {
src = links.toAbsolute(src, options.base, options.output);
}
+ // Convert if needed
+ if (options.convertImages) {
+ var ext = path.extname(src);
+ if (_.contains(imgUtils.INVALID, ext)) {
+ // Replace extension
+ var dest = path.join(path.dirname(src), path.basename(src, ext)+".png");
+
+ // Absolute with input
+ dest = path.resolve(options.book.root, dest);
+
+ // Get a name that doesn't exists
+ dest = fs.getUniqueFilename(dest);
+
+ // Reset as relative to book
+ dest = path.relative(options.book.root, dest);
+
+ options.book.log.debug.ln("detect invalid image (will be converted to png):", src);
+ toConvert.push({
+ source: src,
+ dest: dest
+ });
+ src = dest;
+ }
+ }
+
$(this).attr("src", src);
});
@@ -109,13 +138,40 @@ function normalizeHtml(src, options) {
});
});
- return $.html();
+ return {
+ html: $.html(),
+ images: toConvert
+ };
+};
+
+// Convert svg images to png
+function convertImages(images, options) {
+ return _.reduce(images, function(prev, image) {
+ return prev.then(function() {
+ var imgin = path.resolve(options.book.root, image.source);
+ var imgout = path.resolve(options.book.options.output, image.dest);
+
+ options.book.log.debug("convert image", image.source, "to", image.dest, "...");
+ return imgUtils.convert(imgin, imgout)
+ .then(function() {
+ options.book.log.debug.ok();
+ }, function() {
+ options.book.log.debug.fail();
+ });
+ });
+ }, Q());
};
// Adapt page content to be relative to a base folder
function normalizePage(sections, options) {
options = _.defaults(options || {}, {
+ // Current book
+ book: null,
+
+ // Do we need to convert svg?
+ convertImages: false,
+
// Current file path
input: ".",
@@ -132,11 +188,24 @@ function normalizePage(sections, options) {
glossary: []
});
- return _.map(sections, function(section) {
+ // List of images to convert
+ var toConvert = [];
+
+ sections = _.map(sections, function(section) {
if (section.type != "normal") return section;
- section.content = normalizeHtml(section.content, options);
+
+ var out = normalizeHtml(section.content, options);;
+
+ toConvert = toConvert.concat(out.images);
+ section.content = out.html;
return section;
});
+
+ return Q()
+ .then(function() {
+ return convertImages(toConvert, options);
+ })
+ .thenResolve(sections);
};
// Extract text from sections