diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/book.js | 11 | ||||
-rw-r--r-- | lib/generators/ebook.js | 3 | ||||
-rw-r--r-- | lib/generators/website.js | 4 | ||||
-rw-r--r-- | lib/utils/fs.js | 22 | ||||
-rw-r--r-- | lib/utils/images.js | 29 | ||||
-rw-r--r-- | lib/utils/page.js | 75 |
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 |