js-beautify 1.5.6 → 1.5.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -119,7 +119,7 @@
119
119
  // Matches a whole line break (where CRLF is considered a single
120
120
  // line break). Used to count lines.
121
121
 
122
- var lineBreak = /\r\n|[\n\r\u2028\u2029]/g;
122
+ var lineBreak = exports.lineBreak = /\r\n|[\n\r\u2028\u2029]/g;
123
123
 
124
124
  // Test whether a given character code starts an identifier.
125
125
 
@@ -207,7 +207,6 @@
207
207
  'TK_OPERATOR': handle_operator,
208
208
  'TK_COMMA': handle_comma,
209
209
  'TK_BLOCK_COMMENT': handle_block_comment,
210
- 'TK_INLINE_COMMENT': handle_inline_comment,
211
210
  'TK_COMMENT': handle_comment,
212
211
  'TK_DOT': handle_dot,
213
212
  'TK_UNKNOWN': handle_unknown,
@@ -281,6 +280,8 @@
281
280
  opt.end_with_newline = (options.end_with_newline === undefined) ? false : options.end_with_newline;
282
281
  opt.comma_first = (options.comma_first === undefined) ? false : options.comma_first;
283
282
 
283
+ // For testing of beautify ignore:start directive
284
+ opt.test_output_raw = (options.test_output_raw === undefined) ? false : options.test_output_raw;
284
285
 
285
286
  // force opt.space_after_anon_function to true if opt.jslint_happy
286
287
  if(opt.jslint_happy) {
@@ -315,6 +316,9 @@
315
316
  last_last_text = ''; // pre-last token text
316
317
  output = new Output(indent_string, baseIndentString);
317
318
 
319
+ // If testing the ignore directive, start with output disable set to true
320
+ output.raw = opt.test_output_raw;
321
+
318
322
 
319
323
  // Stack of parsing/formatting states, including MODE.
320
324
  // We tokenize, parse, and output in an almost purely a forward-only stream of token input
@@ -359,7 +363,7 @@
359
363
  }
360
364
 
361
365
  if (opt.eol != '\n') {
362
- sweet_code = sweet_code.replace(/[\r]?[\n]/mg, opt.eol);
366
+ sweet_code = sweet_code.replace(/[\n]/g, opt.eol);
363
367
  }
364
368
 
365
369
  return sweet_code;
@@ -456,6 +460,11 @@
456
460
  }
457
461
 
