mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-16 23:55:20 +00:00
Improve performance of svg conversion
This commit is contained in:
@@ -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;
|
||||
|
||||
+17
-1
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -80,7 +80,7 @@ function uniqueFilename(base, filename) {
|
||||
i = i + 1;
|
||||
}
|
||||
|
||||
return path.relative(base, _filename);
|
||||
return Promise(path.relative(base, _filename));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -14,7 +14,8 @@ describe('Assets Inliner Output', function() {
|
||||
return mock.outputDefaultBook(AssetsInliner, {
|
||||
'README.md': '',
|
||||
'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?
|
||||
|
||||
Reference in New Issue
Block a user