Skip to content

Commit c6a66c7

Browse files
kastesindresorhus
andauthored
Implement automatic selector if plugins are used (#20)
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
1 parent 29aac0b commit c6a66c7

File tree

2 files changed

+78
-2
lines changed

2 files changed

+78
-2
lines changed

linter.py

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
1+
import os
12
from SublimeLinter.lint import NodeLinter
23

4+
# TODO: Properly export these in SL core: https://github.com/SublimeLinter/SublimeLinter/issues/1713
5+
from SublimeLinter.lint.linter import PermanentError
6+
from SublimeLinter.lint.base_linter.node_linter import read_json_file
7+
8+
9+
STANDARD_SELECTOR = 'source.js'
10+
PLUGINS = {
11+
'eslint-plugin-html': 'text.html',
12+
'eslint-plugin-json': 'source.json',
13+
'eslint-plugin-markdown': 'text.html.markdown',
14+
'eslint-plugin-svelte3': 'text.html',
15+
'eslint-plugin-vue': 'text.html.vue',
16+
'@typescript-eslint/parser': 'source.ts',
17+
}
18+
OPTIMISTIC_SELECTOR = ', '.join({STANDARD_SELECTOR} | set(PLUGINS.values()))
19+
20+
321
class XO(NodeLinter):
422
npm_name = 'xo'
523
cmd = ('xo', '--stdin', '--reporter', 'compact', '--filename', '${file}')
@@ -10,6 +28,48 @@ class XO(NodeLinter):
1028
r' \((?P<code>.+)\)$'
1129
)
1230
defaults = {
13-
'selector': 'source.js - meta.attribute-with-value',
31+
'selector': OPTIMISTIC_SELECTOR,
1432
'disable_if_not_dependency': True
1533
}
34+
35+
def run(self, cmd, code):
36+
self.ensure_plugin_installed()
37+
return super().run(cmd, code)
38+
39+
def ensure_plugin_installed(self) -> bool:
40+
# If the user changed the selector, we take it as is.
41+
if self.settings['selector'] != OPTIMISTIC_SELECTOR:
42+
return True
43+
44+
# Happy path.
45+
if self.view.match_selector(0, STANDARD_SELECTOR):
46+
return True
47+
48+
# If we're here we must be pessimistic.
49+
50+
# The `project_root` has the relevant `package.json` file colocated.
51+
# If we fallback to a global installation there is no `project_root`,
52+
# t.i. no auto-selector in that case as well.
53+
project_root = self.context.get('project_root')
54+
if project_root:
55+
# We still need to be careful, in case SublimeLinter deduced a `project_root`
56+
# without checking for the `package.json` explicitly. Basically, a
57+
# happy path for SublimeLinter core.
58+
manifest_file = os.path.join(project_root, 'package.json')
59+
try:
60+
manifest = read_json_file(manifest_file)
61+
except Exception:
62+
pass
63+
else:
64+
defined_plugins = PLUGINS.keys() & (
65+
manifest.get('dependencies', {}).keys()
66+
| manifest.get('devDependencies', {}).keys()
67+
)
68+
selector = ', '.join(PLUGINS[name] for name in defined_plugins)
69+
if selector and self.view.match_selector(0, selector):
70+
return True
71+
72+
# Indicate an error which usually can only be solved by changing
73+
# the environment. Silently, do not notify and disturb the user!
74+
self.notify_unassign()
75+
raise PermanentError()

readme.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ In order for `xo` to be executed by SublimeLinter, you must ensure that its path
3030

3131
### Using non-JS syntax
3232

33-
If you're using an ESLint plugin with XO that provides non-JS syntax, like TypeScript, Vue, etc, you need to change the SublimeLinter [`selector` setting](http://www.sublimelinter.com/en/stable/linter_settings.html#selector) to include the syntax scope. For Vue, that would be:
33+
Typical plugins for ESLint, for example, for TypeScript or Vue, should just work automatically if they're installed locally in your project (defined in the same `package.json`).
34+
35+
For plugins not supported out-of-the-box, you may need to change the SublimeLinter [`selector` setting](http://www.sublimelinter.com/en/stable/linter_settings.html#selector) to include the correct syntax scope. For Vue, that could be:
3436

3537
```json
3638
{
@@ -42,6 +44,20 @@ If you're using an ESLint plugin with XO that provides non-JS syntax, like TypeS
4244
}
4345
```
4446

47+
### Help, `xo` doesn't lint my HTML files anymore!
48+
49+
`xo` will only lint `*.js` files for standard, vanilla config without further plugins. Either install the [eslint-plugin-html](https://github.com/BenoitZugmeyer/eslint-plugin-html) or tweak the `selector`:
50+
51+
```json
52+
{
53+
"linters": {
54+
"xo": {
55+
"selector": "source.js - meta.attribute-with-value"
56+
}
57+
}
58+
}
59+
```
60+
4561

4662
## Note
4763

0 commit comments

Comments
 (0)