/
index.js
139 lines (126 loc) · 3.75 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
const scope = ['source.js', 'source.js.jsx', 'source.js.jquery', 'source.vue']
const defaults = {
prettier: true,
fix: true
}
module.exports = {
scope: scope,
activate: function (state) {
window.requestIdleCallback(function () {
require('atom-package-deps')
.install('atom-standard', true)
.catch(function (err) {
window.atom.notifications.addError('Error activating atom-standard', {
detail: err.message,
dismissable: true
})
})
})
// console.time('requiring')
// .then(function () {
// console.timeEnd('requiring')
// })
},
provideLinter: function () {
const lint = Lint()
return {
name: 'standard',
scope: 'file',
grammarScopes: scope,
lintsOnChange: false,
lint: lint
}
}
}
function Lint () {
let minimatch = null
let prettier = null
let standard = null
let findRoot = null
let setText = null
return function lint (textEditor) {
return new Promise(function (resolve, reject) {
window.requestIdleCallback(resolve)
}).then(function () {
standard = standard || unsafe(() => require('standard'))
minimatch = minimatch || require('minimatch')
prettier = prettier || require('prettier')
setText = setText || require('atom-set-text')
findRoot = findRoot || require('find-root')
let fileContent = textEditor.getText()
const filePath = textEditor.getPath()
let pkgconf = {}
const root = findRoot(filePath)
if (root) {
pkgconf = require('pkg-config')(null, {
cwd: root,
root: 'standard',
cache: false
})
}
const conf = Object.assign({}, defaults, pkgconf)
// ignore file
if (conf.ignore) {
ignored = conf.ignore.filter(function (ignore) {
if (ignore[ignore.length - 1] === '/') ignore += '**'
return minimatch(filePath, path.join(root, ignore))
})
// we've got a match
if (ignored.length) return Promise.resolve([])
}
// pass through prettier first
if (conf.prettier) {
try {
fileContent = prettier.format(fileContent, {
semi: false,
singleQuote: true
})
} catch (e) {
console.log(e);
// this will happen when there's a parsing error
// let standard handle it down the stack
}
}
return new Promise(function (resolve, reject) {
unsafe(function () {
standard.lintText(fileContent, conf, function (err, res) {
if (err) return reject(err)
// format the text
var fixed =
res &&
Array.isArray(res.results) &&
res.results[0] &&
res.results[0].output
setText(fixed || fileContent, textEditor)
if (!res.errorCount) return resolve([])
resolve(formatErrors(filePath, res))
})
})
})
})
}
}
function unsafe (fn) {
return require('loophole').allowUnsafeNewFunction(fn)
}
function getRange (line, col, src, lineStart) {
line = typeof line !== 'undefined' ? parseInt(line - 1 + lineStart, 10) : 0
col = typeof col !== 'undefined' ? parseInt(col - 1, 10) : 0
src = src || ''
src = src.substring(0, col)
return [[line, col - src.trim().length], [line, col]]
}
function formatErrors (filePath, output) {
var msgs = output.results[0].messages
return msgs.map(function (msg) {
return {
severity: msg.fatal ? 'error' : 'warning',
location: {
file: filePath,
position: getRange(msg.line, msg.column, msg.source, 0)
},
excerpt: msg.message,
description: typeof msg.source === 'string' ? msg.source.trim() : ''
}
})
}