diff --git a/draftlogs/8066_change.md b/draftlogs/8066_change.md
new file mode 100644
index 00000000000..e7d9ed31ddd
--- /dev/null
+++ b/draftlogs/8066_change.md
@@ -0,0 +1 @@
+- Describe `config.toImageButtonOptions` in the plot schema [[#8066](https://github.com/plotly/plotly.js/pull/8066)]
diff --git a/draftlogs/8066_fix.md b/draftlogs/8066_fix.md
new file mode 100644
index 00000000000..ca7111e7781
--- /dev/null
+++ b/draftlogs/8066_fix.md
@@ -0,0 +1 @@
+- Correct the image export types: `format` now accepts `full-json`, `width` and `height` accept `null`, and `ToImgopts.format`, `ToImgopts.width`, `ToImgopts.height` and `DownloadImgopts.filename` are optional because `toImage` and `downloadImage` supply them [[#8066](https://github.com/plotly/plotly.js/pull/8066)]
diff --git a/src/plot_api/plot_config.js b/src/plot_api/plot_config.js
index dc67084bb35..6d75724da00 100644
--- a/src/plot_api/plot_config.js
+++ b/src/plot_api/plot_config.js
@@ -12,6 +12,12 @@
* at the moment.
*/
+const { format, width, height, scale } = require('./to_image_attributes').default;
+
+// `toImage` owns the scale default, not the button. A default here would reach
+// `downloadImage` on every click and change what the caller receives.
+const { dflt: scaleDflt, ...buttonScale } = scale;
+
var configAttributes = {
staticPlot: {
valType: 'boolean',
@@ -50,6 +56,11 @@ var configAttributes = {
].join(' ')
},
edits: {
+ description: [
+ 'Determines which parts of the graph a user can edit directly.',
+ '`editable` sets every key here at once, and a key set here overrides it.',
+ '`staticPlot` disables all of them.'
+ ].join(' '),
annotationPosition: {
valType: 'boolean',
dflt: false,
@@ -279,13 +290,24 @@ var configAttributes = {
].join(' ')
},
toImageButtonOptions: {
- valType: 'any',
- dflt: {},
description: [
- 'Statically override options for toImage modebar button',
- 'allowed keys are format, filename, width, height, scale',
- 'see ../components/modebar/buttons.js'
- ].join(' ')
+ 'Statically overrides options for the toImage modebar button.',
+ 'The button reads only `format`, `filename`, `width`, `height` and `scale`,',
+ 'and drops every other key.'
+ ].join(' '),
+ format,
+ filename: {
+ valType: 'string',
+ description: [
+ 'Sets the name of the downloaded file, without an extension.',
+ 'The button appends the extension that matches `format`.',
+ 'The name defaults to the plot title, then the plot subtitle,',
+ 'then *plot-image*.'
+ ].join(' ')
+ },
+ width,
+ height,
+ scale: buttonScale
},
displaylogo: {
valType: 'boolean',
@@ -414,12 +436,17 @@ var configAttributes = {
var dfltConfig = {};
function crawl(src, target) {
- for(var k in src) {
- var obj = src[k];
- if(obj.valType) {
- target[k] = obj.dflt;
+ for (const k in src) {
+ const obj = src[k];
+ // A container carries its own `description` string beside the child
+ // attributes. Recursing into a string never terminates.
+ if (typeof obj !== 'object' || obj === null) continue;
+ if (obj.valType) {
+ // An attribute without a `dflt` seeds no key. A key holding
+ // `undefined` reads as present to `in`, which callers test.
+ if ('dflt' in obj) target[k] = obj.dflt;
} else {
- if(!target[k]) {
+ if (!target[k]) {
target[k] = {};
}
crawl(obj, target[k]);
diff --git a/src/plot_api/to_image.js b/src/plot_api/to_image.js
index bf6bec98f39..7d67b6f0caf 100644
--- a/src/plot_api/to_image.js
+++ b/src/plot_api/to_image.js
@@ -10,63 +10,7 @@ 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', 'full-json'],
- dflt: 'png',
- description: 'Sets the format of exported image.'
- },
- width: {
- valType: 'number',
- min: 1,
- description: [
- 'Sets the exported image width.',
- 'Defaults to the value found in `layout.width`',
- 'If set to *null*, the exported image width will match the current graph width.'
- ].join(' ')
- },
- height: {
- valType: 'number',
- min: 1,
- description: [
- 'Sets the exported image height.',
- 'Defaults to the value found in `layout.height`',
- 'If set to *null*, the exported image height will match the current graph height.'
- ].join(' ')
- },
- scale: {
- valType: 'number',
- min: 0,
- dflt: 1,
- description: [
- 'Sets a scaling for the generated image.',
- 'If set, all features of a graphs (e.g. text, line width)',
- 'are scaled, unlike simply setting',
- 'a bigger *width* and *height*.'
- ].join(' ')
- },
- setBackground: {
- valType: 'any',
- dflt: false,
- description: [
- 'Sets the image background mode.',
- 'By default, the image background is determined by `layout.paper_bgcolor`,',
- 'the *transparent* mode.',
- 'One might consider setting `setBackground` to *opaque*',
- 'when exporting a *jpeg* image as JPEGs do not support opacity.'
- ].join(' ')
- },
- imageDataOnly: {
- valType: 'boolean',
- dflt: false,
- description: [
- 'Determines whether or not the return value is prefixed by',
- 'the image format\'s corresponding \'data:image;\' spec.'
- ].join(' ')
- }
-};
+const attrs = require('./to_image_attributes').default;
/** Plotly.toImage
*
@@ -74,7 +18,7 @@ var attrs = {
* can either be a data/layout/config object
* or an existing graph
* or an id to an existing graph
- * @param {object} opts (see above)
+ * @param {object} opts (see ./to_image_attributes)
* @return {promise}
*/
function toImage(gd, opts) {
diff --git a/src/plot_api/to_image_attributes.ts b/src/plot_api/to_image_attributes.ts
new file mode 100644
index 00000000000..6c61246ac2f
--- /dev/null
+++ b/src/plot_api/to_image_attributes.ts
@@ -0,0 +1,66 @@
+import type { AttributeMap } from '../types/lib/attributes';
+
+/**
+ * Options for `Plotly.toImage` and `Plotly.downloadImage`.
+ * `plot_config.js` reuses `format.values` for `config.toImageButtonOptions`.
+ * A separate module prevents the require cycle that `plot_config.js` would
+ * close through `to_image.js`.
+ */
+const attributes = {
+ format: {
+ valType: 'enumerated',
+ values: ['png', 'jpeg', 'webp', 'svg', 'full-json'] as const,
+ dflt: 'png',
+ description: 'Sets the format of exported image.'
+ },
+ width: {
+ valType: 'number',
+ min: 1,
+ description: [
+ 'Sets the exported image width.',
+ 'Defaults to the value found in `layout.width`',
+ 'If set to *null*, the exported image width will match the current graph width.'
+ ].join(' ')
+ },
+ height: {
+ valType: 'number',
+ min: 1,
+ description: [
+ 'Sets the exported image height.',
+ 'Defaults to the value found in `layout.height`',
+ 'If set to *null*, the exported image height will match the current graph height.'
+ ].join(' ')
+ },
+ scale: {
+ valType: 'number',
+ min: 0,
+ dflt: 1,
+ description: [
+ 'Sets a scaling for the generated image.',
+ 'If set, all features of a graphs (e.g. text, line width)',
+ 'are scaled, unlike simply setting',
+ 'a bigger *width* and *height*.'
+ ].join(' ')
+ },
+ setBackground: {
+ valType: 'any',
+ dflt: false,
+ description: [
+ 'Sets the image background mode.',
+ 'By default, the image background is determined by `layout.paper_bgcolor`,',
+ 'the *transparent* mode.',
+ 'One might consider setting `setBackground` to *opaque*',
+ 'when exporting a *jpeg* image as JPEGs do not support opacity.'
+ ].join(' ')
+ },
+ imageDataOnly: {
+ valType: 'boolean',
+ dflt: false,
+ description: [
+ 'Determines whether or not the return value is prefixed by',
+ "the image format's corresponding 'data:image;' spec."
+ ].join(' ')
+ }
+} as const satisfies AttributeMap;
+
+export default attributes;
diff --git a/src/types/core/config.d.ts b/src/types/core/config.d.ts
index 5d8e57e63c0..f705374e90f 100644
--- a/src/types/core/config.d.ts
+++ b/src/types/core/config.d.ts
@@ -1,97 +1,80 @@
/**
* Config types
*
- * `Config` is built by overlaying a small hand-written interface on top of
- * the schema-derived `ConfigBase`. Most fields come straight from the
- * schema; the overrides cover seven fields whose schema `valType` is `any`
- * because the underlying JS attribute accepts a function value, an
- * arbitrary-key map, or a structure too irregular for the schema to model.
+ * This file overlays a small hand-written interface on the schema-derived
+ * `ConfigBase` to build `Config`. Most fields come straight from the schema.
+ * The overrides cover the five fields whose schema `valType` is `any`. Those
+ * fields accept a function value, an arbitrary-key map, or a structure too
+ * irregular for the schema to model.
*/
-import type { ConfigBase, Edits } from '../generated/schema';
+import type { ConfigBase, Edits, ToImageButtonOptions, ToImageFormat } from '../generated/schema';
import type { PlotlyHTMLElement } from './events';
import type { ModeBarButtonAny, ModeBarDefaultButtons } from './layout';
-export type { Edits };
+export type { Edits, ToImageButtonOptions, ToImageFormat };
// ---------------------------------------------------------------------------
// Image export options
// ---------------------------------------------------------------------------
/**
- * Options for `Plotly.toImage`. The graph is rendered to a string suitable
- * for use as a data URI or as raw SVG markup.
+ * Background mode for `Plotly.toImage` and `config.setBackground`.
+ * A function receives the graph div and the resolved background color.
*/
-export interface ToImgopts {
- /** Output image format. */
- format: 'jpeg' | 'png' | 'webp' | 'svg';
- /** If null, uses current graph width */
- width: number | null;
- /** If null, uses current graph height */
- height: number | null;
- /** Resolution multiplier for raster formats. */
- scale?: number | undefined;
-}
+export type SetBackground = 'opaque' | 'transparent' | ((gd: PlotlyHTMLElement, bgColor: string) => void);
/**
- * Options for `Plotly.downloadImage`. Like `ToImgopts`, but also requires
- * a `filename` because the result is saved to disk by the browser.
+ * Options for `Plotly.toImage`. `toImage` renders the graph to a string that
+ * works as a data URI or as raw SVG markup. The mode-bar button reads the same
+ * fields, minus the two below, through `config.toImageButtonOptions`.
*/
-export interface DownloadImgopts {
- /** Output image format. */
- format: 'jpeg' | 'png' | 'webp' | 'svg';
- /** Output width in pixels. */
- width: number | null;
- /** Output height in pixels. */
- height: number | null;
- /** Filename used for the downloaded file (no extension required). */
- filename: string;
+export interface ToImgopts extends Omit
{
+ /** Override the background color with a static color name, or with a function that runs on each render */
+ setBackground?: SetBackground;
+ /** Return the bare image data, without the leading `data:image;` prefix */
+ imageDataOnly?: boolean;
}
/**
- * Static defaults applied to the mode-bar "download image" button. Set
- * via `config.toImageButtonOptions`.
+ * Options for `Plotly.downloadImage`. Like `ToImgopts`, but adds a `filename`
+ * because the browser saves the result to disk. `downloadImage` forces
+ * `imageDataOnly` on, so a caller cannot set it.
*/
-export interface ToImageButtonOptions {
- /** Output image format. */
- format?: 'png' | 'svg' | 'jpeg' | 'webp';
- /** Downloaded filename. */
+export interface DownloadImgopts extends Omit {
+ /**
+ * Name for the downloaded file, without an extension. `downloadImage`
+ * appends the extension that matches `format`. The name defaults to the
+ * plot title, then the plot subtitle, then `plot-image`.
+ */
filename?: string;
- /** Output height in pixels. */
- height?: number;
- /** Output width in pixels. */
- width?: number;
- /** Resolution multiplier for raster formats. */
- scale?: number;
}
// ---------------------------------------------------------------------------
-// Config — hybrid (schema-derived + hand-written overrides)
+// Config - hybrid (schema-derived + hand-written overrides)
// ---------------------------------------------------------------------------
/**
- * Hand-written overrides for the six `schema.config` fields whose
- * `valType` is `any`. These accept functions or arbitrary-key maps that the
- * JSON schema fundamentally cannot describe, so they stay typed by hand.
+ * Hand-written overrides for the five `schema.config` fields whose `valType`
+ * is `any`. These fields accept functions or arbitrary-key maps, which the
+ * JSON schema cannot describe.
*/
interface ConfigOverrides {
- /** Override the background color: a static color name, or a function called per-render. */
- setBackground?: 'opaque' | 'transparent' | ((gd: PlotlyHTMLElement, bgColor: string) => void);
- /** Define fully custom mode bar buttons as nested array of button groups. */
+ /** Override the background color with a static color name, or with a function that runs on each render */
+ setBackground?: SetBackground;
+ /** Define fully custom mode bar buttons as a nested array of button groups */
modeBarButtons?: ModeBarButtonAny[][] | false;
- /** Add mode bar buttons using config objects or default-button names. */
+ /** Add mode bar buttons with config objects or default-button names */
modeBarButtonsToAdd?: ModeBarButtonAny[];
- /** Remove mode bar buttons by name. */
+ /** Remove mode bar buttons by name */
modeBarButtonsToRemove?: ModeBarDefaultButtons[];
- /** Statically override options for the toImage mode bar button. */
- toImageButtonOptions?: ToImageButtonOptions;
- /** Localization definitions keyed by locale id (e.g. `'en-US'`, `'fr'`). */
+ /** Localization definitions under a locale id key, for example `'en-US'` or `'fr'` */
locales?: Record; format?: Record }>;
}
/**
- * Full plot config. Combines `ConfigBase` (schema-derived) with the
- * hand-written `ConfigOverrides` so the hand-written entries replace the
- * loosely-typed `any` versions from the schema.
+ * Full plot config. `Config` combines `ConfigBase` (schema-derived) with the
+ * hand-written `ConfigOverrides`, so the hand-written entries replace the
+ * loosely-typed versions from the schema.
*/
export type Config = Omit & ConfigOverrides;
diff --git a/src/types/generated/schema.d.ts b/src/types/generated/schema.d.ts
index fda9a6817e9..5283911ff43 100644
--- a/src/types/generated/schema.d.ts
+++ b/src/types/generated/schema.d.ts
@@ -32,6 +32,8 @@ export type PatternShape = '' | '/' | '\\' | 'x' | '-' | '|' | '+' | '.';
export type TransitionEasing = 'linear' | 'quad' | 'cubic' | 'sin' | 'exp' | 'circle' | 'elastic' | 'back' | 'bounce' | 'linear-in' | 'quad-in' | 'cubic-in' | 'sin-in' | 'exp-in' | 'circle-in' | 'elastic-in' | 'back-in' | 'bounce-in' | 'linear-out' | 'quad-out' | 'cubic-out' | 'sin-out' | 'exp-out' | 'circle-out' | 'elastic-out' | 'back-out' | 'bounce-out' | 'linear-in-out' | 'quad-in-out' | 'cubic-in-out' | 'sin-in-out' | 'exp-in-out' | 'circle-in-out' | 'elastic-in-out' | 'back-in-out' | 'bounce-in-out';
+export type ToImageFormat = 'png' | 'jpeg' | 'webp' | 'svg' | 'full-json';
+
export type TraceType = 'bar' | 'barpolar' | 'box' | 'candlestick' | 'carpet' | 'choropleth' | 'choroplethmap' | 'cone' | 'contour' | 'contourcarpet' | 'densitymap' | 'funnel' | 'funnelarea' | 'heatmap' | 'histogram' | 'histogram2d' | 'histogram2dcontour' | 'icicle' | 'image' | 'indicator' | 'isosurface' | 'mesh3d' | 'ohlc' | 'parcats' | 'parcoords' | 'pie' | 'quiver' | 'sankey' | 'scatter' | 'scatter3d' | 'scattercarpet' | 'scattergeo' | 'scattergl' | 'scattermap' | 'scatterpolar' | 'scatterpolargl' | 'scattersmith' | 'scatterternary' | 'splom' | 'streamtube' | 'sunburst' | 'surface' | 'table' | 'treemap' | 'violin' | 'volume' | 'waterfall';
/** @deprecated Renamed to TraceType. */
@@ -16700,6 +16702,31 @@ export interface Edits {
titleText?: boolean;
}
+export interface ToImageButtonOptions {
+ /** Sets the name of the downloaded file, without an extension. The button appends the extension that matches `format`. The name defaults to the plot title, then the plot subtitle, then *plot-image*. */
+ filename?: string;
+ /**
+ * Sets the format of exported image.
+ * @default 'png'
+ */
+ format?: ToImageFormat;
+ /**
+ * Sets the exported image height. Defaults to the value found in `layout.height` If set to *null*, the exported image height will match the current graph height.
+ * Minimum: 1
+ */
+ height?: number | null;
+ /**
+ * Sets a scaling for the generated image. If set, all features of a graphs (e.g. text, line width) are scaled, unlike simply setting a bigger *width* and *height*.
+ * Minimum: 0
+ */
+ scale?: number;
+ /**
+ * Sets the exported image width. Defaults to the value found in `layout.width` If set to *null*, the exported image width will match the current graph width.
+ * Minimum: 1
+ */
+ width?: number | null;
+}
+
export interface ConfigBase {
/**
* Determines whether the graphs are plotted with respect to layout.autosize:true and infer its container size.
@@ -16742,6 +16769,7 @@ export interface ConfigBase {
* @default false
*/
editable?: boolean;
+ /** Determines which parts of the graph a user can edit directly. `editable` sets every key here at once, and a key set here overrides it. `staticPlot` disables all of them. */
edits?: Edits;
/**
* When `layout.autosize` is turned on, determines whether the graph fills the container (the default) or the screen (if set to *true*).
@@ -16848,11 +16876,8 @@ export interface ConfigBase {
* @default false
*/
staticPlot?: boolean;
- /**
- * Statically override options for toImage modebar button allowed keys are format, filename, width, height, scale see ../components/modebar/buttons.js
- * @default {}
- */
- toImageButtonOptions?: any;
+ /** Statically overrides options for the toImage modebar button. The button reads only `format`, `filename`, `width`, `height` and `scale`, and drops every other key. */
+ toImageButtonOptions?: ToImageButtonOptions;
/**
* Set the URL to topojson used in geo charts. By default, the topojson files are fetched from cdn.plot.ly. For example, set this option to: /dist/topojson/ to render geographical feature using the topojson files that ship with the plotly.js module.
* @default 'https://cdn.plot.ly/un/'
diff --git a/tasks/generate_schema_types.mjs b/tasks/generate_schema_types.mjs
index 01c9ed5961d..ce462bb7fdf 100644
--- a/tasks/generate_schema_types.mjs
+++ b/tasks/generate_schema_types.mjs
@@ -48,7 +48,8 @@ const COMMON_TYPE_ANCHORS = [
match: (key, _path, values) => key === 'yref' && values.length === 2 && values.includes('container')
},
{ name: 'PatternShape', match: (key, path) => key === 'shape' && /\.pattern\.shape$/.test(path) },
- { name: 'TransitionEasing', match: (key) => key === 'easing' }
+ { name: 'TransitionEasing', match: (key) => key === 'easing' },
+ { name: 'ToImageFormat', match: (_key, path) => path === 'config.toImageButtonOptions.format' }
];
/**
@@ -116,6 +117,7 @@ function discoverCommonTypes(schema) {
visit(schema.traces, 'traces');
visit(schema.layout, 'layout');
if (schema.animation) visit(schema.animation, 'animation');
+ if (schema.config) visit(schema.config, 'config');
// For each anchor, pick the largest value set. When sizes tie, the first
// match wins. The superset rule handles axis-type-style cases where
@@ -1389,14 +1391,30 @@ export function generateSchemaTypes(schema, outputPath) {
// references `edits?: Edits` instead of re-inlining the subtree.
sharedTypes.set(containerFingerprint(schema.config.edits), 'Edits');
}
+ if (schema.config && schema.config.toImageButtonOptions) {
+ // The runtime reads `null` for `width` and `height` as the current graph
+ // size. A `number` valType cannot express that, so widen the two fields
+ // here rather than in `core/config.d.ts`.
+ const toImageButtonProps = attrsToProperties(
+ schema.config.toImageButtonOptions,
+ ' ',
+ 'toImageButtonOptions',
+ sharedTypes,
+ { width: 'number | null', height: 'number | null' }
+ );
+ extraInterfaces.push({ name: 'ToImageButtonOptions', properties: toImageButtonProps });
+
+ // Register the fingerprint so the ConfigBase emission below references
+ // `toImageButtonOptions?: ToImageButtonOptions` instead of re-inlining the subtree.
+ sharedTypes.set(containerFingerprint(schema.config.toImageButtonOptions), 'ToImageButtonOptions');
+ }
if (schema.config) {
// Generate the schema-derived Config building block. Fields whose
- // schema valType is `any` (locales, modeBarButtons, setBackground,
- // toImageButtonOptions, ...) come through as `any` and are
- // overridden with precise types in `core/config.d.ts`'s `Config`
- // via Omit/intersection. The schema is fundamentally unable to
- // describe functions or arbitrary-key maps, so those overrides are
- // permanent.
+ // schema valType is `any` (locales, modeBarButtons, setBackground, ...)
+ // come through as `any` and are overridden with precise types in
+ // `core/config.d.ts`'s `Config` via Omit/intersection. The schema is
+ // fundamentally unable to describe functions or arbitrary-key maps, so
+ // those overrides are permanent.
const configProps = attrsToProperties(schema.config, ' ', 'config', sharedTypes);
extraInterfaces.push({ name: 'ConfigBase', properties: configProps });
}
diff --git a/test/jasmine/bundle_tests/plotschema_test.js b/test/jasmine/bundle_tests/plotschema_test.js
index ac5301316cf..1496bf3cb4b 100644
--- a/test/jasmine/bundle_tests/plotschema_test.js
+++ b/test/jasmine/bundle_tests/plotschema_test.js
@@ -291,6 +291,14 @@ describe('plot schema', function() {
expect(plotSchema.config.scrollZoom).toBeDefined();
});
+ it('should describe every toImageButtonOptions key', () => {
+ const opts = plotSchema.config.toImageButtonOptions;
+ expect(opts.role).toBe('object');
+ expect(Object.keys(opts).sort()).toEqual(['description', 'filename', 'format', 'height', 'role', 'scale', 'width']);
+ expect(opts.format.values).toEqual(['png', 'jpeg', 'webp', 'svg', 'full-json']);
+ expect(opts.format.dflt).toBe('png');
+ });
+
it('should list trace-dependent & direction-dependent error bar attributes', function() {
var scatterSchema = plotSchema.traces.scatter.attributes;
expect(scatterSchema.error_x.copy_ystyle).toBeDefined();
diff --git a/test/plot-schema.json b/test/plot-schema.json
index cebf8f090da..3f8728d1b01 100644
--- a/test/plot-schema.json
+++ b/test/plot-schema.json
@@ -182,6 +182,7 @@
"dflt": false,
"valType": "boolean"
},
+ "description": "Determines which parts of the graph a user can edit directly. `editable` sets every key here at once, and a key set here overrides it. `staticPlot` disables all of them.",
"legendPosition": {
"description": "Enables moving the legend.",
"dflt": false,
@@ -329,9 +330,39 @@
"valType": "boolean"
},
"toImageButtonOptions": {
- "description": "Statically override options for toImage modebar button allowed keys are format, filename, width, height, scale see ../components/modebar/buttons.js",
- "dflt": {},
- "valType": "any"
+ "description": "Statically overrides options for the toImage modebar button. The button reads only `format`, `filename`, `width`, `height` and `scale`, and drops every other key.",
+ "filename": {
+ "description": "Sets the name of the downloaded file, without an extension. The button appends the extension that matches `format`. The name defaults to the plot title, then the plot subtitle, then *plot-image*.",
+ "valType": "string"
+ },
+ "format": {
+ "description": "Sets the format of exported image.",
+ "dflt": "png",
+ "valType": "enumerated",
+ "values": [
+ "png",
+ "jpeg",
+ "webp",
+ "svg",
+ "full-json"
+ ]
+ },
+ "height": {
+ "description": "Sets the exported image height. Defaults to the value found in `layout.height` If set to *null*, the exported image height will match the current graph height.",
+ "min": 1,
+ "valType": "number"
+ },
+ "role": "object",
+ "scale": {
+ "description": "Sets a scaling for the generated image. If set, all features of a graphs (e.g. text, line width) are scaled, unlike simply setting a bigger *width* and *height*.",
+ "min": 0,
+ "valType": "number"
+ },
+ "width": {
+ "description": "Sets the exported image width. Defaults to the value found in `layout.width` If set to *null*, the exported image width will match the current graph width.",
+ "min": 1,
+ "valType": "number"
+ }
},
"topojsonURL": {
"description": "Set the URL to topojson used in geo charts. By default, the topojson files are fetched from cdn.plot.ly. For example, set this option to: /dist/topojson/ to render geographical feature using the topojson files that ship with the plotly.js module.",