458
462
  function print_token(printable_token) {
463
+ if (output.raw) {
464
+ output.add_raw_token(current_token)
465
+ return;
466
+ }
467
+
459
468
  if (opt.comma_first && last_type === 'TK_COMMA'
460
469
  && output.just_added_newline()) {
461
470
  if(output.previous_line.last() === ',') {
@@ -1180,6 +1189,35 @@
1180
1189
  }
1181
1190
 
1182
1191
  function handle_block_comment() {
1192
+ if (output.raw) {
1193
+ output.add_raw_token(current_token)
1194
+ if (current_token.directives && current_token.directives['preserve'] === 'end') {
1195
+ // If we're testing the raw output behavior, do not allow a directive to turn it off.
1196
+ if (!opt.test_output_raw) {
1197
+ output.raw = false;
1198
+ }
1199
+ }
1200
+ return;
1201
+ }
1202
+
1203
+ if (current_token.directives) {
1204
+ print_newline(false, true);
1205
+ print_token();
1206
+ if (current_token.directives['preserve'] === 'start') {
1207
+ output.raw = true;
1208
+ }
1209
+ print_newline(false, true);
1210
+ return;
1211
+ }
1212
+
1213
+ // inline block
1214
+ if (!acorn.newline.test(current_token.text) && !current_token.wanted_newline) {
1215
+ output.space_before_token = true;
1216
+ print_token();
1217
+ output.space_before_token = true;
1218
+ return;
1219
+ }
1220
+
1183
1221
  var lines = split_newlines(current_token.text);
1184
1222
  var j; // iterator for this case
1185
1223
  var javadoc = false;
@@ -1218,12 +1256,6 @@
1218
1256
  print_newline(false, true);
1219
1257
  }
1220
1258
 
1221
- function handle_inline_comment() {
1222
- output.space_before_token = true;
1223
- print_token();
1224
- output.space_before_token = true;
1225
- }
1226
-
1227
1259
  function handle_comment() {
1228
1260
  if (current_token.wanted_newline) {
1229
1261
  print_newline(false, true);
@@ -1346,6 +1378,7 @@
1346
1378
  this.indent_cache = [ baseIndentString ];
1347
1379
  this.baseIndentLength = baseIndentString.length;
1348
1380
  this.indent_length = indent_string.length;
1381
+ this.raw = false;
1349
1382
 
1350
1383
  var lines =[];
1351
1384
  this.baseIndentString = baseIndentString;
@@ -1354,6 +1387,16 @@
1354
1387
  this.current_line = null;
1355
1388
  this.space_before_token = false;
1356
1389
 
1390
+ this.add_outputline = function() {
1391
+ this.previous_line = this.current_line;
1392
+ this.current_line = new OutputLine(this);
1393
+ lines.push(this.current_line);
1394
+ }
1395
+
1396
+ // initialize
1397
+ this.add_outputline();
1398
+
1399
+
1357
1400
  this.get_line_number = function() {
1358
1401
  return lines.length;
1359
1402
  }
@@ -1365,18 +1408,15 @@
1365
1408
  }
1366
1409
 
1367
1410
  if (force_newline || !this.just_added_newline()) {
1368
- this.previous_line = this.current_line;
1369
- this.current_line = new OutputLine(this);
1370
- lines.push(this.current_line);
1411
+ if (!this.raw) {
1412
+ this.add_outputline();
1413
+ }
1371
1414
  return true;
1372
1415
  }
1373
1416
 
1374
1417
  return false;
1375
1418
  }
1376
1419
 
1377
- // initialize
1378
- this.add_new_line(true);
1379
-
1380
1420
  this.get_code = function() {
1381
1421
  var sweet_code = lines.join('\n').replace(/[\r\n\t ]+$/, '');
1382
1422
  return sweet_code;
@@ -1396,6 +1436,15 @@
1396
1436
  return false;
1397
1437
  }
1398
1438
 
1439
+ this.add_raw_token = function(token) {
1440
+ for (var x = 0; x < token.newlines; x++) {
1441
+ this.add_outputline();
1442
+ }
1443
+ this.current_line.push(token.whitespace_before);
1444
+ this.current_line.push(token.text);
1445
+ this.space_before_token = false;
1446
+ }
1447
+
1399
1448
  this.add_token = function(printable_token) {
1400
1449
  this.add_space_before_token();
1401
1450
  this.current_line.push(printable_token);
@@ -1472,12 +1521,14 @@
1472
1521
  this.wanted_newline = newlines > 0;
1473
1522
  this.whitespace_before = whitespace_before || '';
1474
1523
  this.parent = null;
1524
+ this.directives = null;
1475
1525
  }
1476
1526
 
1477
1527
  function tokenizer(input, opts, indent_string) {
1478
1528
 
1479
1529
  var whitespace = "\n\r\t ".split('');
1480
1530
  var digit = /[0-9]/;
1531
+ var digit_hex = /[0123456789abcdefABCDEF]/;
1481
1532
 
1482
1533
  var punct = ('+ - * / % & ++ -- = += -= *= /= %= == === != !== > < >= <= >> << >>> >>>= >>= <<= && &= | || ! ~ , : ? ^ ^= |= :: =>'
1483
1534
  +' <%= <% %> <?= <? ?>').split(' '); // try to be a good boy and try not to break the markup language identifiers
@@ -1486,6 +1537,18 @@
1486
1537
  this.line_starters = 'continue,try,throw,return,var,let,const,if,switch,case,default,for,while,break,function,import,export'.split(',');
1487
1538
  var reserved_words = this.line_starters.concat(['do', 'in', 'else', 'get', 'set', 'new', 'catch', 'finally', 'typeof', 'yield', 'async', 'await']);
1488
1539
 
1540
+ // /* ... */ comment ends with nearest */ or end of file
1541
+ var block_comment_pattern = /([\s\S]*?)((?:\*\/)|$)/g;
1542
+
1543
+ // comment ends just before nearest linefeed or end of file
1544
+ var comment_pattern = /([^\n\r\u2028\u2029]*)/g;
1545
+
1546
+ var directives_block_pattern = /\/\* beautify( \w+[:]\w+)+ \*\//g;
1547
+ var directive_pattern = / (\w+)[:](\w+)/g;
1548
+ var directives_end_ignore_pattern = /([\s\S]*?)((?:\/\*\sbeautify\signore:end\s\*\/)|$)/g;
1549
+
1550
+ var template_pattern = /((<\?php|<\?=)[\s\S]*?\?>)|(<%[\s\S]*?%>)/g
1551
+
1489
1552
  var n_newlines, whitespace_before_token, in_html_comment, tokens, parser_pos;
1490
1553
  var input_length;
1491
1554
 
@@ -1505,8 +1568,10 @@
1505
1568
  while (!(last && last.type === 'TK_EOF')) {
1506
1569
  token_values = tokenize_next();
1507
1570
  next = new Token(token_values[1], token_values[0], n_newlines, whitespace_before_token);
1508
- while(next.type === 'TK_INLINE_COMMENT' || next.type === 'TK_COMMENT' ||
1509
- next.type === 'TK_BLOCK_COMMENT' || next.type === 'TK_UNKNOWN') {
1571
+ while(next.type === 'TK_COMMENT' || next.type === 'TK_BLOCK_COMMENT' || next.type === 'TK_UNKNOWN') {
1572
+ if (next.type === 'TK_BLOCK_COMMENT') {
1573
+ next.directives = token_values[2];
1574
+ }
1510
1575
  comments.push(next);
1511
1576
  token_values = tokenize_next();
1512
1577
  next = new Token(token_values[1], token_values[0], n_newlines, whitespace_before_token);
@@ -1537,6 +1602,23 @@
1537
1602
  return tokens;
1538
1603
  }
1539
1604
 
1605
+ function get_directives (text) {
1606
+ if (!text.match(directives_block_pattern)) {
1607
+ return null;
1608
+ }
1609
+
1610
+ var directives = {};
1611
+ directive_pattern.lastIndex = 0;
1612
+ var directive_match = directive_pattern.exec(text);
1613
+
1614
+ while (directive_match) {
1615
+ directives[directive_match[1]] = directive_match[2];
1616
+ directive_match = directive_pattern.exec(text);
1617
+ }
1618
+
1619
+ return directives;
1620
+ }
1621
+
1540
1622
  function tokenize_next() {
1541
1623
  var i, resulting_string;
1542
1624
  var whitespace_on_this_line = [];
@@ -1562,15 +1644,13 @@
1562
1644
 
1563
1645
  while (in_array(c, whitespace)) {
1564
1646
 
1565
- if (c === '\n') {
1566
- n_newlines += 1;
1567
- whitespace_on_this_line = [];
1568
- } else if (n_newlines) {
1569
- if (c === indent_string) {
1570
- whitespace_on_this_line.push(indent_string);
1571
- } else if (c !== '\r') {
1572
- whitespace_on_this_line.push(' ');
1647
+ if (acorn.newline.test(c)) {
1648
+ if (!(c === '\n' && input.charAt(parser_pos-2) === '\r')) {
1649
+ n_newlines += 1;
1650
+ whitespace_on_this_line = [];
1573
1651
  }
1652
+ } else {
1653
+ whitespace_on_this_line.push(c);
1574
1654
  }
1575
1655
 
1576
1656
  if (parser_pos >= input_length) {
@@ -1596,7 +1676,7 @@
1596
1676
  allow_e = false;
1597
1677
  c += input.charAt(parser_pos);
1598
1678
  parser_pos += 1;
1599
- local_digit = /[0123456789abcdefABCDEF]/
1679
+ local_digit = digit_hex
1600
1680
  } else {
1601
1681
  // we know this first loop will run. It keeps the logic simpler.
1602
1682
  c = '';
@@ -1677,39 +1757,29 @@
1677
1757
  if (c === '/') {
1678
1758
  var comment = '';
1679
1759
  // peek for comment /* ... */
1680
- var inline_comment = true;
1681
1760
  if (input.charAt(parser_pos) === '*') {
1682
1761
  parser_pos += 1;
1683
- if (parser_pos < input_length) {
1684
- while (parser_pos < input_length && !(input.charAt(parser_pos) === '*' && input.charAt(parser_pos + 1) && input.charAt(parser_pos + 1) === '/')) {
1685
- c = input.charAt(parser_pos);
1686
- comment += c;
1687
- if (c === "\n" || c === "\r") {
1688
- inline_comment = false;
1689
- }
1690
- parser_pos += 1;
1691
- if (parser_pos >= input_length) {
1692
- break;
1693
- }
1694
- }
1695
- }
1696
- parser_pos += 2;
1697
- if (inline_comment && n_newlines === 0) {
1698
- return ['/*' + comment + '*/', 'TK_INLINE_COMMENT'];
1699
- } else {
1700
- return ['/*' + comment + '*/', 'TK_BLOCK_COMMENT'];
1762
+ block_comment_pattern.lastIndex = parser_pos;
1763
+ var comment_match = block_comment_pattern.exec(input);
1764
+ comment = '/*' + comment_match[0];
1765
+ parser_pos += comment_match[0].length;
1766
+ var directives = get_directives(comment);
1767
+ if (directives && directives['ignore'] === 'start') {
1768
+ directives_end_ignore_pattern.lastIndex = parser_pos;
1769
+ comment_match = directives_end_ignore_pattern.exec(input)
1770
+ comment += comment_match[0];
1771
+ parser_pos += comment_match[0].length;
1701
1772
  }
1773
+ comment = comment.replace(acorn.lineBreak, '\n');
1774
+ return [comment, 'TK_BLOCK_COMMENT', directives];
1702
1775
  }
1703
1776
  // peek for comment // ...
1704
1777
  if (input.charAt(parser_pos) === '/') {
1705
- comment = c;
1706
- while (input.charAt(parser_pos) !== '\r' && input.charAt(parser_pos) !== '\n') {
1707
- comment += input.charAt(parser_pos);
1708
- parser_pos += 1;
1709
- if (parser_pos >= input_length) {
1710
- break;
1711
- }
1712
- }
1778
+ parser_pos += 1;
1779
+ comment_pattern.lastIndex = parser_pos;
1780
+ var comment_match = comment_pattern.exec(input);
1781
+ comment = '//' + comment_match[0];
1782
+ parser_pos += comment_match[0].length;
1713
1783
  return [comment, 'TK_COMMENT'];
1714
1784
  }
1715
1785
 
@@ -1784,6 +1854,7 @@
1784
1854
  var xmlLength = match ? match.index + match[0].length : xmlStr.length;
1785
1855
  xmlStr = xmlStr.slice(0, xmlLength);
1786
1856
  parser_pos += xmlLength - 1;
1857
+ xmlStr = xmlStr.replace(acorn.lineBreak, '\n');
1787
1858
  return [xmlStr, "TK_STRING"];
1788
1859
  }
1789
1860
  } else {
@@ -1795,11 +1866,14 @@
1795
1866
  while (parser_pos < input_length &&
1796
1867
  (esc || (input.charAt(parser_pos) !== sep &&
1797
1868
  (sep === '`' || !acorn.newline.test(input.charAt(parser_pos)))))) {
1798
- resulting_string += input.charAt(parser_pos);
1799
1869
  // Handle \r\n linebreaks after escapes or in template strings
1800
- if (input.charAt(parser_pos) === '\r' && input.charAt(parser_pos + 1) === '\n') {
1801
- parser_pos += 1;
1870
+ if ((esc || sep === '`') && acorn.newline.test(input.charAt(parser_pos))) {
1871
+ if (input.charAt(parser_pos) === '\r' && input.charAt(parser_pos + 1) === '\n') {
1872
+ parser_pos += 1;
1873
+ }
1802
1874
  resulting_string += '\n';
1875
+ } else {
1876
+ resulting_string += input.charAt(parser_pos);
1803
1877
  }
1804
1878
  if (esc) {
1805
1879
  if (input.charAt(parser_pos) === 'x' || input.charAt(parser_pos) === 'u') {
@@ -1872,10 +1946,21 @@
1872
1946
  }
1873
1947
  }
1874
1948
 
1949
+ if (c === '<' && (input.charAt(parser_pos) === '?' || input.charAt(parser_pos) === '%')) {
1950
+ template_pattern.lastIndex = parser_pos - 1;
1951
+ var template_match = template_pattern.exec(input);
1952
+ if(template_match) {
1953
+ c = template_match[0];
1954
+ parser_pos += c.length - 1;
1955
+ c = c.replace(acorn.lineBreak, '\n');
1956
+ return [c, 'TK_STRING'];
1957
+ }
1958
+ }
1959
+
1875
1960
  if (c === '<' && input.substring(parser_pos - 1, parser_pos + 3) === '<!--') {
1876
1961
  parser_pos += 3;
1877
1962
  c = '<!--';
1878
- while (input.charAt(parser_pos) !== '\n' && parser_pos < input_length) {
1963
+ while (!acorn.newline.test(input.charAt(parser_pos)) && parser_pos < input_length) {
1879
1964
  c += input.charAt(parser_pos);
1880
1965
  parser_pos++;
1881
1966
  }
package/js/lib/cli.js CHANGED
@@ -220,14 +220,15 @@ function usage(err) {
220
220
  '',
221
221
  'Beautifier Options:',
222
222
  ' -s, --indent-size Indentation size [4]',
223
- ' -c, --indent-char Indentation character [" "]'
223
+ ' -c, --indent-char Indentation character [" "]',
224
+ ' -t, --indent-with-tabs Indent with tabs, overrides -s and -c',
225
+ ' -e, --eol Character(s) to use as line terminators. (default newline - "\\n")',
226
+ ' -n, --end-with-newline End output with newline'
224
227
  ];
225
228
 
226
229
  switch (scriptName.split('-').shift()) {
227
230
  case "js":
228
231
  msg.push(' -l, --indent-level Initial indentation level [0]');
229
- msg.push(' -t, --indent-with-tabs Indent with tabs, overrides -s and -c');
230
- msg.push(' -e, --eol character(s) to use as line terminators. (default newline - "\\n")');
231
232
  msg.push(' -p, --preserve-newlines Preserve line-breaks (--no-preserve-newlines disables)');
232
233
  msg.push(' -m, --max-preserve-newlines Number of line-breaks to be preserved in one chunk [10]');
233
234
  msg.push(' -P, --space-in-paren Add padding spaces within paren, ie. f( a, b )');
@@ -241,7 +242,6 @@ function usage(err) {
241
242
  msg.push(' -w, --wrap-line-length Wrap lines at next opportunity after N characters [0]');
242
243
  msg.push(' -X, --e4x Pass E4X xml literals through untouched');
243
244
  msg.push(' --good-stuff Warm the cockles of Crockford\'s heart');
244
- msg.push(' -n, --end-with-newline End output with newline');
245
245
  msg.push(' -C, --comma-first Put commas at the beginning of new line instead of end');
246
246
  break;
247
247
  case "html":
@@ -254,7 +254,7 @@ function usage(err) {
254
254
  msg.push(' -p, --preserve-newlines Preserve line-breaks (--no-preserve-newlines disables)');
255
255
  msg.push(' -m, --max-preserve-newlines Number of line-breaks to be preserved in one chunk [10]');
256
256
  msg.push(' -U, --unformatted List of tags (defaults to inline) that should not be reformatted');
257
- msg.push(' -E, --extra_liners List of tags (defaults to [head,body,/html] that should have an extra newline');
257
+ msg.push(' -E, --extra_liners List of tags (defaults to [head,body,/html] that should have an extra newline');
258
258
  break;
259
259
  case "css":
260
260
  msg.push(' -L, --selector-separator-newline Add a newline between multiple selectors.')
@@ -14,7 +14,7 @@ function run_css_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_bea
14
14
  break_chained_methods: false,
15
15
  selector_separator: '\n',
16
16
  end_with_newline: false,
17
- newline_between_rules: true,
17
+ newline_between_rules: true
18
18
  };
19
19
 
20
20
  function test_css_beautifier(input)
@@ -35,6 +35,14 @@ function run_css_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_bea
35
35
  if (expected !== input) {
36
36
  sanitytest.expect(expected, expected);
37
37
  }
38
+
39
+ // Everywhere we do newlines, they should be replaced with opts.eol
40
+ opts.eol = '\r\\n';
41
+ expected = expected.replace(/[\n]/g, '\r\n');
42
+ sanitytest.expect(input, expected);
43
+ input = input.replace(/[\n]/g, '\r\n');
44
+ sanitytest.expect(input, expected);
45
+ opts.eol = '\n';
38
46
  }
39
47
 
40
48
  // test css
@@ -86,6 +94,42 @@ function run_css_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_bea
86
94
  //
87
95
  t('#cboxOverlay {\n\tbackground: url(images/overlay.png) repeat 0 0;\n\topacity: 0.9;\n\tfilter: alpha(opacity = 90);\n}', '#cboxOverlay {\n\tbackground: url(images/overlay.png) repeat 0 0;\n\topacity: 0.9;\n\tfilter: alpha(opacity=90);\n}');
88
96
 
97
+ // Selector Separator - (separator = " ", separator1 = " ")
98
+ opts.selector_separator_newline = false;
99
+ opts.selector_separator = " ";
100
+ t('#bla, #foo{color:green}', '#bla, #foo {\n\tcolor: green\n}');
101
+ t('@media print {.tab{}}', '@media print {\n\t.tab {}\n}');
102
+ t('@media print {.tab,.bat{}}', '@media print {\n\t.tab, .bat {}\n}');
103
+ t('#bla, #foo{color:black}', '#bla, #foo {\n\tcolor: black\n}');
104
+ t('a:first-child,a:first-child{color:red;div:first-child,div:hover{color:black;}}', 'a:first-child, a:first-child {\n\tcolor: red;\n\tdiv:first-child, div:hover {\n\t\tcolor: black;\n\t}\n}');
105
+
106
+ // Selector Separator - (separator = " ", separator1 = " ")
107
+ opts.selector_separator_newline = false;
108
+ opts.selector_separator = " ";
109
+ t('#bla, #foo{color:green}', '#bla, #foo {\n\tcolor: green\n}');
110
+ t('@media print {.tab{}}', '@media print {\n\t.tab {}\n}');
111
+ t('@media print {.tab,.bat{}}', '@media print {\n\t.tab, .bat {}\n}');
112
+ t('#bla, #foo{color:black}', '#bla, #foo {\n\tcolor: black\n}');
113
+ t('a:first-child,a:first-child{color:red;div:first-child,div:hover{color:black;}}', 'a:first-child, a:first-child {\n\tcolor: red;\n\tdiv:first-child, div:hover {\n\t\tcolor: black;\n\t}\n}');
114
+
115
+ // Selector Separator - (separator = "\n", separator1 = "\n\t")
116
+ opts.selector_separator_newline = true;
117
+ opts.selector_separator = " ";
118
+ t('#bla, #foo{color:green}', '#bla,\n#foo {\n\tcolor: green\n}');
119
+ t('@media print {.tab{}}', '@media print {\n\t.tab {}\n}');
120
+ t('@media print {.tab,.bat{}}', '@media print {\n\t.tab,\n\t.bat {}\n}');
121
+ t('#bla, #foo{color:black}', '#bla,\n#foo {\n\tcolor: black\n}');
122
+ t('a:first-child,a:first-child{color:red;div:first-child,div:hover{color:black;}}', 'a:first-child,\na:first-child {\n\tcolor: red;\n\tdiv:first-child,\n\tdiv:hover {\n\t\tcolor: black;\n\t}\n}');
123
+
124
+ // Selector Separator - (separator = "\n", separator1 = "\n\t")
125
+ opts.selector_separator_newline = true;
126
+ opts.selector_separator = " ";
127
+ t('#bla, #foo{color:green}', '#bla,\n#foo {\n\tcolor: green\n}');
128
+ t('@media print {.tab{}}', '@media print {\n\t.tab {}\n}');
129
+ t('@media print {.tab,.bat{}}', '@media print {\n\t.tab,\n\t.bat {}\n}');
130
+ t('#bla, #foo{color:black}', '#bla,\n#foo {\n\tcolor: black\n}');
131
+ t('a:first-child,a:first-child{color:red;div:first-child,div:hover{color:black;}}', 'a:first-child,\na:first-child {\n\tcolor: red;\n\tdiv:first-child,\n\tdiv:hover {\n\t\tcolor: black;\n\t}\n}');
132
+
89
133
  // Newline Between Rules - (separator = "\n")
90
134
  opts.newline_between_rules = true;
91
135
  t('.div {}\n.span {}', '.div {}\n\n.span {}');
@@ -98,6 +142,7 @@ function run_css_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_bea
98
142
  t('@media screen {\n\t#foo:hover {\n\t\tbackground-image: url(foo@2x.png);\n\t}\n\t@font-face {\n\t\tfont-family: "Bitstream Vera Serif Bold";\n\t\tsrc: url("http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf");\n\t}\n}\n.div{height:15px;}', '@media screen {\n\t#foo:hover {\n\t\tbackground-image: url(foo@2x.png);\n\t}\n\t@font-face {\n\t\tfont-family: "Bitstream Vera Serif Bold";\n\t\tsrc: url("http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf");\n\t}\n}\n\n.div {\n\theight: 15px;\n}');
99
143
  t('@font-face {\n\tfont-family: "Bitstream Vera Serif Bold";\n\tsrc: url("http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf");\n}\n@media screen {\n\t#foo:hover {\n\t\tbackground-image: url(foo.png);\n\t}\n\t@media screen and (min-device-pixel-ratio: 2) {\n\t\t@font-face {\n\t\t\tfont-family: "Helvetica Neue"\n\t\t}\n\t\t#foo:hover {\n\t\t\tbackground-image: url(foo@2x.png);\n\t\t}\n\t}\n}', '@font-face {\n\tfont-family: "Bitstream Vera Serif Bold";\n\tsrc: url("http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf");\n}\n\n@media screen {\n\t#foo:hover {\n\t\tbackground-image: url(foo.png);\n\t}\n\t@media screen and (min-device-pixel-ratio: 2) {\n\t\t@font-face {\n\t\t\tfont-family: "Helvetica Neue"\n\t\t}\n\t\t#foo:hover {\n\t\t\tbackground-image: url(foo@2x.png);\n\t\t}\n\t}\n}');
100
144
  t('a:first-child{color:red;div:first-child{color:black;}}\n.div{height:15px;}', 'a:first-child {\n\tcolor: red;\n\tdiv:first-child {\n\t\tcolor: black;\n\t}\n}\n\n.div {\n\theight: 15px;\n}');
145
+ t('a:first-child{color:red;div:not(.peq){color:black;}}\n.div{height:15px;}', 'a:first-child {\n\tcolor: red;\n\tdiv:not(.peq) {\n\t\tcolor: black;\n\t}\n}\n\n.div {\n\theight: 15px;\n}');
101
146
 
102
147
  // Newline Between Rules - (separator = "")
103
148
  opts.newline_between_rules = false;
@@ -111,6 +156,7 @@ function run_css_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_bea
111
156
  t('@media screen {\n\t#foo:hover {\n\t\tbackground-image: url(foo@2x.png);\n\t}\n\t@font-face {\n\t\tfont-family: "Bitstream Vera Serif Bold";\n\t\tsrc: url("http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf");\n\t}\n}\n.div{height:15px;}', '@media screen {\n\t#foo:hover {\n\t\tbackground-image: url(foo@2x.png);\n\t}\n\t@font-face {\n\t\tfont-family: "Bitstream Vera Serif Bold";\n\t\tsrc: url("http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf");\n\t}\n}\n.div {\n\theight: 15px;\n}');
112
157
  t('@font-face {\n\tfont-family: "Bitstream Vera Serif Bold";\n\tsrc: url("http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf");\n}\n@media screen {\n\t#foo:hover {\n\t\tbackground-image: url(foo.png);\n\t}\n\t@media screen and (min-device-pixel-ratio: 2) {\n\t\t@font-face {\n\t\t\tfont-family: "Helvetica Neue"\n\t\t}\n\t\t#foo:hover {\n\t\t\tbackground-image: url(foo@2x.png);\n\t\t}\n\t}\n}');
113
158
  t('a:first-child{color:red;div:first-child{color:black;}}\n.div{height:15px;}', 'a:first-child {\n\tcolor: red;\n\tdiv:first-child {\n\t\tcolor: black;\n\t}\n}\n.div {\n\theight: 15px;\n}');
159
+ t('a:first-child{color:red;div:not(.peq){color:black;}}\n.div{height:15px;}', 'a:first-child {\n\tcolor: red;\n\tdiv:not(.peq) {\n\t\tcolor: black;\n\t}\n}\n.div {\n\theight: 15px;\n}');
114
160
 
115
161
  // Functions braces
116
162
  t('.tabs(){}', '.tabs() {}');
@@ -148,6 +194,17 @@ function run_css_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_bea
148
194
  t('@page:first {}', '@page: first {}');
149
195
  t('@page: first {}');
150
196
 
197
+ // SASS/SCSS
198
+
199
+ // Basic Interpolation
200
+ t('p {\n\t$font-size: 12px;\n\t$line-height: 30px;\n\tfont: #{$font-size}/#{$line-height};\n}');
201
+ t('p.#{$name} {}');
202
+ t(
203
+ '@mixin itemPropertiesCoverItem($items, $margin) {\n' +
204
+ '\twidth: calc((100% - ((#{$items} - 1) * #{$margin}rem)) / #{$items});\n' +
205
+ '\tmargin: 1.6rem #{$margin}rem 1.6rem 0;\n' +
206
+ '}');
207
+
151
208
  //
152
209
 
153
210
  // test basic css beautifier
@@ -231,9 +288,6 @@ function run_css_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_bea
231
288
  t("a:first-child{color:red;div:first-child{color:black;}}",
232
289
  "a:first-child {\n\tcolor: red;\n\tdiv:first-child {\n\t\tcolor: black;\n\t}\n}");
233
290
 
234
- t("a:first-child,a:first-child{color:red;div:first-child,div:hover{color:black;}}",
235
- "a:first-child,\na:first-child {\n\tcolor: red;\n\tdiv:first-child, div:hover {\n\t\tcolor: black;\n\t}\n}");
236
-
237
291
  // handle SASS/LESS parent reference
238
292
  t("div{&:first-letter {text-transform: uppercase;}}",
239
293
  "div {\n\t&:first-letter {\n\t\ttext-transform: uppercase;\n\t}\n}");
@@ -256,11 +310,6 @@ function run_css_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_bea
256
310
  opts.indent_char = ' ';
257
311
  opts.selector_separator_newline = false;
258
312
 
259
- t("#bla, #foo{color:green}", "#bla, #foo {\n color: green\n}");
260
- t("@media print {.tab{}}", "@media print {\n .tab {}\n}");
261
- t("@media print {.tab,.bat{}}", "@media print {\n .tab, .bat {}\n}");
262
- t("#bla, #foo{color:black}", "#bla, #foo {\n color: black\n}");
263
-
264
313
  // pseudo-classes and pseudo-elements
265
314
  t("#foo:hover {\n background-image: url(foo@2x.png)\n}");
266
315
  t("#foo *:hover {\n color: purple\n}");
@@ -34,6 +34,14 @@ function run_html_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_be
34
34
  if (expected !== input) {
35
35
  sanitytest.expect(expected, expected);
36
36
  }
37
+
38
+ // Everywhere we do newlines, they should be replaced with opts.eol
39
+ opts.eol = '\r\n';
40
+ expected = expected.replace(/[\n]/g, '\r\n');
41
+ sanitytest.expect(input, expected);
42
+ input = input.replace(/[\n]/g, '\r\n');
43
+ sanitytest.expect(input, expected);
44
+ opts.eol = '\n';
37
45
  }
38
46
 
39
47
  // test html
@@ -48,9 +56,6 @@ function run_html_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_be
48
56
  if (opts.indent_size === 4 && input) {
49
57
  wrapped_input = '<div>\n' + input.replace(/^(.+)$/mg, ' $1') + '\n <span>inline</span>\n</div>';
50
58
  wrapped_expectation = '<div>\n' + expectation.replace(/^(.+)$/mg, ' $1') + '\n <span>inline</span>\n</div>';
51
- if (opts.end_with_newline) {
52
- wrapped_expectation += '\n';
53
- }
54
59
  test_fragment(wrapped_input, wrapped_expectation);
55
60
  }
56
61
  }
@@ -155,6 +160,7 @@ function run_html_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_be
155
160
 
156
161
  // Handlebars Indenting On - (content = "{{field}}")
157
162
  opts.indent_handlebars = true;
163
+ test_fragment('{{page-title}}');
158
164
  test_fragment('{{#if 0}}{{/if}}');
159
165
  test_fragment('{{#if 0}}{{field}}{{/if}}');
160
166
  test_fragment('{{#if 0}}\n{{/if}}');
@@ -209,6 +215,7 @@ function run_html_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_be
209
215
 
210
216
  // Handlebars Indenting On - (content = "{{! comment}}")
211
217
  opts.indent_handlebars = true;
218
+ test_fragment('{{page-title}}');
212
219
  test_fragment('{{#if 0}}{{/if}}');
213
220
  test_fragment('{{#if 0}}{{! comment}}{{/if}}');
214
221
  test_fragment('{{#if 0}}\n{{/if}}');
@@ -263,6 +270,7 @@ function run_html_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_be
263
270
 
264
271
  // Handlebars Indenting On - (content = "{pre{{field1}} {{field2}} {{field3}}post")
265
272
  opts.indent_handlebars = true;
273
+ test_fragment('{{page-title}}');
266
274
  test_fragment('{{#if 0}}{{/if}}');
267
275
  test_fragment('{{#if 0}}{pre{{field1}} {{field2}} {{field3}}post{{/if}}');
268
276
  test_fragment('{{#if 0}}\n{{/if}}');
@@ -317,6 +325,7 @@ function run_html_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_be
317
325
 
318
326
  // Handlebars Indenting On - (content = "{{! \n mult-line\ncomment \n with spacing\n}}")
319
327
  opts.indent_handlebars = true;
328
+ test_fragment('{{page-title}}');
320
329
  test_fragment('{{#if 0}}{{/if}}');
321
330
  test_fragment('{{#if 0}}{{! \n mult-line\ncomment \n with spacing\n}}{{/if}}');
322
331
  test_fragment('{{#if 0}}\n{{/if}}');
@@ -386,6 +395,28 @@ function run_html_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_be
386
395
 
387
396
 
388
397
 
398
+ // Php formatting
399
+ test_fragment('<h1 class="content-page-header"><?=$view["name"]; ?></h1>');
400
+ test_fragment(
401
+ '<?php\n' +
402
+ 'for($i = 1; $i <= 100; $i++;) {\n' +
403
+ ' #count to 100!\n' +
404
+ ' echo($i . "</br>");\n' +
405
+ '}\n' +
406
+ '?>');
407
+
408
+
409
+
410
+ // underscore.js formatting
411
+ test_fragment(
412
+ '<div class="col-sm-9">\n' +
413
+ ' <textarea id="notes" class="form-control" rows="3">\n' +
414
+ ' <%= notes %>\n' +
415
+ ' </textarea>\n' +
416
+ '</div>');
417
+
418
+
419
+
389
420
  // Indent with tabs
390
421
  opts.indent_with_tabs = true;
391
422
  test_fragment(