erp_app 3.0.10 → 3.0.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. data/lib/erp_app/version.rb +1 -1
  2. data/public/javascripts/erp_app/codemirror/README.md +1 -1
  3. data/public/javascripts/erp_app/codemirror/doc/compress.html +11 -3
  4. data/public/javascripts/erp_app/codemirror/doc/docs.css +16 -5
  5. data/public/javascripts/erp_app/codemirror/doc/internals.html +6 -3
  6. data/public/javascripts/erp_app/codemirror/doc/manual.html +103 -41
  7. data/public/javascripts/erp_app/codemirror/doc/oldrelease.html +43 -5
  8. data/public/javascripts/erp_app/codemirror/doc/reporting.html +6 -3
  9. data/public/javascripts/erp_app/codemirror/doc/upgrade_v2.2.html +7 -4
  10. data/public/javascripts/erp_app/codemirror/keymap/vim.js +10 -6
  11. data/public/javascripts/erp_app/codemirror/lib/codemirror.css +16 -12
  12. data/public/javascripts/erp_app/codemirror/lib/codemirror.js +699 -787
  13. data/public/javascripts/erp_app/codemirror/lib/util/closetag.js +35 -35
  14. data/public/javascripts/erp_app/codemirror/lib/util/dialog.js +4 -1
  15. data/public/javascripts/erp_app/codemirror/lib/util/formatting.js +147 -253
  16. data/public/javascripts/erp_app/codemirror/lib/util/javascript-hint.js +3 -3
  17. data/public/javascripts/erp_app/codemirror/lib/util/loadmode.js +1 -1
  18. data/public/javascripts/erp_app/codemirror/lib/util/multiplex.js +5 -9
  19. data/public/javascripts/erp_app/codemirror/lib/util/overlay.js +3 -1
  20. data/public/javascripts/erp_app/codemirror/lib/util/pig-hint.js +1 -1
  21. data/public/javascripts/erp_app/codemirror/lib/util/runmode-standalone.js +90 -0
  22. data/public/javascripts/erp_app/codemirror/lib/util/runmode.js +8 -4
  23. data/public/javascripts/erp_app/codemirror/lib/util/search.js +4 -4
  24. data/public/javascripts/erp_app/codemirror/lib/util/searchcursor.js +13 -11
  25. data/public/javascripts/erp_app/codemirror/lib/util/simple-hint.js +89 -68
  26. data/public/javascripts/erp_app/codemirror/lib/util/xml-hint.js +8 -8
  27. data/public/javascripts/erp_app/codemirror/mode/clike/clike.js +6 -2
  28. data/public/javascripts/erp_app/codemirror/mode/clike/index.html +1 -0
  29. data/public/javascripts/erp_app/codemirror/mode/clike/scala.html +1 -0
  30. data/public/javascripts/erp_app/codemirror/mode/clojure/clojure.js +8 -9
  31. data/public/javascripts/erp_app/codemirror/mode/clojure/index.html +1 -0
  32. data/public/javascripts/erp_app/codemirror/mode/coffeescript/coffeescript.js +3 -3
  33. data/public/javascripts/erp_app/codemirror/mode/coffeescript/index.html +1 -0
  34. data/public/javascripts/erp_app/codemirror/mode/commonlisp/commonlisp.js +101 -0
  35. data/public/javascripts/erp_app/codemirror/mode/commonlisp/index.html +165 -0
  36. data/public/javascripts/erp_app/codemirror/mode/css/css.js +339 -15
  37. data/public/javascripts/erp_app/codemirror/mode/css/index.html +3 -0
  38. data/public/javascripts/erp_app/codemirror/mode/css/test.js +501 -0
  39. data/public/javascripts/erp_app/codemirror/mode/diff/index.html +1 -0
  40. data/public/javascripts/erp_app/codemirror/mode/ecl/ecl.js +1 -1
  41. data/public/javascripts/erp_app/codemirror/mode/erlang/index.html +1 -0
  42. data/public/javascripts/erp_app/codemirror/mode/gfm/gfm.js +10 -4
  43. data/public/javascripts/erp_app/codemirror/mode/gfm/index.html +1 -0
  44. data/public/javascripts/erp_app/codemirror/mode/go/go.js +2 -2
  45. data/public/javascripts/erp_app/codemirror/mode/go/index.html +1 -0
  46. data/public/javascripts/erp_app/codemirror/mode/groovy/groovy.js +1 -1
  47. data/public/javascripts/erp_app/codemirror/mode/groovy/index.html +1 -0
  48. data/public/javascripts/erp_app/codemirror/mode/haskell/haskell.js +2 -2
  49. data/public/javascripts/erp_app/codemirror/mode/haskell/index.html +1 -0
  50. data/public/javascripts/erp_app/codemirror/mode/haxe/haxe.js +4 -7
  51. data/public/javascripts/erp_app/codemirror/mode/haxe/index.html +1 -0
  52. data/public/javascripts/erp_app/codemirror/mode/htmlembedded/htmlembedded.js +8 -4
  53. data/public/javascripts/erp_app/codemirror/mode/htmlembedded/index.html +1 -0
  54. data/public/javascripts/erp_app/codemirror/mode/htmlmixed/htmlmixed.js +12 -13
  55. data/public/javascripts/erp_app/codemirror/mode/htmlmixed/index.html +1 -0
  56. data/public/javascripts/erp_app/codemirror/mode/javascript/index.html +1 -0
  57. data/public/javascripts/erp_app/codemirror/mode/javascript/javascript.js +3 -3
  58. data/public/javascripts/erp_app/codemirror/mode/jinja2/index.html +1 -0
  59. data/public/javascripts/erp_app/codemirror/mode/less/index.html +124 -2
  60. data/public/javascripts/erp_app/codemirror/mode/less/less.js +94 -60
  61. data/public/javascripts/erp_app/codemirror/mode/lua/index.html +1 -0
  62. data/public/javascripts/erp_app/codemirror/mode/markdown/index.html +3 -0
  63. data/public/javascripts/erp_app/codemirror/mode/markdown/markdown.js +134 -20
  64. data/public/javascripts/erp_app/codemirror/mode/markdown/test.js +1084 -0
  65. data/public/javascripts/erp_app/codemirror/mode/mysql/index.html +1 -0
  66. data/public/javascripts/erp_app/codemirror/mode/ntriples/index.html +1 -0
  67. data/public/javascripts/erp_app/codemirror/mode/ntriples/ntriples.js +4 -4
  68. data/public/javascripts/erp_app/codemirror/mode/ocaml/ocaml.js +1 -1
  69. data/public/javascripts/erp_app/codemirror/mode/pascal/index.html +1 -0
  70. data/public/javascripts/erp_app/codemirror/mode/pascal/pascal.js +1 -1
  71. data/public/javascripts/erp_app/codemirror/mode/perl/index.html +1 -0
  72. data/public/javascripts/erp_app/codemirror/mode/perl/perl.js +71 -71
  73. data/public/javascripts/erp_app/codemirror/mode/php/index.html +1 -0
  74. data/public/javascripts/erp_app/codemirror/mode/php/php.js +7 -9
  75. data/public/javascripts/erp_app/codemirror/mode/pig/index.html +1 -0
  76. data/public/javascripts/erp_app/codemirror/mode/pig/pig.js +3 -3
  77. data/public/javascripts/erp_app/codemirror/mode/plsql/index.html +1 -0
  78. data/public/javascripts/erp_app/codemirror/mode/properties/index.html +1 -0
  79. data/public/javascripts/erp_app/codemirror/mode/python/index.html +1 -0
  80. data/public/javascripts/erp_app/codemirror/mode/python/python.js +1 -1
  81. data/public/javascripts/erp_app/codemirror/mode/r/index.html +1 -0
  82. data/public/javascripts/erp_app/codemirror/mode/rpm/changes/index.html +1 -0
  83. data/public/javascripts/erp_app/codemirror/mode/rpm/spec/index.html +1 -0
  84. data/public/javascripts/erp_app/codemirror/mode/rst/index.html +1 -0
  85. data/public/javascripts/erp_app/codemirror/mode/ruby/index.html +1 -0
  86. data/public/javascripts/erp_app/codemirror/mode/rust/index.html +1 -0
  87. data/public/javascripts/erp_app/codemirror/mode/scheme/index.html +1 -0
  88. data/public/javascripts/erp_app/codemirror/mode/scheme/scheme.js +1 -1
  89. data/public/javascripts/erp_app/codemirror/mode/shell/shell.js +2 -2
  90. data/public/javascripts/erp_app/codemirror/mode/sieve/LICENSE +23 -0
  91. data/public/javascripts/erp_app/codemirror/mode/sieve/index.html +81 -0
  92. data/public/javascripts/erp_app/codemirror/mode/sieve/sieve.js +156 -0
  93. data/public/javascripts/erp_app/codemirror/mode/smalltalk/index.html +1 -0
  94. data/public/javascripts/erp_app/codemirror/mode/smalltalk/smalltalk.js +2 -2
  95. data/public/javascripts/erp_app/codemirror/mode/smarty/index.html +1 -0
  96. data/public/javascripts/erp_app/codemirror/mode/smarty/smarty.js +2 -2
  97. data/public/javascripts/erp_app/codemirror/mode/sparql/index.html +1 -0
  98. data/public/javascripts/erp_app/codemirror/mode/stex/index.html +3 -0
  99. data/public/javascripts/erp_app/codemirror/mode/stex/stex.js +1 -1
  100. data/public/javascripts/erp_app/codemirror/mode/stex/test.js +343 -0
  101. data/public/javascripts/erp_app/codemirror/mode/tiddlywiki/index.html +1 -0
  102. data/public/javascripts/erp_app/codemirror/mode/tiki/index.html +1 -0
  103. data/public/javascripts/erp_app/codemirror/mode/tiki/tiki.js +4 -11
  104. data/public/javascripts/erp_app/codemirror/mode/vb/index.html +1 -0
  105. data/public/javascripts/erp_app/codemirror/mode/vb/vb.js +2 -2
  106. data/public/javascripts/erp_app/codemirror/mode/vbscript/index.html +1 -0
  107. data/public/javascripts/erp_app/codemirror/mode/velocity/index.html +1 -0
  108. data/public/javascripts/erp_app/codemirror/mode/velocity/velocity.js +1 -1
  109. data/public/javascripts/erp_app/codemirror/mode/verilog/index.html +1 -0
  110. data/public/javascripts/erp_app/codemirror/mode/verilog/verilog.js +1 -1
  111. data/public/javascripts/erp_app/codemirror/mode/xml/index.html +2 -1
  112. data/public/javascripts/erp_app/codemirror/mode/xml/xml.js +2 -10
  113. data/public/javascripts/erp_app/codemirror/mode/xquery/index.html +3 -2
  114. data/public/javascripts/erp_app/codemirror/mode/xquery/xquery.js +7 -4
  115. data/public/javascripts/erp_app/codemirror/mode/yaml/index.html +1 -0
  116. data/public/javascripts/erp_app/codemirror/package.json +15 -23
  117. data/public/javascripts/erp_app/codemirror/test/driver.js +109 -22
  118. data/public/javascripts/erp_app/codemirror/test/index.html +129 -16
  119. data/public/javascripts/erp_app/codemirror/test/lint/lint.js +120 -0
  120. data/public/javascripts/erp_app/codemirror/test/lint/parse-js.js +1372 -0
  121. data/public/javascripts/erp_app/codemirror/test/mode_test.css +0 -12
  122. data/public/javascripts/erp_app/codemirror/test/mode_test.js +66 -27
  123. data/public/javascripts/erp_app/codemirror/test/phantom_driver.js +30 -0
  124. data/public/javascripts/erp_app/codemirror/test/run.js +32 -0
  125. data/public/javascripts/erp_app/codemirror/test/test.js +213 -8
  126. data/public/javascripts/erp_app/shared/dynamic_editable_grid.js +33 -27
  127. data/public/javascripts/erp_app/shared/dynamic_editable_grid_loader_panel.js +2 -1
  128. metadata +15 -3
  129. data/public/javascripts/erp_app/codemirror/mode/stex/test.html +0 -263
