Skip to content

Commit

Permalink
[fix] Conditionally apply escapeXhtml to prevent export image crash (#…
Browse files Browse the repository at this point in the history
…2313)

Signed-off-by: Ihor Dykhta <dikhta.igor@gmail.com>
Co-authored-by: Ilya Boyandin <ilya@boyandin.me>
  • Loading branch information
igorDykhta and ilyabo committed Sep 18, 2023
1 parent 8bb0d46 commit 090ef0b
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 20 deletions.
5 changes: 3 additions & 2 deletions src/components/src/plot-container.tsx
Expand Up @@ -159,11 +159,12 @@ export default function PlotContainerFactory(

_retrieveNewScreenshot = () => {
if (this.plottingAreaRef.current) {
const {imageSize} = this.props.exportImageSetting;
const {imageSize, escapeXhtmlForWebpack} = this.props.exportImageSetting;
convertToPng(this.plottingAreaRef.current, {
filter: DOM_FILTER_FUNC,
width: imageSize.imageW,
height: imageSize.imageH
height: imageSize.imageH,
escapeXhtmlForWebpack
})
.then(this.props.setExportImageDataUri)
.catch(err => {
Expand Down
1 change: 1 addition & 0 deletions src/constants/src/default-settings.ts
Expand Up @@ -851,6 +851,7 @@ export type ExportImage = {
exporting: boolean;
processing: boolean;
error: Error | false;
escapeXhtmlForWebpack?: boolean;
// This field was not in the .d.ts file
center: boolean;
};
Expand Down
5 changes: 4 additions & 1 deletion src/reducers/src/ui-state-updaters.ts
Expand Up @@ -138,6 +138,7 @@ export const DEFAULT_MAP_CONTROLS: MapControls = (Object.keys(MAP_CONTROLS) as A
* @property imageDataUri Default: `''`,
* @property exporting Default: `false`
* @property error Default: `false`
* @property escapeXhtmlForWebpack Default: `true`
* @public
*/
export const DEFAULT_EXPORT_IMAGE: ExportImage = {
Expand All @@ -161,7 +162,9 @@ export const DEFAULT_EXPORT_IMAGE: ExportImage = {
exporting: false,
// processing: used as loading indicator when export image is being produced
processing: false,
error: false
error: false,
// whether to apply fix for uglify error in dom-to-image (should be true for webpack builds)
escapeXhtmlForWebpack: true
};

export const DEFAULT_LOAD_FILES = {
Expand Down
39 changes: 22 additions & 17 deletions src/utils/src/dom-to-image.ts
Expand Up @@ -75,20 +75,20 @@ const domtoimage = {
};

/**
* @param {Node} node - The DOM Node object to render
* @param {Object} options - Rendering options
* @param {Function} [options.filter] - Should return true if passed node should be included in the output
* (excluding node means excluding it's children as well). Not called on the root node.
* @param {String} [options.bgcolor] - color for the background, any valid CSS color value.
* @param {Number} [options.width] - width to be applied to node before rendering.
* @param {Number} [options.height] - height to be applied to node before rendering.
* @param {Object} [options.style] - an object whose properties to be copied to node's style before rendering.
* @param {Number} [options.quality] - a Number between 0 and 1 indicating image quality (applicable to JPEG only),
defaults to 1.0.
* @param {String} [options.imagePlaceholder] - dataURL to use as a placeholder for failed images, default behaviour is to fail fast on images we can't fetch
* @param {Boolean} [options.cacheBust] - set to true to cache bust by appending the time to the request url
* @return {Promise} - A promise that is fulfilled with a SVG image data URL
* */
* @param {Node} node - The DOM Node object to render
* @param {Object} options - Rendering options
* @param {Function} [options.filter] - Should return true if passed node should be included in the output
* (excluding node means excluding it's children as well). Not called on the root node.
* @param {String} [options.bgcolor] - color for the background, any valid CSS color value.
* @param {Number} [options.width] - width to be applied to node before rendering.
* @param {Number} [options.height] - height to be applied to node before rendering.
* @param {Object} [options.style] - an object whose properties to be copied to node's style before rendering.
* @param {Number} [options.quality] - a Number between 0 and 1 indicating image quality (applicable to JPEG only), defaults to 1.0.
* @param {boolean} [options.escapeXhtmlForWebpack] - whether to apply fix for uglify error in dom-to-image (should be true for webpack builds), defaults to true.
* @param {String} [options.imagePlaceholder] - dataURL to use as a placeholder for failed images, default behaviour is to fail fast on images we can't fetch
* @param {Boolean} [options.cacheBust] - set to true to cache bust by appending the time to the request url
* @return {Promise} - A promise that is fulfilled with a SVG image data URL
* */
function toSvg(node, options) {
options = options || {};
copyOptions(options);
Expand All @@ -98,7 +98,12 @@ function toSvg(node, options) {
.then(inlineImages)
.then(applyOptions)
.then(clone =>
makeSvgDataUri(clone, options.width || getWidth(node), options.height || getHeight(node))
makeSvgDataUri(
clone,
options.width || getWidth(node),
options.height || getHeight(node),
options.escapeXhtmlForWebpack
)
);

function applyOptions(clone) {
Expand Down Expand Up @@ -249,12 +254,12 @@ function inlineImages(node) {
return images.inlineAll(node).then(() => node);
}

function makeSvgDataUri(node, width, height) {
function makeSvgDataUri(node, width, height, escapeXhtmlForWebpack = true) {
return Promise.resolve(node).then(nd => {
nd.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');
const serializedString = new window.XMLSerializer().serializeToString(nd);

const xhtml = escapeXhtml(serializedString);
const xhtml = escapeXhtmlForWebpack ? escapeXhtml(serializedString) : serializedString;
const foreignObject = `<foreignObject x="0" y="0" width="100%" height="100%">${xhtml}</foreignObject>`;
const svgStr = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}">${foreignObject}</svg>`;

Expand Down

0 comments on commit 090ef0b

Please sign in to comment.