Implement better handling of Raster#source and Raster#toDataURL() on Node.js

Closes #914
This commit is contained in:
Jürg Lehni 2016-01-22 17:05:50 +01:00
parent 381d015f98
commit 36e31eb250
2 changed files with 40 additions and 16 deletions

View file

@ -30,10 +30,11 @@
}, },
"dependencies": { "dependencies": {
"jsdom": ">=3.1.2 <8.0.0", "jsdom": ">=3.1.2 <8.0.0",
"request": "~2.61.0" "mime": "^1.3.0",
"request": "^2.61.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"canvas": ">=1.2.9 <2.0.0" "canvas": "^1.2.9"
}, },
"devDependencies": { "devDependencies": {
"del": "^2.2.0", "del": "^2.2.0",

View file

@ -323,7 +323,12 @@ var Raster = Item.extend(/** @lends Raster# */{
* }); * });
*/ */
getSource: function() { getSource: function() {
return this._image && this._image.src || this.toDataURL(); var image = this._image;
/*#*/ if (__options.environment == 'node') {
// See #toDataURL()
image = image && this._src;
/*#*/ } // __options.environment == 'node'
return image && image.src || this.toDataURL();
}, },
setSource: function(src) { setSource: function(src) {
@ -367,9 +372,9 @@ var Raster = Item.extend(/** @lends Raster# */{
// If we're running on the server and it's a string, // If we're running on the server and it's a string,
// check if it is a data URL // check if it is a data URL
if (/^data:/.test(src)) { if (/^data:/.test(src)) {
// Preserve the data in this._data since canvas-node eats it. // Preserve the data in this._src since canvas-node eats it.
// TODO: Fix canvas-node instead image.src = src;
image.src = this._data = src; this._src = { src: src, data: src };
// Emit load event with a delay, so behavior is the same as when // Emit load event with a delay, so behavior is the same as when
// it's actually loaded and we give the code time to install event. // it's actually loaded and we give the code time to install event.
setTimeout(loaded, 0); setTimeout(loaded, 0);
@ -378,20 +383,31 @@ var Raster = Item.extend(/** @lends Raster# */{
require('request').get({ require('request').get({
url: src, url: src,
encoding: null // So the response data is a Buffer encoding: null // So the response data is a Buffer
}, function (err, response, data) { }, function (err, response, buffer) {
if (err) if (err)
throw err; throw err;
if (response.statusCode == 200) { if (response.statusCode == 200) {
image.src = this._data = data; image.src = buffer;
that._src = {
src: src,
buffer: buffer,
type: response.headers['content-type']
};
loaded(); loaded();
} }
}); });
} else { } else {
// Load it from disk: // Load it from disk:
require('fs').readFile(src, function (err, data) { src = (src.match(/^file:\/\/(.*)$/) || [null, src])[1];
require('fs').readFile(src, function (err, buffer) {
if (err) if (err)
throw err; throw err;
image.src = this._data = data; image.src = buffer;
that._src = {
src: 'file://' + src,
buffer: buffer,
type: require('mime').lookup(src)
};
loaded(); loaded();
}); });
} }
@ -483,17 +499,24 @@ var Raster = Item.extend(/** @lends Raster# */{
toDataURL: function() { toDataURL: function() {
// See if the linked image is base64 encoded already, if so reuse it, // See if the linked image is base64 encoded already, if so reuse it,
// otherwise try using canvas.toDataURL() // otherwise try using canvas.toDataURL()
var image = this._image,
src;
/*#*/ if (__options.environment == 'node') { /*#*/ if (__options.environment == 'node') {
if (this._data) { // Only use the information stored in _src if we still use the _image
if (this._data instanceof Buffer) // that goes with it.
this._data = this._data.toString('base64'); var obj = image && this._src;
return this._data; if (obj) {
if (!obj.data) {
obj.data = 'data:' + obj.type + ';base64,' +
obj.buffer.toString('base64');
}
src = obj.data;
} }
/*#*/ } else { /*#*/ } else {
var src = this._image && this._image.src; src = image && image.src;
/*#*/ } // __options.environment == 'node'
if (/^data:/.test(src)) if (/^data:/.test(src))
return src; return src;
/*#*/ }
var canvas = this.getCanvas(); var canvas = this.getCanvas();
return canvas ? canvas.toDataURL.apply(canvas, arguments) : null; return canvas ? canvas.toDataURL.apply(canvas, arguments) : null;
}, },