Skip to content

Commit

Permalink
Fix rendering of exported SVG (#2794)
Browse files Browse the repository at this point in the history
Replace invalid characters in attribute value; fixes the error

        Unescaped '<' not allowed in attributes values

Fixes #2534
  • Loading branch information
rndstr authored Aug 8, 2017
1 parent c2053b4 commit 656fbac
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 4 deletions.
7 changes: 4 additions & 3 deletions client/app/scripts/charts/edge.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { connect } from 'react-redux';
import classNames from 'classnames';

import { enterEdge, leaveEdge } from '../actions/app-actions';
import { encodeIdAttribute, decodeIdAttribute } from '../utils/dom-utils';

class Edge extends React.Component {

Expand All @@ -19,7 +20,7 @@ class Edge extends React.Component {

return (
<g
id={id} className={className}
id={encodeIdAttribute(id)} className={className}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
>
Expand All @@ -35,11 +36,11 @@ class Edge extends React.Component {
}

handleMouseEnter(ev) {
this.props.enterEdge(ev.currentTarget.id);
this.props.enterEdge(decodeIdAttribute(ev.currentTarget.id));
}

handleMouseLeave(ev) {
this.props.leaveEdge(ev.currentTarget.id);
this.props.leaveEdge(decodeIdAttribute(ev.currentTarget.id));
}
}

Expand Down
3 changes: 2 additions & 1 deletion client/app/scripts/charts/node-shapes.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ import {
octagonShapeProps,
cloudShapeProps,
} from '../utils/node-shape-utils';
import { encodeIdAttribute } from '../utils/dom-utils';


function NodeShape(shapeType, shapeElement, shapeProps, { id, highlighted, color, metric }) {
const { height, hasMetric, formattedValue } = getMetricValue(metric);
const className = classNames('shape', `shape-${shapeType}`, { metrics: hasMetric });
const metricStyle = { fill: getMetricColor(metric) };
const clipId = `metric-clip-${id}`;
const clipId = encodeIdAttribute(`metric-clip-${id}`);

return (
<g className={className}>
Expand Down
15 changes: 15 additions & 0 deletions client/app/scripts/utils/__tests__/dom-utils-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { encodeIdAttribute, decodeIdAttribute } from '../dom-utils';

describe('DomUtils', () => {
describe('encodeIdAttribute/decodeIdAttribute', () => {
it('encode should be reversible by decode ', () => {
[
'123-abc;<foo>',
';;<<><>',
'!@#$%^&*()+-\'"',
].forEach((input) => {
expect(decodeIdAttribute(encodeIdAttribute(input))).toEqual(input);
});
});
});
});
16 changes: 16 additions & 0 deletions client/app/scripts/utils/dom-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Cleans up a value to be used as an element ID.
*
* Encodes invalid characters to be valid in XHTML and makes it
* so that it can be reversed by {@link decodeIdAttribute}.
*/
export function encodeIdAttribute(id) {
return id.replace(/[<>&;]/gm, m => `__u${m.charCodeAt(0)}__`);
}

/**
* Reverts {@link encodeIdAttribute}.
*/
export function decodeIdAttribute(id) {
return id.replace(/__u(\d+)__/gm, (m, d) => String.fromCharCode(d));
}

0 comments on commit 656fbac

Please sign in to comment.