├── .gitignore ├── Makefile ├── README.md ├── app ├── about-text.html ├── about.jsx ├── ast-node.jsx ├── ast-output.jsx ├── event.js ├── input.jsx ├── main.jsx ├── mixins │ ├── path.js │ ├── render-node-property.jsx │ └── toggle.js ├── node-component-finder.js ├── node-location.jsx ├── nodes │ ├── assignment-expression.jsx │ ├── binary-expression.jsx │ ├── block-statement.jsx │ ├── break-statement.jsx │ ├── call-expression.jsx │ ├── expression-statement.jsx │ ├── for-statement.jsx │ ├── function-declaration.jsx │ ├── function-expression.jsx │ ├── identifier.jsx │ ├── if-statement.jsx │ ├── literal.jsx │ ├── member-expression.jsx │ ├── object-expression.jsx │ ├── property.jsx │ ├── return-statement.jsx │ ├── this-expression.jsx │ ├── update-expression.jsx │ ├── variable-declaration.jsx │ └── variable-declarator.jsx ├── null-nodes.js ├── path.jsx └── starting-code.js ├── build-script.js ├── config.js ├── index.html ├── package.json └── style.css /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | jspm_packages/ 3 | dist/ 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | server: 2 | ./node_modules/.bin/serve -p 9876 3 | 4 | install: 5 | npm install 6 | jspm install 7 | 8 | build: 9 | mkdir -p dist/ 10 | cp jspm_packages/traceur-runtime.js dist/traceur-runtime.js 11 | node build-script.js 12 | jspm bundle-sfx app/main.jsx! dist/app.js 13 | cat dist/traceur-runtime.js dist/app.js > dist/dist.js 14 | ./node_modules/.bin/uglifyjs dist/dist.js -o dist/dist.min.js 15 | 16 | 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AST Viewer 2 | 3 | # Install 4 | 5 | ``` 6 | npm install --global jspm 7 | make install 8 | ``` 9 | 10 | # Run 11 | 12 | ``` 13 | make server 14 | ``` 15 | 16 | Now visit `http://localhost:9876`. 17 | 18 | ## TODO 19 | 20 | - swap to [espree](https://github.com/eslint/espree) for ES6 support? 21 | - deal with invalid input code 22 | - add ability to "zoom in" on a section of the code (will require the ability to find some of the AST given the path of the component) 23 | - test with more complex code examples 24 | - have a few pre-generated code examples to load in 25 | - ability to fetch and load in a URL from GitHub or similar 26 | - add build task to minify all the things for production 27 | - add text to the homepage about checking console if nothing renders 28 | 29 | -------------------------------------------------------------------------------- /app/about-text.html: -------------------------------------------------------------------------------- 1 |

ReactJS AST Viewer

2 | 3 |

Built using the following:

