UNPKG

jsdoc-75lb

Version:

An API documentation generator for JavaScript.

1,184 lines (1,087 loc) 111 kB
/*global js_beautify: true */ function run_javascript_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_beautify) { var opts = { indent_size: 4, indent_char: ' ', preserve_newlines: true, jslint_happy: false, keep_array_indentation: false, brace_style: 'collapse', space_before_conditional: true, break_chained_methods: false, selector_separator: '\n', end_with_newline: false }; function test_js_beautifier(input) { return js_beautify(input, opts); } function test_html_beautifier(input) { return html_beautify(input, opts); } var sanitytest; // test the input on beautifier with the current flag settings // does not check the indentation / surroundings as bt() does function test_fragment(input, expected) { expected = expected || expected === '' ? expected : input; sanitytest.expect(input, expected); // if the expected is different from input, run it again // expected output should be unchanged when run twice. if (expected !== input) { sanitytest.expect(expected, expected); } // Everywhere we do newlines, they should be replaced with opts.eol opts.eol = '\r\\n'; expected = expected.replace(/[\n]/g, '\r\n'); sanitytest.expect(input, expected); input = input.replace(/[\n]/g, '\r\n'); sanitytest.expect(input, expected); opts.eol = '\n'; } // test the input on beautifier with the current flag settings // test both the input as well as { input } wrapping function bt(input, expectation) { var wrapped_input, wrapped_expectation; expectation = expectation || expectation === '' ? expectation : input; sanitytest.test_function(test_js_beautifier, 'js_beautify'); test_fragment(input, expectation); // If we set raw, input should be unchanged opts.test_output_raw = true; if (!opts.end_with_newline) { test_fragment(input, input); } opts.test_output_raw = false; // test also the returned indentation // e.g if input = "asdf();" // then test that this remains properly formatted as well: // { // asdf(); // indent; // } if (opts.indent_size === 4 && input) { wrapped_input = '{\n' + input.replace(/^(.+)$/mg, ' $1') + '\n foo = bar;\n}'; wrapped_expectation = '{\n' + expectation.replace(/^(.+)$/mg, ' $1') + '\n foo = bar;\n}'; test_fragment(wrapped_input, wrapped_expectation); // If we set raw, input should be unchanged opts.test_output_raw = true; if (!opts.end_with_newline) { test_fragment(wrapped_input, wrapped_input); } opts.test_output_raw = false; } } // run all tests for the given brace style ("collapse", "expand", "end-expand", or "none"). // uses various whitespace combinations before and after opening and closing braces, // respectively, for most of the tests' inputs. function beautify_brace_tests(brace_style) { var ex_brace_style = opts.brace_style, indent_on_wrap_str = ' '; // could use Array(opts.indent_size + 1).join(' '); if we wanted to replace _all_ of the hardcoded 4-space in the test and expectation strings function permute_brace_tests(expect_open_white, expect_close_white) { // run the tests that need permutation against a specific combination of // pre-opening-brace and pre-closing-brace whitespace function run_brace_permutation(test_open_white, test_close_white) { var to = test_open_white, tc = test_close_white, eo = expect_open_white ? expect_open_white : to === '' ? ' ' : to, ec = expect_close_white ? expect_close_white : tc === '' ? ' ' : tc, i = eo === '\n' ? indent_on_wrap_str: ''; bt( '//case 1\nif (a == 1)' + to + '{}\n//case 2\nelse if (a == 2)' + to + '{}', '//case 1\nif (a == 1)' + eo + '{}\n//case 2\nelse if (a == 2)' + eo + '{}'); bt( 'if(1)' + to + '{2}' + tc + 'else' + to + '{3}', 'if (1)' + eo + '{\n 2\n}' + ec + 'else' + eo + '{\n 3\n}'); bt( 'try' + to + '{a();}' + tc + 'catch(b)' + to + '{c();}' + tc + 'catch(d)' + to + '{}' + tc + 'finally' + to + '{e();}', // expected 'try' + eo + '{\n a();\n}' + ec + 'catch (b)' + eo + '{\n c();\n}' + ec + 'catch (d)' + eo + '{}' + ec + 'finally' + eo + '{\n e();\n}'); bt( 'if(a)' + to + '{b();}' + tc + 'else if(c) foo();', 'if (a)' + eo + '{\n b();\n}' + ec + 'else if (c) foo();'); // if/else statement with empty body bt( 'if (a)' + to + '{\n// comment\n}' + tc + 'else' + to + '{\n// comment\n}', 'if (a)' + eo + '{\n // comment\n}' + ec + 'else' + eo + '{\n // comment\n}'); bt( 'if (x)' + to + '{y}' + tc + 'else' + to + '{ if (x)' + to + '{y}}', 'if (x)' + eo + '{\n y\n}' + ec + 'else' + eo + '{\n if (x)' + eo + i + '{\n y\n }\n}'); bt( 'if (a)' + to + '{\nb;\n}' + tc + 'else' + to + '{\nc;\n}', 'if (a)' + eo + '{\n b;\n}' + ec + 'else' + eo + '{\n c;\n}'); test_fragment(' /*\n* xx\n*/\n// xx\nif (foo)' + to + '{\n bar();\n}', ' /*\n * xx\n */\n // xx\n if (foo)' + eo + i + '{\n bar();\n }'); bt( 'if (foo)' + to + '{}' + tc + 'else /regex/.test();', 'if (foo)' + eo + '{}' + ec + 'else /regex/.test();'); test_fragment('if (foo)' + to + '{', 'if (foo)' + eo + '{'); test_fragment('foo' + to + '{', 'foo' + eo + '{'); test_fragment('return;' + to + '{', 'return;' + eo + '{'); bt( 'function x()' + to + '{\n foo();\n}zzz', 'function x()' + eo +'{\n foo();\n}\nzzz'); bt( 'var a = new function a()' + to + '{};', 'var a = new function a()' + eo + '{};'); bt( 'var a = new function a()' + to + ' {},\n b = new function b()' + to + ' {};', 'var a = new function a()' + eo + i + '{},\n b = new function b()' + eo + i + '{};'); bt("foo(" + to + "{\n 'a': 1\n},\n10);", "foo(" + (eo === ' ' ? '' : eo) + i + "{\n 'a': 1\n },\n 10);"); // "foo( {..." is a weird case bt('(["foo","bar"]).each(function(i)' + to + '{return i;});', '(["foo", "bar"]).each(function(i)' + eo + '{\n return i;\n});'); bt('(function(i)' + to + '{return i;})();', '(function(i)' + eo + '{\n return i;\n})();'); bt( "test( /*Argument 1*/" + to + "{\n" + " 'Value1': '1'\n" + "}, /*Argument 2\n" + " */ {\n" + " 'Value2': '2'\n" + "});", // expected "test( /*Argument 1*/" + eo + i + "{\n" + " 'Value1': '1'\n" + " },\n" + " /*Argument 2\n" + " */\n" + " {\n" + " 'Value2': '2'\n" + " });"); bt( "test( /*Argument 1*/" + to + "{\n" + " 'Value1': '1'\n" + "}, /*Argument 2\n" + " */\n" + "{\n" + " 'Value2': '2'\n" + "});", // expected "test( /*Argument 1*/" + eo + i + "{\n" + " 'Value1': '1'\n" + " },\n" + " /*Argument 2\n" + " */\n" + " {\n" + " 'Value2': '2'\n" + " });"); } run_brace_permutation('\n', '\n'); run_brace_permutation('\n', ' '); run_brace_permutation(' ', ' '); run_brace_permutation(' ', '\n'); run_brace_permutation('',''); // brace tests that don't make sense to permutate test_fragment('return {'); // return needs the brace. test_fragment('return /* inline */ {'); bt('throw {}'); bt('throw {\n foo;\n}'); bt( 'var foo = {}'); test_fragment('a: do {} while (); xxx', 'a: do {} while ();\nxxx'); bt( '{a: do {} while (); xxx}', '{\n a: do {} while ();xxx\n}'); bt( 'var a = new function() {};'); bt( 'var a = new function()\n{};', 'var a = new function() {};'); bt( "test(\n" + "/*Argument 1*/ {\n" + " 'Value1': '1'\n" + "},\n" + "/*Argument 2\n" + " */ {\n" + " 'Value2': '2'\n" + "});", // expected "test(\n" + " /*Argument 1*/\n" + " {\n" + " 'Value1': '1'\n" + " },\n" + " /*Argument 2\n" + " */\n" + " {\n" + " 'Value2': '2'\n" + " });"); } opts.brace_style = brace_style; switch(opts.brace_style) { case 'collapse': permute_brace_tests(' ', ' '); break; case 'expand': permute_brace_tests('\n', '\n'); break; case 'end-expand': permute_brace_tests(' ', '\n'); break; case 'none': permute_brace_tests(); break; } opts.brace_style = ex_brace_style; } function unicode_char(value) { return String.fromCharCode(value) } function beautifier_tests() { sanitytest = test_obj; opts.indent_size = 4; opts.indent_char = ' '; opts.preserve_newlines = true; opts.jslint_happy = false; opts.keep_array_indentation = false; opts.brace_style = 'collapse'; // Unicode Support bt('var ' + unicode_char(3232) + '_' + unicode_char(3232) + ' = "hi";'); bt( 'var ' + unicode_char(228) + 'x = {\n' + ' ' + unicode_char(228) + 'rgerlich: true\n' + '};'); // End With Newline - (eof = "\n") opts.end_with_newline = true; test_fragment('', '\n'); test_fragment(' return .5', ' return .5\n'); test_fragment(' \n\nreturn .5\n\n\n\n', ' return .5\n'); test_fragment('\n'); // End With Newline - (eof = "") opts.end_with_newline = false; test_fragment(''); test_fragment(' return .5'); test_fragment(' \n\nreturn .5\n\n\n\n', ' return .5'); test_fragment('\n', ''); // Comma-first option - (c0 = "\n, ", c1 = "\n , ", c2 = "\n , ", c3 = "\n , ") opts.comma_first = true; bt('{a:1, b:2}', '{\n a: 1\n , b: 2\n}'); bt('var a=1, b=c[d], e=6;', 'var a = 1\n , b = c[d]\n , e = 6;'); bt('for(var a=1,b=2,c=3;d<3;d++)\ne', 'for (var a = 1, b = 2, c = 3; d < 3; d++)\n e'); bt('for(var a=1,b=2,\nc=3;d<3;d++)\ne', 'for (var a = 1, b = 2\n , c = 3; d < 3; d++)\n e'); bt('function foo() {\n return [\n "one"\n , "two"\n ];\n}'); bt('a=[[1,2],[4,5],[7,8]]', 'a = [\n [1, 2]\n , [4, 5]\n , [7, 8]\n]'); bt('a=[[1,2],[4,5],[7,8],]', 'a = [\n [1, 2]\n , [4, 5]\n , [7, 8]\n, ]'); bt('a=[[1,2],[4,5],function(){},[7,8]]', 'a = [\n [1, 2]\n , [4, 5]\n , function() {}\n , [7, 8]\n]'); bt('a=[[1,2],[4,5],function(){},function(){},[7,8]]', 'a = [\n [1, 2]\n , [4, 5]\n , function() {}\n , function() {}\n , [7, 8]\n]'); bt('a=[[1,2],[4,5],function(){},[7,8]]', 'a = [\n [1, 2]\n , [4, 5]\n , function() {}\n , [7, 8]\n]'); bt('a=[b,c,function(){},function(){},d]', 'a = [b, c, function() {}, function() {}, d]'); bt('a=[b,c,\nfunction(){},function(){},d]', 'a = [b, c\n , function() {}\n , function() {}\n , d\n]'); bt('a=[a[1],b[4],c[d[7]]]', 'a = [a[1], b[4], c[d[7]]]'); bt('[1,2,[3,4,[5,6],7],8]', '[1, 2, [3, 4, [5, 6], 7], 8]'); bt('[[["1","2"],["3","4"]],[["5","6","7"],["8","9","0"]],[["1","2","3"],["4","5","6","7"],["8","9","0"]]]', '[\n [\n ["1", "2"]\n , ["3", "4"]\n ]\n , [\n ["5", "6", "7"]\n , ["8", "9", "0"]\n ]\n , [\n ["1", "2", "3"]\n , ["4", "5", "6", "7"]\n , ["8", "9", "0"]\n ]\n]'); // Comma-first option - (c0 = ",\n", c1 = ",\n ", c2 = ",\n ", c3 = ",\n ") opts.comma_first = false; bt('{a:1, b:2}', '{\n a: 1,\n b: 2\n}'); bt('var a=1, b=c[d], e=6;', 'var a = 1,\n b = c[d],\n e = 6;'); bt('for(var a=1,b=2,c=3;d<3;d++)\ne', 'for (var a = 1, b = 2, c = 3; d < 3; d++)\n e'); bt('for(var a=1,b=2,\nc=3;d<3;d++)\ne', 'for (var a = 1, b = 2,\n c = 3; d < 3; d++)\n e'); bt('function foo() {\n return [\n "one",\n "two"\n ];\n}'); bt('a=[[1,2],[4,5],[7,8]]', 'a = [\n [1, 2],\n [4, 5],\n [7, 8]\n]'); bt('a=[[1,2],[4,5],[7,8],]', 'a = [\n [1, 2],\n [4, 5],\n [7, 8],\n]'); bt('a=[[1,2],[4,5],function(){},[7,8]]', 'a = [\n [1, 2],\n [4, 5],\n function() {},\n [7, 8]\n]'); bt('a=[[1,2],[4,5],function(){},function(){},[7,8]]', 'a = [\n [1, 2],\n [4, 5],\n function() {},\n function() {},\n [7, 8]\n]'); bt('a=[[1,2],[4,5],function(){},[7,8]]', 'a = [\n [1, 2],\n [4, 5],\n function() {},\n [7, 8]\n]'); bt('a=[b,c,function(){},function(){},d]', 'a = [b, c, function() {}, function() {}, d]'); bt('a=[b,c,\nfunction(){},function(){},d]', 'a = [b, c,\n function() {},\n function() {},\n d\n]'); bt('a=[a[1],b[4],c[d[7]]]', 'a = [a[1], b[4], c[d[7]]]'); bt('[1,2,[3,4,[5,6],7],8]', '[1, 2, [3, 4, [5, 6], 7], 8]'); bt('[[["1","2"],["3","4"]],[["5","6","7"],["8","9","0"]],[["1","2","3"],["4","5","6","7"],["8","9","0"]]]', '[\n [\n ["1", "2"],\n ["3", "4"]\n ],\n [\n ["5", "6", "7"],\n ["8", "9", "0"]\n ],\n [\n ["1", "2", "3"],\n ["4", "5", "6", "7"],\n ["8", "9", "0"]\n ]\n]'); // New Test Suite // Async / await tests bt('async function foo() {}'); bt('let w = async function foo() {}'); bt('async function foo() {}\nvar x = await foo();'); // async function as an input to another function bt('wrapper(async function foo() {})'); // await on inline anonymous function. should have a space after await bt( 'async function() {\n var w = await(async function() {\n return await foo();\n })();\n}', 'async function() {\n var w = await (async function() {\n return await foo();\n })();\n}'); // ensure that this doesn't break anyone with the async library bt('async.map(function(t) {})'); // e4x - Test that e4x literals passed through when e4x-option is enabled opts.e4x = true; bt('xml=<a b="c"><d/><e>\n foo</e>x</a>;', 'xml = <a b="c"><d/><e>\n foo</e>x</a>;'); bt('<a b=\'This is a quoted "c".\'/>'); bt('<a b="This is a quoted \'c\'."/>'); bt('<a b="A quote \' inside string."/>'); bt('<a b=\'A quote " inside string.\'/>'); bt('<a b=\'Some """ quotes "" inside string.\'/>'); // Handles inline expressions bt('xml=<{a} b="c"><d/><e v={z}>\n foo</e>x</{a}>;', 'xml = <{a} b="c"><d/><e v={z}>\n foo</e>x</{a}>;'); bt('xml=<{a} b="c">\n <e v={z}>\n foo</e>x</{a}>;', 'xml = <{a} b="c">\n <e v={z}>\n foo</e>x</{a}>;'); // xml literals with special characters in elem names - see http://www.w3.org/TR/REC-xml/#NT-NameChar bt('xml = <_:.valid.xml- _:.valid.xml-="123"/>;'); // Handles CDATA bt('xml=<![CDATA[ b="c"><d/><e v={z}>\n foo</e>x/]]>;', 'xml = <![CDATA[ b="c"><d/><e v={z}>\n foo</e>x/]]>;'); 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. bt( 'xml=<a x="jn"><c></b></f><a><d jnj="jnn"><f></a ></nj></a>;', 'xml = <a x="jn"><c></b></f><a><d jnj="jnn"><f></a ></nj></a>;'); // If xml is not terminated, the remainder of the file is treated // as part of the xml-literal (passed through unaltered) test_fragment( 'xml=<a></b>\nc<b;', 'xml = <a></b>\nc<b;'); // Issue #646 = whitespace is allowed in attribute declarations bt( 'let a = React.createClass({\n' + ' render() {\n' + ' return (\n' + ' <p className=\'a\'>\n' + ' <span>c</span>\n' + ' </p>\n' + ' );\n' + ' }\n' + '});'); bt( 'let a = React.createClass({\n' + ' render() {\n' + ' return (\n' + ' <p className = \'b\'>\n' + ' <span>c</span>\n' + ' </p>\n' + ' );\n' + ' }\n' + '});'); bt( 'let a = React.createClass({\n' + ' render() {\n' + ' return (\n' + ' <p className = "c">\n' + ' <span>c</span>\n' + ' </p>\n' + ' );\n' + ' }\n' + '});'); bt( 'let a = React.createClass({\n' + ' render() {\n' + ' return (\n' + ' <{e} className = {d}>\n' + ' <span>c</span>\n' + ' </{e}>\n' + ' );\n' + ' }\n' + '});'); // e4x disabled opts.e4x = false; bt( 'xml=<a b="c"><d/><e>\n foo</e>x</a>;', 'xml = < a b = "c" > < d / > < e >\n foo < /e>x</a > ;'); // Multiple braces bt('{{}/z/}', '{\n {}\n /z/\n}'); // Beautify preserve formatting bt('/* beautify preserve:start */\n/* beautify preserve:end */'); bt('/* beautify preserve:start */\n var a = 1;\n/* beautify preserve:end */'); bt('var a = 1;\n/* beautify preserve:start */\n var a = 1;\n/* beautify preserve:end */'); bt('/* beautify preserve:start */ {asdklgh;y;;{}dd2d}/* beautify preserve:end */'); bt( 'var a = 1;\n/* beautify preserve:start */\n var a = 1;\n/* beautify preserve:end */', 'var a = 1;\n/* beautify preserve:start */\n var a = 1;\n/* beautify preserve:end */'); bt( 'var a = 1;\n /* beautify preserve:start */\n var a = 1;\n/* beautify preserve:end */', 'var a = 1;\n/* beautify preserve:start */\n var a = 1;\n/* beautify preserve:end */'); bt( 'var a = {\n' + ' /* beautify preserve:start */\n' + ' one : 1\n' + ' two : 2,\n' + ' three : 3,\n' + ' ten : 10\n' + ' /* beautify preserve:end */\n' + '};'); bt( 'var a = {\n' + '/* beautify preserve:start */\n' + ' one : 1,\n' + ' two : 2,\n' + ' three : 3,\n' + ' ten : 10\n' + '/* beautify preserve:end */\n' + '};', 'var a = {\n' + ' /* beautify preserve:start */\n' + ' one : 1,\n' + ' two : 2,\n' + ' three : 3,\n' + ' ten : 10\n' + '/* beautify preserve:end */\n' + '};'); // one space before and after required, only single spaces inside. bt( 'var a = {\n' + '/* beautify preserve:start */\n' + ' one : 1,\n' + ' two : 2,\n' + ' three : 3,\n' + ' ten : 10\n' + '};', 'var a = {\n' + ' /* beautify preserve:start */\n' + ' one: 1,\n' + ' two: 2,\n' + ' three: 3,\n' + ' ten: 10\n' + '};'); bt( 'var a = {\n' + '/*beautify preserve:start*/\n' + ' one : 1,\n' + ' two : 2,\n' + ' three : 3,\n' + ' ten : 10\n' + '};', 'var a = {\n' + ' /*beautify preserve:start*/\n' + ' one: 1,\n' + ' two: 2,\n' + ' three: 3,\n' + ' ten: 10\n' + '};'); bt( 'var a = {\n' + '/*beautify preserve:start*/\n' + ' one : 1,\n' + ' two : 2,\n' + ' three : 3,\n' + ' ten : 10\n' + '};', 'var a = {\n' + ' /*beautify preserve:start*/\n' + ' one: 1,\n' + ' two: 2,\n' + ' three: 3,\n' + ' ten: 10\n' + '};'); // Directive: ignore bt('/* beautify ignore:start */\n/* beautify ignore:end */'); bt('/* beautify ignore:start */\n var a,,,{ 1;\n/* beautify ignore:end */'); bt('var a = 1;\n/* beautify ignore:start */\n var a = 1;\n/* beautify ignore:end */'); bt('/* beautify ignore:start */ {asdklgh;y;+++;dd2d}/* beautify ignore:end */'); bt( 'var a = 1;\n/* beautify ignore:start */\n var a,,,{ 1;\n/* beautify ignore:end */', 'var a = 1;\n/* beautify ignore:start */\n var a,,,{ 1;\n/* beautify ignore:end */'); bt( 'var a = 1;\n /* beautify ignore:start */\n var a,,,{ 1;\n/* beautify ignore:end */', 'var a = 1;\n/* beautify ignore:start */\n var a,,,{ 1;\n/* beautify ignore:end */'); bt( 'var a = {\n' + ' /* beautify ignore:start */\n' + ' one : 1\n' + ' two : 2,\n' + ' three : {\n' + ' ten : 10\n' + ' /* beautify ignore:end */\n' + '};'); bt( 'var a = {\n' + '/* beautify ignore:start */\n' + ' one : 1\n' + ' two : 2,\n' + ' three : {\n' + ' ten : 10\n' + '/* beautify ignore:end */\n' + '};', 'var a = {\n' + ' /* beautify ignore:start */\n' + ' one : 1\n' + ' two : 2,\n' + ' three : {\n' + ' ten : 10\n' + '/* beautify ignore:end */\n' + '};'); // Directives - multiple and interacting bt( 'var a = {\n' + '/* beautify preserve:start */\n' + '/* beautify preserve:start */\n' + ' one : 1,\n' + ' /* beautify preserve:end */\n' + ' two : 2,\n' + ' three : 3,\n' + '/* beautify preserve:start */\n' + ' ten : 10\n' + '/* beautify preserve:end */\n' + '};', 'var a = {\n' + ' /* beautify preserve:start */\n' + '/* beautify preserve:start */\n' + ' one : 1,\n' + ' /* beautify preserve:end */\n' + ' two: 2,\n' + ' three: 3,\n' + ' /* beautify preserve:start */\n' + ' ten : 10\n' + '/* beautify preserve:end */\n' + '};'); bt( 'var a = {\n' + '/* beautify ignore:start */\n' + ' one : 1\n' + ' /* beautify ignore:end */\n' + ' two : 2,\n' + '/* beautify ignore:start */\n' + ' three : {\n' + ' ten : 10\n' + '/* beautify ignore:end */\n' + '};', 'var a = {\n' + ' /* beautify ignore:start */\n' + ' one : 1\n' + ' /* beautify ignore:end */\n' + ' two: 2,\n' + ' /* beautify ignore:start */\n' + ' three : {\n' + ' ten : 10\n' + '/* beautify ignore:end */\n' + '};'); // Starts can occur together, ignore:end must occur alone. bt( 'var a = {\n' + '/* beautify ignore:start */\n' + ' one : 1\n' + ' NOTE: ignore end block does not support starting other directives\n' + ' This does not match the ending the ignore...\n' + ' /* beautify ignore:end preserve:start */\n' + ' two : 2,\n' + '/* beautify ignore:start */\n' + ' three : {\n' + ' ten : 10\n' + ' ==The next comment ends the starting ignore==\n' + '/* beautify ignore:end */\n' + '};', 'var a = {\n' + ' /* beautify ignore:start */\n' + ' one : 1\n' + ' NOTE: ignore end block does not support starting other directives\n' + ' This does not match the ending the ignore...\n' + ' /* beautify ignore:end preserve:start */\n' + ' two : 2,\n' + '/* beautify ignore:start */\n' + ' three : {\n' + ' ten : 10\n' + ' ==The next comment ends the starting ignore==\n' + '/* beautify ignore:end */\n' + '};'); bt( 'var a = {\n' + '/* beautify ignore:start preserve:start */\n' + ' one : {\n' + ' /* beautify ignore:end */\n' + ' two : 2,\n' + ' /* beautify ignore:start */\n' + ' three : {\n' + '/* beautify ignore:end */\n' + ' ten : 10\n' + ' // This is all preserved\n' + '};', 'var a = {\n' + ' /* beautify ignore:start preserve:start */\n' + ' one : {\n' + ' /* beautify ignore:end */\n' + ' two : 2,\n' + ' /* beautify ignore:start */\n' + ' three : {\n' + '/* beautify ignore:end */\n' + ' ten : 10\n' + ' // This is all preserved\n' + '};'); bt( 'var a = {\n' + '/* beautify ignore:start preserve:start */\n' + ' one : {\n' + ' /* beautify ignore:end */\n' + ' two : 2,\n' + ' /* beautify ignore:start */\n' + ' three : {\n' + '/* beautify ignore:end */\n' + ' ten : 10,\n' + '/* beautify preserve:end */\n' + ' eleven: 11\n' + '};', 'var a = {\n' + ' /* beautify ignore:start preserve:start */\n' + ' one : {\n' + ' /* beautify ignore:end */\n' + ' two : 2,\n' + ' /* beautify ignore:start */\n' + ' three : {\n' + '/* beautify ignore:end */\n' + ' ten : 10,\n' + '/* beautify preserve:end */\n' + ' eleven: 11\n' + '};'); // Template Formatting bt('<?=$view["name"]; ?>'); bt('a = <?= external() ?>;'); bt( '<?php\n' + 'for($i = 1; $i <= 100; $i++;) {\n' + ' #count to 100!\n' + ' echo($i . "</br>");\n' + '}\n' + '?>'); bt('a = <%= external() %>;'); // jslint and space after anon function - (f = " ", c = "") opts.jslint_happy = true; opts.space_after_anon_function = true; bt( 'a=typeof(x)', 'a = typeof (x)'); bt( 'x();\n\nfunction(){}', 'x();\n\nfunction () {}'); bt( 'function () {\n var a, b, c, d, e = [],\n f;\n}'); bt( 'switch(x) {case 0: case 1: a(); break; default: break}', 'switch (x) {\ncase 0:\ncase 1:\n a();\n break;\ndefault:\n break\n}'); bt('switch(x){case -1:break;case !y:break;}', 'switch (x) {\ncase -1:\n break;\ncase !y:\n break;\n}'); // typical greasemonkey start test_fragment('// comment 2\n(function ()'); bt( 'var a2, b2, c2, d2 = 0, c = function() {}, d = \'\';', 'var a2, b2, c2, d2 = 0,\n c = function () {},\n d = \'\';'); bt( 'var a2, b2, c2, d2 = 0, c = function() {},\nd = \'\';', 'var a2, b2, c2, d2 = 0,\n c = function () {},\n d = \'\';'); bt( 'var o2=$.extend(a);function(){alert(x);}', 'var o2 = $.extend(a);\n\nfunction () {\n alert(x);\n}'); bt('function*() {\n yield 1;\n}', 'function* () {\n yield 1;\n}'); bt('function* x() {\n yield 1;\n}'); // jslint and space after anon function - (f = " ", c = "") opts.jslint_happy = true; opts.space_after_anon_function = false; bt( 'a=typeof(x)', 'a = typeof (x)'); bt( 'x();\n\nfunction(){}', 'x();\n\nfunction () {}'); bt( 'function () {\n var a, b, c, d, e = [],\n f;\n}'); bt( 'switch(x) {case 0: case 1: a(); break; default: break}', 'switch (x) {\ncase 0:\ncase 1:\n a();\n break;\ndefault:\n break\n}'); bt('switch(x){case -1:break;case !y:break;}', 'switch (x) {\ncase -1:\n break;\ncase !y:\n break;\n}'); // typical greasemonkey start test_fragment('// comment 2\n(function ()'); bt( 'var a2, b2, c2, d2 = 0, c = function() {}, d = \'\';', 'var a2, b2, c2, d2 = 0,\n c = function () {},\n d = \'\';'); bt( 'var a2, b2, c2, d2 = 0, c = function() {},\nd = \'\';', 'var a2, b2, c2, d2 = 0,\n c = function () {},\n d = \'\';'); bt( 'var o2=$.extend(a);function(){alert(x);}', 'var o2 = $.extend(a);\n\nfunction () {\n alert(x);\n}'); bt('function*() {\n yield 1;\n}', 'function* () {\n yield 1;\n}'); bt('function* x() {\n yield 1;\n}'); // jslint and space after anon function - (f = " ", c = " ") opts.jslint_happy = false; opts.space_after_anon_function = true; bt( 'a=typeof(x)', 'a = typeof (x)'); bt( 'x();\n\nfunction(){}', 'x();\n\nfunction () {}'); bt( 'function () {\n var a, b, c, d, e = [],\n f;\n}'); bt( 'switch(x) {case 0: case 1: a(); break; default: break}', 'switch (x) {\n case 0:\n case 1:\n a();\n break;\n default:\n break\n}'); bt('switch(x){case -1:break;case !y:break;}', 'switch (x) {\n case -1:\n break;\n case !y:\n break;\n}'); // typical greasemonkey start test_fragment('// comment 2\n(function ()'); bt( 'var a2, b2, c2, d2 = 0, c = function() {}, d = \'\';', 'var a2, b2, c2, d2 = 0,\n c = function () {},\n d = \'\';'); bt( 'var a2, b2, c2, d2 = 0, c = function() {},\nd = \'\';', 'var a2, b2, c2, d2 = 0,\n c = function () {},\n d = \'\';'); bt( 'var o2=$.extend(a);function(){alert(x);}', 'var o2 = $.extend(a);\n\nfunction () {\n alert(x);\n}'); bt('function*() {\n yield 1;\n}', 'function* () {\n yield 1;\n}'); bt('function* x() {\n yield 1;\n}'); // jslint and space after anon function - (f = "", c = " ") opts.jslint_happy = false; opts.space_after_anon_function = false; bt( 'a=typeof(x)', 'a = typeof(x)'); bt( 'x();\n\nfunction(){}', 'x();\n\nfunction() {}'); bt( 'function () {\n var a, b, c, d, e = [],\n f;\n}', 'function() {\n var a, b, c, d, e = [],\n f;\n}'); bt( 'switch(x) {case 0: case 1: a(); break; default: break}', 'switch (x) {\n case 0:\n case 1:\n a();\n break;\n default:\n break\n}'); bt('switch(x){case -1:break;case !y:break;}', 'switch (x) {\n case -1:\n break;\n case !y:\n break;\n}'); // typical greasemonkey start test_fragment('// comment 2\n(function()'); bt( 'var a2, b2, c2, d2 = 0, c = function() {}, d = \'\';', 'var a2, b2, c2, d2 = 0,\n c = function() {},\n d = \'\';'); bt( 'var a2, b2, c2, d2 = 0, c = function() {},\nd = \'\';', 'var a2, b2, c2, d2 = 0,\n c = function() {},\n d = \'\';'); bt( 'var o2=$.extend(a);function(){alert(x);}', 'var o2 = $.extend(a);\n\nfunction() {\n alert(x);\n}'); bt('function*() {\n yield 1;\n}'); bt('function* x() {\n yield 1;\n}'); // Regression tests // Issue 241 bt( 'obj\n' + ' .last({\n' + ' foo: 1,\n' + ' bar: 2\n' + ' });\n' + 'var test = 1;'); bt( 'obj\n' + ' .last(a, function() {\n' + ' var test;\n' + ' });\n' + 'var test = 1;'); bt( 'obj.first()\n' + ' .second()\n' + ' .last(function(err, response) {\n' + ' console.log(err);\n' + ' });'); // Issue 268 and 275 bt( 'obj.last(a, function() {\n' + ' var test;\n' + '});\n' + 'var test = 1;'); bt( 'obj.last(a,\n' + ' function() {\n' + ' var test;\n' + ' });\n' + 'var test = 1;'); bt( '(function() {if (!window.FOO) window.FOO || (window.FOO = function() {var b = {bar: "zort"};});})();', '(function() {\n' + ' if (!window.FOO) window.FOO || (window.FOO = function() {\n' + ' var b = {\n' + ' bar: "zort"\n' + ' };\n' + ' });\n' + '})();'); // Issue 281 bt( 'define(["dojo/_base/declare", "my/Employee", "dijit/form/Button",\n' + ' "dojo/_base/lang", "dojo/Deferred"\n' + '], function(declare, Employee, Button, lang, Deferred) {\n' + ' return declare(Employee, {\n' + ' constructor: function() {\n' + ' new Button({\n' + ' onClick: lang.hitch(this, function() {\n' + ' new Deferred().then(lang.hitch(this, function() {\n' + ' this.salary * 0.25;\n' + ' }));\n' + ' })\n' + ' });\n' + ' }\n' + ' });\n' + '});'); bt( 'define(["dojo/_base/declare", "my/Employee", "dijit/form/Button",\n' + ' "dojo/_base/lang", "dojo/Deferred"\n' + ' ],\n' + ' function(declare, Employee, Button, lang, Deferred) {\n' + ' return declare(Employee, {\n' + ' constructor: function() {\n' + ' new Button({\n' + ' onClick: lang.hitch(this, function() {\n' + ' new Deferred().then(lang.hitch(this, function() {\n' + ' this.salary * 0.25;\n' + ' }));\n' + ' })\n' + ' });\n' + ' }\n' + ' });\n' + ' });'); // Issue 459 bt( '(function() {\n' + ' return {\n' + ' foo: function() {\n' + ' return "bar";\n' + ' },\n' + ' bar: ["bar"]\n' + ' };\n' + '}());'); // Issue 505 - strings should end at newline unless continued by backslash bt( 'var name = "a;\n' + 'name = "b";'); bt( 'var name = "a;\\\n' + ' name = b";'); // Issue 514 - some operators require spaces to distinguish them bt('var c = "_ACTION_TO_NATIVEAPI_" + ++g++ + +new Date;'); bt('var c = "_ACTION_TO_NATIVEAPI_" - --g-- - -new Date;'); // Issue 440 - reserved words can be used as object property names bt( 'a = {\n' + ' function: {},\n' + ' "function": {},\n' + ' throw: {},\n' + ' "throw": {},\n' + ' var: {},\n' + ' "var": {},\n' + ' set: {},\n' + ' "set": {},\n' + ' get: {},\n' + ' "get": {},\n' + ' if: {},\n' + ' "if": {},\n' + ' then: {},\n' + ' "then": {},\n' + ' else: {},\n' + ' "else": {},\n' + ' yay: {}\n' + '};'); // Issue 331 - if-else with braces edge case bt( 'if(x){a();}else{b();}if(y){c();}', 'if (x) {\n' + ' a();\n' + '} else {\n' + ' b();\n' + '}\n' + 'if (y) {\n' + ' c();\n' + '}'); // Issue 485 - ensure function declarations behave the same in arrays as elsewhere bt( 'var v = ["a",\n' + ' function() {\n' + ' return;\n' + ' }, {\n' + ' id: 1\n' + ' }\n' + '];'); bt( 'var v = ["a", function() {\n' + ' return;\n' + '}, {\n' + ' id: 1\n' + '}];'); // Issue 382 - initial totally cursory support for es6 module export bt( 'module "Even" {\n'