diff --git a/src/components/App/__snapshots__/test.js.snap b/src/components/App/__snapshots__/test.js.snap
index c84d246..6304af7 100644
--- a/src/components/App/__snapshots__/test.js.snap
+++ b/src/components/App/__snapshots__/test.js.snap
@@ -22,8 +22,8 @@ exports[`App removing rendered expression 1`] = `
`;
@@ -139,8 +139,8 @@ exports[`App rendering an expression 3`] = `
`;
@@ -167,8 +167,8 @@ exports[`App rendering image details 1`] = `
`;
@@ -201,8 +201,8 @@ exports[`App rendering image details 2`] = `
/>
`;
diff --git a/src/components/App/index.js b/src/components/App/index.js
index df11c78..95c3683 100644
--- a/src/components/App/index.js
+++ b/src/components/App/index.js
@@ -73,13 +73,13 @@ class App extends React.PureComponent {
`syntax/${ syntax }`
);
- const parsed = syntaxModule.parse(expr);
+ const exprData = syntaxModule.layout(syntaxModule.parse(expr));
this.setState({
loading: false,
render: {
syntax,
- parsed,
+ exprData,
Component: syntaxModule.Render
}
});
@@ -119,7 +119,7 @@ class App extends React.PureComponent {
imageDetails,
render: {
syntax: renderSyntax,
- parsed,
+ exprData,
Component
}
} = this.state;
@@ -137,7 +137,7 @@ class App extends React.PureComponent {
};
const renderProps = {
onRender: this.handleSvg,
- parsed
+ data: exprData
};
const doRender = renderSyntax === syntax;
diff --git a/src/components/App/test.js b/src/components/App/test.js
index 3d66b22..982ff1c 100644
--- a/src/components/App/test.js
+++ b/src/components/App/test.js
@@ -6,6 +6,7 @@ import { App } from 'components/App';
jest.mock('syntax/js', () => ({
parse: expr => `PARSED(${ expr })`,
+ layout: parsed => `LAYOUT(${ parsed })`,
Render: () => ''
}));
diff --git a/src/components/Render/index.js b/src/components/Render/index.js
index 1e1c790..73ac638 100644
--- a/src/components/Render/index.js
+++ b/src/components/Render/index.js
@@ -28,13 +28,21 @@ const render = (data, extraProps) => {
class Render extends React.PureComponent {
static propTypes = {
- parsed: PropTypes.object.isRequired,
+ data: PropTypes.object.isRequired,
onRender: PropTypes.func.isRequired
}
svgContainer = React.createRef()
- provideSVGData = () => {
+ componentDidMount() {
+ this.provideSVGData();
+ }
+
+ componentDidUpdate() {
+ this.provideSVGData();
+ }
+
+ provideSVGData() {
if (!this.svgContainer.current) {
return;
}
@@ -48,10 +56,10 @@ class Render extends React.PureComponent {
}
render() {
- const { parsed } = this.props;
+ const { data } = this.props;
return
- { render(parsed, { onReflow: this.provideSVGData }) }
+ { render(data, { onReflow: this.provideSVGData }) }
;
}
}
diff --git a/src/layout.js b/src/layout.js
new file mode 100644
index 0000000..6b05543
--- /dev/null
+++ b/src/layout.js
@@ -0,0 +1,22 @@
+import SVG from 'rendering/SVG/layout';
+import Text from 'rendering/Text/layout';
+
+const nodeTypes = {
+ SVG,
+ Text
+};
+
+const layout = data => {
+ if (typeof data == 'string') {
+ return data;
+ }
+
+ const { type } = data;
+
+ return nodeTypes[type]({
+ props: {},
+ ...data
+ });
+};
+
+export default layout;
diff --git a/src/rendering/SVG/index.js b/src/rendering/SVG/index.js
index 4db45d6..1eb24bd 100644
--- a/src/rendering/SVG/index.js
+++ b/src/rendering/SVG/index.js
@@ -24,7 +24,9 @@ class SVG extends React.PureComponent {
static propTypes = {
onReflow: PropTypes.func,
children: PropTypes.node,
- padding: PropTypes.number
+ padding: PropTypes.number,
+ innerWidth: PropTypes.number,
+ innerHeight: PropTypes.number
}
static defaultProps = {
@@ -36,18 +38,11 @@ class SVG extends React.PureComponent {
height: 0
}
- handleReflow = box => {
- const { padding } = this.props;
-
- this.setState({
- width: Math.round(box.width + 2 * padding),
- height: Math.round(box.height + 2 * padding)
- }, () => this.props.onReflow(this));
- }
-
render() {
- const { width, height } = this.state;
- const { padding, children } = this.props;
+ const { padding, innerWidth, innerHeight, children } = this.props;
+
+ const width = Math.round(innerWidth + 2 * padding);
+ const height = Math.round(innerHeight + 2 * padding);
const svgProps = {
width,
@@ -60,9 +55,7 @@ class SVG extends React.PureComponent {
return ;
}
diff --git a/src/rendering/SVG/layout.js b/src/rendering/SVG/layout.js
new file mode 100644
index 0000000..1caf46d
--- /dev/null
+++ b/src/rendering/SVG/layout.js
@@ -0,0 +1,12 @@
+import layout from 'layout';
+
+const layoutSVG = data => {
+ const child = layout(data.children[0]);
+
+ data.props.innerWidth = child.box.width;
+ data.props.innerHeight = child.box.height;
+
+ return data;
+};
+
+export default layoutSVG;
diff --git a/src/rendering/Text/index.js b/src/rendering/Text/index.js
index 0b446fd..118ebcb 100644
--- a/src/rendering/Text/index.js
+++ b/src/rendering/Text/index.js
@@ -6,6 +6,7 @@ import * as style from './style';
class Text extends React.PureComponent {
static propTypes = {
quoted: PropTypes.bool,
+ transform: PropTypes.string,
onReflow: PropTypes.func,
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
@@ -13,31 +14,6 @@ class Text extends React.PureComponent {
]).isRequired
}
- state = {
- transform: ''
- }
-
- textRef = React.createRef()
-
- componentDidMount() {
- this.reflow();
- }
-
- componentDidUpdate() {
- this.reflow();
- }
-
- reflow() {
- const box = this.textRef.current.getBBox();
- const transform = `translate(${ -box.x } ${ -box.y })`;
-
- if (transform === this.state.transform) {
- return; // No update required
- }
-
- this.setState({ transform }, () => this.props.onReflow(box));
- }
-
renderContent() {
const { children, quoted } = this.props;
@@ -53,12 +29,11 @@ class Text extends React.PureComponent {
}
render() {
- const { transform } = this.state;
+ const { transform } = this.props;
const textProps = {
style: style.text,
- transform,
- ref: this.textRef
+ transform
};
return
diff --git a/src/rendering/Text/layout.js b/src/rendering/Text/layout.js
new file mode 100644
index 0000000..cfe82e1
--- /dev/null
+++ b/src/rendering/Text/layout.js
@@ -0,0 +1,27 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+
+import Text from 'rendering/Text';
+
+const layoutText = data => {
+ const container = document.createElement('div');
+ document.body.appendChild(container);
+
+ ReactDOM.render(
+ ,
+ container);
+
+ const box = container.querySelector('svg > text').getBBox();
+ document.body.removeChild(container);
+
+ data.box = {
+ width: box.width,
+ height: box.height
+ };
+ data.props.transform = `translate(${ -box.x } ${ -box.y })`;
+ return data;
+};
+
+export default layoutText;
diff --git a/src/syntax/js.js b/src/syntax/js.js
index 7214bd3..a3c68bd 100644
--- a/src/syntax/js.js
+++ b/src/syntax/js.js
@@ -1,4 +1,5 @@
import Render from 'components/Render';
+import layout from 'layout';
const parse = expr => {
return {
@@ -19,5 +20,6 @@ const parse = expr => {
export {
parse,
+ layout,
Render
};
diff --git a/src/syntax/pcre.js b/src/syntax/pcre.js
index a078762..997046a 100644
--- a/src/syntax/pcre.js
+++ b/src/syntax/pcre.js
@@ -1,4 +1,5 @@
import Render from 'components/Render';
+import layout from 'layout';
const parse = expr => {
return {
@@ -19,5 +20,6 @@ const parse = expr => {
export {
parse,
+ layout,
Render
};