Skip to content

Commit

Permalink
[sync]
Browse files Browse the repository at this point in the history
Improve jsx support in e4x
beautifier/js-beautify@f8abc15
Additional jsx tests
beautifier/js-beautify@8c3ddc5
  • Loading branch information
Infocatcher committed Mar 17, 2015
1 parent 9582b3f commit c13dcc9
Showing 1 changed file with 217 additions and 4 deletions.
221 changes: 217 additions & 4 deletions jsBeautifier.js
Expand Up @@ -6,7 +6,7 @@
// Version: 0.2.7 - 2015-01-10
// Author: Infocatcher
// Based on scripts from http://jsbeautifier.org/
// [built from https://github.com/beautify-web/js-beautify/tree/master 2015-03-12 23:42:38 UTC]
// [built from https://github.com/beautify-web/js-beautify/tree/master 2015-03-16 20:29:32 UTC]

//===================
//// JavaScript unpacker and beautifier, also can unpack HTML with scripts and styles inside
Expand Down Expand Up @@ -2019,7 +2019,7 @@ function detectXMLType(str) {
if (c === '`' || c === "'" || c === '"' || // string
(
(c === '/') || // regexp
(opts.e4x && c === "<" && input.slice(parser_pos - 1).match(/^<([-a-zA-Z:0-9_.]+|{[^{}]*}|!\[CDATA\[[\s\S]*?\]\])(\s+[-a-zA-Z:0-9_.]+\s*=\s*('[^']*'|"[^"]*"|{[^{}]*}))*\s*(\/?)\s*>/)) // xml
(opts.e4x && c === "<" && input.slice(parser_pos - 1).match(/^<([-a-zA-Z:0-9_.]+|{[^{}]*}|!\[CDATA\[[\s\S]*?\]\])(\s+[-a-zA-Z:0-9_.]+\s*=\s*('[^']*'|"[^"]*"|{.*?}))*\s*(\/?)\s*>/)) // xml
) && ( // regex and xml can only appear in specific locations during parsing
(last_token.type === 'TK_RESERVED' && in_array(last_token.text , ['return', 'case', 'throw', 'else', 'do', 'typeof', 'yield'])) ||
(last_token.type === 'TK_END_EXPR' && last_token.text === ')' &&
Expand Down Expand Up @@ -2060,7 +2060,7 @@ function detectXMLType(str) {
//
// handle e4x xml literals
//
var xmlRegExp = /<(\/?)([-a-zA-Z:0-9_.]+|{[^{}]*}|!\[CDATA\[[\s\S]*?\]\])(\s+[-a-zA-Z:0-9_.]+\s*=\s*('[^']*'|"[^"]*"|{[^{}]*}))*\s*(\/?)\s*>/g;
var xmlRegExp = /<(\/?)([-a-zA-Z:0-9_.]+|{[^{}]*}|!\[CDATA\[[\s\S]*?\]\])(\s+[-a-zA-Z:0-9_.]+\s*=\s*('[^']*'|"[^"]*"|{.*?}))*\s*(\/?)\s*>/g;
var xmlStr = input.slice(parser_pos - 1);
var match = xmlRegExp.exec(xmlStr);
if (match && match.index === 0) {
Expand All @@ -2083,8 +2083,9 @@ function detectXMLType(str) {
match = xmlRegExp.exec(xmlStr);
}
var xmlLength = match ? match.index + match[0].length : xmlStr.length;
xmlStr = xmlStr.slice(0, xmlLength);
parser_pos += xmlLength - 1;
return [xmlStr.slice(0, xmlLength), "TK_STRING"];
return [xmlStr, "TK_STRING"];
}
} else {
//
Expand Down Expand Up @@ -4376,6 +4377,218 @@ function run_javascript_tests(test_obj, Urlencoded, js_beautify, html_beautify,
bt('xml=<![CDATA[]]>;', 'xml = <![CDATA[]]>;');
bt('xml=<a b="c"><![CDATA[d/></a></{}]]></a>;', 'xml = <a b="c"><![CDATA[d/></a></{}]]></a>;');

// JSX - working jsx from http://prettydiff.com/unit_tests/beautification_javascript_jsx.txt
bt(
'var ListItem = React.createClass({\n' +
' render: function() {\n' +
' return (\n' +
' <li className="ListItem">\n' +
' <a href={ "/items/" + this.props.item.id }>\n' +
' this.props.item.name\n' +
' </a>\n' +
' </li>\n' +
' );\n' +
' }\n' +
'});');
bt(
'var List = React.createClass({\n' +
' renderList: function() {\n' +
' return this.props.items.map(function(item) {\n' +
' return <ListItem item={item} key={item.id} />;\n' +
' });\n' +
' },\n' +
'\n' +
' render: function() {\n' +
' return <ul className="List">\n' +
' this.renderList()\n' +
' </ul>\n' +
' }\n' +
'});');
bt(
'var Mist = React.createClass({\n' +
' renderList: function() {\n' +
' return this.props.items.map(function(item) {\n' +
' return <ListItem item={return <tag>{item}</tag>} key={item.id} />;\n' +
' });\n' +
' }\n' +
'});');
bt(
'// JSX\n' +
'var box = <Box>\n' +
' {shouldShowAnswer(user) ?\n' +
' <Answer value={false}>no</Answer> : <Box.Comment>\n' +
' Text Content\n' +
' </Box.Comment>}\n' +
' </Box>;\n' +
'var a = function() {\n' +
' return <tsdf>asdf</tsdf>;\n' +
'};\n' +
'\n' +
'var HelloMessage = React.createClass({\n' +
' render: function() {\n' +
' return <div>Hello {this.props.name}</div>;\n' +
' }\n' +
'});\n' +
'React.render(<HelloMessage name="John" />, mountNode);');
bt(
'var Timer = React.createClass({\n' +
' getInitialState: function() {\n' +
' return {\n' +
' secondsElapsed: 0\n' +
' };\n' +
' },\n' +
' tick: function() {\n' +
' this.setState({\n' +
' secondsElapsed: this.state.secondsElapsed + 1\n' +
' });\n' +
' },\n' +
' componentDidMount: function() {\n' +
' this.interval = setInterval(this.tick, 1000);\n' +
' },\n' +
' componentWillUnmount: function() {\n' +
' clearInterval(this.interval);\n' +
' },\n' +
' render: function() {\n' +
' return (\n' +
' <div>Seconds Elapsed: {this.state.secondsElapsed}</div>\n' +
' );\n' +
' }\n' +
'});\n' +
'React.render(<Timer />, mountNode);');
bt(
'var TodoList = React.createClass({\n' +
' render: function() {\n' +
' var createItem = function(itemText) {\n' +
' return <li>{itemText}</li>;\n' +
' };\n' +
' return <ul>{this.props.items.map(createItem)}</ul>;\n' +
' }\n' +
'});');
bt(
'var TodoApp = React.createClass({\n' +
' getInitialState: function() {\n' +
' return {\n' +
' items: [],\n' +
' text: \'\'\n' +
' };\n' +
' },\n' +
' onChange: function(e) {\n' +
' this.setState({\n' +
' text: e.target.value\n' +
' });\n' +
' },\n' +
' handleSubmit: function(e) {\n' +
' e.preventDefault();\n' +
' var nextItems = this.state.items.concat([this.state.text]);\n' +
' var nextText = \'\';\n' +
' this.setState({\n' +
' items: nextItems,\n' +
' text: nextText\n' +
' });\n' +
' },\n' +
' render: function() {\n' +
' return (\n' +
' <div>\n' +
' <h3>TODO</h3>\n' +
' <TodoList items={this.state.items} />\n' +
' <form onSubmit={this.handleSubmit}>\n' +
' <input onChange={this.onChange} value={this.state.text} />\n' +
' <button>{\'Add #\' + (this.state.items.length + 1)}</button>\n' +
' </form>\n' +
' </div>\n' +
' );\n' +
' }\n' +
'});\n' +
'React.render(<TodoApp />, mountNode);');
bt(
'var converter = new Showdown.converter();\n' +
'var MarkdownEditor = React.createClass({\n' +
' getInitialState: function() {\n' +
' return {value: \'Type some *markdown* here!\'};\n' +
' },\n' +
' handleChange: function() {\n' +
' this.setState({value: this.refs.textarea.getDOMNode().value});\n' +
' },\n' +
' render: function() {\n' +
' return (\n' +
' <div className="MarkdownEditor">\n' +
' <h3>Input</h3>\n' +
' <textarea\n' +
' onChange={this.handleChange}\n' +
' ref="textarea"\n' +
' defaultValue={this.state.value} />\n' +
' <h3>Output</h3>\n' +
' <div\n' +
' className="content"\n' +
' dangerouslySetInnerHTML=\n' +
' />\n' +
' </div>\n' +
' );\n' +
' }\n' +
'});\n' +
'React.render(<MarkdownEditor />, mountNode);',
'var converter = new Showdown.converter();\n' +
'var MarkdownEditor = React.createClass({\n' +
' getInitialState: function() {\n' +
' return {\n' +
' value: \'Type some *markdown* here!\'\n' +
' };\n' +
' },\n' +
' handleChange: function() {\n' +
' this.setState({\n' +
' value: this.refs.textarea.getDOMNode().value\n' +
' });\n' +
' },\n' +
' render: function() {\n' +
' return (\n' +
' <div className="MarkdownEditor">\n' +
' <h3>Input</h3>\n' +
' <textarea\n' +
' onChange={this.handleChange}\n' +
' ref="textarea"\n' +
' defaultValue={this.state.value} />\n' +
' <h3>Output</h3>\n' +
' <div\n' +
' className="content"\n' +
' dangerouslySetInnerHTML=\n' +
' />\n' +
' </div>\n' +
' );\n' +
' }\n' +
'});\n' +
'React.render(<MarkdownEditor />, mountNode);');

// JSX - Not quite correct jsx formatting that still works
bt(
'var content = (\n' +
' <Nav>\n' +
' {/* child comment, put {} around */}\n' +
' <Person\n' +
' /* multi\n' +
' line\n' +
' comment */\n' +
' //attr="test"\n' +
' name={window.isLoggedIn ? window.name : \'\'} // end of line comment\n' +
' />\n' +
' </Nav>\n' +
' );\n' +
'var qwer = <DropDown> A dropdown list <Menu> <MenuItem>Do Something</MenuItem> <MenuItem>Do Something Fun!</MenuItem> <MenuItem>Do Something Else</MenuItem> </Menu> </DropDown>;\n' +
'render(dropdown);',
'var content = (\n' +
' <Nav>\n' +
' {/* child comment, put {} around */}\n' +
' <Person\n' +
' /* multi\n' +
' line\n' +
' comment */\n' +
' //attr="test"\n' +
' name={window.isLoggedIn ? window.name : \'\'} // end of line comment\n' +
' />\n' +
' </Nav>\n' +
');\n' +
'var qwer = <DropDown> A dropdown list <Menu> <MenuItem>Do Something</MenuItem> <MenuItem>Do Something Fun!</MenuItem> <MenuItem>Do Something Else</MenuItem> </Menu> </DropDown>;\n' +
'render(dropdown);');

// Handles messed up tags, as long as it isn't the same name
// as the root tag. Also handles tags of same name as root tag
// as long as nesting matches.
Expand Down

0 comments on commit c13dcc9

Please sign in to comment.