├── .gitignore
├── .no-sublime-package
├── Context.sublime-menu
├── Default (Linux).sublime-keymap
├── Default (OSX).sublime-keymap
├── Default (Windows).sublime-keymap
├── Default.sublime-commands
├── ESLint.py
├── ESLint.sublime-build
├── ESLint.sublime-settings
├── Main.sublime-menu
├── README.md
└── linter.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | ESLint.pyc
--------------------------------------------------------------------------------
/.no-sublime-package:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Context.sublime-menu:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "eslint",
4 | "caption": "ESLint",
5 | "command": "eslint"
6 | }
7 | ]
8 |
--------------------------------------------------------------------------------
/Default (Linux).sublime-keymap:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "keys": ["ctrl+alt+e"],
4 | "command": "eslint"
5 | }
6 | ]
7 |
--------------------------------------------------------------------------------
/Default (OSX).sublime-keymap:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "keys": ["ctrl+alt+e"],
4 | "command": "eslint"
5 | }
6 | ]
7 |
--------------------------------------------------------------------------------
/Default (Windows).sublime-keymap:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "keys": ["ctrl+alt+e"],
4 | "command": "eslint"
5 | }
6 | ]
7 |
--------------------------------------------------------------------------------
/Default.sublime-commands:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "eslint",
4 | "caption": "ESLint",
5 | "command": "eslint"
6 | }
7 | ]
8 |
--------------------------------------------------------------------------------
/ESLint.py:
--------------------------------------------------------------------------------
1 | import os
2 | import platform
3 | import sublime
4 | import sublime_plugin
5 |
6 | SETTINGS_KEY = 'ESLint.sublime-settings'
7 | DEFAULT_NODE_PATH = ''
8 | DEFAULT_NODE_MODULES_PATH = ''
9 | DEFAULT_CONFIGFILE = ''
10 |
11 | class Preferences:
12 | def load(self, settings):
13 | self.node_path = settings.get('node_path', DEFAULT_NODE_PATH)
14 | self.node_modules_path = settings.get('node_modules_path', DEFAULT_NODE_MODULES_PATH)
15 | self.config_file = settings.get('config_file', DEFAULT_CONFIGFILE)
16 |
17 | Pref = Preferences()
18 |
19 | def plugin_loaded():
20 | settings = sublime.load_settings(SETTINGS_KEY)
21 | Pref.load(settings)
22 | settings.add_on_change('reload', lambda: Pref.load(settings))
23 |
24 |
25 | class EslintExecCommand(sublime_plugin.WindowCommand):
26 | def run(self, files=[]):
27 | packages = sublime.packages_path()
28 | linter_path = os.path.join(packages, 'ESLint', 'linter.js')
29 | node_modules_path = os.path.expandvars(os.path.expanduser(Pref.node_modules_path))
30 | config_file = os.path.expandvars(os.path.expanduser(Pref.config_file))
31 |
32 | path = Pref.node_path
33 | if not path:
34 | if sublime.platform() == 'osx':
35 | path = '/usr/local/bin:' + os.environ['PATH']
36 | else:
37 | path = os.environ['PATH']
38 |
39 | args = {
40 | 'cmd': [
41 | 'node',
42 | linter_path,
43 | files[0],
44 | node_modules_path,
45 | config_file
46 | ],
47 | 'path': path,
48 | 'file_regex': r'ESLint: (.+)\]',
49 | 'line_regex': r'(\d+),(\d+): (.*)$'
50 | }
51 | self.window.run_command('exec', args)
52 |
53 | class EslintCommand(sublime_plugin.WindowCommand):
54 | def run(self):
55 | self.window.run_command('eslint_exec', {
56 | 'files': [self.window.active_view().file_name()]
57 | })
58 |
59 | # ST2 backwards compatibility
60 | if int(sublime.version()) < 3000:
61 | plugin_loaded()
62 |
--------------------------------------------------------------------------------
/ESLint.sublime-build:
--------------------------------------------------------------------------------
1 | {
2 | "selector": "source.js",
3 | "target": "eslint"
4 | }
5 |
--------------------------------------------------------------------------------
/ESLint.sublime-settings:
--------------------------------------------------------------------------------
1 | // ESLint' default settings.
2 | //
3 | // In order to tweak the settings, you should NOT edit this file, but instead
4 | // the user-specific, empty-by-default version under
5 | // "Preferences / Package Settings / ESLint / Settings - User".
6 | //
7 | // See ESLint' README for detailed instructions.
8 | {
9 | // The directory location of your `node` executable lives. If this is not
10 | // specified, then it is expected to be on Sublime's environment path.
11 | //
12 | // On OSX, for example: "/usr/local/bin"
13 | // Example for nodebrew: "$HOME/.nodebrew/current/bin"
14 | // Example for Windows: "C:/Program Files/nodejs"
15 | "node_path": "",
16 |
17 | // The directory location of global `node_modules` via `npm`. If this
18 | // is not specified, then it is expected to be on system environment
19 | // variable `NODE_PATH`.
20 | //
21 | // On OSX, for example: "/usr/local/lib/node_modules"
22 | // Example for nodebrew: "$HOME/.nodebrew/current/lib/node_modules"
23 | // Example for Windows: "%APPDATA%/npm/node_modules"
24 | "node_modules_path": "",
25 |
26 | // The location of your configuration file.
27 | // This option works same as ESLint `-c` option.
28 | // This option allows you to specify the location of your `.eslintrc` file
29 | //
30 | // Example: "/path/to/.eslintrc.js"
31 | "config_file": ""
32 | }
33 |
--------------------------------------------------------------------------------
/Main.sublime-menu:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "caption": "Tools",
4 | "id": "tools",
5 | "children": [
6 | {
7 | "id": "eslint",
8 | "caption": "ESLint",
9 | "command": "eslint"
10 | }
11 | ]
12 | },
13 | {
14 | "caption": "Preferences",
15 | "mnemonic": "n",
16 | "id": "preferences",
17 | "children": [
18 | {
19 | "caption": "Package Settings",
20 | "mnemonic": "P",
21 | "id": "package-settings",
22 | "children": [
23 | {
24 | "caption": "ESLint",
25 | "children": [
26 | {
27 | "command": "open_file",
28 | "args": {
29 | "file": "${packages}/ESLint/ESLint.sublime-settings"
30 | },
31 | "caption": "Settings – Default"
32 | },
33 | {
34 | "command": "open_file",
35 | "args": {
36 | "file": "${packages}/User/ESLint.sublime-settings"
37 | },
38 | "caption": "Settings – User"
39 | },
40 | {
41 | "caption": "-"
42 | },
43 | {
44 | "command": "open_file",
45 | "args": {
46 | "file": "${packages}/ESLint/Default (Windows).sublime-keymap",
47 | "platform": "Windows"
48 | },
49 | "caption": "Key Bindings – Default"
50 | },
51 | {
52 | "command": "open_file",
53 | "args": {
54 | "file": "${packages}/ESLint/Default (OSX).sublime-keymap",
55 | "platform": "OSX"
56 | },
57 | "caption": "Key Bindings – Default"
58 | },
59 | {
60 | "command": "open_file",
61 | "args": {
62 | "file": "${packages}/ESLint/Default (Linux).sublime-keymap",
63 | "platform": "Linux"
64 | },
65 | "caption": "Key Bindings – Default"
66 | },
67 | {
68 | "command": "open_file",
69 | "args": {
70 | "file": "${packages}/User/Default (Windows).sublime-keymap",
71 | "platform": "Windows"
72 | },
73 | "caption": "Key Bindings – User"
74 | },
75 | {
76 | "command": "open_file",
77 | "args": {
78 | "file": "${packages}/User/Default (OSX).sublime-keymap",
79 | "platform": "OSX"
80 | },
81 | "caption": "Key Bindings – User"
82 | },
83 | {
84 | "command": "open_file",
85 | "args": {
86 | "file": "${packages}/User/Default (Linux).sublime-keymap",
87 | "platform": "Linux"
88 | },
89 | "caption": "Key Bindings – User"
90 | },
91 | {
92 | "caption": "-"
93 | }
94 | ]
95 | }
96 | ]
97 | }
98 | ]
99 | }
100 | ]
101 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ESLint for Sublime Text
2 |
3 | Lint ECMAScript/JavaScript syntax by [ESLint][ESLint Official] in [Sublime Text 2][Sublime Text 2] and [3][Sublime Text 3].
4 |
5 | ## Prerequisites
6 |
7 | * [Sublime Package Control][Package Control]
8 | * [Node.js][Node.js]
9 | * [eslint][ESLint Official GitHub]
10 |
11 | ## Installation
12 |
13 | ### Install Node.js and eslint
14 |
15 | Before using this plugin, you must ensure that `eslint` is installed on your system.
16 | To install `eslint`, do the following:
17 |
18 | 1. Install [Node.js][Node.js] (and [npm][npm] on Linux).
19 |
20 | 2. Install `eslint` globally by typing the following in a terminal:
21 | ```bash
22 | npm install -g eslint
23 | ```
24 |
25 | ### Install plugin
26 |
27 | Install this plugin by using Sublime Text [Package Control][Package Control].
28 |
29 | 1. Open **"Command Pallet"** Ctrl + Shift + p (Cmd + Shift + p on OSX)
30 | 2. Select **"Package Control: Install Package"**
31 | 3. Select **ESLint**
32 |
33 | ## Run ESLint
34 |
35 | ESLint an active JavaScript file.
36 |
37 |
38 | * Open the context menu (right-click), and Select **ESLint**,
39 | Or Open "Command Pallet" and Select **ESLint**,
40 | Or keyboard shortcut: Ctrl + Alt + e (Cmd + Option + e on OSX)
41 |
42 | * F4 : Jump to next error row/column
43 | * Shift + F4 : Jump to previous error row-column
44 |
45 | **Note:**
46 | The Ctrl + Alt + e (Cmd + Option + e on OSX) shortcut changes the Build System on the current file to ESLint,
47 | then Builds to run ESLint on the file and output any errors for jumping to within the file.
48 | You could alternatively set the Build System to Automatic and Ctrl + b (Cmd + b on OSX) or F7,
49 | but only on files that end with `.js`.
50 |
51 | ## Configuring ESLint
52 |
53 | [ESLint][ESLint Official] allows you to specify the JavaScript language options you want to support by using `.eslintrc` file,
54 | it will use the first `.eslintrc` file found traversing from the active file in Sublime Text up to your project's root.
55 |
56 | You can configure ESLint options by specify `.eslintrc` file.
57 | For more information, see the [ESLint docs][ESLint Official Configuration Docs].
58 |
59 | ## Settings
60 |
61 | Several settings are available to customize the plugin's behavior.
62 | Those settings are stored in a configuration file, as JSON.
63 |
64 | Go to "`Preferences` / `Package Settings` / `ESLint` / `Settings - User`" to add your custom settings.
65 |
66 | ### node_path
67 |
68 | *Default: `""`*
69 |
70 | The directory location of your `node` executable lives.
71 | If this is not specified, then it is expected to be on Sublime's environment path.
72 |
73 | ### node_modules_path
74 |
75 | *Default: `""`*
76 |
77 | The directory location of global `node_modules` via `npm`.
78 | If this is not specified, then it is expected to be on system environment variable `NODE_PATH`.
79 |
80 | ### config_file
81 |
82 | *Default: `""`*
83 |
84 | This option allows you to specify an additional configuration file for ESLint.
85 | If not specified, follows the default config file hierarchy.
86 | This option works same as ESLint `-c` or `--config` command line option.
87 |
88 | For more information, see the [ESLint docs][ESLint Official Specifying Basic Configuration File Docs].
89 |
90 |
91 | Example:
92 |
93 | ```javascript
94 | {
95 | "node_path": "/usr/local/bin",
96 | "node_modules_path": "/usr/local/lib/node_modules",
97 | "config_file": "/path/to/.eslintrc.js"
98 | }
99 | ```
100 |
101 | ## ESLint on save
102 |
103 | Install [SublimeOnSaveBuild][SublimeOnSaveBuild]
104 |
105 |
106 | [ESLint Official]: http://eslint.org/
107 | [ESLint Official Configuration Docs]: http://eslint.org/docs/user-guide/configuring#configuration-file-formats
108 | [ESLint Official Specifying Basic Configuration File Docs]: http://eslint.org/docs/user-guide/command-line-interface#basic-configuration
109 | [Sublime Text 2]: http://www.sublimetext.com/2
110 | [Sublime Text 3]: http://www.sublimetext.com/3
111 | [ECMAScript 6]: http://www.ecma-international.org/publications/standards/Ecma-262.htm
112 | [React]: https://facebook.github.io/react/
113 | [JSX]: https://facebook.github.io/jsx/
114 | [Package Control]: http://wbond.net/sublime_packages/package_control/installation
115 | [Node.js]: https://nodejs.org/
116 | [ESLint Official GitHub]: https://github.com/eslint/eslint
117 | [npm]: https://nodejs.org/en/download/package-manager/
118 | [SublimeOnSaveBuild]: https://github.com/alexnj/SublimeOnSaveBuild
119 | [React plugin]: https://github.com/yannickcr/eslint-plugin-react
120 |
--------------------------------------------------------------------------------
/linter.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var fs = require('fs');
4 | var path = require('path');
5 | var args = process.argv.slice(2);
6 |
7 | var minNodeVersion = ["8","9","0"];
8 | var targetPath = args[0];
9 | var targetDir = path.dirname(targetPath);
10 |
11 | var nodeModulesPath = args[1];
12 | if (nodeModulesPath) {
13 | module.paths.push(nodeModulesPath);
14 | }
15 | var configFile = args[2];
16 | var isNodeMinVersion = checkNodeMinVersion(process.version);
17 |
18 | var eslintPath = (isNodeMinVersion)
19 | ? require.resolve('eslint', {paths: [targetDir, nodeModulesPath]})
20 | : require.resolve('eslint');
21 |
22 | var eslint = require(eslintPath);
23 |
24 | var cli;
25 | var options = {};
26 |
27 | if (eslint.ESLint) {
28 | // eslint version >= 7
29 | if (configFile) {
30 | options.overrideConfigFile = configFile;
31 | }
32 | cli = new eslint.ESLint(options);
33 | cli.lintFiles([targetPath]).then(function(results) {
34 | // eslint-disable-next-line no-console
35 | console.log(format(results))
36 | });
37 | } else {
38 | if (configFile) {
39 | options.configFile = configFile;
40 | }
41 | cli = new eslint.CLIEngine(options);
42 | var report = cli.executeOnFiles([targetPath]);
43 | // eslint-disable-next-line no-console
44 | console.log(format(report.results));
45 | }
46 |
47 | function format(results) {
48 | var lines = [];
49 |
50 | function numberWang(wangaNumb) {
51 | var thatsNumberWang = 7 - wangaNumb;
52 | var stayNumberWang = '';
53 | var i;
54 |
55 | for (i = 0; i < thatsNumberWang; i++) {
56 | stayNumberWang += ' ';
57 | }
58 |
59 | return stayNumberWang;
60 | }
61 |
62 | lines.push('[ESLint: ' + results[0].filePath + ']');
63 | lines.push('');
64 |
65 | var messages = results[0].messages;
66 | var errorCount = results[0].errorCount || 0;
67 | var warningCount = results[0].warningCount || 0;
68 |
69 | if (errorCount || warningCount) {
70 |
71 | messages.forEach(function(error) {
72 | var ruleId = error.ruleId ? ' (' + error.ruleId + ')' : '';
73 | var severity = (error.severity === 1 ? 'Warn ' : 'Error');
74 | var hasPosition = (error.line !== undefined && error.column !== undefined);
75 | var messageParts = ['\t', severity];
76 |
77 | if (hasPosition) {
78 | messageParts.push(numberWang((error.line + error.column.toString()).length));
79 | messageParts.push(error.line + ',' + error.column + ':');
80 | }
81 |
82 | messageParts.push(error.message + ruleId);
83 |
84 | lines.push(messageParts.join(' '));
85 | });
86 |
87 | lines.push('');
88 | lines.push('✗ ' +
89 | errorCount + ' ' + (errorCount === 1 ? 'error' : 'errors') + ', ' +
90 | warningCount + ' ' + (warningCount === 1 ? 'warning' : 'warnings'));
91 | lines.push('');
92 | lines.push('Double-click on lines to jump to location, [F4] for next, [shift-F4] for previous.'
93 | );
94 | } else {
95 | lines.push('✓ 0 errors and warnings, [esc] to hide.');
96 | }
97 |
98 | lines.push('');
99 | return lines.join('\n');
100 | }
101 |
102 |
103 | function checkNodeMinVersion(version) {
104 | var isNodeMinVersion = false;
105 | var nodeVersion = (version + "").replace(/v/gi, "").split(".");
106 |
107 | if(nodeVersion.length===3){
108 | minNodeVersion.every(function(itm, idx) {
109 | var isGreater = (nodeVersion[idx]*1 > itm*1)?true:false;
110 | var isEqual = (itm*1 == nodeVersion[idx]*1)?true:false;
111 |
112 | isNodeMinVersion = (isGreater || isEqual);
113 | return (!isGreater && isEqual);
114 | });
115 | }
116 | return isNodeMinVersion;
117 | }
118 |
--------------------------------------------------------------------------------