summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/output/assets-inliner.js95
-rw-r--r--lib/output/folder.js18
-rw-r--r--lib/utils/fs.js2
-rw-r--r--test/assets-inliner.js5
4 files changed, 94 insertions, 26 deletions
diff --git a/lib/output/assets-inliner.js b/lib/output/assets-inliner.js
index 2156bef..fb348b4 100644
--- a/lib/output/assets-inliner.js
+++ b/lib/output/assets-inliner.js
@@ -1,6 +1,6 @@
-var _ = require('lodash');
var util = require('util');
var path = require('path');
+var crc = require('crc');
var FolderOutput = require('./folder');
var Promise = require('../utils/promise');
@@ -13,52 +13,50 @@ var DEFAULT_ASSETS_FOLDER = 'assets';
/*
Utility mixin to inline all the assets in a book:
- Outline <svg> tags
- - Convert svg images as png
- Download remote images
+ - Convert .svg images as png
*/
function AssetsInliner() {
FolderOutput.apply(this, arguments);
+
+ // Map of svg already converted
+ this.svgs = {};
+ this.inlineSvgs = {};
+
+ // Map of images already downloaded
+ this.downloaded = {};
}
util.inherits(AssetsInliner, FolderOutput);
// Output a SVG buffer as a file
AssetsInliner.prototype.onOutputSVG = function(page, svg) {
this.log.debug.ln('output svg from', page.path);
- var filename = _.uniqueId('svg_') + '.png';
// Convert svg buffer to a png file
- return imagesUtil.convertSVGBufferToPNG(svg, this.resolve(filename))
+ return this.convertSVGBuffer(svg)
// Return relative path from the page
- .thenResolve(function() {
+ .then(function(filename) {
return page.relative('/' + filename);
});
};
+
// Output an image as a file
AssetsInliner.prototype.onOutputImage = function(page, src) {
var that = this;
- var isSVG = false;
- var ext = path.extname(src).toLowerCase();
- if (ext == '.svg') {
- isSVG = false;
- ext = '.png';
- }
return Promise()
- // Allocate a new file
- .then(function() {
-
- return that.
- })
-
// Download file if external
.then(function() {
if (!location.isExternal(src)) return;
- return fs.download(src, )
+ return that.downloadAsset(src)
+ .then(function(_asset) {
+ src = '/' + _asset;
+ });
})
.then(function() {
@@ -67,16 +65,69 @@ AssetsInliner.prototype.onOutputImage = function(page, src) {
}
// Convert SVG to PNG
- var filename = _.uniqueId('svg_') + '.png';
- return imagesUtil.convertSVGToPNG(page.resolve(src), this.resolve(filename))
- .thenResolve('/' + filename);
+ return that.convertSVGFile(page.resolve(src));
})
// Return relative path from the page
- .thenResolve(function(filename) {
+ .then(function(filename) {
return page.relative('/' + filename);
});
};
+// Download an asset if not already download; returns the output file
+AssetsInliner.prototype.downloadAsset = function(src) {
+ if (this.downloaded[src]) return Promise(this.downloaded[src]);
+
+ var that = this;
+ var ext = path.extname(src);
+ var hash = crc.crc32(src).toString(16);
+
+ // Create new file
+ return this.createNewFile(DEFAULT_ASSETS_FOLDER, hash + ext)
+ .then(function(filename) {
+ that.downloaded[src] = filename;
+
+ that.log.debug.ln('downloading asset', src);
+ return fs.download(src, filename)
+ .thenResolve(filename);
+ });
+};
+
+// Convert a .svg into an .png
+// Return the output filename for the .png
+AssetsInliner.prototype.convertSVGFile = function(src) {
+ if (this.svgs[src]) return Promise(this.svgs[src]);
+
+ var that = this;
+ var hash = crc.crc32(src).toString(16);
+
+ // Create new file
+ return this.createNewFile(DEFAULT_ASSETS_FOLDER, hash + '.png')
+ .then(function(filename) {
+ that.svgs[src] = filename;
+
+ return imagesUtil.convertSVGToPNG(src, that.resolve(filename))
+ .thenResolve(filename);
+ });
+};
+
+// Convert an inline svg into an .png
+// Return the output filename for the .png
+AssetsInliner.prototype.convertSVGBuffer = function(buf) {
+ var that = this;
+ var hash = crc.crc32(buf).toString(16);
+
+ // Already converted?
+ if (this.inlineSvgs[hash]) return Promise(this.inlineSvgs[hash]);
+
+ return this.createNewFile(DEFAULT_ASSETS_FOLDER, hash + '.png')
+ .then(function(filename) {
+ that.inlineSvgs[hash] = filename;
+
+ return imagesUtil.convertSVGBufferToPNG(buf, that.resolve(filename))
+ .thenResolve(filename);
+ });
+};
+
module.exports = AssetsInliner;
diff --git a/lib/output/folder.js b/lib/output/folder.js
index aabdcc4..8b899f6 100644
--- a/lib/output/folder.js
+++ b/lib/output/folder.js
@@ -34,7 +34,7 @@ FolderOutput.prototype.prepare = function() {
// ----- Utility methods -----
// Return path to the root folder
-FolderOutput.prototype.root = function(filename) {
+FolderOutput.prototype.root = function() {
return path.resolve(process.cwd(), this.book.config.get('output'));
};
@@ -74,10 +74,26 @@ FolderOutput.prototype.writeFile = function(filename, buf) {
});
};
+// Return true if a file exists in the output folder
+FolderOutput.prototype.hasFile = function(filename) {
+ var that = this;
+
+ return Promise()
+ .then(function() {
+ return fs.exists(that.resolve(filename));
+ });
+};
+
+
// Create a new unique file
// Returns its filename
FolderOutput.prototype.createNewFile = function(base, filename) {
+ if (!filename) {
+ filename = path.basename(filename);
+ base = path.dirname(base);
+ }
+ return fs.uniqueFilename(this.resolve(base), filename);
};
diff --git a/lib/utils/fs.js b/lib/utils/fs.js
index bf5e51d..3f1c11f 100644
--- a/lib/utils/fs.js
+++ b/lib/utils/fs.js
@@ -80,7 +80,7 @@ function uniqueFilename(base, filename) {
i = i + 1;
}
- return path.relative(base, _filename);
+ return Promise(path.relative(base, _filename));
}
module.exports = {
diff --git a/test/assets-inliner.js b/test/assets-inliner.js
index cb02e42..76b04f6 100644
--- a/test/assets-inliner.js
+++ b/test/assets-inliner.js
@@ -14,7 +14,8 @@ describe('Assets Inliner Output', function() {
return mock.outputDefaultBook(AssetsInliner, {
'README.md': '![image](test.svg)',
'inline.md': 'This is a svg: '+SVG,
- 'test.svg': '<?xml version="1.0" encoding="UTF-8"?>' + SVG
+ 'test.svg': '<?xml version="1.0" encoding="UTF-8"?>' + SVG,
+ 'SUMMARY.md': '* [inline](inline.md)\n\n'
})
.then(function(_output) {
output = _output;
@@ -35,7 +36,7 @@ describe('Assets Inliner Output', function() {
});
it('should correctly inline SVG convert to PNG', function() {
- var page = output.book.addPage('README.md');
+ var page = output.book.getPage('inline.md');
var $ = cheerio.load(page.content);
// Is there an image?