erp_app 3.0.10 → 3.0.12

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.
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; };