@@ -1,42 +1,129 @@
1
- var tests = [], runOnly = null;
1
+ var tests = [], debug = null, debugUsed = new Array(), allNames = [];
2
2
 
3
3
  function Failure(why) {this.message = why;}
4
4
 
5
- function test(name, run) {tests.push({name: name, func: run}); return name;}
6
- function testCM(name, run, opts) {
7
- return test(name, function() {
5
+ function indexOf(collection, elt) {
6
+ if (collection.indexOf) return collection.indexOf(elt);
7
+ for (var i = 0, e = collection.length; i < e; ++i)
8
+ if (collection[i] == elt) return i;
9
+ return -1;
10
+ }
11
+
12
+ function test(name, run, expectedFail) {
13
+ // Force unique names
14
+ var originalName = name;
15
+ var i = 2; // Second function would be NAME_2
16
+ while (indexOf(allNames, name) !== -1){
17
+ name = originalName + "_" + i;
18
+ i++;
19
+ }
20
+ allNames.push(name);
21
+ // Add test
22
+ tests.push({name: name, func: run, expectedFail: expectedFail});
23
+ return name;
24
+ }
25
+ function testCM(name, run, opts, expectedFail) {
26
+ return test("core_" + name, function() {
8
27
  var place = document.getElementById("testground"), cm = CodeMirror(place, opts);
9
- try {run(cm);}
10
- finally {place.removeChild(cm.getWrapperElement());}
11
- });
28
+ var successful = false;
29
+ try {
30
+ run(cm);
31
+ successful = true;
32
+ } finally {
33
+ if ((debug && !successful) || verbose) {
34
+ place.style.visibility = "";
35
+ } else {
36
+ place.removeChild(cm.getWrapperElement());
37
+ }
38
+ }
39
+ }, expectedFail);
12
40
  }
13
41
 
14
42
  function runTests(callback) {
43
+ if (debug) {
44
+ if (indexOf(debug, "verbose") === 0) {
45
+ verbose = true;
46
+ debug.splice(0, 1);
47
+ }
48
+ if (debug.length < 1) {
49
+ debug = null;
50
+ } else {
51
+ if (totalTests > debug.length) {
52
+ totalTests = debug.length;
53
+ }
54
+ }
55
+ }
56
+ var totalTime = 0;
15
57
  function step(i) {
16
- if (i == tests.length) return callback("done");
17
- var test = tests[i];
18
- if (runOnly != null && runOnly != test.name) return step(i + 1);
19
- try {test.func(); callback("ok", test.name);}
20
- catch(e) {
21
- if (e instanceof Failure)
22
- callback("fail", test.name, e.message);
23
- else
24
- callback("error", test.name, e.toString());
58
+ if (i === tests.length){
59
+ running = false;
60
+ return callback("done");
61
+ }
62
+ var test = tests[i], expFail = test.expectedFail, startTime = +new Date;
63
+ if (debug !== null) {
64
+ var debugIndex = indexOf(debug, test.name);
65
+ if (debugIndex !== -1) {
66
+ // Remove from array for reporting incorrect tests later
67
+ debug.splice(debugIndex, 1);
68
+ } else {
69
+ var wildcardName = test.name.split("_").shift() + "_*";
70
+ debugIndex = indexOf(debug, wildcardName);
71
+ if (debugIndex !== -1) {
72
+ // Remove from array for reporting incorrect tests later
73
+ debug.splice(debugIndex, 1);
74
+ debugUsed.push(wildcardName);
75
+ } else {
76
+ debugIndex = indexOf(debugUsed, wildcardName);
77
+ if (debugIndex !== -1) {
78
+ totalTests++;
79
+ } else {
80
+ return step(i + 1);
81
+ }
82
+ }
83
+ }
84
+ }
85
+ try {
86
+ var message = test.func();
87
+ if (expFail) callback("fail", test.name, message);
88
+ else callback("ok", test.name, message);
89
+ } catch(e) {
90
+ if (expFail) callback("expected", test.name);
91
+ else if (e instanceof Failure) callback("fail", test.name, e.message);
92
+ else {
93
+ var pos = /\bat .*?([^\/:]+):(\d+):/.exec(e.stack);
94
+ callback("error", test.name, e.toString() + (pos ? " (" + pos[1] + ":" + pos[2] + ")" : ""));
95
+ }
96
+ }
97
+ if (!quit) { // Run next test
98
+ var delay = 0;
99
+ totalTime += (+new Date) - startTime;
100
+ if (totalTime > 500){
101
+ totalTime = 0;
102
+ delay = 50;
103
+ }
104
+ setTimeout(function(){step(i + 1);}, delay);
105
+ } else { // Quit tests
106
+ running = false;
107
+ return null;
25
108
  }
26
- setTimeout(function(){step(i + 1);}, 20);
27
109
  }
28
110
  step(0);
29
111
  }
30
112
 
113
+ function label(str, msg) {
114
+ if (msg) return str + " (" + msg + ")";
115
+ return str;
116
+ }
31
117
  function eq(a, b, msg) {
32
- if (a != b) throw new Failure(a + " != " + b + (msg ? " (" + msg + ")" : ""));
118
+ if (a != b) throw new Failure(label(a + " != " + b, msg));
33
119
  }
34
120
  function eqPos(a, b, msg) {
121
+ function str(p) { return "{line:" + p.line + ",ch:" + p.ch + "}"; }
35
122
  if (a == b) return;
36
- if (a == null || b == null) throw new Failure("comparing point to null");
37
- eq(a.line, b.line, msg);
38
- eq(a.ch, b.ch, msg);
123
+ if (a == null) throw new Failure(label("comparing null to " + str(b)));
124
+ if (b == null) throw new Failure(label("comparing " + str(a) + " to null"));
125
+ if (a.line != b.line || a.ch != b.ch) throw new Failure(label(str(a) + " != " + str(b), msg));
39
126
  }
40
127
  function is(a, msg) {
41
- if (!a) throw new Failure("assertion failed" + (msg ? " (" + msg + ")" : ""));
128
+ if (!a) throw new Failure(label("assertion failed", msg));
42
129
  }
@@ -1,15 +1,27 @@
1
1
  <!doctype html>
2
2
  <html>
3
3
  <head>
4
+ <meta charset="utf-8">
4
5
  <title>CodeMirror: Test Suite</title>
5
6
  <link rel="stylesheet" href="../lib/codemirror.css">
7
+ <link rel="stylesheet" href="../doc/docs.css">
8
+ <link rel="stylesheet" href="mode_test.css">
6
9
  <script src="../lib/codemirror.js"></script>
7
10
  <script src="../mode/javascript/javascript.js"></script>
11
+ <script src="../mode/xml/xml.js"></script>
8
12
 
9
13
  <style type="text/css">
10
14
  .ok {color: #090;}
11
15
  .fail {color: #e00;}
12
16
  .error {color: #c90;}
17
+ .done {font-weight: bold;}
18
+ #progress {
19
+ background: #45d;
20
+ color: white;
21
+ text-shadow: 0 0 1px #45d, 0 0 2px #45d, 0 0 3px #45d;
22
+ font-weight: bold;
23
+ white-space: pre;
24
+ }
13
25
  </style>
14
26
  </head>
15
27
  <body>
@@ -18,36 +30,137 @@
18
30
  <p>A limited set of programmatic sanity tests for CodeMirror.</p>
19
31
 
20
32
  <div style="border: 1px solid black; padding: 1px; max-width: 700px;">
21
- <div style="background: #45d; white-space: pre; width: 0px; font-weight: bold; color: white; padding: 3px;" id=progress></div>
33
+ <div style="width: 0px;" id=progress><div style="padding: 3px;">Ran <span id="progress_ran">0</span><span id="progress_total"> of 0</span> tests</div></div>
22
34
  </div>
23
- <pre style="padding-left: 5px" id=output></pre>
35
+ <p id=status>Please enable JavaScript...</p>
36
+ <div id=output></div>
24
37
 
25
- <div style="visibility: hidden" id=testground>
26
- <form><textarea id="code" name="code"></textarea><input type=submit value=ok name=submit></form>
27
- </div>
38
+ <div style="visibility: hidden" id=testground></div>
28
39
 
29
40
  <script src="driver.js"></script>
30
41
  <script src="test.js"></script>
42
+ <script src="mode_test.js"></script>
43
+ <script src="../mode/css/css.js"></script>
44
+ <script src="../mode/css/test.js"></script>
45
+ <script src="../mode/markdown/markdown.js"></script>
46
+ <script src="../mode/markdown/test.js"></script>
47
+ <script src="../mode/stex/stex.js"></script>
48
+ <script src="../mode/stex/test.js"></script>
31
49
  <script>
32
50
  window.onload = function() {
33
- runTests(displayTest);
51
+ runHarness();
34
52
  };
53
+ CodeMirror.connect(window, 'hashchange', function(){
54
+ runHarness();
55
+ });
35
56
 
36
- var output = document.getElementById("output"), progress = document.getElementById("progress");
37
- var count = 0, failed = 0, bad = "";
38
- function displayTest(type, name, msg) {
57
+ function esc(str) {
58
+ return str.replace(/[<&]/, function(ch) { return ch == "<" ? "&lt;" : "&amp;"; });
59
+ }
60
+
61
+ var output = document.getElementById("output"),
62
+ progress = document.getElementById("progress"),
63
+ progressRan = document.getElementById("progress_ran").childNodes[0],
64
+ progressTotal = document.getElementById("progress_total").childNodes[0];
65
+ var count = 0,
66
+ failed = 0,
67
+ bad = "",
68
+ running = false, // Flag that states tests are running
69
+ quit = false, // Flag to quit tests ASAP
70
+ verbose = false; // Adds message for *every* test to output
71
+
72
+ function runHarness(){
73
+ if (running) {
74
+ quit = true;
75
+ setStatus("Restarting tests...", '', true);
76
+ setTimeout(function(){runHarness();}, 500);
77
+ return;
78
+ }
79
+ if (window.location.hash.substr(1)){
80
+ debug = window.location.hash.substr(1).split(",");
81
+ } else {
82
+ debug = null;
83
+ }
84
+ quit = false;
85
+ running = true;
86
+ setStatus("Loading tests...");
87
+ count = 0;
88
+ failed = 0;
89
+ bad = "";
90
+ verbose = false;
91
+ debugUsed = Array();
92
+ totalTests = tests.length;
93
+ progressTotal.nodeValue = " of " + totalTests;
94
+ progressRan.nodeValue = count;
95
+ output.innerHTML = '';
96
+ document.getElementById("testground").innerHTML = "<form>" +
97
+ "<textarea id=\"code\" name=\"code\"></textarea>" +
98
+ "<input type=submit value=ok name=submit>" +
99
+ "</form>";
100
+ runTests(displayTest);
101
+ }
102
+
103
+ function setStatus(message, className, force){
104
+ if (quit && !force) return;
105
+ if (!message) throw("must provide message");
106
+ var status = document.getElementById("status").childNodes[0];
107
+ status.nodeValue = message;
108
+ status.parentNode.className = className;
109
+ }
110
+ function addOutput(name, className, code){
111
+ var newOutput = document.createElement("dl");
112
+ var newTitle = document.createElement("dt");
113
+ newTitle.className = className;
114
+ newTitle.appendChild(document.createTextNode(name));
115
+ newOutput.appendChild(newTitle);
116
+ var newMessage = document.createElement("dd");
117
+ newMessage.innerHTML = code;
118
+ newOutput.appendChild(newTitle);
119
+ newOutput.appendChild(newMessage);
120
+ output.appendChild(newOutput);
121
+ }
122
+ function displayTest(type, name, customMessage) {
123
+ var message = "???";
39
124
  if (type != "done") ++count;
40
- progress.style.width = (count * (progress.parentNode.clientWidth - 8) / tests.length) + "px";
41
- progress.innerHTML = "Ran " + count + (count < tests.length ? " of " + tests.length : "") + " tests";
125
+ progress.style.width = (count * (progress.parentNode.clientWidth - 2) / totalTests) + "px";
126
+ progressTotal.nodeValue = " of " + totalTests +
127
+ (debugUsed.length && type != "done" ? "+" : "");
128
+ progressRan.nodeValue = count;
42
129
  if (type == "ok") {
43
- output.innerHTML = bad + "<span class=ok>Test '" + CodeMirror.htmlEscape(name) + "' succeeded</span>";
130
+ message = "Test '" + name + "' succeeded";
131
+ if (!verbose) customMessage = false;
132
+ } else if (type == "expected") {
133
+ message = "Test '" + name + "' failed as expected";
134
+ if (!verbose) customMessage = false;
44
135
  } else if (type == "error" || type == "fail") {
45
136
  ++failed;
46
- bad += CodeMirror.htmlEscape(name) + ": <span class=" + type + ">" + CodeMirror.htmlEscape(msg) + "</span>\n";
47
- output.innerHTML = bad;
137
+ message = "Test '" + name + "' failed";
48
138
  } else if (type == "done") {
49
- output.innerHTML = bad + (failed ? "<span class=fail>" + failed + " failure" + (failed > 1 ? "s" : "") + "</span>"
50
- : "<span class=ok>All passed</span>");
139
+ if (failed) {
140
+ type += " fail";
141
+ message = failed + " failure" + (failed > 1 ? "s" : "");
142
+ } else if (count < totalTests) {
143
+ failed = totalTests - count;
144
+ type += " fail";
145
+ message = failed + " failure" + (failed > 1 ? "s" : "");
146
+ } else {
147
+ type += " ok";
148
+ message = "All passed";
149
+ }
150
+ if (debug && debug.length) {
151
+ var bogusTests = totalTests - count;
152
+ message += " — " + bogusTests + " nonexistent test" +
153
+ (bogusTests > 1 ? "s" : "") + " requested by location.hash: " +
154
+ "`" + debug.join("`, `") + "`";
155
+ } else {
156
+ progressTotal.nodeValue = '';
157
+ }
158
+ customMessage = true; // Hack to avoid adding to output
159
+ }
160
+ if (verbose && !customMessage) customMessage = message;
161
+ setStatus(message, type);
162
+ if (customMessage.length > 0) {
163
+ addOutput(name, type, customMessage);
51
164
  }
52
165
  }
53
166
  </script>
@@ -0,0 +1,120 @@
1
+ /*
2
+ Simple linter, based on UglifyJS's [1] parse-js module
3
+
4
+ All of the existing linters either cramp my style or have huge
5
+ dependencies (Closure). So here's a very simple, non-invasive one
6
+ that only spots
7
+
8
+ - missing semicolons and trailing commas
9
+ - variables or properties that are reserved words
10
+ - assigning to a variable you didn't declare
11
+
12
+ [1]: https://github.com/mishoo/UglifyJS/
13
+ */
14
+
15
+ var fs = require("fs"), parse_js = require("./parse-js").parse;
16
+
17
+ var reserved = {};
18
+ "break case catch continue debugger default delete do else false finally for function if in\
19
+ instanceof new null return switch throw true try typeof var void while with abstract enum\
20
+ int short boolean export interface static byte extends long super char final native\
21
+ synchonized class float package throws const goto private transient implements protected\
22
+ volatile double import public const".split(" ").forEach(function(word) { reserved[word] = true; });
23
+
24
+ function checkVariable(scope, name, pos) {
25
+ while (scope) {
26
+ if (scope.cur.hasOwnProperty(name)) return;
27
+ scope = scope.prev;
28
+ }
29
+ fail("Accidental global: " + name, pos);
30
+ }
31
+ function checkProperty(name, pos) {
32
+ if (reserved.hasOwnProperty(name)) {
33
+ fail("Using a keyword or reserved word as a property: " + name, pos);
34
+ }
35
+ }
36
+
37
+ function walk(ast, scope) {
38
+ var tp = ast[0];
39
+ if (typeof tp != "string") tp = tp.name;
40
+ function sub(ast) { if (ast) walk(ast, scope); }
41
+ function subn(array) { if (array) array.forEach(sub); }
42
+ if (tp == "block" || tp == "splice" || tp == "toplevel" || tp == "array") {
43
+ subn(ast[1]);
44
+ } else if (tp == "var" || tp == "const") {
45
+ ast[1].forEach(function(def) { scope.cur[def[0]] = true; if (def[1]) sub(def[1]); });
46
+ } else if (tp == "try") {
47
+ subn(ast[1]);
48
+ if (ast[2]) { scope.cur[ast[2][0]] = true; subn(ast[2][1]); }
49
+ subn(ast[3]);
50
+ } else if (tp == "throw" || tp == "return" || tp == "dot" || tp == "stat") {
51
+ sub(ast[1]);
52
+ } else if (tp == "dot") {
53
+ sub(ast[1]);
54
+ checkProperty(ast[2], ast[0]);
55
+ } else if (tp == "new" || tp == "call") {
56
+ sub(ast[1]); subn(ast[2]);
57
+ } else if (tp == "switch") {
58
+ sub(ast[1]);
59
+ ast[2].forEach(function(part) { sub(part[0]); subn(part[1]); });
60
+ } else if (tp == "conditional" || tp == "if" || tp == "for" || tp == "for-in") {
61
+ sub(ast[1]); sub(ast[2]); sub(ast[3]); sub(ast[4]);
62
+ } else if (tp == "assign") {
63
+ if (ast[2][0].name == "name") checkVariable(scope, ast[2][1], ast[2][0]);
64
+ sub(ast[2]); sub(ast[3]);
65
+ } else if (tp == "function" || tp == "defun") {
66
+ if (tp == "defun") scope.cur[ast[1]] = true;
67
+ var nscope = {prev: scope, cur: {}};
68
+ ast[2].forEach(function(arg) { nscope.cur[arg] = true; });
69
+ ast[3].forEach(function(ast) { walk(ast, nscope); });
70
+ } else if (tp == "while" || tp == "do" || tp == "sub" || tp == "with") {
71
+ sub(ast[1]); sub(ast[2]);
72
+ } else if (tp == "binary" || tp == "unary-prefix" || tp == "unary-postfix" || tp == "label") {
73
+ if (/\+\+|--/.test(ast[1]) && ast[2][0].name == "name") checkVariable(scope, ast[2][1], ast[2][0]);
74
+ sub(ast[2]); sub(ast[3]);
75
+ } else if (tp == "object") {
76
+ ast[1].forEach(function(prop) {
77
+ if (prop.type != "string") checkProperty(prop[0], ast[0]);
78
+ sub(prop[1]); sub(prop[2]);
79
+ });
80
+ } else if (tp == "seq") {
81
+ subn(ast.slice(1));
82
+ } else if (tp == "name") {
83
+ if (reserved.hasOwnProperty(ast[1]) && !/^(?:null|true|false)$/.test(ast[1]))
84
+ fail("Using reserved word as variable name: " + ast[1], ast[0]);
85
+ }
86
+ }
87
+
88
+ var failed = false, curFile;
89
+ function fail(msg, pos) {
90
+ if (typeof pos == "object") pos = pos.start.line + 1;
91
+ console.log(curFile + ": " + msg + (typeof pos == "number" ? " (" + pos + ")" : ""));
92
+ failed = true;
93
+ }
94
+
95
+ function checkFile(fileName) {
96
+ curFile = fileName.match(/[^\/+]*\.js$/)[0];
97
+ var file = fs.readFileSync(fileName, "utf8");
98
+ var badChar = file.match(/[\x00-\x08\x0b\x0c\x0e-\x19\uFEFF]/);
99
+ if (badChar) fail("Undesirable character " + badChar[0].charCodeAt(0) + " at position " + badChar.index);
100
+ if (/^#!/.test(file)) file = file.slice(file.indexOf("\n") + 1);
101
+ try {
102
+ var parsed = parse_js(file, true, true);
103
+ } catch(e) {
104
+ fail(e.message, e.line);
105
+ return;
106
+ }
107
+ walk(parsed, {prev: null, cur: {}});
108
+ }
109
+
110
+ function checkDir(dir) {
111
+ fs.readdirSync(dir).forEach(function(file) {
112
+ var fname = dir + "/" + file;
113
+ if (/\.js$/.test(file)) checkFile(fname);
114
+ else if (fs.lstatSync(fname).isDirectory()) checkDir(fname);
115
+ });
116
+ }
117
+
118
+ exports.checkDir = checkDir;
119
+ exports.checkFile = checkFile;
120
+ exports.success = function() { return !failed; };