Skip to content

Commit

Permalink
Add panel to transform code.
Browse files Browse the repository at this point in the history
(cherry-picked f92ab58 from @cpojer)
  • Loading branch information
fkling committed Jul 30, 2015
1 parent d7b76e3 commit c69d857
Show file tree
Hide file tree
Showing 9 changed files with 254 additions and 40 deletions.
51 changes: 51 additions & 0 deletions app.js

Large diffs are not rendered by default.

24 changes: 17 additions & 7 deletions css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,17 @@ html {
cursor: col-resize;
}

#output {
.splitpane.splitpane-top {
bottom: 50%;
}

.splitpane.splitpane-bottom {
border-top: solid 2px #ddd;
top: 50%;
bottom: 0;
}

.output {
box-sizing: border-box;
position: absolute;
top: 0;
Expand All @@ -150,13 +160,13 @@ html {
border: none;
}

#output > .toolbar {
.output > .toolbar {
font-size: 14px;
margin-left: -1px;
border-bottom: 1px solid #ddd;
}

#output > .toolbar > button {
.output > .toolbar > button {
margin: 0;
height: 100%;
min-width: 90px;
Expand All @@ -171,13 +181,13 @@ html {
cursor: pointer;
}

#output > .toolbar > button.active {
.output > .toolbar > button.active {
border-color: #999;
background-color: #999;
color: #f5f5f5;
}

#output > .container {
.output > .container {
overflow: auto;
position: absolute;
top: 25px;
Expand Down Expand Up @@ -211,7 +221,7 @@ html {
background-color: #efefef;
}

#Editor {
.editor {
position: absolute;
left: 0;
right: 0;
Expand Down Expand Up @@ -280,7 +290,7 @@ li.entry {
overflow: auto;
}

#Editor .CodeMirror-gutters {
.editor .CodeMirror-gutters {
background-color: white;
border: none;
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@
"codemirror": "^5.1.0",
"escodegen": "^1.4.1",
"esprima-fb": "^15001.1.0-dev-harmony-fb",
"jscodeshift": "^0.3",
"keypress": "git://github.com/dmauro/Keypress",
"pubsub-js": "^1.4.2",
"react": "^0.12.1",
"react": "^0.13.1",
"react-tools": "^0.12.x"
},
"browserify": {
Expand Down
2 changes: 1 addition & 1 deletion src/ASTOutput.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ var ASTOutput = React.createClass({
}

return (
<div id="output" className="highlight">
<div className="output highlight">
<div className="toolbar">
<button
onClick={this._changeOutput}
Expand Down
79 changes: 49 additions & 30 deletions src/Editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@ var keypress = require('keypress').keypress;

var Editor = React.createClass({

propTypes: {
highlight: React.PropTypes.bool,
lineNumbers: React.PropTypes.bool,
readOnly: React.PropTypes.bool,
},

getDefaultProps: function() {
return {
highlight: true,
lineNumbers: true,
readOnly: false,
}
},

getValue: function() {
return this.codeMirror && this.codeMirror.getValue();
},
Expand All @@ -31,7 +45,8 @@ var Editor = React.createClass({
this.refs.container.getDOMNode(),
{
value: this.props.value,
lineNumbers: true
lineNumbers: this.props.lineNumbers,
readOnly: this.props.readOnly
}
);

Expand All @@ -55,41 +70,45 @@ var Editor = React.createClass({
}
});

this._markerRange = null;
this._mark = null;
this._subscriptions.push(
PubSub.subscribe('CM.HIGHLIGHT', (_, range) => {
var doc = this.codeMirror.getDoc();
this._markerRange = range;
// We only want one mark at a time.
if (this._mark) this._mark.clear();
this._mark = this.codeMirror.markText(
doc.posFromIndex(range[0]),
doc.posFromIndex(range[1]),
{className: 'marked'}
);
}),

PubSub.subscribe('CM.CLEAR_HIGHLIGHT', (_, range) => {
if (!range ||
this._markerRange &&
range[0] === this._markerRange[0] &&
range[1] === this._markerRange[1]
) {
this._markerRange = null;
if (this._mark) {
this._mark.clear();
this._mark = null;
}
}
}),

PubSub.subscribe('PANEL_RESIZE', () => {
if (this.codeMirror) {
this.codeMirror.refresh();
}
})
);

if (this.props.highlight) {
this._markerRange = null;
this._mark = null;
this._subscriptions.push(
PubSub.subscribe('CM.HIGHLIGHT', (_, range) => {
var doc = this.codeMirror.getDoc();
this._markerRange = range;
// We only want one mark at a time.
if (this._mark) this._mark.clear();
this._mark = this.codeMirror.markText(
doc.posFromIndex(range[0]),
doc.posFromIndex(range[1]),
{className: 'marked'}
);
}),

PubSub.subscribe('CM.CLEAR_HIGHLIGHT', (_, range) => {
if (!range ||
this._markerRange &&
range[0] === this._markerRange[0] &&
range[1] === this._markerRange[1]
) {
this._markerRange = null;
if (this._mark) {
this._mark.clear();
this._mark = null;
}
}
})
);
}
},

componentWillUnmount: function() {
Expand Down Expand Up @@ -132,7 +151,7 @@ var Editor = React.createClass({

render: function() {
return (
<div id="Editor" ref="container" />
<div className="editor" ref="container" />
);
}
});
Expand Down
14 changes: 14 additions & 0 deletions src/Toolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,20 @@ var Toolbar = React.createClass({
/>
&nbsp;{this.props.parserName}
</button>
<button
type="button"
onClick={this.props.onToggleTransform}>
<i
className={cx({
fa: true,
'fa-lg': true,
'fa-toggle-off': !this.props.transformPanelIsEnabled,
'fa-toggle-on': this.props.transformPanelIsEnabled,
'fa-fw': true,
})}
/>
Transform
</button>
<div id="parser">
Parser: {this.props.parserName}-{this.props.parserVersion}
</div>
Expand Down
74 changes: 74 additions & 0 deletions src/TransformOutput.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* @jsx React.DOM
*/
"use strict";

var Editor = require('./Editor');
var React = require('react/addons');

var babel = require('babel');
var jscodeshift = require('jscodeshift');

var cx = React.addons.classSet;

var TransformOutput = React.createClass({
mixins: [React.addons.PureRenderMixin],

propTypes: {
transform: React.PropTypes.string,
code: React.PropTypes.string,
},

transform: function() {
// This might throw
var transform = babel.transform(this.props.transform).code;
var module = {};
var args = [
{
path: 'Live.js',
source: this.props.code,
},
{jscodeshift},
{}
];
return eval([
"(function() {",
transform,
"})();",
"module.exports.apply(module.exports, args);"
].join("\n"));
},

renderTransform: function() {
try {
return (
<Editor
highlight={false}
key="output"
readOnly={true}
value={this.transform()}
/>
);
} catch (e) {
return (
<Editor
highlight={false}
key="error"
lineNumbers={false}
readOnly={true}
value={e.message}
/>
);
}
},

render: function() {
return (
<div className="output highlight">
{this.renderTransform()}
</div>
);
}
});

module.exports = TransformOutput;
37 changes: 36 additions & 1 deletion src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ var React = require('react/addons');
var Snippet = require('./Snippet');
var SplitPane = require('./SplitPane');
var Toolbar = require('./Toolbar');
var TransformOutput = require('./TransformOutput');

var babel;
var getFocusPath = require('./getFocusPath');
Expand All @@ -22,6 +23,8 @@ var fs = require('fs');
var keypress = require('keypress').keypress;

var initialCode = fs.readFileSync(__dirname + '/codeExample.txt', 'utf8');
var initialTransform =
fs.readFileSync(__dirname + '/transformExample.txt', 'utf8');

function updateHashWithIDAndRevision(id, rev) {
global.location.hash = '/' + id + (rev && rev !== 0 ? '/' + rev : '');
Expand All @@ -41,6 +44,8 @@ var App = React.createClass({
focusPath: [],
content: revision && revision.get('code') || initialCode,
snippet: snippet,
showTransformPanel: false,
transformContent: initialTransform,
revision: revision,
parser: 'esprima-fb',
};
Expand Down Expand Up @@ -166,6 +171,13 @@ var App = React.createClass({
);
},

onTransformContentChange: function(data) {
var content = data.value;
this.setState({
transformContent: content
});
},

onActivity: function(cursorPos) {
this.setState({
focusPath: getFocusPath(this.state.ast, cursorPos)
Expand Down Expand Up @@ -250,8 +262,16 @@ var App = React.createClass({
return this.state.parser === 'esprima-fb' ? esprima : babel;
},

_onToggleTransform: function() {
this.setState({
showTransformPanel: !this.state.showTransformPanel,
});
},

render: function() {
var revision = this.state.revision;
var splitPaneClassName =
'splitpane' + (this.state.showTransformPanel ? ' splitpane-top' : '');
return (
<PasteDropTarget
className="dropTarget"
Expand All @@ -268,17 +288,19 @@ var App = React.createClass({
onSave={this._onSave}
onFork={this._onFork}
onParserChange={this._onParserChange}
onToggleTransform={this._onToggleTransform}
canSave={
this.state.content !== initialCode && !revision ||
revision && revision.get('code') !== this.state.content
}
canFork={!!revision}
parserName={this.state.parser}
parserVersion={this._getParser().version}
transformPanelIsEnabled={this.state.showTransformPanel}
/>
{this.state.error ? <ErrorMessage message={this.state.error} /> : null}
<SplitPane
className="splitpane"
className={splitPaneClassName}
onResize={this._onResize}>
<Editor
ref="editor"
Expand All @@ -292,6 +314,19 @@ var App = React.createClass({
ast={this.state.ast}
/>
</SplitPane>
{this.state.showTransformPanel ? <SplitPane
className="splitpane splitpane-bottom"
onResize={this._onResize}>
<Editor
highlight={false}
value={this.state.transformContent}
onContentChange={this.onTransformContentChange}
/>
<TransformOutput
transform={this.state.transformContent}
code={this.state.content}
/>
</SplitPane> : null}
</PasteDropTarget>
);
}
Expand Down

0 comments on commit c69d857

Please sign in to comment.