@@ -8,6 +8,13 @@ var toImage = require('../plot_api/to_image');
88var fileSaver = require ( './filesaver' ) ;
99var helpers = require ( './helpers' ) ;
1010
11+ // Maximum length of filename (without extension) when deriving filename from plot title.
12+ // 40 is somewhat arbitrary, just trying to strike a balance between being informative
13+ // while still generating a reasonable-length filename.
14+ // Technically, this is actually the number of code points rather than characters, which only differs
15+ // from character count in the case of certain emojis or special characters containing multiple code points
16+ const MAX_FILENAME_LENGTH_CHARS = 40 ;
17+
1118/**
1219 * Plotly.downloadImage
1320 *
@@ -30,7 +37,7 @@ function downloadImage(gd, opts) {
3037
3138 return new Promise ( function ( resolve , reject ) {
3239 if ( _gd && _gd . _snapshotInProgress ) {
33- reject ( new Error ( 'Snapshotting already in progress.' ) ) ;
40+ reject ( new Error ( 'Image capture already in progress.' ) ) ;
3441 }
3542
3643 if ( _gd ) _gd . _snapshotInProgress = true ;
@@ -41,8 +48,14 @@ function downloadImage(gd, opts) {
4148 const plotTitle = helpers . getPlotTitle ( gd ) ;
4249 // Trying to slugify a LaTeX string can result in weird ugly filenames,
4350 // so ignore the title entirely if it contains LaTeX markup
44- if ( ! svgTextUtils . matchTex ( plotTitle ) ) {
45- potentialFilename = Lib . slugify ( plotTitle , 40 ) ;
51+ if ( plotTitle && ! svgTextUtils . matchTex ( plotTitle ) ) {
52+ potentialFilename = Lib . slugify ( plotTitle , MAX_FILENAME_LENGTH_CHARS ) ;
53+ } else {
54+ // If the title is empty or contains LaTeX, fall back to subtitle
55+ const plotSubtitle = helpers . getPlotSubtitle ( gd ) ;
56+ if ( plotSubtitle && ! svgTextUtils . matchTex ( plotSubtitle ) ) {
57+ potentialFilename = Lib . slugify ( plotSubtitle , MAX_FILENAME_LENGTH_CHARS ) ;
58+ }
4659 }
4760 }
4861
0 commit comments