3 var bogus
= [ "Dangerous comment" ];
5 var warnings
= [ [ "Expected '{'",
6 "Statement body should be inside '{ }' braces." ] ];
8 var errors
= [ "Missing semicolon", "Extra comma", "Missing property name",
9 "Unmatched ", " and instead saw", " is not defined",
10 "Unclosed string", "Stopping, unable to continue" ];
12 function validator(options
, text
) {
13 JSHINT(text
, options
);
14 var errors
= JSHINT
.data().errors
, result
= [];
15 if (errors
) parseErrors(errors
, result
);
19 CodeMirror
.javascriptValidatorWithOptions = function(options
) {
20 return function(text
) { return validator(options
, text
); };
23 CodeMirror
.javascriptValidator
= CodeMirror
.javascriptValidatorWithOptions(null);
25 function cleanup(error
) {
26 // All problems are warnings by default
27 fixWith(error
, warnings
, "warning", true);
28 fixWith(error
, errors
, "error");
30 return isBogus(error
) ? null : error
;
33 function fixWith(error
, fixes
, severity
, force
) {
34 var description
, fix
, find
, replace
, found
;
36 description
= error
.description
;
38 for ( var i
= 0; i
< fixes
.length
; i
++) {
40 find
= (typeof fix
=== "string" ? fix
: fix
[0]);
41 replace
= (typeof fix
=== "string" ? null : fix
[1]);
42 found
= description
.indexOf(find
) !== -1;
45 error
.severity
= severity
;
47 if (found
&& replace
) {
48 error
.description
= replace
;
53 function isBogus(error
) {
54 var description
= error
.description
;
55 for ( var i
= 0; i
< bogus
.length
; i
++) {
56 if (description
.indexOf(bogus
[i
]) !== -1) {
63 function parseErrors(errors
, output
) {
64 for ( var i
= 0; i
< errors
.length
; i
++) {
65 var error
= errors
[i
];
67 var linetabpositions
, index
;
69 linetabpositions
= [];
71 // This next block is to fix a problem in jshint. Jshint
73 // all tabs with spaces then performs some checks. The error
74 // positions (character/space) are then reported incorrectly,
75 // not taking the replacement step into account. Here we look
76 // at the evidence line and try to adjust the character position
77 // to the correct value.
79 // Tab positions are computed once per line and cached
80 var tabpositions
= linetabpositions
[error
.line
];
82 var evidence
= error
.evidence
;
84 // ugggh phantomjs does not like this
85 // forEachChar(evidence, function(item, index) {
86 Array
.prototype.forEach
.call(evidence
, function(item
,
89 // First col is 1 (not 0) to match error
91 tabpositions
.push(index
+ 1);
94 linetabpositions
[error
.line
] = tabpositions
;
96 if (tabpositions
.length
> 0) {
97 var pos
= error
.character
;
98 tabpositions
.forEach(function(tabposition
) {
99 if (pos
> tabposition
) pos
-= 1;
101 error
.character
= pos
;
105 var start
= error
.character
- 1, end
= start
+ 1;
106 if (error
.evidence
) {
107 index
= error
.evidence
.substring(start
).search(/.\b/);
113 // Convert to format expected by validation service
114 error
.description
= error
.reason
;// + "(jshint)";
115 error
.start
= error
.character
;
117 error
= cleanup(error
);
120 output
.push({message
: error
.description
,
121 severity
: error
.severity
,
122 from: CodeMirror
.Pos(error
.line
- 1, start
),
123 to
: CodeMirror
.Pos(error
.line
- 1, end
)});