Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/assets/geo_assets.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
var saneTopojson = require('sane-topojson');


// package version injected by `npm run preprocess`
exports.version = '1.52.2';
exports.version = require('../version').version;

exports.topojson = saneTopojson;
3 changes: 1 addition & 2 deletions src/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@

'use strict';

// package version injected by `npm run preprocess`
exports.version = '1.52.2';
exports.version = require('./version').version;

// inject promise polyfill
require('es6-promise').polyfill();
Expand Down
24 changes: 21 additions & 3 deletions src/plot_api/to_image.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,18 @@
var isNumeric = require('fast-isnumeric');

var plotApi = require('./plot_api');
var plots = require('../plots/plots');
var Lib = require('../lib');

var helpers = require('../snapshot/helpers');
var toSVG = require('../snapshot/tosvg');
var svgToImg = require('../snapshot/svgtoimg');
var version = require('../version').version;

var attrs = {
format: {
valType: 'enumerated',
values: ['png', 'jpeg', 'webp', 'svg'],
values: ['png', 'jpeg', 'webp', 'svg', 'full-json'],
dflt: 'png',
description: 'Sets the format of exported image.'
},
Expand Down Expand Up @@ -170,8 +172,24 @@ function toImage(gd, opts) {
var width = clonedGd._fullLayout.width;
var height = clonedGd._fullLayout.height;

plotApi.purge(clonedGd);
document.body.removeChild(clonedGd);
function cleanup() {
plotApi.purge(clonedGd);
document.body.removeChild(clonedGd);
}

if(format === 'full-json') {
var json = plots.graphJson(clonedGd, false, 'keepdata', 'object', true, true);
json.version = version;
json = JSON.stringify(json);
cleanup();
if(imageDataOnly) {
return resolve(json);
} else {
return resolve(helpers.encodeJSON(json));
}
}

cleanup();

if(format === 'svg') {
if(imageDataOnly) {
Expand Down
20 changes: 13 additions & 7 deletions src/plots/plots.js
Original file line number Diff line number Diff line change
Expand Up @@ -2037,9 +2037,10 @@ plots.didMarginChange = function(margin0, margin1) {
* keepall: keep data and src
* @param {String} output If you specify 'object', the result will not be stringified
* @param {Boolean} useDefaults If truthy, use _fullLayout and _fullData
* @param {Boolean} includeConfig If truthy, include _context
* @returns {Object|String}
*/
plots.graphJson = function(gd, dataonly, mode, output, useDefaults) {
plots.graphJson = function(gd, dataonly, mode, output, useDefaults, includeConfig) {
// if the defaults aren't supplied yet, we need to do that...
if((useDefaults && dataonly && !gd._fullData) ||
(useDefaults && !dataonly && !gd._fullLayout)) {
Expand All @@ -2050,18 +2051,21 @@ plots.graphJson = function(gd, dataonly, mode, output, useDefaults) {
var layout = (useDefaults) ? gd._fullLayout : gd.layout;
var frames = (gd._transitionData || {})._frames;

function stripObj(d) {
function stripObj(d, keepFunction) {
if(typeof d === 'function') {
return null;
return keepFunction ? '_function_' : null;
}
if(Lib.isPlainObject(d)) {
var o = {};
var v, src;
for(v in d) {
// remove private elements and functions
// _ is for private, [ is a mistake ie [object Object]
if(typeof d[v] === 'function' ||
['_', '['].indexOf(v.charAt(0)) !== -1) {
if(['_', '['].indexOf(v.charAt(0)) !== -1) continue;

// if a function, add if necessary then move on
if(typeof d[v] === 'function') {
if(keepFunction) o[v] = '_function';
continue;
}

Expand Down Expand Up @@ -2091,13 +2095,13 @@ plots.graphJson = function(gd, dataonly, mode, output, useDefaults) {
}

// OK, we're including this... recurse into it
o[v] = stripObj(d[v]);
o[v] = stripObj(d[v], keepFunction);
}
return o;
}

if(Array.isArray(d)) {
return d.map(stripObj);
return d.map(function(x) {return stripObj(x, keepFunction);});
}

if(Lib.isTypedArray(d)) {
Expand Down Expand Up @@ -2126,6 +2130,8 @@ plots.graphJson = function(gd, dataonly, mode, output, useDefaults) {

if(frames) obj.frames = stripObj(frames);

if(includeConfig) obj.config = stripObj(gd._context, true);

return (output === 'object') ? obj : JSON.stringify(obj);
};

Expand Down
6 changes: 6 additions & 0 deletions src/snapshot/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ exports.encodeSVG = function(svg) {
return 'data:image/svg+xml,' + encodeURIComponent(svg);
};

exports.encodeJSON = function(json) {
return 'data:application/json,' + encodeURIComponent(json);
};

var DOM_URL = window.URL || window.webkitURL;

exports.createObjectURL = function(blob) {
Expand All @@ -49,6 +53,8 @@ exports.revokeObjectURL = function(url) {
exports.createBlob = function(url, format) {
if(format === 'svg') {
return new window.Blob([url], {type: 'image/svg+xml;charset=utf-8'});
} else if(format === 'full-json') {
return new window.Blob([url], {type: 'application/json;charset=utf-8'});
} else {
var binary = fixBinary(window.atob(url));
return new window.Blob([binary], {type: 'image/' + format});
Expand Down
12 changes: 12 additions & 0 deletions src/version.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* Copyright 2012-2020, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

// package version injected by `npm run preprocess`
exports.version = '1.52.2';
3 changes: 1 addition & 2 deletions tasks/preprocess.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ var updateVersion = require('./util/update_version');
// main
makeBuildCSS();
copyTopojsonFiles();
updateVersion(constants.pathToPlotlyCore);
updateVersion(constants.pathToPlotlyGeoAssetsSrc);
updateVersion(constants.pathToPlotlyVersion);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nicely done !!


// convert scss to css to js
function makeBuildCSS() {
Expand Down
1 change: 1 addition & 0 deletions tasks/util/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ module.exports = {

pathToPlotlyIndex: path.join(pathToLib, 'index.js'),
pathToPlotlyCore: path.join(pathToSrc, 'core.js'),
pathToPlotlyVersion: path.join(pathToSrc, 'version.js'),
pathToPlotlyBuild: path.join(pathToBuild, 'plotly.js'),
pathToPlotlyDist: path.join(pathToDist, 'plotly.js'),
pathToPlotlyDistMin: path.join(pathToDist, 'plotly.min.js'),
Expand Down
6 changes: 6 additions & 0 deletions test/jasmine/tests/download_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ describe('Plotly.downloadImage', function() {
.then(done);
}, LONG_TIMEOUT_INTERVAL);

it('should create link, remove link, accept options', function(done) {
downloadTest(gd, 'full-json')
.catch(failTest)
.then(done);
}, LONG_TIMEOUT_INTERVAL);

it('should create link, remove link, accept options', function(done) {
checkWebp(function(supported) {
if(supported) {
Expand Down
39 changes: 39 additions & 0 deletions test/jasmine/tests/toimage_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -263,4 +263,43 @@ describe('Plotly.toImage', function() {
done();
});
});

describe('with format `full-json`', function() {
var imgOpts = {format: 'full-json', imageDataOnly: true};
var gd;

beforeEach(function() {
gd = createGraphDiv();
});
afterEach(destroyGraphDiv);

it('export a graph div', function(done) {
Plotly.plot(gd, [{y: [1, 2, 3]}])
.then(function(gd) { return Plotly.toImage(gd, imgOpts);})
.then(function(fig) {
fig = JSON.parse(fig);
['data', 'layout', 'config'].forEach(function(key) {
expect(fig.hasOwnProperty(key)).toBeTruthy('is missing key: ' + key);
});
expect(fig.data[0].mode).toBe('lines+markers', 'contain default mode');
expect(fig.version).toBe(Plotly.version, 'contains Plotly version');
})
.catch(failTest)
.then(done);
});

it('export an object with data/layout/config', function(done) {
Plotly.toImage({data: [{y: [1, 2, 3]}]}, imgOpts)
.then(function(fig) {
fig = JSON.parse(fig);
['data', 'layout', 'config'].forEach(function(key) {
expect(fig.hasOwnProperty(key)).toBeTruthy('is missing key: ' + key);
});
expect(fig.data[0].mode).toBe('lines+markers', 'contain default mode');
expect(fig.version).toBe(Plotly.version, 'contains Plotly version');
})
.catch(failTest)
.then(done);
});
});
});