├── .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 | --------------------------------------------------------------------------------