Skip to content

Commit 0714747

Browse files
committed
Merge pull request #604 from plotly/toimage-bug
Toimage bug
2 parents 19a3735 + 03b586a commit 0714747

File tree

4 files changed

+86
-56
lines changed

4 files changed

+86
-56
lines changed

src/snapshot/svgtoimg.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ function svgToImg(opts) {
8686
imgData = canvas.toDataURL('image/webp');
8787
break;
8888
case 'svg':
89-
imgData = svg;
89+
imgData = url;
9090
break;
9191
default:
9292
reject(new Error('Image format is not jpeg, png or svg'));

src/snapshot/tosvg.js

+7-16
Original file line numberDiff line numberDiff line change
@@ -78,24 +78,12 @@ module.exports = function toSVG(gd, format) {
7878
return;
7979
}
8080

81-
// I've seen font-family styles with non-escaped double quotes in them - breaks the
82-
// serialized svg because the style attribute itself is double-quoted!
83-
// Is this an IE thing? Any other attributes or style elements that can have quotes in them?
84-
// TODO: this looks like a noop right now - what happened to it?
85-
86-
/*
87-
* Font-family styles with double quotes in them breaks the to-image
88-
* step in FF42 because the style attribute itself is wrapped in
89-
* double quotes. See:
90-
*
91-
* - http://codepen.io/etpinard/pen/bEdQWK
92-
* - https://github.com/plotly/plotly.js/pull/104
93-
*
94-
* for more info.
95-
*/
81+
// Font family styles break things because of quotation marks,
82+
// so we must remove them *after* the SVG DOM has been serialized
83+
// to a string (browsers convert singles back)
9684
var ff = txt.style('font-family');
9785
if(ff && ff.indexOf('"') !== -1) {
98-
txt.style('font-family', ff.replace(/"/g, '\\\''));
86+
txt.style('font-family', ff.replace(/"/g, 'TOBESTRIPPED'));
9987
}
10088
});
10189

@@ -115,5 +103,8 @@ module.exports = function toSVG(gd, format) {
115103
s = svgTextUtils.html_entity_decode(s);
116104
s = svgTextUtils.xml_entity_encode(s);
117105

106+
// Fix quotations around font strings
107+
s = s.replace(/("TOBESTRIPPED)|(TOBESTRIPPED")/g, '\'');
108+
118109
return s;
119110
};

test/jasmine/tests/download_test.js

+77-38
Original file line numberDiff line numberDiff line change
@@ -44,45 +44,84 @@ describe('Plotly.downloadImage', function() {
4444
});
4545

4646
it('should create link, remove link, accept options', function(done) {
47-
//use MutationObserver to monitor the DOM
48-
//for changes
49-
//code modeled after
50-
//https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
51-
// select the target node
52-
var target = document.body;
53-
var domchanges = [];
54-
55-
// create an observer instance
56-
var observer = new MutationObserver(function(mutations) {
57-
mutations.forEach(function(mutation) {
58-
domchanges.push(mutation);
59-
});
60-
});
47+
downloadTest(gd, 'jpeg', done);
48+
});
6149

62-
Plotly.plot(gd, textchartMock.data, textchartMock.layout).then(function(gd) {
63-
// start observing dom
64-
// configuration of the observer:
65-
var config = { childList: true };
66-
67-
// pass in the target node and observer options
68-
observer.observe(target, config);
69-
70-
return Plotly.downloadImage(gd, {format: 'jpeg', height: 300, width: 300, filename: 'plotly_download'});
71-
}).then(function(filename) {
72-
// stop observing
73-
observer.disconnect();
74-
// look for an added and removed link
75-
var linkadded = domchanges[domchanges.length - 2].addedNodes[0].outerHTML;
76-
var linkdeleted = domchanges[domchanges.length - 1].removedNodes[0].outerHTML;
77-
78-
// check for a <a element and proper file type
79-
expect(linkadded.split('href="')[1].split('jpeg;')[0]).toEqual('data:image/');
80-
// check that filename option handled properly
81-
expect(filename).toBe('plotly_download.jpeg');
82-
83-
// check that link removed
84-
expect(linkadded).toBe(linkdeleted);
85-
done();
50+
it('should create link, remove link, accept options', function(done) {
51+
downloadTest(gd, 'png', done);
52+
});
53+
54+
it('should create link, remove link, accept options', function(done) {
55+
checkWebp(function(supported) {
56+
if(supported) {
57+
downloadTest(gd, 'webp', done);
58+
} else {
59+
done();
60+
}
8661
});
62+
63+
});
64+
65+
it('should create link, remove link, accept options', function(done) {
66+
downloadTest(gd, 'svg', done);
8767
});
8868
});
69+
70+
71+
function downloadTest(gd, format, done) {
72+
//use MutationObserver to monitor the DOM
73+
//for changes
74+
//code modeled after
75+
//https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
76+
// select the target node
77+
var target = document.body;
78+
var domchanges = [];
79+
80+
// create an observer instance
81+
var observer = new MutationObserver(function(mutations) {
82+
mutations.forEach(function(mutation) {
83+
domchanges.push(mutation);
84+
});
85+
});
86+
87+
Plotly.plot(gd, textchartMock.data, textchartMock.layout).then(function(gd) {
88+
// start observing dom
89+
// configuration of the observer:
90+
var config = { childList: true };
91+
92+
// pass in the target node and observer options
93+
observer.observe(target, config);
94+
95+
return Plotly.downloadImage(gd, {format: format, height: 300, width: 300, filename: 'plotly_download'});
96+
}).then(function(filename) {
97+
// stop observing
98+
observer.disconnect();
99+
// look for an added and removed link
100+
var linkadded = domchanges[domchanges.length - 2].addedNodes[0];
101+
var linkdeleted = domchanges[domchanges.length - 1].removedNodes[0];
102+
103+
// check for a <a element and proper file type
104+
expect(linkadded.getAttribute('href').split(format)[0]).toEqual('data:image/');
105+
// check that filename option handled properly
106+
expect(filename).toEqual('plotly_download.' + format);
107+
108+
// check that link removed
109+
expect(linkadded).toBe(linkdeleted);
110+
done();
111+
});
112+
}
113+
114+
115+
// Only chrome supports webp at the time of writing
116+
function checkWebp(cb) {
117+
var img = new Image();
118+
img.onload = function() {
119+
cb(true);
120+
};
121+
122+
img.onerror = function() {
123+
cb(false);
124+
};
125+
126+
img.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
127+
}

test/jasmine/tests/toimage_test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ describe('Plotly.toImage', function() {
105105
// now do svg
106106
return Plotly.toImage(gd, {format: 'svg'});
107107
}).then(function(url) {
108-
expect(url.substr(1, 3)).toBe('svg');
108+
expect(url.split('svg')[0]).toBe('data:image/');
109109
done();
110110
});
111111
});

0 commit comments

Comments
 (0)