Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

⚛️ Add DataFormsJS JSX Loader #631

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ The AST explorer provides following code parsers:
- [typescript][]
- [typescript-eslint-parser][]
- [uglify-js][]
- JSX:
- [dataformsjs][]
- JSON:
- [JSON][]
- [Momoa][]
Expand Down
1 change: 1 addition & 0 deletions website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
"css": "^2.2.1",
"css-tree": "^2.0.0",
"cssom": "^0.4.4",
"dataformsjs": "^5.10.6",
"domhandler": "^4.0.0",
"ember-template-recast": "^5.0.1",
"escodegen": "^1.14.1",
Expand Down
66 changes: 66 additions & 0 deletions website/src/parsers/jsx/codeExample.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
class TodoApp extends React.Component {
constructor(props) {
super(props);
this.state = { items: [], text: '' };
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}

render() {
return (
<div>
<h3>To Do List</h3>
<TodoList items={this.state.items} />
<form onSubmit={this.handleSubmit}>
<label htmlFor="new-todo">
What needs to be done?
</label>
<input
id="new-todo"
onChange={this.handleChange}
value={this.state.text}
/>
<button>
Add #{this.state.items.length + 1}
</button>
</form>
</div>
);
}

handleChange(e) {
this.setState({ text: e.target.value });
}

handleSubmit(e) {
e.preventDefault();
if (this.state.text.length === 0) {
return;
}
const newItem = {
text: this.state.text,
id: Date.now()
};
this.setState(state => ({
items: state.items.concat(newItem),
text: ''
}));
}
}

class TodoList extends React.Component {
render() {
return (
<ul>
{this.props.items.map(item => (
<li key={item.id}>{item.text}</li>
))}
</ul>
);
}
}

ReactDOM.render(
<TodoApp />,
document.getElementById('todos-example')
);
104 changes: 104 additions & 0 deletions website/src/parsers/jsx/dataformsjs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import defaultParserInterface from '../utils/defaultParserInterface';
import pkg from 'dataformsjs/package.json';

const ID = 'dataformsjs';

export default {
...defaultParserInterface,

id: ID,
displayName: ID,
version: pkg.version,
// Link to the main DataFormsJS JSX Loader Documentation rather than project Homepage.
// The main project homepage contains additional JS code not related to the compiler.
//
// homepage: pkg.homepage,
homepage: 'https://github.com/dataformsjs/dataformsjs/blob/master/docs/jsx-loader.md',
locationProps: new Set(['pos']),
typeProps: new Set(['type']),

loadParser(callback) {
require(['dataformsjs/js/react/jsxLoader'], () => {
callback({ jsxLoader: window.jsxLoader });
});
},

parse({ jsxLoader }, code, options) {
// AST is built using internal logic from `jsxLoader.compiler.compile()`.
// When calling the `compile()` function, generated JS code is returned
// while AST is needed for this site.
if (jsxLoader.compiler.isMinimized(code)) {
throw new Error('Unable to parse minimized code');
}
var newInput = jsxLoader.compiler.removeComments(code);
var tokens = jsxLoader.compiler.tokenizer(newInput);
var ast = jsxLoader.compiler.parser(tokens, code);
return ast;
},

nodeToRange(node) {
// The property `pos` is included in the AST by jsxLoader for developer debugging
// however the compiler itself does not use it other than for error messages.
// `pos` is not completely accurate so code here makes some corrections.
// A length property is not included by the in the AST but one is needed for this
// site so it is calculated here. The result is often correct but not 100% of
// the time. When the node doesn't match it will generally be very close.
if (node.pos !== null) {
let pos = node.pos;
let len = 0;
switch (node.type) {
case 'js':
len = node.value.length;
break;
case 'e_child_whitespace':
case 'e_child_js':
case 'e_child_js_start':
case 'e_child_js_end':
case 'e_child_text':
len = node.value.length;
pos -= len;
break;
case 'createElement':
if (node.children.length > 0) {
len = node.children[node.children.length-1].pos - pos;
} else {
len = node.name.length + 1;
for (var n = 0; n < node.props.length; n++) {
if (typeof node.props[n].value === 'string') {
len += node.props[n].name.length + node.props[n].value.length + 1;
}
}
}
len++;
pos -= node.name.length + 1;
break;
case 'e_start':
if (node.value && node.value.type && node.value.type === 'createElement') {
const name = node.value.name;
len = name.length + 1;
pos -= name.length + 1;
}
break;
}
return [pos, pos + len];
}
},

getNodeName(node) {
return node.type;
},

opensByDefault(node, key) {
return (
(node.type === 'program')
|| (node.children && node.children.length)
|| (node.props && node.props.length)
);
},

getDefaultOptions() {
// JSX Loader provides some options for run-time code generation
// and do not apply to the lower-level API calls made for this site.
return {};
},
};
6 changes: 6 additions & 0 deletions website/src/parsers/jsx/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import 'codemirror/mode/jsx/jsx';

export const id = 'jsx';
export const displayName = 'JSX';
export const mimeTypes = ['text/jsx'];
export const fileExtension = '.jsx';
5 changes: 5 additions & 0 deletions website/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4373,6 +4373,11 @@ d@1, d@^1.0.1:
es5-ext "^0.10.50"
type "^1.0.1"

dataformsjs@^5.10.6:
version "5.10.6"
resolved "https://registry.yarnpkg.com/dataformsjs/-/dataformsjs-5.10.6.tgz#caf9bb7593e9cd9e2190a4af6f557666e2d1a5f1"
integrity sha512-B8uQqKXpdcIAGIrdzrkL2IMelRu1spWDsOgDD3e+JzKEykRByV4K74IBZdbYSl+knFHtYoezCzn6Mf7P4qj2iA==

date-fns@^2.16.1:
version "2.23.0"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.23.0.tgz#4e886c941659af0cf7b30fafdd1eaa37e88788a9"
Expand Down