javascript.js 70 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572
  1. exports.test_data = {
  2. default_options: [
  3. { name: "indent_size", value: "4" },
  4. { name: "indent_char", value: "' '" },
  5. { name: "preserve_newlines", value: "true" },
  6. { name: "jslint_happy", value: "false" },
  7. { name: "keep_array_indentation", value: "false" },
  8. { name: "brace_style", value: "'collapse'" }
  9. ],
  10. groups: [{
  11. name: "Unicode Support",
  12. description: "",
  13. tests: [
  14. {
  15. input: "var ' + unicode_char(3232) + '_' + unicode_char(3232) + ' = \"hi\";"
  16. },
  17. {
  18. input: [
  19. "var ' + unicode_char(228) + 'x = {",
  20. " ' + unicode_char(228) + 'rgerlich: true",
  21. "};"]
  22. }
  23. ],
  24. }, {
  25. name: "End With Newline",
  26. description: "",
  27. matrix: [
  28. {
  29. options: [
  30. { name: "end_with_newline", value: "true" }
  31. ],
  32. eof: '\\n'
  33. }, {
  34. options: [
  35. { name: "end_with_newline", value: "false" }
  36. ],
  37. eof: ''
  38. }
  39. ],
  40. tests: [
  41. { fragment: true, input: '', output: '{{eof}}' },
  42. { fragment: true, input: ' return .5', output: ' return .5{{eof}}' },
  43. { fragment: true, input: ' \n\nreturn .5\n\n\n\n', output: ' return .5{{eof}}' },
  44. { fragment: true, input: '\n', output: '{{eof}}' }
  45. ],
  46. }, {
  47. name: "Comma-first option",
  48. description: "Put commas at the start of lines instead of the end",
  49. matrix: [
  50. {
  51. options: [
  52. { name: "comma_first", value: "true" }
  53. ],
  54. c0: '\\n, ',
  55. c1: '\\n , ',
  56. c2: '\\n , ',
  57. c3: '\\n , '
  58. }, {
  59. options: [
  60. { name: "comma_first", value: "false" }
  61. ],
  62. c0: ',\\n',
  63. c1: ',\\n ',
  64. c2: ',\\n ',
  65. c3: ',\\n '
  66. }
  67. ],
  68. tests: [
  69. { input: '{a:1, b:2}', output: "{\n a: 1{{c1}}b: 2\n}" },
  70. { input: 'var a=1, b=c[d], e=6;', output: 'var a = 1{{c1}}b = c[d]{{c1}}e = 6;' },
  71. { input: "for(var a=1,b=2,c=3;d<3;d++)\ne", output: "for (var a = 1, b = 2, c = 3; d < 3; d++)\n e" },
  72. { input: "for(var a=1,b=2,\nc=3;d<3;d++)\ne", output: "for (var a = 1, b = 2{{c2}}c = 3; d < 3; d++)\n e" },
  73. { input: 'function foo() {\n return [\n "one"{{c2}}"two"\n ];\n}' },
  74. { input: 'a=[[1,2],[4,5],[7,8]]', output: "a = [\n [1, 2]{{c1}}[4, 5]{{c1}}[7, 8]\n]" },
  75. { input: 'a=[[1,2],[4,5],[7,8],]', output: "a = [\n [1, 2]{{c1}}[4, 5]{{c1}}[7, 8]{{c0}}]" },
  76. { input: 'a=[[1,2],[4,5],function(){},[7,8]]',
  77. output: "a = [\n [1, 2]{{c1}}[4, 5]{{c1}}function() {}{{c1}}[7, 8]\n]" },
  78. { input: 'a=[[1,2],[4,5],function(){},function(){},[7,8]]',
  79. output: "a = [\n [1, 2]{{c1}}[4, 5]{{c1}}function() {}{{c1}}function() {}{{c1}}[7, 8]\n]" },
  80. { input: 'a=[[1,2],[4,5],function(){},[7,8]]',
  81. output: "a = [\n [1, 2]{{c1}}[4, 5]{{c1}}function() {}{{c1}}[7, 8]\n]" },
  82. { input: 'a=[b,c,function(){},function(){},d]',
  83. output: "a = [b, c, function() {}, function() {}, d]" },
  84. { input: 'a=[b,c,\nfunction(){},function(){},d]',
  85. output: "a = [b, c{{c1}}function() {}{{c1}}function() {}{{c1}}d\n]" },
  86. { input: 'a=[a[1],b[4],c[d[7]]]', output: "a = [a[1], b[4], c[d[7]]]" },
  87. { input: '[1,2,[3,4,[5,6],7],8]', output: "[1, 2, [3, 4, [5, 6], 7], 8]" },
  88. { input: '[[["1","2"],["3","4"]],[["5","6","7"],["8","9","0"]],[["1","2","3"],["4","5","6","7"],["8","9","0"]]]',
  89. output: '[\n [\n ["1", "2"]{{c2}}["3", "4"]\n ]{{c1}}[\n ["5", "6", "7"]{{c2}}["8", "9", "0"]\n ]{{c1}}[\n ["1", "2", "3"]{{c2}}["4", "5", "6", "7"]{{c2}}["8", "9", "0"]\n ]\n]' },
  90. ],
  91. }, {
  92. name: "New Test Suite"
  93. },
  94. {
  95. name: "Async / await tests",
  96. description: "ES7 async / await tests",
  97. tests: [
  98. { input: "async function foo() {}" },
  99. { input: "let w = async function foo() {}" },
  100. { input: "async function foo() {}\nvar x = await foo();"},
  101. {
  102. comment: "async function as an input to another function",
  103. input: "wrapper(async function foo() {})"},
  104. {
  105. comment: "await on inline anonymous function. should have a space after await",
  106. input_: "async function() {\n var w = await(async function() {\n return await foo();\n })();\n}",
  107. output: "async function() {\n var w = await (async function() {\n return await foo();\n })();\n}"
  108. },
  109. {
  110. comment: "ensure that this doesn't break anyone with the async library",
  111. input: "async.map(function(t) {})"
  112. }
  113. ]
  114. },
  115. {
  116. name: "e4x - Test that e4x literals passed through when e4x-option is enabled",
  117. description: "",
  118. options: [
  119. { name: 'e4x', value: true }
  120. ],
  121. tests: [
  122. { input: 'xml=<a b="c"><d/><e>\n foo</e>x</a>;', output: 'xml = <a b="c"><d/><e>\n foo</e>x</a>;' },
  123. { unchanged: '<a b=\\\'This is a quoted "c".\\\'/>' },
  124. { unchanged: '<a b="This is a quoted \\\'c\\\'."/>' },
  125. { unchanged: '<a b="A quote \\\' inside string."/>' },
  126. { unchanged: '<a b=\\\'A quote " inside string.\\\'/>' },
  127. { unchanged: '<a b=\\\'Some """ quotes "" inside string.\\\'/>' },
  128. {
  129. comment: 'Handles inline expressions',
  130. input: 'xml=<{a} b="c"><d/><e v={z}>\n foo</e>x</{a}>;',
  131. output: 'xml = <{a} b="c"><d/><e v={z}>\n foo</e>x</{a}>;' },
  132. {
  133. input: 'xml=<{a} b="c">\n <e v={z}>\n foo</e>x</{a}>;',
  134. output: 'xml = <{a} b="c">\n <e v={z}>\n foo</e>x</{a}>;' },
  135. {
  136. comment: 'xml literals with special characters in elem names - see http://www.w3.org/TR/REC-xml/#NT-NameChar',
  137. unchanged: 'xml = <_:.valid.xml- _:.valid.xml-="123"/>;'
  138. },
  139. {
  140. comment: 'Handles CDATA',
  141. input: 'xml=<![CDATA[ b="c"><d/><e v={z}>\n foo</e>x/]]>;',
  142. output: 'xml = <![CDATA[ b="c"><d/><e v={z}>\n foo</e>x/]]>;' },
  143. { input: 'xml=<![CDATA[]]>;', output: 'xml = <![CDATA[]]>;' },
  144. { input: 'xml=<a b="c"><![CDATA[d/></a></{}]]></a>;', output: 'xml = <a b="c"><![CDATA[d/></a></{}]]></a>;' },
  145. {
  146. comment: 'JSX - working jsx from http://prettydiff.com/unit_tests/beautification_javascript_jsx.txt',
  147. unchanged:
  148. [
  149. 'var ListItem = React.createClass({',
  150. ' render: function() {',
  151. ' return (',
  152. ' <li className="ListItem">',
  153. ' <a href={ "/items/" + this.props.item.id }>',
  154. ' this.props.item.name',
  155. ' </a>',
  156. ' </li>',
  157. ' );',
  158. ' }',
  159. '});'
  160. ]
  161. },
  162. {
  163. unchanged:
  164. [
  165. 'var List = React.createClass({',
  166. ' renderList: function() {',
  167. ' return this.props.items.map(function(item) {',
  168. ' return <ListItem item={item} key={item.id} />;',
  169. ' });',
  170. ' },',
  171. '',
  172. ' render: function() {',
  173. ' return <ul className="List">',
  174. ' this.renderList()',
  175. ' </ul>',
  176. ' }',
  177. '});'
  178. ]
  179. },
  180. {
  181. unchanged:
  182. [
  183. 'var Mist = React.createClass({',
  184. ' renderList: function() {',
  185. ' return this.props.items.map(function(item) {',
  186. ' return <ListItem item={return <tag>{item}</tag>} key={item.id} />;',
  187. ' });',
  188. ' }',
  189. '});',
  190. ]
  191. },
  192. {
  193. unchanged:
  194. [
  195. '// JSX',
  196. 'var box = <Box>',
  197. ' {shouldShowAnswer(user) ?',
  198. ' <Answer value={false}>no</Answer> : <Box.Comment>',
  199. ' Text Content',
  200. ' </Box.Comment>}',
  201. ' </Box>;',
  202. 'var a = function() {',
  203. ' return <tsdf>asdf</tsdf>;',
  204. '};',
  205. '',
  206. 'var HelloMessage = React.createClass({',
  207. ' render: function() {',
  208. ' return <div>Hello {this.props.name}</div>;',
  209. ' }',
  210. '});',
  211. 'React.render(<HelloMessage name="John" />, mountNode);',
  212. ]
  213. },
  214. {
  215. unchanged:
  216. [
  217. 'var Timer = React.createClass({',
  218. ' getInitialState: function() {',
  219. ' return {',
  220. ' secondsElapsed: 0',
  221. ' };',
  222. ' },',
  223. ' tick: function() {',
  224. ' this.setState({',
  225. ' secondsElapsed: this.state.secondsElapsed + 1',
  226. ' });',
  227. ' },',
  228. ' componentDidMount: function() {',
  229. ' this.interval = setInterval(this.tick, 1000);',
  230. ' },',
  231. ' componentWillUnmount: function() {',
  232. ' clearInterval(this.interval);',
  233. ' },',
  234. ' render: function() {',
  235. ' return (',
  236. ' <div>Seconds Elapsed: {this.state.secondsElapsed}</div>',
  237. ' );',
  238. ' }',
  239. '});',
  240. 'React.render(<Timer />, mountNode);'
  241. ]
  242. },
  243. {
  244. unchanged:
  245. [
  246. 'var TodoList = React.createClass({',
  247. ' render: function() {',
  248. ' var createItem = function(itemText) {',
  249. ' return <li>{itemText}</li>;',
  250. ' };',
  251. ' return <ul>{this.props.items.map(createItem)}</ul>;',
  252. ' }',
  253. '});'
  254. ]
  255. },
  256. {
  257. unchanged:
  258. [
  259. 'var TodoApp = React.createClass({',
  260. ' getInitialState: function() {',
  261. ' return {',
  262. ' items: [],',
  263. ' text: \\\'\\\'',
  264. ' };',
  265. ' },',
  266. ' onChange: function(e) {',
  267. ' this.setState({',
  268. ' text: e.target.value',
  269. ' });',
  270. ' },',
  271. ' handleSubmit: function(e) {',
  272. ' e.preventDefault();',
  273. ' var nextItems = this.state.items.concat([this.state.text]);',
  274. ' var nextText = \\\'\\\';',
  275. ' this.setState({',
  276. ' items: nextItems,',
  277. ' text: nextText',
  278. ' });',
  279. ' },',
  280. ' render: function() {',
  281. ' return (',
  282. ' <div>',
  283. ' <h3>TODO</h3>',
  284. ' <TodoList items={this.state.items} />',
  285. ' <form onSubmit={this.handleSubmit}>',
  286. ' <input onChange={this.onChange} value={this.state.text} />',
  287. ' <button>{\\\'Add #\\\' + (this.state.items.length + 1)}</button>',
  288. ' </form>',
  289. ' </div>',
  290. ' );',
  291. ' }',
  292. '});',
  293. 'React.render(<TodoApp />, mountNode);'
  294. ]
  295. },
  296. {
  297. input:
  298. [
  299. 'var converter = new Showdown.converter();',
  300. 'var MarkdownEditor = React.createClass({',
  301. ' getInitialState: function() {',
  302. ' return {value: \\\'Type some *markdown* here!\\\'};',
  303. ' },',
  304. ' handleChange: function() {',
  305. ' this.setState({value: this.refs.textarea.getDOMNode().value});',
  306. ' },',
  307. ' render: function() {',
  308. ' return (',
  309. ' <div className="MarkdownEditor">',
  310. ' <h3>Input</h3>',
  311. ' <textarea',
  312. ' onChange={this.handleChange}',
  313. ' ref="textarea"',
  314. ' defaultValue={this.state.value} />',
  315. ' <h3>Output</h3>',
  316. ' <div',
  317. ' className="content"',
  318. ' dangerouslySetInnerHTML={{',
  319. ' __html: converter.makeHtml(this.state.value)',
  320. ' }}',
  321. ' />',
  322. ' </div>',
  323. ' );',
  324. ' }',
  325. '});',
  326. 'React.render(<MarkdownEditor />, mountNode);'
  327. ],
  328. output:
  329. [
  330. 'var converter = new Showdown.converter();',
  331. 'var MarkdownEditor = React.createClass({',
  332. ' getInitialState: function() {',
  333. ' return {',
  334. ' value: \\\'Type some *markdown* here!\\\'',
  335. ' };',
  336. ' },',
  337. ' handleChange: function() {',
  338. ' this.setState({',
  339. ' value: this.refs.textarea.getDOMNode().value',
  340. ' });',
  341. ' },',
  342. ' render: function() {',
  343. ' return (',
  344. ' <div className="MarkdownEditor">',
  345. ' <h3>Input</h3>',
  346. ' <textarea',
  347. ' onChange={this.handleChange}',
  348. ' ref="textarea"',
  349. ' defaultValue={this.state.value} />',
  350. ' <h3>Output</h3>',
  351. ' <div',
  352. ' className="content"',
  353. ' dangerouslySetInnerHTML={{',
  354. ' __html: converter.makeHtml(this.state.value)',
  355. ' }}',
  356. ' />',
  357. ' </div>',
  358. ' );',
  359. ' }',
  360. '});',
  361. 'React.render(<MarkdownEditor />, mountNode);'
  362. ]
  363. },
  364. {
  365. comment: 'JSX - Not quite correct jsx formatting that still works',
  366. input:
  367. [
  368. 'var content = (',
  369. ' <Nav>',
  370. ' {/* child comment, put {} around */}',
  371. ' <Person',
  372. ' /* multi',
  373. ' line',
  374. ' comment */',
  375. ' //attr="test"',
  376. ' name={window.isLoggedIn ? window.name : \\\'\\\'} // end of line comment',
  377. ' />',
  378. ' </Nav>',
  379. ' );',
  380. 'var qwer = <DropDown> A dropdown list <Menu> <MenuItem>Do Something</MenuItem> <MenuItem>Do Something Fun!</MenuItem> <MenuItem>Do Something Else</MenuItem> </Menu> </DropDown>;',
  381. 'render(dropdown);',
  382. ],
  383. output:
  384. [
  385. 'var content = (',
  386. ' <Nav>',
  387. ' {/* child comment, put {} around */}',
  388. ' <Person',
  389. ' /* multi',
  390. ' line',
  391. ' comment */',
  392. ' //attr="test"',
  393. ' name={window.isLoggedIn ? window.name : \\\'\\\'} // end of line comment',
  394. ' />',
  395. ' </Nav>',
  396. ');',
  397. 'var qwer = <DropDown> A dropdown list <Menu> <MenuItem>Do Something</MenuItem> <MenuItem>Do Something Fun!</MenuItem> <MenuItem>Do Something Else</MenuItem> </Menu> </DropDown>;',
  398. 'render(dropdown);',
  399. ]
  400. },
  401. {
  402. comment: [
  403. "Handles messed up tags, as long as it isn't the same name",
  404. "as the root tag. Also handles tags of same name as root tag",
  405. "as long as nesting matches."
  406. ],
  407. input_: 'xml=<a x="jn"><c></b></f><a><d jnj="jnn"><f></a ></nj></a>;',
  408. output: 'xml = <a x="jn"><c></b></f><a><d jnj="jnn"><f></a ></nj></a>;' },
  409. {
  410. comment: [
  411. "If xml is not terminated, the remainder of the file is treated",
  412. "as part of the xml-literal (passed through unaltered)"
  413. ],
  414. fragment: true,
  415. input_: 'xml=<a></b>\nc<b;',
  416. output: 'xml = <a></b>\nc<b;' },
  417. {
  418. comment: 'Issue #646 = whitespace is allowed in attribute declarations',
  419. unchanged: [
  420. 'let a = React.createClass({',
  421. ' render() {',
  422. ' return (',
  423. ' <p className=\\\'a\\\'>',
  424. ' <span>c</span>',
  425. ' </p>',
  426. ' );',
  427. ' }',
  428. '});'
  429. ]
  430. },
  431. {
  432. unchanged: [
  433. 'let a = React.createClass({',
  434. ' render() {',
  435. ' return (',
  436. ' <p className = \\\'b\\\'>',
  437. ' <span>c</span>',
  438. ' </p>',
  439. ' );',
  440. ' }',
  441. '});'
  442. ]
  443. },
  444. {
  445. unchanged: [
  446. 'let a = React.createClass({',
  447. ' render() {',
  448. ' return (',
  449. ' <p className = "c">',
  450. ' <span>c</span>',
  451. ' </p>',
  452. ' );',
  453. ' }',
  454. '});'
  455. ]
  456. },
  457. {
  458. unchanged: [
  459. 'let a = React.createClass({',
  460. ' render() {',
  461. ' return (',
  462. ' <{e} className = {d}>',
  463. ' <span>c</span>',
  464. ' </{e}>',
  465. ' );',
  466. ' }',
  467. '});'
  468. ]
  469. }
  470. ]
  471. },
  472. {
  473. name: "e4x disabled",
  474. description: "",
  475. options: [
  476. { name: 'e4x', value: false }
  477. ],
  478. tests: [
  479. {
  480. input_: 'xml=<a b="c"><d/><e>\n foo</e>x</a>;',
  481. output: 'xml = < a b = "c" > < d / > < e >\n foo < /e>x</a > ;'
  482. }
  483. ]
  484. },
  485. {
  486. name: "Multiple braces",
  487. description: "",
  488. template: "^^^ $$$",
  489. options: [],
  490. tests: [
  491. { input: '{{}/z/}', output: '{\n {}\n /z/\n}' }
  492. ]
  493. },
  494. {
  495. name: "Beautify preserve formatting",
  496. description: "Allow beautifier to preserve sections",
  497. tests: [
  498. { unchanged: "/* beautify preserve:start */\n/* beautify preserve:end */" },
  499. { unchanged: "/* beautify preserve:start */\n var a = 1;\n/* beautify preserve:end */" },
  500. { unchanged: "var a = 1;\n/* beautify preserve:start */\n var a = 1;\n/* beautify preserve:end */" },
  501. { unchanged: "/* beautify preserve:start */ {asdklgh;y;;{}dd2d}/* beautify preserve:end */" },
  502. {
  503. input_: "var a = 1;\n/* beautify preserve:start */\n var a = 1;\n/* beautify preserve:end */",
  504. output: "var a = 1;\n/* beautify preserve:start */\n var a = 1;\n/* beautify preserve:end */"
  505. },
  506. {
  507. input_: "var a = 1;\n /* beautify preserve:start */\n var a = 1;\n/* beautify preserve:end */",
  508. output: "var a = 1;\n/* beautify preserve:start */\n var a = 1;\n/* beautify preserve:end */"
  509. },
  510. {
  511. unchanged: [
  512. 'var a = {',
  513. ' /* beautify preserve:start */',
  514. ' one : 1',
  515. ' two : 2,',
  516. ' three : 3,',
  517. ' ten : 10',
  518. ' /* beautify preserve:end */',
  519. '};'
  520. ]
  521. },
  522. {
  523. input: [
  524. 'var a = {',
  525. '/* beautify preserve:start */',
  526. ' one : 1,',
  527. ' two : 2,',
  528. ' three : 3,',
  529. ' ten : 10',
  530. '/* beautify preserve:end */',
  531. '};'
  532. ],
  533. output: [
  534. 'var a = {',
  535. ' /* beautify preserve:start */',
  536. ' one : 1,',
  537. ' two : 2,',
  538. ' three : 3,',
  539. ' ten : 10',
  540. '/* beautify preserve:end */',
  541. '};'
  542. ]
  543. },
  544. {
  545. comment: 'one space before and after required, only single spaces inside.',
  546. input: [
  547. 'var a = {',
  548. '/* beautify preserve:start */',
  549. ' one : 1,',
  550. ' two : 2,',
  551. ' three : 3,',
  552. ' ten : 10',
  553. '};'
  554. ],
  555. output: [
  556. 'var a = {',
  557. ' /* beautify preserve:start */',
  558. ' one: 1,',
  559. ' two: 2,',
  560. ' three: 3,',
  561. ' ten: 10',
  562. '};'
  563. ]
  564. },
  565. {
  566. input: [
  567. 'var a = {',
  568. '/*beautify preserve:start*/',
  569. ' one : 1,',
  570. ' two : 2,',
  571. ' three : 3,',
  572. ' ten : 10',
  573. '};'
  574. ],
  575. output: [
  576. 'var a = {',
  577. ' /*beautify preserve:start*/',
  578. ' one: 1,',
  579. ' two: 2,',
  580. ' three: 3,',
  581. ' ten: 10',
  582. '};'
  583. ]
  584. },
  585. {
  586. input: [
  587. 'var a = {',
  588. '/*beautify preserve:start*/',
  589. ' one : 1,',
  590. ' two : 2,',
  591. ' three : 3,',
  592. ' ten : 10',
  593. '};'
  594. ],
  595. output: [
  596. 'var a = {',
  597. ' /*beautify preserve:start*/',
  598. ' one: 1,',
  599. ' two: 2,',
  600. ' three: 3,',
  601. ' ten: 10',
  602. '};'
  603. ]
  604. },
  605. { comment: 'Directive: ignore',
  606. unchanged: "/* beautify ignore:start */\n/* beautify ignore:end */" },
  607. { unchanged: "/* beautify ignore:start */\n var a,,,{ 1;\n/* beautify ignore:end */" },
  608. { unchanged: "var a = 1;\n/* beautify ignore:start */\n var a = 1;\n/* beautify ignore:end */" },
  609. { unchanged: "/* beautify ignore:start */ {asdklgh;y;+++;dd2d}/* beautify ignore:end */" },
  610. {
  611. input_: "var a = 1;\n/* beautify ignore:start */\n var a,,,{ 1;\n/* beautify ignore:end */",
  612. output: "var a = 1;\n/* beautify ignore:start */\n var a,,,{ 1;\n/* beautify ignore:end */"
  613. },
  614. {
  615. input_: "var a = 1;\n /* beautify ignore:start */\n var a,,,{ 1;\n/* beautify ignore:end */",
  616. output: "var a = 1;\n/* beautify ignore:start */\n var a,,,{ 1;\n/* beautify ignore:end */"
  617. },
  618. {
  619. unchanged: [
  620. 'var a = {',
  621. ' /* beautify ignore:start */',
  622. ' one : 1',
  623. ' two : 2,',
  624. ' three : {',
  625. ' ten : 10',
  626. ' /* beautify ignore:end */',
  627. '};'
  628. ]
  629. },
  630. {
  631. input: [
  632. 'var a = {',
  633. '/* beautify ignore:start */',
  634. ' one : 1',
  635. ' two : 2,',
  636. ' three : {',
  637. ' ten : 10',
  638. '/* beautify ignore:end */',
  639. '};'
  640. ],
  641. output: [
  642. 'var a = {',
  643. ' /* beautify ignore:start */',
  644. ' one : 1',
  645. ' two : 2,',
  646. ' three : {',
  647. ' ten : 10',
  648. '/* beautify ignore:end */',
  649. '};'
  650. ]
  651. },
  652. {
  653. comment: 'Directives - multiple and interacting',
  654. input: [
  655. 'var a = {',
  656. '/* beautify preserve:start */',
  657. '/* beautify preserve:start */',
  658. ' one : 1,',
  659. ' /* beautify preserve:end */',
  660. ' two : 2,',
  661. ' three : 3,',
  662. '/* beautify preserve:start */',
  663. ' ten : 10',
  664. '/* beautify preserve:end */',
  665. '};'
  666. ],
  667. output: [
  668. 'var a = {',
  669. ' /* beautify preserve:start */',
  670. '/* beautify preserve:start */',
  671. ' one : 1,',
  672. ' /* beautify preserve:end */',
  673. ' two: 2,',
  674. ' three: 3,',
  675. ' /* beautify preserve:start */',
  676. ' ten : 10',
  677. '/* beautify preserve:end */',
  678. '};'
  679. ]
  680. },
  681. {
  682. input: [
  683. 'var a = {',
  684. '/* beautify ignore:start */',
  685. ' one : 1',
  686. ' /* beautify ignore:end */',
  687. ' two : 2,',
  688. '/* beautify ignore:start */',
  689. ' three : {',
  690. ' ten : 10',
  691. '/* beautify ignore:end */',
  692. '};'
  693. ],
  694. output: [
  695. 'var a = {',
  696. ' /* beautify ignore:start */',
  697. ' one : 1',
  698. ' /* beautify ignore:end */',
  699. ' two: 2,',
  700. ' /* beautify ignore:start */',
  701. ' three : {',
  702. ' ten : 10',
  703. '/* beautify ignore:end */',
  704. '};'
  705. ]
  706. },
  707. {
  708. comment: 'Starts can occur together, ignore:end must occur alone.',
  709. input: [
  710. 'var a = {',
  711. '/* beautify ignore:start */',
  712. ' one : 1',
  713. ' NOTE: ignore end block does not support starting other directives',
  714. ' This does not match the ending the ignore...',
  715. ' /* beautify ignore:end preserve:start */',
  716. ' two : 2,',
  717. '/* beautify ignore:start */',
  718. ' three : {',
  719. ' ten : 10',
  720. ' ==The next comment ends the starting ignore==',
  721. '/* beautify ignore:end */',
  722. '};'
  723. ],
  724. output: [
  725. 'var a = {',
  726. ' /* beautify ignore:start */',
  727. ' one : 1',
  728. ' NOTE: ignore end block does not support starting other directives',
  729. ' This does not match the ending the ignore...',
  730. ' /* beautify ignore:end preserve:start */',
  731. ' two : 2,',
  732. '/* beautify ignore:start */',
  733. ' three : {',
  734. ' ten : 10',
  735. ' ==The next comment ends the starting ignore==',
  736. '/* beautify ignore:end */',
  737. '};'
  738. ]
  739. },
  740. {
  741. input: [
  742. 'var a = {',
  743. '/* beautify ignore:start preserve:start */',
  744. ' one : {',
  745. ' /* beautify ignore:end */',
  746. ' two : 2,',
  747. ' /* beautify ignore:start */',
  748. ' three : {',
  749. '/* beautify ignore:end */',
  750. ' ten : 10',
  751. ' // This is all preserved',
  752. '};'
  753. ],
  754. output: [
  755. 'var a = {',
  756. ' /* beautify ignore:start preserve:start */',
  757. ' one : {',
  758. ' /* beautify ignore:end */',
  759. ' two : 2,',
  760. ' /* beautify ignore:start */',
  761. ' three : {',
  762. '/* beautify ignore:end */',
  763. ' ten : 10',
  764. ' // This is all preserved',
  765. '};'
  766. ]
  767. },
  768. {
  769. input: [
  770. 'var a = {',
  771. '/* beautify ignore:start preserve:start */',
  772. ' one : {',
  773. ' /* beautify ignore:end */',
  774. ' two : 2,',
  775. ' /* beautify ignore:start */',
  776. ' three : {',
  777. '/* beautify ignore:end */',
  778. ' ten : 10,',
  779. '/* beautify preserve:end */',
  780. ' eleven: 11',
  781. '};'
  782. ],
  783. output: [
  784. 'var a = {',
  785. ' /* beautify ignore:start preserve:start */',
  786. ' one : {',
  787. ' /* beautify ignore:end */',
  788. ' two : 2,',
  789. ' /* beautify ignore:start */',
  790. ' three : {',
  791. '/* beautify ignore:end */',
  792. ' ten : 10,',
  793. '/* beautify preserve:end */',
  794. ' eleven: 11',
  795. '};'
  796. ]
  797. },
  798. ]
  799. },
  800. {
  801. name: "Template Formatting",
  802. description: "Php (<?php ... ?>) and underscore.js templating treated as strings.",
  803. options: [],
  804. tests: [
  805. { unchanged: '<?=$view["name"]; ?>' },
  806. { unchanged: 'a = <?= external() ?>;' },
  807. { unchanged:
  808. [
  809. '<?php',
  810. 'for($i = 1; $i <= 100; $i++;) {',
  811. ' #count to 100!',
  812. ' echo($i . "</br>");',
  813. '}',
  814. '?>'
  815. ]
  816. },
  817. { unchanged: 'a = <%= external() %>;' }
  818. ]
  819. },
  820. {
  821. name: "jslint and space after anon function",
  822. description: "jslint_happy and space_after_anon_function tests",
  823. matrix: [
  824. {
  825. options: [
  826. { name: "jslint_happy", value: "true" },
  827. { name: "space_after_anon_function", value: "true" }
  828. ],
  829. f: ' ',
  830. c: ''
  831. }, {
  832. options: [
  833. { name: "jslint_happy", value: "true" },
  834. { name: "space_after_anon_function", value: "false" }
  835. ],
  836. f: ' ',
  837. c: ''
  838. }, {
  839. options: [
  840. { name: "jslint_happy", value: "false" },
  841. { name: "space_after_anon_function", value: "true" }
  842. ],
  843. f: ' ',
  844. c: ' '
  845. }, {
  846. options: [
  847. { name: "jslint_happy", value: "false" },
  848. { name: "space_after_anon_function", value: "false" }
  849. ],
  850. f: '',
  851. c: ' '
  852. }
  853. ],
  854. tests: [
  855. { input_: 'a=typeof(x)',
  856. output: 'a = typeof{{f}}(x)' },
  857. { input_: 'x();\n\nfunction(){}',
  858. output: 'x();\n\nfunction{{f}}() {}' },
  859. { input_: 'function () {\n var a, b, c, d, e = [],\n f;\n}',
  860. output: 'function{{f}}() {\n var a, b, c, d, e = [],\n f;\n}' },
  861. { input_: 'switch(x) {case 0: case 1: a(); break; default: break}',
  862. output: 'switch (x) {\n{{c}}case 0:\n{{c}}case 1:\n{{c}} a();\n{{c}} break;\n{{c}}default:\n{{c}} break\n}' },
  863. { input: 'switch(x){case -1:break;case !y:break;}',
  864. output: 'switch (x) {\n{{c}}case -1:\n{{c}} break;\n{{c}}case !y:\n{{c}} break;\n}' },
  865. { comment: 'typical greasemonkey start',
  866. fragment: true,
  867. unchanged: '// comment 2\n(function{{f}}()'
  868. },
  869. {
  870. input_: 'var a2, b2, c2, d2 = 0, c = function() {}, d = \\\'\\\';',
  871. output: 'var a2, b2, c2, d2 = 0,\n c = function{{f}}() {},\n d = \\\'\\\';'
  872. },
  873. {
  874. input_: 'var a2, b2, c2, d2 = 0, c = function() {},\nd = \\\'\\\';',
  875. output: 'var a2, b2, c2, d2 = 0,\n c = function{{f}}() {},\n d = \\\'\\\';'
  876. },
  877. {
  878. input_: 'var o2=$.extend(a);function(){alert(x);}',
  879. output: 'var o2 = $.extend(a);\n\nfunction{{f}}() {\n alert(x);\n}'
  880. },
  881. { input: 'function*() {\n yield 1;\n}', output: 'function*{{f}}() {\n yield 1;\n}'},
  882. { unchanged: 'function* x() {\n yield 1;\n}' },
  883. ]
  884. }, {
  885. name: "Regression tests",
  886. description: "Ensure specific bugs do not recur",
  887. options: [],
  888. tests: [
  889. {
  890. comment: "Issue 241",
  891. unchanged: [
  892. 'obj',
  893. ' .last({',
  894. ' foo: 1,',
  895. ' bar: 2',
  896. ' });',
  897. 'var test = 1;' ]
  898. },
  899. {
  900. unchanged: [
  901. 'obj',
  902. ' .last(a, function() {',
  903. ' var test;',
  904. ' });',
  905. 'var test = 1;' ]
  906. },
  907. {
  908. unchanged: [
  909. 'obj.first()',
  910. ' .second()',
  911. ' .last(function(err, response) {',
  912. ' console.log(err);',
  913. ' });' ]
  914. },
  915. {
  916. comment: "Issue 268 and 275",
  917. unchanged: [
  918. 'obj.last(a, function() {',
  919. ' var test;',
  920. '});',
  921. 'var test = 1;' ]
  922. },
  923. {
  924. unchanged: [
  925. 'obj.last(a,',
  926. ' function() {',
  927. ' var test;',
  928. ' });',
  929. 'var test = 1;' ]
  930. },
  931. {
  932. input: '(function() {if (!window.FOO) window.FOO || (window.FOO = function() {var b = {bar: "zort"};});})();',
  933. output: [
  934. '(function() {',
  935. ' if (!window.FOO) window.FOO || (window.FOO = function() {',
  936. ' var b = {',
  937. ' bar: "zort"',
  938. ' };',
  939. ' });',
  940. '})();' ]
  941. },
  942. {
  943. comment: "Issue 281",
  944. unchanged: [
  945. 'define(["dojo/_base/declare", "my/Employee", "dijit/form/Button",',
  946. ' "dojo/_base/lang", "dojo/Deferred"',
  947. '], function(declare, Employee, Button, lang, Deferred) {',
  948. ' return declare(Employee, {',
  949. ' constructor: function() {',
  950. ' new Button({',
  951. ' onClick: lang.hitch(this, function() {',
  952. ' new Deferred().then(lang.hitch(this, function() {',
  953. ' this.salary * 0.25;',
  954. ' }));',
  955. ' })',
  956. ' });',
  957. ' }',
  958. ' });',
  959. '});' ]
  960. },
  961. {
  962. unchanged: [
  963. 'define(["dojo/_base/declare", "my/Employee", "dijit/form/Button",',
  964. ' "dojo/_base/lang", "dojo/Deferred"',
  965. ' ],',
  966. ' function(declare, Employee, Button, lang, Deferred) {',
  967. ' return declare(Employee, {',
  968. ' constructor: function() {',
  969. ' new Button({',
  970. ' onClick: lang.hitch(this, function() {',
  971. ' new Deferred().then(lang.hitch(this, function() {',
  972. ' this.salary * 0.25;',
  973. ' }));',
  974. ' })',
  975. ' });',
  976. ' }',
  977. ' });',
  978. ' });' ]
  979. },
  980. {
  981. comment: "Issue 459",
  982. unchanged: [
  983. '(function() {',
  984. ' return {',
  985. ' foo: function() {',
  986. ' return "bar";',
  987. ' },',
  988. ' bar: ["bar"]',
  989. ' };',
  990. '}());' ]
  991. },
  992. {
  993. comment: "Issue 505 - strings should end at newline unless continued by backslash",
  994. unchanged: [
  995. 'var name = "a;',
  996. 'name = "b";' ]
  997. },
  998. {
  999. unchanged: [
  1000. 'var name = "a;\\\\',
  1001. ' name = b";' ]
  1002. },
  1003. {
  1004. comment: "Issue 514 - some operators require spaces to distinguish them",
  1005. unchanged: 'var c = "_ACTION_TO_NATIVEAPI_" + ++g++ + +new Date;'
  1006. },
  1007. {
  1008. unchanged: 'var c = "_ACTION_TO_NATIVEAPI_" - --g-- - -new Date;'
  1009. },
  1010. {
  1011. comment: "Issue 440 - reserved words can be used as object property names",
  1012. unchanged: [
  1013. 'a = {',
  1014. ' function: {},',
  1015. ' "function": {},',
  1016. ' throw: {},',
  1017. ' "throw": {},',
  1018. ' var: {},',
  1019. ' "var": {},',
  1020. ' set: {},',
  1021. ' "set": {},',
  1022. ' get: {},',
  1023. ' "get": {},',
  1024. ' if: {},',
  1025. ' "if": {},',
  1026. ' then: {},',
  1027. ' "then": {},',
  1028. ' else: {},',
  1029. ' "else": {},',
  1030. ' yay: {}',
  1031. '};' ]
  1032. },
  1033. {
  1034. comment: "Issue 331 - if-else with braces edge case",
  1035. input: 'if(x){a();}else{b();}if(y){c();}',
  1036. output: [
  1037. 'if (x) {',
  1038. ' a();',
  1039. '} else {',
  1040. ' b();',
  1041. '}',
  1042. 'if (y) {',
  1043. ' c();',
  1044. '}' ]
  1045. },
  1046. {
  1047. comment: "Issue 485 - ensure function declarations behave the same in arrays as elsewhere",
  1048. unchanged: [
  1049. 'var v = ["a",',
  1050. ' function() {',
  1051. ' return;',
  1052. ' }, {',
  1053. ' id: 1',
  1054. ' }',
  1055. '];' ]
  1056. },
  1057. {
  1058. unchanged: [
  1059. 'var v = ["a", function() {',
  1060. ' return;',
  1061. '}, {',
  1062. ' id: 1',
  1063. '}];' ]
  1064. },
  1065. {
  1066. comment: "Issue 382 - initial totally cursory support for es6 module export",
  1067. unchanged: [
  1068. 'module "Even" {',
  1069. ' import odd from "Odd";',
  1070. ' export function sum(x, y) {',
  1071. ' return x + y;',
  1072. ' }',
  1073. ' export var pi = 3.141593;',
  1074. ' export default moduleName;',
  1075. '}' ]
  1076. },
  1077. {
  1078. unchanged: [
  1079. 'module "Even" {',
  1080. ' export default function div(x, y) {}',
  1081. '}' ]
  1082. },
  1083. {
  1084. comment: "Issue 508",
  1085. unchanged: 'set["name"]'
  1086. },
  1087. {
  1088. unchanged: 'get["name"]'
  1089. },
  1090. {
  1091. fragmeent: true,
  1092. unchanged: [
  1093. 'a = {',
  1094. ' set b(x) {},',
  1095. ' c: 1,',
  1096. ' d: function() {}',
  1097. '};' ]
  1098. },
  1099. {
  1100. fragmeent: true,
  1101. unchanged: [
  1102. 'a = {',
  1103. ' get b() {',
  1104. ' retun 0;',
  1105. ' },',
  1106. ' c: 1,',
  1107. ' d: function() {}',
  1108. '};' ]
  1109. },
  1110. {
  1111. comment: "Issue 298 - do not under indent if/while/for condtionals experesions",
  1112. unchanged: [
  1113. '\\\'use strict\\\';',
  1114. 'if ([].some(function() {',
  1115. ' return false;',
  1116. ' })) {',
  1117. ' console.log("hello");',
  1118. '}' ]
  1119. },
  1120. {
  1121. comment: "Issue 298 - do not under indent if/while/for condtionals experesions",
  1122. unchanged: [
  1123. '\\\'use strict\\\';',
  1124. 'if ([].some(function() {',
  1125. ' return false;',
  1126. ' })) {',
  1127. ' console.log("hello");',
  1128. '}' ]
  1129. },
  1130. {
  1131. comment: "Issue 552 - Typescript? Okay... we didn't break it before, so try not to break it now.",
  1132. unchanged: [
  1133. 'class Test {',
  1134. ' blah: string[];',
  1135. ' foo(): number {',
  1136. ' return 0;',
  1137. ' }',
  1138. ' bar(): number {',
  1139. ' return 0;',
  1140. ' }',
  1141. '}' ]
  1142. },
  1143. {
  1144. unchanged: [
  1145. 'interface Test {',
  1146. ' blah: string[];',
  1147. ' foo(): number {',
  1148. ' return 0;',
  1149. ' }',
  1150. ' bar(): number {',
  1151. ' return 0;',
  1152. ' }',
  1153. '}' ]
  1154. },
  1155. {
  1156. comment: "Issue 583 - Functions with comments after them should still indent correctly.",
  1157. unchanged: [
  1158. 'function exit(code) {',
  1159. ' setTimeout(function() {',
  1160. ' phantom.exit(code);',
  1161. ' }, 0);',
  1162. ' phantom.onError = function() {};',
  1163. '}',
  1164. '// Comment' ]
  1165. },
  1166. ]
  1167. },
  1168. // =======================================================
  1169. // New tests groups should be added above this line.
  1170. // Everything below is a work in progress - converting
  1171. // old test to generated form.
  1172. // =======================================================
  1173. {
  1174. name: "Old tests",
  1175. description: "Largely unorganized pile of tests",
  1176. options: [],
  1177. tests: [
  1178. { unchanged: '' },
  1179. { fragment: true, unchanged: ' return .5'},
  1180. { fragment: true, unchanged: ' return .5;\n a();' },
  1181. { fragment: true, unchanged: ' return .5;\n a();' },
  1182. { fragment: true, unchanged: ' return .5;\n a();' },
  1183. { fragment: true, unchanged: ' < div'},
  1184. { input: 'a = 1', output: 'a = 1' },
  1185. { input: 'a=1', output: 'a = 1' },
  1186. { unchanged: '(3) / 2' },
  1187. { input: '["a", "b"].join("")' },
  1188. { unchanged: 'a();\n\nb();' },
  1189. { input: 'var a = 1 var b = 2', output: 'var a = 1\nvar b = 2' },
  1190. { input: 'var a=1, b=c[d], e=6;', output: 'var a = 1,\n b = c[d],\n e = 6;' },
  1191. { unchanged: 'var a,\n b,\n c;' },
  1192. { input: 'let a = 1 let b = 2', output: 'let a = 1\nlet b = 2' },
  1193. { input: 'let a=1, b=c[d], e=6;', output: 'let a = 1,\n b = c[d],\n e = 6;' },
  1194. { unchanged: 'let a,\n b,\n c;' },
  1195. { input: 'const a = 1 const b = 2', output: 'const a = 1\nconst b = 2' },
  1196. { input: 'const a=1, b=c[d], e=6;', output: 'const a = 1,\n b = c[d],\n e = 6;' },
  1197. { unchanged: 'const a,\n b,\n c;' },
  1198. { unchanged: 'a = " 12345 "' },
  1199. { unchanged: "a = \\' 12345 \\'" },
  1200. { unchanged: 'if (a == 1) b = 2;' },
  1201. { input: 'if(1){2}else{3}', output: 'if (1) {\n 2\n} else {\n 3\n}' },
  1202. { input: 'if(1||2);', output: 'if (1 || 2);' },
  1203. { input: '(a==1)||(b==2)', output: '(a == 1) || (b == 2)' },
  1204. { input: 'var a = 1 if (2) 3;', output: 'var a = 1\nif (2) 3;' },
  1205. { unchanged: 'a = a + 1' },
  1206. { unchanged: 'a = a == 1' },
  1207. { input: '/12345[^678]*9+/.match(a)' },
  1208. { unchanged: 'a /= 5' },
  1209. { unchanged: 'a = 0.5 * 3' },
  1210. { unchanged: 'a *= 10.55' },
  1211. { unchanged: 'a < .5' },
  1212. { unchanged: 'a <= .5' },
  1213. { input: 'a<.5', output: 'a < .5' },
  1214. { input: 'a<=.5', output: 'a <= .5' },
  1215. { unchanged: 'a = 0xff;' },
  1216. { input: 'a=0xff+4', output: 'a = 0xff + 4' },
  1217. { unchanged: 'a = [1, 2, 3, 4]' },
  1218. { input: 'F*(g/=f)*g+b', output: 'F * (g /= f) * g + b' },
  1219. { input: 'a.b({c:d})', output: 'a.b({\n c: d\n})' },
  1220. { input: 'a.b\n(\n{\nc:\nd\n}\n)', output: 'a.b({\n c: d\n})' },
  1221. { input: 'a.b({c:"d"})', output: 'a.b({\n c: "d"\n})' },
  1222. { input: 'a.b\n(\n{\nc:\n"d"\n}\n)', output: 'a.b({\n c: "d"\n})' },
  1223. { input: 'a=!b', output: 'a = !b' },
  1224. { input: 'a=!!b', output: 'a = !!b' },
  1225. { input: 'a?b:c', output: 'a ? b : c' },
  1226. { input: 'a?1:2', output: 'a ? 1 : 2' },
  1227. { input: 'a?(b):c', output: 'a ? (b) : c' },
  1228. { input: 'x={a:1,b:w=="foo"?x:y,c:z}', output: 'x = {\n a: 1,\n b: w == "foo" ? x : y,\n c: z\n}' },
  1229. { input: 'x=a?b?c?d:e:f:g;', output: 'x = a ? b ? c ? d : e : f : g;' },
  1230. { input: 'x=a?b?c?d:{e1:1,e2:2}:f:g;', output: 'x = a ? b ? c ? d : {\n e1: 1,\n e2: 2\n} : f : g;' },
  1231. { input: 'function void(void) {}' },
  1232. { input: 'if(!a)foo();', output: 'if (!a) foo();' },
  1233. { input: 'a=~a', output: 'a = ~a' },
  1234. { input: 'a;/*comment*/b;', output: "a; /*comment*/\nb;" },
  1235. { input: 'a;/* comment */b;', output: "a; /* comment */\nb;" },
  1236. { fragment: true, input: 'a;/*\ncomment\n*/b;', output: "a;\n/*\ncomment\n*/\nb;", comment: "simple comments don't get touched at all" },
  1237. { input: 'a;/**\n* javadoc\n*/b;', output: "a;\n/**\n * javadoc\n */\nb;" },
  1238. { fragment: true, input: 'a;/**\n\nno javadoc\n*/b;', output: "a;\n/**\n\nno javadoc\n*/\nb;" },
  1239. { input: 'a;/*\n* javadoc\n*/b;', output: "a;\n/*\n * javadoc\n */\nb;", comment: 'comment blocks detected and reindented even w/o javadoc starter' },
  1240. { input: 'if(a)break;', output: "if (a) break;" },
  1241. { input: 'if(a){break}', output: "if (a) {\n break\n}" },
  1242. { input: 'if((a))foo();', output: 'if ((a)) foo();' },
  1243. { input: 'for(var i=0;;) a', output: 'for (var i = 0;;) a' },
  1244. { input: 'for(var i=0;;)\na', output: 'for (var i = 0;;)\n a' },
  1245. { unchanged: 'a++;' },
  1246. { input: 'for(;;i++)a()', output: 'for (;; i++) a()' },
  1247. { input: 'for(;;i++)\na()', output: 'for (;; i++)\n a()' },
  1248. { input: 'for(;;++i)a', output: 'for (;; ++i) a' },
  1249. { input: 'return(1)', output: 'return (1)' },
  1250. { input: 'try{a();}catch(b){c();}finally{d();}', output: "try {\n a();\n} catch (b) {\n c();\n} finally {\n d();\n}" },
  1251. { input: '(xx)()', comment: ' magic function call'},
  1252. { input: 'a[1]()', comment: 'another magic function call'},
  1253. { input: 'if(a){b();}else if(c) foo();', output: "if (a) {\n b();\n} else if (c) foo();" },
  1254. { input: 'switch(x) {case 0: case 1: a(); break; default: break}', output: "switch (x) {\n case 0:\n case 1:\n a();\n break;\n default:\n break\n}" },
  1255. { input: 'switch(x){case -1:break;case !y:break;}', output: 'switch (x) {\n case -1:\n break;\n case !y:\n break;\n}' },
  1256. { input: 'a !== b' },
  1257. { input: 'if (a) b(); else c();', output: "if (a) b();\nelse c();" },
  1258. { input: "// comment\n(function something() {})", comment: 'typical greasemonkey start' },
  1259. { input: "{\n\n x();\n\n}", comment: 'duplicating newlines' },
  1260. { input: 'if (a in b) foo();' },
  1261. { input: 'if(X)if(Y)a();else b();else c();',
  1262. output: "if (X)\n if (Y) a();\n else b();\nelse c();" },
  1263. { input: 'if (foo) bar();\nelse break' },
  1264. { unchanged: 'var a, b;' },
  1265. { unchanged: 'var a = new function();' },
  1266. { fragment: true, unchanged: 'new function' },
  1267. { unchanged: 'var a, b' },
  1268. { input: '{a:1, b:2}', output: "{\n a: 1,\n b: 2\n}" },
  1269. { input: 'a={1:[-1],2:[+1]}', output: 'a = {\n 1: [-1],\n 2: [+1]\n}' },
  1270. { input: "var l = {\\'a\\':\\'1\\', \\'b\\':\\'2\\'}", output: "var l = {\n \\'a\\': \\'1\\',\n \\'b\\': \\'2\\'\n}" },
  1271. { input: 'if (template.user[n] in bk) foo();' },
  1272. { unchanged: 'return 45' },
  1273. { unchanged: 'return this.prevObject ||\n\n this.constructor(null);' },
  1274. { unchanged: 'If[1]' },
  1275. { unchanged: 'Then[1]' },
  1276. { unchanged: 'a = 1e10' },
  1277. { unchanged: 'a = 1.3e10' },
  1278. { unchanged: 'a = 1.3e-10' },
  1279. { unchanged: 'a = -1.3e-10' },
  1280. { unchanged: 'a = 1e-10' },
  1281. { unchanged: 'a = e - 10' },
  1282. { input: 'a = 11-10', output: "a = 11 - 10" },
  1283. { input: "a = 1;// comment", output: "a = 1; // comment" },
  1284. { unchanged: "a = 1; // comment" },
  1285. { input: "a = 1;\n // comment", output: "a = 1;\n// comment" },
  1286. { unchanged: 'a = [-1, -1, -1]' },
  1287. { comment: 'The exact formatting these should have is open for discussion, but they are at least reasonable',
  1288. unchanged: 'a = [ // comment\n -1, -1, -1\n]' },
  1289. { unchanged: 'var a = [ // comment\n -1, -1, -1\n]' },
  1290. { unchanged: 'a = [ // comment\n -1, // comment\n -1, -1\n]' },
  1291. { unchanged: 'var a = [ // comment\n -1, // comment\n -1, -1\n]' },
  1292. { input: 'o = [{a:b},{c:d}]', output: 'o = [{\n a: b\n}, {\n c: d\n}]' },
  1293. { comment: 'was: extra space appended',
  1294. input: "if (a) {\n do();\n}" },
  1295. { comment: 'if/else statement with empty body',
  1296. input: "if (a) {\n// comment\n}else{\n// comment\n}", output: "if (a) {\n // comment\n} else {\n // comment\n}" },
  1297. { comment: 'multiple comments indentation', input: "if (a) {\n// comment\n// comment\n}", output: "if (a) {\n // comment\n // comment\n}" },
  1298. { input: "if (a) b() else c();", output: "if (a) b()\nelse c();" },
  1299. { input: "if (a) b() else if c() d();", output: "if (a) b()\nelse if c() d();" },
  1300. { unchanged: "{}" },
  1301. { unchanged: "{\n\n}" },
  1302. { input: "do { a(); } while ( 1 );", output: "do {\n a();\n} while (1);" },
  1303. { unchanged: "do {} while (1);" },
  1304. { input: "do {\n} while (1);", output: "do {} while (1);" },
  1305. { unchanged: "do {\n\n} while (1);" },
  1306. { unchanged: "var a = x(a, b, c)" },
  1307. { input: "delete x if (a) b();", output: "delete x\nif (a) b();" },
  1308. { input: "delete x[x] if (a) b();", output: "delete x[x]\nif (a) b();" },
  1309. { input: "for(var a=1,b=2)d", output: "for (var a = 1, b = 2) d" },
  1310. { input: "for(var a=1,b=2,c=3) d", output: "for (var a = 1, b = 2, c = 3) d" },
  1311. { input: "for(var a=1,b=2,c=3;d<3;d++)\ne", output: "for (var a = 1, b = 2, c = 3; d < 3; d++)\n e" },
  1312. { input: "function x(){(a||b).c()}", output: "function x() {\n (a || b).c()\n}" },
  1313. { input: "function x(){return - 1}", output: "function x() {\n return -1\n}" },
  1314. { input: "function x(){return ! a}", output: "function x() {\n return !a\n}" },
  1315. { unchanged: "x => x" },
  1316. { unchanged: "(x) => x" },
  1317. { input: "x => { x }", output: "x => {\n x\n}" },
  1318. { input: "(x) => { x }", output: "(x) => {\n x\n}" },
  1319. { comment: 'a common snippet in jQuery plugins',
  1320. input_: "settings = $.extend({},defaults,settings);",
  1321. output: "settings = $.extend({}, defaults, settings);" },
  1322. // reserved words used as property names
  1323. { unchanged: "$http().then().finally().default()" },
  1324. { input: "$http()\n.then()\n.finally()\n.default()", output: "$http()\n .then()\n .finally()\n .default()" },
  1325. { unchanged: "$http().when.in.new.catch().throw()" },
  1326. { input: "$http()\n.when\n.in\n.new\n.catch()\n.throw()", output: "$http()\n .when\n .in\n .new\n .catch()\n .throw()" },
  1327. { input: '{xxx;}()', output: '{\n xxx;\n}()' },
  1328. { unchanged: "a = \\'a\\'\nb = \\'b\\'" },
  1329. { unchanged: "a = /reg/exp" },
  1330. { unchanged: "a = /reg/" },
  1331. { unchanged: '/abc/.test()' },
  1332. { unchanged: '/abc/i.test()' },
  1333. { input: "{/abc/i.test()}", output: "{\n /abc/i.test()\n}" },
  1334. { input: 'var x=(a)/a;', output: 'var x = (a) / a;' },
  1335. { unchanged: 'x != -1' },
  1336. { input: 'for (; s-->0;)t', output: 'for (; s-- > 0;) t' },
  1337. { input: 'for (; s++>0;)u', output: 'for (; s++ > 0;) u' },
  1338. { input: 'a = s++>s--;', output: 'a = s++ > s--;' },
  1339. { input: 'a = s++>--s;', output: 'a = s++ > --s;' },
  1340. { input: '{x=#1=[]}', output: '{\n x = #1=[]\n}' },
  1341. { input: '{a:#1={}}', output: '{\n a: #1={}\n}' },
  1342. { input: '{a:#1#}', output: '{\n a: #1#\n}' },
  1343. { fragment: true, unchanged: '"incomplete-string' },
  1344. { fragment: true, unchanged: "\\'incomplete-string" },
  1345. { fragment: true, unchanged: '/incomplete-regex' },
  1346. { fragment: true, unchanged: '`incomplete-template-string' },
  1347. { fragment: true, input: '{a:1},{a:2}', output: '{\n a: 1\n}, {\n a: 2\n}' },
  1348. { fragment: true, input: 'var ary=[{a:1}, {a:2}];', output: 'var ary = [{\n a: 1\n}, {\n a: 2\n}];' },
  1349. { comment: 'incomplete', fragment: true, input: '{a:#1', output: '{\n a: #1' },
  1350. { comment: 'incomplete', fragment: true, input: '{a:#', output: '{\n a: #' },
  1351. { comment: 'incomplete', fragment: true, input: '}}}', output: '}\n}\n}' },
  1352. { fragment: true, unchanged: '<!--\nvoid();\n// -->' },
  1353. { comment: 'incomplete regexp', fragment: true, input: 'a=/regexp', output: 'a = /regexp' },
  1354. { input: '{a:#1=[],b:#1#,c:#999999#}', output: '{\n a: #1=[],\n b: #1#,\n c: #999999#\n}' },
  1355. { unchanged: "a = 1e+2" },
  1356. { unchanged: "a = 1e-2" },
  1357. { input: "do{x()}while(a>1)", output: "do {\n x()\n} while (a > 1)" },
  1358. { input: "x(); /reg/exp.match(something)", output: "x();\n/reg/exp.match(something)" },
  1359. { fragment: true, input: "something();(", output: "something();\n(" },
  1360. { fragment: true, input: "#!she/bangs, she bangs\nf=1", output: "#!she/bangs, she bangs\n\nf = 1" },
  1361. { fragment: true, input: "#!she/bangs, she bangs\n\nf=1", output: "#!she/bangs, she bangs\n\nf = 1" },
  1362. { fragment: true, unchanged: "#!she/bangs, she bangs\n\n/* comment */" },
  1363. { fragment: true, unchanged: "#!she/bangs, she bangs\n\n\n/* comment */" },
  1364. { fragment: true, unchanged: "#" },
  1365. { fragment: true, unchanged: "#!" },
  1366. { input: "function namespace::something()" },
  1367. { fragment: true, unchanged: "<!--\nsomething();\n-->" },
  1368. { fragment: true, input: "<!--\nif(i<0){bla();}\n-->", output: "<!--\nif (i < 0) {\n bla();\n}\n-->" },
  1369. { input: '{foo();--bar;}', output: '{\n foo();\n --bar;\n}' },
  1370. { input: '{foo();++bar;}', output: '{\n foo();\n ++bar;\n}' },
  1371. { input: '{--bar;}', output: '{\n --bar;\n}' },
  1372. { input: '{++bar;}', output: '{\n ++bar;\n}' },
  1373. { input: 'if(true)++a;', output: 'if (true) ++a;' },
  1374. { input: 'if(true)\n++a;', output: 'if (true)\n ++a;' },
  1375. { input: 'if(true)--a;', output: 'if (true) --a;' },
  1376. { input: 'if(true)\n--a;', output: 'if (true)\n --a;' },
  1377. { unchanged: 'elem[array]++;' },
  1378. { unchanged: 'elem++ * elem[array]++;' },
  1379. { unchanged: 'elem-- * -elem[array]++;' },
  1380. { unchanged: 'elem-- + elem[array]++;' },
  1381. { unchanged: 'elem-- - elem[array]++;' },
  1382. { unchanged: 'elem-- - -elem[array]++;' },
  1383. { unchanged: 'elem-- - +elem[array]++;' },
  1384. { comment: 'Handling of newlines around unary ++ and -- operators',
  1385. input: '{foo\n++bar;}', output: '{\n foo\n ++bar;\n}' },
  1386. { input: '{foo++\nbar;}', output: '{\n foo++\n bar;\n}' },
  1387. { comment: 'This is invalid, but harder to guard against. Issue #203.',
  1388. input: '{foo\n++\nbar;}', output: '{\n foo\n ++\n bar;\n}' },
  1389. { comment: 'regexps',
  1390. input: 'a(/abc\\\\/\\\\/def/);b()', output: "a(/abc\\\\/\\\\/def/);\nb()" },
  1391. { input: 'a(/a[b\\\\[\\\\]c]d/);b()', output: "a(/a[b\\\\[\\\\]c]d/);\nb()" },
  1392. { comment: 'incomplete char class', fragment: true, unchanged: 'a(/a[b\\\\[' },
  1393. { comment: 'allow unescaped / in char classes',
  1394. input: 'a(/[a/b]/);b()', output: "a(/[a/b]/);\nb()" },
  1395. { unchanged: 'typeof /foo\\\\//;' },
  1396. { unchanged: 'yield /foo\\\\//;' },
  1397. { unchanged: 'throw /foo\\\\//;' },
  1398. { unchanged: 'do /foo\\\\//;' },
  1399. { unchanged: 'return /foo\\\\//;' },
  1400. { unchanged: 'switch (a) {\n case /foo\\\\//:\n b\n}' },
  1401. { unchanged: 'if (a) /foo\\\\//\nelse /foo\\\\//;' },
  1402. { unchanged: 'if (foo) /regex/.test();' },
  1403. { unchanged: "for (index in [1, 2, 3]) /^test$/i.test(s)"},
  1404. { unchanged: 'result = yield pgClient.query_(queryString);' },
  1405. { unchanged: 'function foo() {\n return [\n "one",\n "two"\n ];\n}' },
  1406. { input: 'a=[[1,2],[4,5],[7,8]]', output: "a = [\n [1, 2],\n [4, 5],\n [7, 8]\n]" },
  1407. { input: 'a=[[1,2],[4,5],function(){},[7,8]]',
  1408. output: "a = [\n [1, 2],\n [4, 5],\n function() {},\n [7, 8]\n]" },
  1409. { input: 'a=[[1,2],[4,5],function(){},function(){},[7,8]]',
  1410. output: "a = [\n [1, 2],\n [4, 5],\n function() {},\n function() {},\n [7, 8]\n]" },
  1411. { input: 'a=[[1,2],[4,5],function(){},[7,8]]',
  1412. output: "a = [\n [1, 2],\n [4, 5],\n function() {},\n [7, 8]\n]" },
  1413. { input: 'a=[b,c,function(){},function(){},d]',
  1414. output: "a = [b, c, function() {}, function() {}, d]" },
  1415. { input: 'a=[b,c,\nfunction(){},function(){},d]',
  1416. output: "a = [b, c,\n function() {},\n function() {},\n d\n]" },
  1417. { input: 'a=[a[1],b[4],c[d[7]]]', output: "a = [a[1], b[4], c[d[7]]]" },
  1418. { input: '[1,2,[3,4,[5,6],7],8]', output: "[1, 2, [3, 4, [5, 6], 7], 8]" },
  1419. { input: '[[["1","2"],["3","4"]],[["5","6","7"],["8","9","0"]],[["1","2","3"],["4","5","6","7"],["8","9","0"]]]',
  1420. output: '[\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]' },
  1421. { input: '{[x()[0]];indent;}', output: '{\n [x()[0]];\n indent;\n}' },
  1422. { unchanged: '/*\n foo trailing space \n * bar trailing space \n**/'},
  1423. { unchanged: '{\n /*\n foo \n * bar \n */\n}'},
  1424. { unchanged: 'return ++i' },
  1425. { unchanged: 'return !!x' },
  1426. { unchanged: 'return !x' },
  1427. { input: 'return [1,2]', output: 'return [1, 2]' },
  1428. { unchanged: 'return;' },
  1429. { unchanged: 'return\nfunc' },
  1430. { input: 'catch(e)', output: 'catch (e)' },
  1431. { unchanged: 'yield [1, 2]' },
  1432. { input: 'var a=1,b={foo:2,bar:3},{baz:4,wham:5},c=4;',
  1433. output: 'var a = 1,\n b = {\n foo: 2,\n bar: 3\n },\n {\n baz: 4,\n wham: 5\n }, c = 4;' },
  1434. { input: 'var a=1,b={foo:2,bar:3},{baz:4,wham:5},\nc=4;',
  1435. output: 'var a = 1,\n b = {\n foo: 2,\n bar: 3\n },\n {\n baz: 4,\n wham: 5\n },\n c = 4;' },
  1436. {
  1437. comment: 'inline comment',
  1438. input_: 'function x(/*int*/ start, /*string*/ foo)',
  1439. output: 'function x( /*int*/ start, /*string*/ foo)'
  1440. },
  1441. { comment: 'javadoc comment',
  1442. input: '/**\n* foo\n*/', output: '/**\n * foo\n */' },
  1443. { input: '{\n/**\n* foo\n*/\n}', output: '{\n /**\n * foo\n */\n}' },
  1444. { comment: 'starless block comment',
  1445. unchanged: '/**\nfoo\n*/' },
  1446. { unchanged: '/**\nfoo\n**/' },
  1447. { unchanged: '/**\nfoo\nbar\n**/' },
  1448. { unchanged: '/**\nfoo\n\nbar\n**/' },
  1449. { unchanged: '/**\nfoo\n bar\n**/' },
  1450. { input: '{\n/**\nfoo\n*/\n}', output: '{\n /**\n foo\n */\n}' },
  1451. { input: '{\n/**\nfoo\n**/\n}', output: '{\n /**\n foo\n **/\n}' },
  1452. { input: '{\n/**\nfoo\nbar\n**/\n}', output: '{\n /**\n foo\n bar\n **/\n}' },
  1453. { input: '{\n/**\nfoo\n\nbar\n**/\n}', output: '{\n /**\n foo\n\n bar\n **/\n}' },
  1454. { input: '{\n/**\nfoo\n bar\n**/\n}', output: '{\n /**\n foo\n bar\n **/\n}' },
  1455. { unchanged: '{\n /**\n foo\nbar\n **/\n}' },
  1456. { input: 'var a,b,c=1,d,e,f=2;', output: 'var a, b, c = 1,\n d, e, f = 2;' },
  1457. { input: 'var a,b,c=[],d,e,f=2;', output: 'var a, b, c = [],\n d, e, f = 2;' },
  1458. { unchanged: 'function() {\n var a, b, c, d, e = [],\n f;\n}' },
  1459. { input: 'do/regexp/;\nwhile(1);', output: 'do /regexp/;\nwhile (1);' },
  1460. { input: 'var a = a,\na;\nb = {\nb\n}', output: 'var a = a,\n a;\nb = {\n b\n}' },
  1461. { unchanged: 'var a = a,\n /* c */\n b;' },
  1462. { unchanged: 'var a = a,\n // c\n b;' },
  1463. { comment: 'weird element referencing',
  1464. unchanged: 'foo.("bar");' },
  1465. { unchanged: 'if (a) a()\nelse b()\nnewline()' },
  1466. { unchanged: 'if (a) a()\nnewline()' },
  1467. { input: 'a=typeof(x)', output: 'a = typeof(x)' },
  1468. { unchanged: 'var a = function() {\n return null;\n },\n b = false;' },
  1469. { unchanged: 'var a = function() {\n func1()\n}' },
  1470. { unchanged: 'var a = function() {\n func1()\n}\nvar b = function() {\n func2()\n}' },
  1471. { comment: 'code with and without semicolons',
  1472. input_: 'var whatever = require("whatever");\nfunction() {\n a = 6;\n}',
  1473. output: 'var whatever = require("whatever");\n\nfunction() {\n a = 6;\n}' },
  1474. { input: 'var whatever = require("whatever")\nfunction() {\n a = 6\n}',
  1475. output: 'var whatever = require("whatever")\n\nfunction() {\n a = 6\n}' },
  1476. { input: '{"x":[{"a":1,"b":3},\n7,8,8,8,8,{"b":99},{"a":11}]}', output: '{\n "x": [{\n "a": 1,\n "b": 3\n },\n 7, 8, 8, 8, 8, {\n "b": 99\n }, {\n "a": 11\n }\n ]\n}' },
  1477. { input: '{"x":[{"a":1,"b":3},7,8,8,8,8,{"b":99},{"a":11}]}', output: '{\n "x": [{\n "a": 1,\n "b": 3\n }, 7, 8, 8, 8, 8, {\n "b": 99\n }, {\n "a": 11\n }]\n}' },
  1478. { input: '{"1":{"1a":"1b"},"2"}', output: '{\n "1": {\n "1a": "1b"\n },\n "2"\n}' },
  1479. { input: '{a:{a:b},c}', output: '{\n a: {\n a: b\n },\n c\n}' },
  1480. { input: '{[y[a]];keep_indent;}', output: '{\n [y[a]];\n keep_indent;\n}' },
  1481. { input: 'if (x) {y} else { if (x) {y}}', output: 'if (x) {\n y\n} else {\n if (x) {\n y\n }\n}' },
  1482. { unchanged: 'if (foo) one()\ntwo()\nthree()' },
  1483. { unchanged: 'if (1 + foo() && bar(baz()) / 2) one()\ntwo()\nthree()' },
  1484. { unchanged: 'if (1 + foo() && bar(baz()) / 2) one();\ntwo();\nthree();' },
  1485. { input: 'var a=1,b={bang:2},c=3;', output: 'var a = 1,\n b = {\n bang: 2\n },\n c = 3;' },
  1486. { input: 'var a={bing:1},b=2,c=3;', output: 'var a = {\n bing: 1\n },\n b = 2,\n c = 3;' },
  1487. ],
  1488. }],
  1489. // Example
  1490. examples: [{
  1491. group_name: "one",
  1492. description: "",
  1493. options: [],
  1494. values: [
  1495. {
  1496. source: "", //string or array of lines
  1497. output: "" //string or array of lines
  1498. }
  1499. ]
  1500. }]
  1501. }