|
1 | | -/* globals define, CodeMirror, JSHINT */ |
| 1 | +/* globals define, CodeMirror */ |
| 2 | + |
| 3 | +/* jshint esversion: 11 */ |
2 | 4 |
|
3 | 5 | // CodeMirror, copyright (c) by Marijn Haverbeke and others |
4 | 6 | // Distributed under an MIT license: https://codemirror.net/5/LICENSE |
|
18 | 20 | } |
19 | 21 | } )( function ( CodeMirror ) { |
20 | 22 | 'use strict'; |
21 | | - // declare global: JSHINT |
22 | 23 |
|
23 | 24 | async function validator( text, options ) { |
24 | | - // TODO: Await import espree. |
| 25 | + const espree = await import( 'espree' ); |
25 | 26 |
|
26 | | - if ( ! window.JSHINT ) { |
27 | | - if ( window.console ) { |
28 | | - window.console.error( |
29 | | - 'Error: window.JSHINT not defined, CodeMirror JavaScript linting cannot run.' |
30 | | - ); |
31 | | - } |
32 | | - return []; |
33 | | - } |
34 | | - if ( ! options.indent ) { |
35 | | - // JSHint error.character actually is a column index, this fixes underlining on lines using tabs for indentation |
36 | | - options.indent = 1; // JSHint default value is 4 |
37 | | - } |
38 | | - JSHINT( text, options, options.globals ); |
| 27 | + const errors = []; |
| 28 | + try { |
| 29 | + espree.parse( text, { |
| 30 | + ...getEspreeOptions( options ), |
| 31 | + loc: true, |
| 32 | + } ); |
| 33 | + } catch ( error ) { |
| 34 | + // Note: A lineNumber of 0 causes CodeMirror to log out a warning in the console. This is as desired for a generic Espree error. |
39 | 35 |
|
40 | | - var errors = JSHINT.data().errors, |
41 | | - result = []; |
42 | | - if ( errors ) { |
43 | | - parseErrors( errors, result ); |
| 36 | + const line = error.lineNumber - 1; |
| 37 | + const start = error.column - 1; |
| 38 | + const end = error.column; |
| 39 | + |
| 40 | + errors.push( { |
| 41 | + message: error.message, |
| 42 | + severity: 'error', |
| 43 | + from: CodeMirror.Pos( line, start ), |
| 44 | + to: CodeMirror.Pos( line, end ), |
| 45 | + } ); |
44 | 46 | } |
45 | | - return result; |
| 47 | + |
| 48 | + return errors; |
46 | 49 | } |
47 | 50 |
|
48 | 51 | CodeMirror.registerHelper( 'lint', 'javascript', validator ); |
49 | 52 |
|
50 | | - function parseErrors( errors, output ) { |
51 | | - for ( var i = 0; i < errors.length; i++ ) { |
52 | | - var error = errors[ i ]; |
53 | | - if ( error ) { |
54 | | - if ( error.line <= 0 ) { |
55 | | - if ( window.console ) { |
56 | | - window.console.warn( |
57 | | - 'Cannot display JSHint error (invalid line ' + |
58 | | - error.line + |
59 | | - ')', |
60 | | - error |
61 | | - ); |
62 | | - } |
63 | | - continue; |
64 | | - } |
| 53 | + /** |
| 54 | + * JSHint options supported by Espree. |
| 55 | + * |
| 56 | + * @see https://jshint.com/docs/options/ |
| 57 | + * @see https://www.npmjs.com/package/espree#options |
| 58 | + * |
| 59 | + * @typedef {Object} SupportedJSHintOptions |
| 60 | + * @property {number} [esversion] - "This option is used to specify the ECMAScript version to which the code must adhere." |
| 61 | + * @property {boolean} [es5] - "This option enables syntax first defined in the ECMAScript 5.1 specification. This includes allowing reserved keywords as object properties." |
| 62 | + * @property {boolean} [es3] - "This option tells JSHint that your code needs to adhere to ECMAScript 3 specification. Use this option if you need your program to be executable in older browsers—such as Internet Explorer 6/7/8/9—and other legacy JavaScript environments." |
| 63 | + * @property {boolean} [module] - "This option informs JSHint that the input code describes an ECMAScript 6 module. All module code is interpreted as strict mode code." |
| 64 | + * @property {'implied'} [strict] - "This option requires the code to run in ECMAScript 5's strict mode." |
| 65 | + */ |
65 | 66 |
|
66 | | - let start = error.character - 1, |
67 | | - end = start + 1; |
68 | | - if ( error.evidence ) { |
69 | | - const index = error.evidence |
70 | | - .substring( start ) |
71 | | - .search( /.\b/ ); |
72 | | - if ( index > -1 ) { |
73 | | - end += index; |
74 | | - } |
75 | | - } |
| 67 | + /** |
| 68 | + * Gets the options for Espree from the supported JSHint options. |
| 69 | + * |
| 70 | + * @param {SupportedJSHintOptions} options - Linting options for JSHint. |
| 71 | + * @return {{ |
| 72 | + * ecmaVersion?: number|'latest', |
| 73 | + * ecmaFeatures?: { |
| 74 | + * impliedStrict?: true |
| 75 | + * } |
| 76 | + * }} |
| 77 | + */ |
| 78 | + function getEspreeOptions( options ) { |
| 79 | + const ecmaFeatures = {}; |
| 80 | + if ( options.strict === 'implied' ) { |
| 81 | + ecmaFeatures.impliedStrict = true; |
| 82 | + } |
76 | 83 |
|
77 | | - // Convert to format expected by validation service |
78 | | - const hint = { |
79 | | - message: error.reason, |
80 | | - severity: error.code ? |
81 | | - ( error.code.startsWith( 'W' ) ? 'warning' : 'error' ) |
82 | | - : 'error', |
83 | | - from: CodeMirror.Pos( error.line - 1, start ), |
84 | | - to: CodeMirror.Pos( error.line - 1, end ), |
85 | | - }; |
| 84 | + return { |
| 85 | + ecmaVersion: getEcmaVersion( options ), |
| 86 | + sourceType: options.module ? 'module' : 'script', |
| 87 | + ecmaFeatures, |
| 88 | + }; |
| 89 | + } |
86 | 90 |
|
87 | | - output.push( hint ); |
88 | | - } |
| 91 | + /** |
| 92 | + * Gets the ECMAScript version. |
| 93 | + * |
| 94 | + * @param {SupportedJSHintOptions} options - Options. |
| 95 | + * @return {number|'latest'} ECMAScript version. |
| 96 | + */ |
| 97 | + function getEcmaVersion( options ) { |
| 98 | + if ( typeof options.esversion === 'number' ) { |
| 99 | + return options.esversion; |
| 100 | + } |
| 101 | + if ( options.es5 ) { |
| 102 | + return 5; |
| 103 | + } |
| 104 | + if ( options.es3 ) { |
| 105 | + return 3; |
89 | 106 | } |
| 107 | + return 'latest'; |
90 | 108 | } |
91 | 109 | } ); |
0 commit comments