4 | 5 | 11 | -------------------------------------------------------------------------------- /app/about.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import aboutText from './about-text.html!text'; 3 | 4 | export default React.createClass({ 5 | render: function() { 6 | return ( 7 |
8 |
9 | ) 10 | } 11 | }); 12 | -------------------------------------------------------------------------------- /app/ast-node.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import _ from 'lodash'; 3 | import componentFinder from './node-component-finder'; 4 | import ToggleMixin from './mixins/toggle'; 5 | import Path from './path.jsx!'; 6 | import PathMixin from './mixins/path'; 7 | import emitter from './event'; 8 | import NodeLocation from './node-location.jsx!'; 9 | 10 | import NULL_NODE_TYPES from './null-nodes'; 11 | 12 | export default React.createClass({ 13 | mixins: [ToggleMixin, PathMixin], 14 | onMouseEnter: function(e) { 15 | e.stopPropagation(); 16 | emitter.emit('active-node', this.props.node); 17 | this.setState({ isFocused: true }); 18 | }, 19 | onMouseLeave: function(e) { 20 | e.stopPropagation(); 21 | emitter.emit('deactive-node', this.props.node); 22 | this.setState({ isFocused: false }); 23 | }, 24 | getRenderedContent: function() { 25 | if(this._content) return this._content; 26 | 27 | var newElementComponent = componentFinder(this.props.node.type); 28 | 29 | if(newElementComponent) { 30 | this._content = React.createElement(newElementComponent, this.props); 31 | return this._content; 32 | } else { 33 | console.err('No element found for node', this.props.node); 34 | } 35 | }, 36 | isNullNode: function() { 37 | return NULL_NODE_TYPES.indexOf(this.props.node.type) > -1; 38 | }, 39 | renderKey: function() { 40 | if(!this.props.nodeKey) return null; 41 | 42 | return {`${this.props.nodeKey}: `}; 43 | }, 44 | renderHeading: function() { 45 | return ( 46 |

{this.renderKey()}{ this.props.node.type } 47 | 48 |

49 | ); 50 | }, 51 | renderContent: function() { 52 | if(this.isNullNode()) return null; 53 | 54 | return ( 55 |
56 | { this.getRenderedContent() } 57 |
58 | ) 59 | }, 60 | renderToggle: function() { 61 | var internalText = this.state.visible ? '-' : '+'; 62 | if(this.isNullNode()) return null; 63 | return ( 64 | 65 | { internalText } 66 | 67 | ); 68 | }, 69 | render: function() { 70 | var outputProperties = this.getRenderedContent(); 71 | 72 | return ( 73 |
74 | 75 |
76 | { this.renderToggle() } 77 | 78 | { this.renderHeading() } 79 |
80 |
81 | { this.renderContent() } 82 |
83 |
84 | ); 85 | } 86 | }); 87 | -------------------------------------------------------------------------------- /app/ast-output.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import esprima from 'esprima'; 3 | import ASTNode from './ast-node.jsx!'; 4 | 5 | export default React.createClass({ 6 | componentWillMount: function() { 7 | this.setState({ 8 | tree: this.parseCode(this.props.code) 9 | }); 10 | }, 11 | componentWillReceiveProps: function(props) { 12 | this.setState({ 13 | tree: this.parseCode(props.code) 14 | }); 15 | }, 16 | parseCode: function(code) { 17 | var tree = esprima.parse(code, { loc: true }); 18 | console.log(tree); 19 | return tree; 20 | }, 21 | render: function() { 22 | var nodes = this.state.tree.body.map((body, index) => { 23 | return
  • ; 24 | }); 25 | 26 | return ; 27 | } 28 | }); 29 | -------------------------------------------------------------------------------- /app/event.js: -------------------------------------------------------------------------------- 1 | import ee from 'event-emitter'; 2 | 3 | export default ee({}); 4 | 5 | -------------------------------------------------------------------------------- /app/input.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import emitter from './event'; 3 | import AboutProject from './about.jsx!'; 4 | 5 | import ace from 'brace'; 6 | import 'brace/mode/javascript' 7 | 8 | var {Range} = ace.acequire('ace/range'); 9 | 10 | export default React.createClass({ 11 | highlightRange: function(startRow, startCol, endRow, endCol) { 12 | var range = new Range(...arguments); 13 | this.marker = this.editor.getSession().addMarker(range, 'code-highlight', 'text', true); 14 | }, 15 | shouldComponentUpdate: function(nextProps) { 16 | return false; 17 | }, 18 | componentDidMount: function() { 19 | this.editor = ace.edit('ace-editor'); 20 | this.editor.getSession().setMode('ace/mode/javascript'); 21 | this.editor.setHighlightActiveLine(false); 22 | 23 | emitter.on('active-node', (node) => { 24 | this.editor.getSession().removeMarker(this.marker); 25 | this.highlightRange( 26 | node.loc.start.line - 1, node.loc.start.column - 1, 27 | node.loc.end.line - 1, node.loc.end.column - 1); 28 | }); 29 | 30 | emitter.on('deactive-node', (node) => { 31 | this.editor.getSession().removeMarker(this.marker); 32 | }); 33 | }, 34 | handleSubmit: function(e) { 35 | e.preventDefault(); 36 | this.emitChange(); 37 | }, 38 | emitChange: function() { 39 | var input = this.editor.getValue(); 40 | emitter.emit('input-change', { code: input }); 41 | }, 42 | render: function() { 43 | return ( 44 |
    45 |
    46 | 47 |
    { this.props.code }
    48 |
    49 | 50 |
    51 | ); 52 | } 53 | }); 54 | 55 | 56 | -------------------------------------------------------------------------------- /app/main.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import CodeInput from './input.jsx!'; 3 | import ASTOutput from './ast-output.jsx!'; 4 | import emitter from './event'; 5 | 6 | import code from './starting-code.js!text'; 7 | 8 | var MainComponent = React.createClass({ 9 | onInputChange: function(args) { 10 | this.setState({ 11 | code: args.code 12 | }); 13 | }, 14 | componentWillMount: function() { 15 | emitter.on('input-change', this.onInputChange); 16 | }, 17 | componentWillUnmount: function() { 18 | emitter.off('input-change', this.onInputChange); 19 | }, 20 | getInitialState: function() { 21 | return { code: code, allVisible: false, showOnlyTree: false }; 22 | }, 23 | onToggleAllClick: function(e) { 24 | e.preventDefault(); 25 | var newVisible = !this.state.allVisible; 26 | emitter.emit('toggle-all', { visible: newVisible }); 27 | this.setState({ allVisible: newVisible }); 28 | }, 29 | onShowTreeToggle: function(e) { 30 | e.preventDefault(); 31 | this.setState({ 32 | showOnlyTree: !this.state.showOnlyTree 33 | }); 34 | }, 35 | renderCodeInput: function() { 36 | if(this.state.showOnlyTree) return; 37 | 38 | return ( 39 |
    40 | 41 |
    42 | ); 43 | }, 44 | renderTreeOutput: function() { 45 | return ( 46 |
    47 | 48 |
    49 | ); 50 | }, 51 | render: function() { 52 | var showOnlyTreeText = this.state.showOnlyTree ? 'View Code and Tree' : 'View Just Tree'; 53 | var toggleText = this.state.allVisible ? 'Close Tree' : 'Expand Tree'; 54 | 55 | return ( 56 |
    57 |
    58 |

    ReactJS AST Viewer

    59 |

    By @Jack_Franklin

    60 |
    61 | 62 |
    63 | { showOnlyTreeText } 64 | { toggleText } 65 |
    66 | 67 | { this.renderCodeInput() } 68 | { this.renderTreeOutput() } 69 |
    70 | ); 71 | } 72 | }); 73 | 74 | 75 | React.render(, document.querySelector('.wrap')); 76 | -------------------------------------------------------------------------------- /app/mixins/path.js: -------------------------------------------------------------------------------- 1 | export default { 2 | parentPath: function() { 3 | if(!this.props.parentPath) { 4 | console.warn('Warning: no parentPath set for', this.props.node); 5 | } 6 | return this.props.parentPath || ''; 7 | }, 8 | path: function() { 9 | return `${this.parentPath()}/${this.props.node.type}` 10 | }, 11 | arrayPath: function(key, index) { 12 | return `${this.path()}.${key}[${index}]`; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/mixins/render-node-property.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ASTNode from 'app/ast-node.jsx!'; 3 | 4 | export default { 5 | renderNode: function(propertyName, optional=false) { 6 | if(optional && !this.props.node[propertyName]) { 7 | return null; 8 | } 9 | 10 | return ( 11 |
  • 12 | 17 |
  • 18 | ); 19 | }, 20 | renderProp: function(propertyName, optional=false) { 21 | if(optional && !this.props.node[propertyName]) { 22 | return null; 23 | } 24 | 25 | return ( 26 |
  • 27 | {propertyName}{ this.props.node[propertyName] } 28 |
  • 29 | ); 30 | }, 31 | renderArrayProps: function(propertyName, optional=false) { 32 | var items = this.props.node[propertyName].map((item, index) => { 33 | return ( 34 |
  • 35 | 36 |
  • 37 | ); 38 | }); 39 | 40 | if(optional && !items.length) { 41 | return null; 42 | } 43 | 44 | return items; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/mixins/toggle.js: -------------------------------------------------------------------------------- 1 | import emitter from '../event'; 2 | 3 | export default { 4 | onToggleAll: function(data) { 5 | if(data && data.visible) { 6 | this.setState({ visible: data.visible }); 7 | } else { 8 | this.setState({ visible: !this.state.visible }); 9 | } 10 | }, 11 | componentWillUnmount: function() { 12 | emitter.off('toggle-all', this.onToggleAll); 13 | }, 14 | componentWillMount: function() { 15 | emitter.on('toggle-all', this.onToggleAll); 16 | }, 17 | getInitialState: function() { 18 | return { visible: false }; 19 | }, 20 | onToggleClick: function() { 21 | this.setState({ visible: !this.state.visible }); 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /app/node-component-finder.js: -------------------------------------------------------------------------------- 1 | import emitter from './event'; 2 | 3 | import FunctionDeclaration from './nodes/function-declaration.jsx!'; 4 | import BlockStatement from './nodes/block-statement.jsx!'; 5 | import ExpressionStatement from './nodes/expression-statement.jsx!'; 6 | import CallExpression from './nodes/call-expression.jsx!'; 7 | import MemberExpression from './nodes/member-expression.jsx!'; 8 | import Literal from './nodes/literal.jsx!'; 9 | import Identifier from './nodes/identifier.jsx!'; 10 | import VariableDeclaration from './nodes/variable-declaration.jsx!'; 11 | import VariableDeclarator from './nodes/variable-declarator.jsx!'; 12 | import ObjectExpression from './nodes/object-expression.jsx!'; 13 | import Property from './nodes/property.jsx!'; 14 | import FunctionExpression from './nodes/function-expression.jsx!'; 15 | import AssignmentExpression from './nodes/assignment-expression.jsx!'; 16 | import ThisExpression from './nodes/this-expression.jsx!'; 17 | import ReturnStatement from './nodes/return-statement.jsx!'; 18 | import BinaryExpression from './nodes/binary-expression.jsx!'; 19 | import ForStatement from './nodes/for-statement.jsx!'; 20 | import UpdateExpression from './nodes/update-expression.jsx!'; 21 | import IfStatement from './nodes/if-statement.jsx!'; 22 | import BreakStatement from './nodes/break-statement.jsx!'; 23 | 24 | const NODE_COMPONENTS = { 25 | FunctionDeclaration, 26 | BlockStatement, 27 | ExpressionStatement, 28 | CallExpression, 29 | MemberExpression, 30 | Literal, 31 | Identifier, 32 | VariableDeclaration, 33 | VariableDeclarator, 34 | ObjectExpression, 35 | Property, 36 | FunctionExpression, 37 | AssignmentExpression, 38 | ThisExpression, 39 | ReturnStatement, 40 | BinaryExpression, 41 | ForStatement, 42 | UpdateExpression, 43 | IfStatement, 44 | BreakStatement 45 | }; 46 | 47 | export default function(type) { 48 | var component = NODE_COMPONENTS[type]; 49 | 50 | if(component) return component; 51 | 52 | throw new Error(`No Component found for ${type}`); 53 | }; 54 | -------------------------------------------------------------------------------- /app/node-location.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default React.createClass({ 4 | render: function() { 5 | return ( 6 | 7 | Lines {this.props.loc.start.line} to {this.props.loc.end.line} 8 | 9 | ); 10 | } 11 | }); 12 | -------------------------------------------------------------------------------- /app/nodes/assignment-expression.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ASTNode from '../ast-node.jsx!'; 3 | import PathMixin from '../mixins/path'; 4 | import RenderNodeMixin from '../mixins/render-node-property.jsx!'; 5 | 6 | export default React.createClass({ 7 | mixins: [PathMixin, RenderNodeMixin], 8 | render: function() { 9 | return ( 10 | 15 | ); 16 | } 17 | }); 18 | -------------------------------------------------------------------------------- /app/nodes/binary-expression.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ASTNode from '../ast-node.jsx!'; 3 | import PathMixin from '../mixins/path'; 4 | import RenderNodeMixin from '../mixins/render-node-property.jsx!'; 5 | 6 | export default React.createClass({ 7 | mixins: [PathMixin, RenderNodeMixin], 8 | render: function() { 9 | return ( 10 | 14 | ); 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /app/nodes/block-statement.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ASTNode from '../ast-node.jsx!'; 3 | import PathMixin from '../mixins/path'; 4 | import RenderNodeMixin from '../mixins/render-node-property.jsx!'; 5 | 6 | export default React.createClass({ 7 | mixins: [PathMixin, RenderNodeMixin], 8 | render: function() { 9 | return ( 10 | 13 | ); 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /app/nodes/break-statement.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import RenderNodeMixin from '../mixins/render-node-property.jsx!'; 3 | 4 | export default React.createClass({ 5 | mixins: [RenderNodeMixin], 6 | render: function() { 7 | return this.renderProp('label', true); 8 | } 9 | }); 10 | -------------------------------------------------------------------------------- /app/nodes/call-expression.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ASTNode from '../ast-node.jsx!'; 3 | import PathMixin from '../mixins/path'; 4 | import RenderNodeMixin from '../mixins/render-node-property.jsx!'; 5 | 6 | export default React.createClass({ 7 | mixins: [PathMixin, RenderNodeMixin], 8 | render: function() { 9 | return ( 10 | 14 | ); 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /app/nodes/expression-statement.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ASTNode from '../ast-node.jsx!'; 3 | import PathMixin from '../mixins/path'; 4 | import RenderNodeMixin from '../mixins/render-node-property.jsx!'; 5 | 6 | export default React.createClass({ 7 | mixins: [PathMixin, RenderNodeMixin], 8 | render: function() { 9 | return ( 10 | 13 | ); 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /app/nodes/for-statement.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ASTNode from '../ast-node.jsx!'; 3 | import PathMixin from '../mixins/path'; 4 | import RenderNodeMixin from '../mixins/render-node-property.jsx!'; 5 | 6 | export default React.createClass({ 7 | mixins: [PathMixin, RenderNodeMixin], 8 | render: function() { 9 | return ( 10 | 16 | ); 17 | } 18 | }); 19 | -------------------------------------------------------------------------------- /app/nodes/function-declaration.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ASTNode from '../ast-node.jsx!'; 3 | import PathMixin from '../mixins/path'; 4 | import RenderNodeMixin from '../mixins/render-node-property.jsx!'; 5 | 6 | export default React.createClass({ 7 | mixins: [PathMixin, RenderNodeMixin], 8 | render: function() { 9 | return ( 10 | 14 | ); 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /app/nodes/function-expression.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ASTNode from '../ast-node.jsx!'; 3 | import PathMixin from '../mixins/path'; 4 | import RenderNodeMixin from '../mixins/render-node-property.jsx!'; 5 | 6 | export default React.createClass({ 7 | mixins: [PathMixin, RenderNodeMixin], 8 | render: function() { 9 | return ( 10 | 14 | ); 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /app/nodes/identifier.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import RenderNodeMixin from '../mixins/render-node-property.jsx!'; 3 | 4 | export default React.createClass({ 5 | mixins: [RenderNodeMixin], 6 | render: function() { 7 | return ( 8 | 9 | ); 10 | } 11 | }); 12 | -------------------------------------------------------------------------------- /app/nodes/if-statement.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ASTNode from '../ast-node.jsx!'; 3 | import PathMixin from '../mixins/path'; 4 | import RenderNodeMixin from '../mixins/render-node-property.jsx!'; 5 | 6 | export default React.createClass({ 7 | mixins: [PathMixin, RenderNodeMixin], 8 | render: function() { 9 | return ( 10 | 15 | ); 16 | } 17 | }); 18 | -------------------------------------------------------------------------------- /app/nodes/literal.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import RenderNodeMixin from '../mixins/render-node-property.jsx!'; 4 | import PathMixin from '../mixins/path'; 5 | 6 | export default React.createClass({ 7 | mixins: [PathMixin, RenderNodeMixin], 8 | render: function() { 9 | return ( 10 | 11 | ); 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /app/nodes/member-expression.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ASTNode from '../ast-node.jsx!'; 3 | import PathMixin from '../mixins/path'; 4 | import RenderNodeMixin from '../mixins/render-node-property.jsx!'; 5 | 6 | export default React.createClass({ 7 | mixins: [PathMixin, RenderNodeMixin], 8 | render: function() { 9 | return ( 10 | 14 | ); 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /app/nodes/object-expression.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ASTNode from '../ast-node.jsx!'; 3 | import PathMixin from '../mixins/path'; 4 | import RenderNodeMixin from '../mixins/render-node-property.jsx!'; 5 | 6 | export default React.createClass({ 7 | mixins: [PathMixin, RenderNodeMixin], 8 | render: function() { 9 | return ( 10 | 13 | ); 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /app/nodes/property.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ASTNode from '../ast-node.jsx!'; 3 | import PathMixin from '../mixins/path'; 4 | import RenderNodeMixin from '../mixins/render-node-property.jsx!'; 5 | 6 | export default React.createClass({ 7 | mixins: [PathMixin, RenderNodeMixin], 8 | render: function() { 9 | return ( 10 | 14 | ); 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /app/nodes/return-statement.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ASTNode from '../ast-node.jsx!'; 3 | import PathMixin from '../mixins/path'; 4 | import RenderNodeMixin from '../mixins/render-node-property.jsx!'; 5 | 6 | export default React.createClass({ 7 | mixins: [PathMixin, RenderNodeMixin], 8 | render: function() { 9 | return ( 10 | 13 | ); 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /app/nodes/this-expression.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default React.createClass({ 4 | render: function() { 5 | // there's nothing in a ThisExpression, it's basically a noop 6 | return null; 7 | } 8 | }); 9 | -------------------------------------------------------------------------------- /app/nodes/update-expression.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ASTNode from '../ast-node.jsx!'; 3 | import PathMixin from '../mixins/path'; 4 | import RenderNodeMixin from '../mixins/render-node-property.jsx!'; 5 | 6 | export default React.createClass({ 7 | mixins: [PathMixin, RenderNodeMixin], 8 | render: function() { 9 | return ( 10 | 15 | ); 16 | } 17 | }); 18 | -------------------------------------------------------------------------------- /app/nodes/variable-declaration.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ASTNode from '../ast-node.jsx!'; 3 | import PathMixin from '../mixins/path'; 4 | import RenderNodeMixin from '../mixins/render-node-property.jsx!'; 5 | 6 | export default React.createClass({ 7 | mixins: [PathMixin, RenderNodeMixin], 8 | getInitialState: function() { 9 | return { isFocused: false } 10 | }, 11 | render: function() { 12 | return ( 13 | 16 | ); 17 | } 18 | }); 19 | -------------------------------------------------------------------------------- /app/nodes/variable-declarator.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ASTNode from '../ast-node.jsx!'; 3 | import PathMixin from '../mixins/path'; 4 | import RenderNodeMixin from '../mixins/render-node-property.jsx!'; 5 | 6 | export default React.createClass({ 7 | mixins: [PathMixin, RenderNodeMixin], 8 | getInitialState: function() { 9 | return { isFocused: false } 10 | }, 11 | render: function() { 12 | return ( 13 | 17 | ); 18 | } 19 | }); 20 | -------------------------------------------------------------------------------- /app/null-nodes.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | 'ThisExpression' 3 | ]; 4 | -------------------------------------------------------------------------------- /app/path.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default React.createClass({ 4 | render: function() { 5 | if(!this.props.visible) return null; 6 | 7 | return ( 8 |
    9 | {this.props.path} 10 |
    11 | ); 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /app/starting-code.js: -------------------------------------------------------------------------------- 1 | var x = obj.init({ 2 | foo: true, 3 | bar: false, 4 | x: function() { 5 | return 2; 6 | } 7 | }); 8 | 9 | -------------------------------------------------------------------------------- /build-script.js: -------------------------------------------------------------------------------- 1 | var cheerio = require('cheerio'); 2 | var _ = require('lodash'); 3 | var fs = require('fs'); 4 | var $ = cheerio.load(fs.readFileSync('index.html')); 5 | 6 | $('script').remove(); 7 | 8 | $('body').append(""); 9 | 10 | fs.writeFileSync('dist/style.css', fs.readFileSync('style.css')); 11 | fs.writeFileSync('dist/index.html', '' + $('html').html() + ''); 12 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | System.config({ 2 | "baseURL": "/", 3 | "paths": { 4 | "*": "*.js", 5 | "github:*": "jspm_packages/github/*.js", 6 | "npm:*": "jspm_packages/npm/*.js" 7 | } 8 | }); 9 | 10 | System.config({ 11 | "map": { 12 | "ace": "github:ajaxorg/ace-builds@1.1.8", 13 | "brace": "npm:brace@0.5.0", 14 | "esprima": "npm:esprima@2.0.0", 15 | "event-emitter": "npm:event-emitter@0.3.3", 16 | "jsx": "github:floatdrop/plugin-jsx@0.1.1", 17 | "lodash": "npm:lodash@3.3.1", 18 | "react": "npm:react@0.12.2", 19 | "text": "github:systemjs/plugin-text@0.0.2", 20 | "github:floatdrop/plugin-jsx@0.1.1": { 21 | "react-tools": "npm:react-tools@0.12.2" 22 | }, 23 | "github:jspm/nodelibs-assert@0.1.0": { 24 | "assert": "npm:assert@1.3.0" 25 | }, 26 | "github:jspm/nodelibs-buffer@0.1.0": { 27 | "buffer": "npm:buffer@3.0.3" 28 | }, 29 | "github:jspm/nodelibs-constants@0.1.0": { 30 | "constants-browserify": "npm:constants-browserify@0.0.1" 31 | }, 32 | "github:jspm/nodelibs-crypto@0.1.0": { 33 | "crypto-browserify": "npm:crypto-browserify@3.9.13" 34 | }, 35 | "github:jspm/nodelibs-events@0.1.0": { 36 | "events-browserify": "npm:events-browserify@0.0.1" 37 | }, 38 | "github:jspm/nodelibs-http@1.7.0": { 39 | "Base64": "npm:Base64@0.2.1", 40 | "events": "github:jspm/nodelibs-events@0.1.0", 41 | "inherits": "npm:inherits@2.0.1", 42 | "stream": "github:jspm/nodelibs-stream@0.1.0", 43 | "url": "github:jspm/nodelibs-url@0.1.0", 44 | "util": "github:jspm/nodelibs-util@0.1.0" 45 | }, 46 | "github:jspm/nodelibs-path@0.1.0": { 47 | "path-browserify": "npm:path-browserify@0.0.0" 48 | }, 49 | "github:jspm/nodelibs-process@0.1.1": { 50 | "process": "npm:process@0.10.1" 51 | }, 52 | "github:jspm/nodelibs-stream@0.1.0": { 53 | "stream-browserify": "npm:stream-browserify@1.0.0" 54 | }, 55 | "github:jspm/nodelibs-string_decoder@0.1.0": { 56 | "string_decoder": "npm:string_decoder@0.10.31" 57 | }, 58 | "github:jspm/nodelibs-url@0.1.0": { 59 | "url": "npm:url@0.10.3" 60 | }, 61 | "github:jspm/nodelibs-util@0.1.0": { 62 | "util": "npm:util@0.10.3" 63 | }, 64 | "github:jspm/nodelibs-vm@0.1.0": { 65 | "vm-browserify": "npm:vm-browserify@0.0.4" 66 | }, 67 | "npm:amdefine@0.1.0": { 68 | "fs": "github:jspm/nodelibs-fs@0.1.1", 69 | "module": "github:jspm/nodelibs-module@0.1.0", 70 | "path": "github:jspm/nodelibs-path@0.1.0", 71 | "process": "github:jspm/nodelibs-process@0.1.1" 72 | }, 73 | "npm:asn1.js-rfc3280@1.0.0": { 74 | "asn1.js": "npm:asn1.js@1.0.3" 75 | }, 76 | "npm:asn1.js@1.0.3": { 77 | "assert": "github:jspm/nodelibs-assert@0.1.0", 78 | "bn.js": "npm:bn.js@1.3.0", 79 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 80 | "inherits": "npm:inherits@2.0.1", 81 | "minimalistic-assert": "npm:minimalistic-assert@1.0.0", 82 | "vm": "github:jspm/nodelibs-vm@0.1.0" 83 | }, 84 | "npm:assert@1.3.0": { 85 | "util": "npm:util@0.10.3" 86 | }, 87 | "npm:ast-types@0.6.16": { 88 | "assert": "github:jspm/nodelibs-assert@0.1.0", 89 | "util": "github:jspm/nodelibs-util@0.1.0" 90 | }, 91 | "npm:brace@0.5.0": { 92 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 93 | "process": "github:jspm/nodelibs-process@0.1.1", 94 | "w3c-blob": "npm:w3c-blob@0.0.1" 95 | }, 96 | "npm:browserify-aes@1.0.0": { 97 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 98 | "create-hash": "npm:create-hash@1.1.0", 99 | "crypto": "github:jspm/nodelibs-crypto@0.1.0", 100 | "fs": "github:jspm/nodelibs-fs@0.1.1", 101 | "inherits": "npm:inherits@2.0.1", 102 | "stream": "github:jspm/nodelibs-stream@0.1.0", 103 | "systemjs-json": "github:systemjs/plugin-json@0.1.0" 104 | }, 105 | "npm:browserify-rsa@1.1.1": { 106 | "bn.js": "npm:bn.js@1.3.0", 107 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 108 | "constants": "github:jspm/nodelibs-constants@0.1.0", 109 | "crypto": "github:jspm/nodelibs-crypto@0.1.0" 110 | }, 111 | "npm:browserify-rsa@2.0.0": { 112 | "bn.js": "npm:bn.js@1.3.0", 113 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 114 | "constants": "github:jspm/nodelibs-constants@0.1.0", 115 | "crypto": "github:jspm/nodelibs-crypto@0.1.0", 116 | "randombytes": "npm:randombytes@2.0.1" 117 | }, 118 | "npm:browserify-sign@2.8.0": { 119 | "bn.js": "npm:bn.js@1.3.0", 120 | "browserify-rsa": "npm:browserify-rsa@1.1.1", 121 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 122 | "crypto": "github:jspm/nodelibs-crypto@0.1.0", 123 | "elliptic": "npm:elliptic@1.0.1", 124 | "inherits": "npm:inherits@2.0.1", 125 | "parse-asn1": "npm:parse-asn1@2.0.0", 126 | "stream": "github:jspm/nodelibs-stream@0.1.0" 127 | }, 128 | "npm:buffer@3.0.3": { 129 | "base64-js": "npm:base64-js@0.0.8", 130 | "ieee754": "npm:ieee754@1.1.4", 131 | "is-array": "npm:is-array@1.0.1" 132 | }, 133 | "npm:commander@2.5.1": { 134 | "child_process": "github:jspm/nodelibs-child_process@0.1.0", 135 | "events": "github:jspm/nodelibs-events@0.1.0", 136 | "path": "github:jspm/nodelibs-path@0.1.0", 137 | "process": "github:jspm/nodelibs-process@0.1.1" 138 | }, 139 | "npm:commoner@0.10.1": { 140 | "assert": "github:jspm/nodelibs-assert@0.1.0", 141 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 142 | "child_process": "github:jspm/nodelibs-child_process@0.1.0", 143 | "commander": "npm:commander@2.5.1", 144 | "crypto": "github:jspm/nodelibs-crypto@0.1.0", 145 | "events": "github:jspm/nodelibs-events@0.1.0", 146 | "fs": "github:jspm/nodelibs-fs@0.1.1", 147 | "glob": "npm:glob@4.2.2", 148 | "graceful-fs": "npm:graceful-fs@3.0.5", 149 | "iconv-lite": "npm:iconv-lite@0.4.7", 150 | "install": "npm:install@0.1.8", 151 | "mkdirp": "npm:mkdirp@0.5.0", 152 | "path": "github:jspm/nodelibs-path@0.1.0", 153 | "private": "npm:private@0.1.6", 154 | "process": "github:jspm/nodelibs-process@0.1.1", 155 | "q": "npm:q@1.1.2", 156 | "recast": "npm:recast@0.9.18", 157 | "systemjs-json": "github:systemjs/plugin-json@0.1.0" 158 | }, 159 | "npm:constants-browserify@0.0.1": { 160 | "systemjs-json": "github:systemjs/plugin-json@0.1.0" 161 | }, 162 | "npm:core-util-is@1.0.1": { 163 | "buffer": "github:jspm/nodelibs-buffer@0.1.0" 164 | }, 165 | "npm:create-ecdh@2.0.0": { 166 | "bn.js": "npm:bn.js@1.3.0", 167 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 168 | "crypto": "github:jspm/nodelibs-crypto@0.1.0", 169 | "elliptic": "npm:elliptic@1.0.1" 170 | }, 171 | "npm:create-hash@1.1.0": { 172 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 173 | "crypto": "github:jspm/nodelibs-crypto@0.1.0", 174 | "fs": "github:jspm/nodelibs-fs@0.1.1", 175 | "inherits": "npm:inherits@2.0.1", 176 | "ripemd160": "npm:ripemd160@1.0.0", 177 | "sha.js": "npm:sha.js@2.3.6", 178 | "stream": "github:jspm/nodelibs-stream@0.1.0" 179 | }, 180 | "npm:create-hmac@1.1.3": { 181 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 182 | "create-hash": "npm:create-hash@1.1.0", 183 | "crypto": "github:jspm/nodelibs-crypto@0.1.0", 184 | "inherits": "npm:inherits@2.0.1", 185 | "stream": "github:jspm/nodelibs-stream@0.1.0" 186 | }, 187 | "npm:crypto-browserify@3.9.13": { 188 | "browserify-aes": "npm:browserify-aes@1.0.0", 189 | "browserify-sign": "npm:browserify-sign@2.8.0", 190 | "create-ecdh": "npm:create-ecdh@2.0.0", 191 | "create-hash": "npm:create-hash@1.1.0", 192 | "create-hmac": "npm:create-hmac@1.1.3", 193 | "diffie-hellman": "npm:diffie-hellman@3.0.1", 194 | "inherits": "npm:inherits@2.0.1", 195 | "pbkdf2-compat": "npm:pbkdf2-compat@3.0.2", 196 | "public-encrypt": "npm:public-encrypt@2.0.0", 197 | "randombytes": "npm:randombytes@2.0.1" 198 | }, 199 | "npm:d@0.1.1": { 200 | "es5-ext": "npm:es5-ext@0.10.6" 201 | }, 202 | "npm:diffie-hellman@3.0.1": { 203 | "bn.js": "npm:bn.js@1.3.0", 204 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 205 | "crypto": "github:jspm/nodelibs-crypto@0.1.0", 206 | "miller-rabin": "npm:miller-rabin@1.1.5", 207 | "process": "github:jspm/nodelibs-process@0.1.1", 208 | "randombytes": "npm:randombytes@2.0.1", 209 | "systemjs-json": "github:systemjs/plugin-json@0.1.0" 210 | }, 211 | "npm:elliptic@1.0.1": { 212 | "bn.js": "npm:bn.js@1.3.0", 213 | "brorand": "npm:brorand@1.0.5", 214 | "hash.js": "npm:hash.js@1.0.2", 215 | "inherits": "npm:inherits@2.0.1", 216 | "systemjs-json": "github:systemjs/plugin-json@0.1.0" 217 | }, 218 | "npm:envify@3.2.0": { 219 | "jstransform": "npm:jstransform@7.0.0", 220 | "process": "github:jspm/nodelibs-process@0.1.1", 221 | "through": "npm:through@2.3.6" 222 | }, 223 | "npm:es5-ext@0.10.6": { 224 | "es6-iterator": "npm:es6-iterator@0.1.3", 225 | "es6-symbol": "npm:es6-symbol@2.0.1", 226 | "process": "github:jspm/nodelibs-process@0.1.1" 227 | }, 228 | "npm:es6-iterator@0.1.3": { 229 | "d": "npm:d@0.1.1", 230 | "es5-ext": "npm:es5-ext@0.10.6", 231 | "es6-symbol": "npm:es6-symbol@2.0.1" 232 | }, 233 | "npm:es6-symbol@2.0.1": { 234 | "d": "npm:d@0.1.1", 235 | "es5-ext": "npm:es5-ext@0.10.6" 236 | }, 237 | "npm:esprima-fb@10001.1.0-dev-harmony-fb": { 238 | "fs": "github:jspm/nodelibs-fs@0.1.1", 239 | "process": "github:jspm/nodelibs-process@0.1.1" 240 | }, 241 | "npm:esprima-fb@7001.1.0-dev-harmony-fb": { 242 | "fs": "github:jspm/nodelibs-fs@0.1.1", 243 | "process": "github:jspm/nodelibs-process@0.1.1" 244 | }, 245 | "npm:esprima-fb@8001.1001.0-dev-harmony-fb": { 246 | "fs": "github:jspm/nodelibs-fs@0.1.1", 247 | "process": "github:jspm/nodelibs-process@0.1.1" 248 | }, 249 | "npm:esprima@2.0.0": { 250 | "fs": "github:jspm/nodelibs-fs@0.1.1", 251 | "process": "github:jspm/nodelibs-process@0.1.1" 252 | }, 253 | "npm:event-emitter@0.3.3": { 254 | "d": "npm:d@0.1.1", 255 | "es5-ext": "npm:es5-ext@0.10.6", 256 | "events": "github:jspm/nodelibs-events@0.1.0" 257 | }, 258 | "npm:events-browserify@0.0.1": { 259 | "process": "github:jspm/nodelibs-process@0.1.1" 260 | }, 261 | "npm:glob@4.2.2": { 262 | "assert": "github:jspm/nodelibs-assert@0.1.0", 263 | "events": "github:jspm/nodelibs-events@0.1.0", 264 | "fs": "github:jspm/nodelibs-fs@0.1.1", 265 | "inflight": "npm:inflight@1.0.4", 266 | "inherits": "npm:inherits@2.0.1", 267 | "minimatch": "npm:minimatch@1.0.0", 268 | "once": "npm:once@1.3.1", 269 | "path": "github:jspm/nodelibs-path@0.1.0", 270 | "process": "github:jspm/nodelibs-process@0.1.1", 271 | "util": "github:jspm/nodelibs-util@0.1.0" 272 | }, 273 | "npm:graceful-fs@3.0.5": { 274 | "assert": "github:jspm/nodelibs-assert@0.1.0", 275 | "constants": "github:jspm/nodelibs-constants@0.1.0", 276 | "module": "github:jspm/nodelibs-module@0.1.0", 277 | "process": "github:jspm/nodelibs-process@0.1.1", 278 | "util": "github:jspm/nodelibs-util@0.1.0", 279 | "vm": "github:jspm/nodelibs-vm@0.1.0" 280 | }, 281 | "npm:hash.js@1.0.2": { 282 | "inherits": "npm:inherits@2.0.1" 283 | }, 284 | "npm:iconv-lite@0.4.7": { 285 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 286 | "process": "github:jspm/nodelibs-process@0.1.1", 287 | "stream": "github:jspm/nodelibs-stream@0.1.0", 288 | "string_decoder": "github:jspm/nodelibs-string_decoder@0.1.0", 289 | "systemjs-json": "github:systemjs/plugin-json@0.1.0" 290 | }, 291 | "npm:inflight@1.0.4": { 292 | "once": "npm:once@1.3.1", 293 | "process": "github:jspm/nodelibs-process@0.1.1", 294 | "wrappy": "npm:wrappy@1.0.1" 295 | }, 296 | "npm:inherits@2.0.1": { 297 | "util": "github:jspm/nodelibs-util@0.1.0" 298 | }, 299 | "npm:install@0.1.8": { 300 | "assert": "github:jspm/nodelibs-assert@0.1.0", 301 | "fs": "github:jspm/nodelibs-fs@0.1.1", 302 | "path": "github:jspm/nodelibs-path@0.1.0", 303 | "process": "github:jspm/nodelibs-process@0.1.1" 304 | }, 305 | "npm:jstransform@7.0.0": { 306 | "base62": "npm:base62@0.1.1", 307 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 308 | "esprima-fb": "npm:esprima-fb@7001.1.0-dev-harmony-fb", 309 | "process": "github:jspm/nodelibs-process@0.1.1", 310 | "source-map": "npm:source-map@0.1.31" 311 | }, 312 | "npm:jstransform@8.2.0": { 313 | "base62": "npm:base62@0.1.1", 314 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 315 | "esprima-fb": "npm:esprima-fb@8001.1001.0-dev-harmony-fb", 316 | "fs": "github:jspm/nodelibs-fs@0.1.1", 317 | "process": "github:jspm/nodelibs-process@0.1.1", 318 | "source-map": "npm:source-map@0.1.31" 319 | }, 320 | "npm:lodash@3.3.1": { 321 | "process": "github:jspm/nodelibs-process@0.1.1" 322 | }, 323 | "npm:miller-rabin@1.1.5": { 324 | "bn.js": "npm:bn.js@1.3.0", 325 | "brorand": "npm:brorand@1.0.5" 326 | }, 327 | "npm:minimatch@1.0.0": { 328 | "lru-cache": "npm:lru-cache@2.5.0", 329 | "path": "github:jspm/nodelibs-path@0.1.0", 330 | "process": "github:jspm/nodelibs-process@0.1.1", 331 | "sigmund": "npm:sigmund@1.0.0" 332 | }, 333 | "npm:mkdirp@0.5.0": { 334 | "fs": "github:jspm/nodelibs-fs@0.1.1", 335 | "minimist": "npm:minimist@0.0.8", 336 | "path": "github:jspm/nodelibs-path@0.1.0", 337 | "process": "github:jspm/nodelibs-process@0.1.1" 338 | }, 339 | "npm:once@1.3.1": { 340 | "wrappy": "npm:wrappy@1.0.1" 341 | }, 342 | "npm:parse-asn1@2.0.0": { 343 | "asn1.js": "npm:asn1.js@1.0.3", 344 | "asn1.js-rfc3280": "npm:asn1.js-rfc3280@1.0.0", 345 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 346 | "pemstrip": "npm:pemstrip@0.0.1", 347 | "systemjs-json": "github:systemjs/plugin-json@0.1.0" 348 | }, 349 | "npm:parse-asn1@3.0.0": { 350 | "asn1.js": "npm:asn1.js@1.0.3", 351 | "browserify-aes": "npm:browserify-aes@1.0.0", 352 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 353 | "create-hash": "npm:create-hash@1.1.0", 354 | "pbkdf2-compat": "npm:pbkdf2-compat@3.0.2", 355 | "systemjs-json": "github:systemjs/plugin-json@0.1.0" 356 | }, 357 | "npm:path-browserify@0.0.0": { 358 | "process": "github:jspm/nodelibs-process@0.1.1" 359 | }, 360 | "npm:pbkdf2-compat@3.0.2": { 361 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 362 | "child_process": "github:jspm/nodelibs-child_process@0.1.0", 363 | "create-hmac": "npm:create-hmac@1.1.3", 364 | "crypto": "github:jspm/nodelibs-crypto@0.1.0", 365 | "path": "github:jspm/nodelibs-path@0.1.0", 366 | "process": "github:jspm/nodelibs-process@0.1.1", 367 | "systemjs-json": "github:systemjs/plugin-json@0.1.0" 368 | }, 369 | "npm:public-encrypt@2.0.0": { 370 | "bn.js": "npm:bn.js@1.3.0", 371 | "browserify-rsa": "npm:browserify-rsa@2.0.0", 372 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 373 | "create-hash": "npm:create-hash@1.1.0", 374 | "crypto": "github:jspm/nodelibs-crypto@0.1.0", 375 | "parse-asn1": "npm:parse-asn1@3.0.0", 376 | "randombytes": "npm:randombytes@2.0.1" 377 | }, 378 | "npm:punycode@1.3.2": { 379 | "process": "github:jspm/nodelibs-process@0.1.1" 380 | }, 381 | "npm:q@1.1.2": { 382 | "process": "github:jspm/nodelibs-process@0.1.1" 383 | }, 384 | "npm:randombytes@2.0.1": { 385 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 386 | "crypto": "github:jspm/nodelibs-crypto@0.1.0", 387 | "process": "github:jspm/nodelibs-process@0.1.1" 388 | }, 389 | "npm:react-tools@0.12.2": { 390 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 391 | "commoner": "npm:commoner@0.10.1", 392 | "jstransform": "npm:jstransform@8.2.0", 393 | "process": "github:jspm/nodelibs-process@0.1.1" 394 | }, 395 | "npm:react@0.12.2": { 396 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 397 | "envify": "npm:envify@3.2.0", 398 | "process": "github:jspm/nodelibs-process@0.1.1" 399 | }, 400 | "npm:readable-stream@1.1.13": { 401 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 402 | "core-util-is": "npm:core-util-is@1.0.1", 403 | "events": "github:jspm/nodelibs-events@0.1.0", 404 | "inherits": "npm:inherits@2.0.1", 405 | "isarray": "npm:isarray@0.0.1", 406 | "process": "github:jspm/nodelibs-process@0.1.1", 407 | "stream": "npm:stream-browserify@1.0.0", 408 | "string_decoder": "npm:string_decoder@0.10.31", 409 | "util": "github:jspm/nodelibs-util@0.1.0" 410 | }, 411 | "npm:recast@0.9.18": { 412 | "assert": "github:jspm/nodelibs-assert@0.1.0", 413 | "ast-types": "npm:ast-types@0.6.16", 414 | "esprima-fb": "npm:esprima-fb@10001.1.0-dev-harmony-fb", 415 | "fs": "github:jspm/nodelibs-fs@0.1.1", 416 | "private": "npm:private@0.1.6", 417 | "process": "github:jspm/nodelibs-process@0.1.1", 418 | "source-map": "npm:source-map@0.1.43" 419 | }, 420 | "npm:ripemd160@1.0.0": { 421 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 422 | "process": "github:jspm/nodelibs-process@0.1.1" 423 | }, 424 | "npm:sha.js@2.3.6": { 425 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 426 | "fs": "github:jspm/nodelibs-fs@0.1.1", 427 | "inherits": "npm:inherits@2.0.1", 428 | "process": "github:jspm/nodelibs-process@0.1.1" 429 | }, 430 | "npm:sigmund@1.0.0": { 431 | "http": "github:jspm/nodelibs-http@1.7.0", 432 | "util": "github:jspm/nodelibs-util@0.1.0" 433 | }, 434 | "npm:source-map@0.1.31": { 435 | "amdefine": "npm:amdefine@0.1.0", 436 | "fs": "github:jspm/nodelibs-fs@0.1.1", 437 | "path": "github:jspm/nodelibs-path@0.1.0", 438 | "process": "github:jspm/nodelibs-process@0.1.1" 439 | }, 440 | "npm:source-map@0.1.43": { 441 | "amdefine": "npm:amdefine@0.1.0", 442 | "fs": "github:jspm/nodelibs-fs@0.1.1", 443 | "path": "github:jspm/nodelibs-path@0.1.0", 444 | "process": "github:jspm/nodelibs-process@0.1.1" 445 | }, 446 | "npm:stream-browserify@1.0.0": { 447 | "events": "github:jspm/nodelibs-events@0.1.0", 448 | "inherits": "npm:inherits@2.0.1", 449 | "readable-stream": "npm:readable-stream@1.1.13" 450 | }, 451 | "npm:string_decoder@0.10.31": { 452 | "buffer": "github:jspm/nodelibs-buffer@0.1.0" 453 | }, 454 | "npm:through@2.3.6": { 455 | "process": "github:jspm/nodelibs-process@0.1.1", 456 | "stream": "github:jspm/nodelibs-stream@0.1.0" 457 | }, 458 | "npm:url@0.10.3": { 459 | "assert": "github:jspm/nodelibs-assert@0.1.0", 460 | "punycode": "npm:punycode@1.3.2", 461 | "querystring": "npm:querystring@0.2.0", 462 | "util": "github:jspm/nodelibs-util@0.1.0" 463 | }, 464 | "npm:util@0.10.3": { 465 | "inherits": "npm:inherits@2.0.1", 466 | "process": "github:jspm/nodelibs-process@0.1.1" 467 | }, 468 | "npm:vm-browserify@0.0.4": { 469 | "indexof": "npm:indexof@0.0.1" 470 | }, 471 | "npm:w3c-blob@0.0.1": { 472 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 473 | "process": "github:jspm/nodelibs-process@0.1.1" 474 | } 475 | } 476 | }); 477 | 478 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | AST Viewer 5 | 6 | 7 | 8 | 9 | 10 | 11 | Fork me on GitHub 12 |
    13 |
    14 | 15 | 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ast-viewer", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "jspm": { 12 | "directories": { 13 | "lib": ".", 14 | "packages": "jspm_packages" 15 | }, 16 | "dependencies": { 17 | "ace": "github:ajaxorg/ace-builds@^1.1.8", 18 | "brace": "npm:brace@^0.5.0", 19 | "esprima": "npm:esprima@^2.0.0", 20 | "event-emitter": "npm:event-emitter@^0.3.3", 21 | "jsx": "github:floatdrop/plugin-jsx@^0.1.1", 22 | "lodash": "npm:lodash@^3.3.1", 23 | "react": "npm:react@^0.12.2", 24 | "text": "github:systemjs/plugin-text@^0.0.2" 25 | } 26 | }, 27 | "devDependencies": { 28 | "cheerio": "^0.18.0", 29 | "serve": "^1.4.0", 30 | "uglify-js": "^2.4.16" 31 | }, 32 | "dependencies": { 33 | "lodash": "^3.4.0" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | .wrap { 2 | width: 90%; 3 | margin: 5px auto; 4 | overflow: auto; 5 | font-family: Helvetica, Arial, sans-serif; 6 | } 7 | 8 | .app { 9 | overflow: auto 10 | } 11 | 12 | .code { 13 | width: 35%; 14 | float: left; 15 | margin-top: -100px; 16 | } 17 | 18 | .ast { 19 | width: 63%; 20 | float: right; 21 | } 22 | 23 | .full-screen.ast { 24 | width: 100%; 25 | float: none; 26 | } 27 | 28 | .input-form textarea { 29 | display: block; 30 | height: 300px; 31 | width: 100%; 32 | font-family: Courier, sans-serif; 33 | font-size: 14px; 34 | padding: 5px; 35 | } 36 | 37 | div.path code { 38 | position: fixed; 39 | z-index: 999; 40 | background: white; 41 | bottom: 20px; 42 | right: 20px; 43 | padding: 5px; 44 | } 45 | 46 | div.path code.hidden, .hidden { display: none; } 47 | 48 | .btn { 49 | border: none; 50 | display: inline-block; 51 | background: #498EE0; 52 | color: white; 53 | width: 200px; 54 | text-decoration: none; 55 | border-radius: 2px; 56 | text-align: center; 57 | padding: 10px; 58 | margin-left: 10px; 59 | font-size: 13px; 60 | margin-bottom: 5px; 61 | } 62 | 63 | .app-btns { 64 | float: right; 65 | } 66 | 67 | .btn:hover { 68 | text-decoration: underline; 69 | } 70 | 71 | .header { 72 | text-align: center; 73 | } 74 | 75 | .input-form input { 76 | margin: 10px 0 0 0; 77 | box-sizing: content-box; 78 | } 79 | 80 | #ace-editor { 81 | border: 1px solid black; 82 | position: relative; 83 | width: 100%; 84 | height: 300px; 85 | } 86 | 87 | 88 | .code-highlight { 89 | background: rgba(255, 50, 50, 0.1); 90 | position: absolute; 91 | width: 100% !important; 92 | left: 0 !important; 93 | } 94 | 95 | .toggle-icon { 96 | display: block; 97 | float: left; 98 | height: 20px; 99 | width: 20px; 100 | text-align: center; 101 | line-height: 20px; 102 | border-radius: 2px; 103 | background: #498EE0; 104 | color: white; 105 | text-decoration: none; 106 | } 107 | 108 | .ast ul, .ast-node ul { 109 | list-style: none; 110 | padding: 0 0 0 10px; 111 | margin: 0; 112 | } 113 | 114 | .ast li, 115 | .ast-node li { 116 | padding: 0; 117 | margin: 0; 118 | } 119 | 120 | .ast-node-head { 121 | padding: 3px; 122 | margin: 0 0 3px 0; 123 | background: #f8faff; 124 | border: 1px solid #dae2ea; 125 | overflow: auto; 126 | } 127 | .ast-node-head h4 { 128 | float: left; 129 | margin: 0; 130 | font-weight: normal; 131 | padding: 3px 0 0 6px; 132 | position: relative; 133 | width: 95%; 134 | } 135 | 136 | .node-location { 137 | position: absolute; 138 | right: 5px; 139 | top: 3px; 140 | } 141 | 142 | .ast-node li.node-property { 143 | margin-left: 20px; 144 | border: 1px solid #498EE0; 145 | border-left: 10px solid #498EE0; 146 | padding-left: 5px; 147 | margin-bottom: 3px; 148 | } 149 | 150 | .node-property, .node-key { 151 | font-family: Courier; 152 | } 153 | 154 | .node-property strong { 155 | padding-right: 5px; 156 | display: inline-block; 157 | font-weight: normal; 158 | font-family: Helvetica, Arial, sans-serif; 159 | } 160 | 161 | --------------------------------------------------------------------------------