Skip to content
This repository was archived by the owner on Aug 7, 2023. It is now read-only.

Commit 6404019

Browse files
authored
Merge pull request #170 from AtomLinter/arcanemagus/csslint-master
Move to using mainline CSSLint
2 parents 392f006 + cd0f049 commit 6404019

File tree

9 files changed

+270
-175
lines changed

9 files changed

+270
-175
lines changed

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
.DS_Store
22
.idea
33
npm-debug.log
4-
node_modules
4+
node_modules/*
55
.github_changelog_generator

.travis.yml

+4-5
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ matrix:
99
- os: linux
1010
env: ATOM_CHANNEL=beta
1111

12-
- os: osx
13-
env: ATOM_CHANNEL=stable
14-
1512
### Generic setup follows ###
1613
script:
1714
- curl -s -O https://raw.githubusercontent.com/atom/ci/master/build-package.sh
@@ -32,10 +29,12 @@ git:
3229

3330
sudo: false
3431

32+
dist: trusty
33+
3534
addons:
3635
apt:
3736
packages:
3837
- build-essential
39-
- git
40-
- libgnome-keyring-dev
4138
- fakeroot
39+
- git
40+
- libsecret-1-dev

CONTRIBUTING.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ Please note that modifications should follow these coding guidelines:
1212

1313
- Indent is 2 spaces.
1414

15-
- Code should pass [CoffeeLint](http://www.coffeelint.org/) with the provided
16-
`coffeelint.json`
15+
- Code should pass [ESlint](https://eslint.org/).
1716

1817
- Vertical whitespace helps readability, don’t be afraid to use it.
1918

lib/main.js

+147-62
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,58 @@
11
'use babel';
22

3-
/* eslint-disable import/extensions, import/no-extraneous-dependencies */
3+
// eslint-disable-next-line import/no-extraneous-dependencies, import/extensions
44
import { CompositeDisposable } from 'atom';
5-
/* eslint-enable import/extensions, import/no-extraneous-dependencies */
65

7-
let helpers = null;
8-
let path = null;
6+
// Dependencies
7+
let fs;
8+
let path;
9+
let helpers;
10+
11+
// Internal Variables
12+
let bundledCsslintPath;
13+
14+
const loadDeps = () => {
15+
if (!fs) {
16+
fs = require('fs-plus');
17+
}
18+
if (!path) {
19+
path = require('path');
20+
}
21+
if (!helpers) {
22+
helpers = require('atom-linter');
23+
}
24+
};
925

1026
export default {
1127
activate() {
12-
require('atom-package-deps').install('linter-csslint');
28+
this.idleCallbacks = new Set();
29+
let depsCallbackID;
30+
const installLinterCsslintDeps = () => {
31+
this.idleCallbacks.delete(depsCallbackID);
32+
if (!atom.inSpecMode()) {
33+
require('atom-package-deps').install('linter-csslint');
34+
}
35+
loadDeps();
36+
37+
// FIXME: Remove this after a few versions
38+
if (atom.config.get('linter-csslint.disableTimeout')) {
39+
atom.config.unset('linter-csslint.disableTimeout');
40+
}
41+
};
42+
depsCallbackID = window.requestIdleCallback(installLinterCsslintDeps);
43+
this.idleCallbacks.add(depsCallbackID);
1344

1445
this.subscriptions = new CompositeDisposable();
1546
this.subscriptions.add(
16-
atom.config.observe('linter-csslint.disableTimeout', (value) => {
17-
this.disableTimeout = value;
47+
atom.config.observe('linter-csslint.executablePath', (value) => {
48+
this.executablePath = value;
1849
}),
1950
);
2051
},
2152

2253
deactivate() {
54+
this.idleCallbacks.forEach(callbackID => window.cancelIdleCallback(callbackID));
55+
this.idleCallbacks.clear();
2356
this.subscriptions.dispose();
2457
},
2558

@@ -28,77 +61,129 @@ export default {
2861
name: 'CSSLint',
2962
grammarScopes: ['source.css', 'source.html'],
3063
scope: 'file',
31-
lintOnFly: true,
32-
lint(textEditor) {
33-
if (!helpers) {
34-
helpers = require('atom-linter');
35-
}
36-
if (!path) {
37-
path = require('path');
38-
}
64+
lintsOnChange: false,
65+
lint: async (textEditor) => {
66+
loadDeps();
3967
const filePath = textEditor.getPath();
4068
const text = textEditor.getText();
41-
if (text.length === 0) {
42-
return Promise.resolve([]);
69+
if (!filePath || text.length === 0) {
70+
// Empty or unsaved file
71+
return [];
4372
}
44-
const parameters = ['--format=json', '-'];
45-
const exec = path.join(__dirname, '..', 'node_modules', 'atomlinter-csslint', 'cli.js');
73+
74+
const parameters = [
75+
'--format=json',
76+
filePath,
77+
];
78+
4679
const projectPath = atom.project.relativizePath(filePath)[0];
4780
let cwd = projectPath;
48-
if (!(cwd)) {
81+
if (!cwd) {
4982
cwd = path.dirname(filePath);
5083
}
51-
const options = { stdin: text, cwd };
52-
if (this.disableTimeout) {
53-
options.timeout = Infinity;
84+
85+
const execOptions = {
86+
cwd,
87+
uniqueKey: `linter-csslint::${filePath}`,
88+
timeout: 1000 * 30, // 30 seconds
89+
ignoreExitCode: true,
90+
};
91+
92+
const execPath = this.determineExecPath(this.executablePath, projectPath);
93+
94+
const output = await helpers.exec(execPath, parameters, execOptions);
95+
96+
if (textEditor.getText() !== text) {
97+
// The editor contents have changed, tell Linter not to update
98+
return null;
5499
}
55-
return helpers.execNode(exec, parameters, options).then((output) => {
56-
if (textEditor.getText() !== text) {
57-
// The editor contents have changed, tell Linter not to update
58-
return null;
59-
}
60100

61-
const toReturn = [];
62-
if (output.length < 1) {
63-
// No output, no errors
64-
return toReturn;
101+
const toReturn = [];
102+
103+
if (output.length < 1) {
104+
// No output, no errors
105+
return toReturn;
106+
}
107+
108+
let lintResult;
109+
try {
110+
lintResult = JSON.parse(output);
111+
} catch (e) {
112+
const excerpt = 'Invalid response received from CSSLint, check ' +
113+
'your console for more details.';
114+
return [{
115+
severity: 'error',
116+
excerpt,
117+
location: {
118+
file: filePath,
119+
position: helpers.generateRange(textEditor, 0),
120+
},
121+
}];
122+
}
123+
124+
if (lintResult.messages.length < 1) {
125+
// Output, but no errors found
126+
return toReturn;
127+
}
128+
129+
lintResult.messages.forEach((data) => {
130+
let line;
131+
let col;
132+
if (!(data.line && data.col)) {
133+
// Use the file start if a location wasn't defined
134+
[line, col] = [0, 0];
135+
} else {
136+
[line, col] = [data.line - 1, data.col - 1];
65137
}
66138

67-
const lintResult = JSON.parse(output);
139+
const severity = data.type === 'error' ? 'error' : 'warning';
68140

69-
if (lintResult.messages.length < 1) {
70-
// Output, but no errors found
71-
return toReturn;
141+
const msg = {
142+
severity,
143+
excerpt: data.message,
144+
location: {
145+
file: filePath,
146+
position: helpers.generateRange(textEditor, line, col),
147+
},
148+
};
149+
if (data.rule.id && data.rule.desc) {
150+
msg.details = `${data.rule.desc} (${data.rule.id})`;
151+
}
152+
if (data.rule.url) {
153+
msg.url = data.rule.url;
72154
}
73155

74-
lintResult.messages.forEach((data) => {
75-
let line;
76-
let col;
77-
if (!(data.line && data.col)) {
78-
// Use the file start if a location wasn't defined
79-
[line, col] = [0, 0];
80-
} else {
81-
[line, col] = [data.line - 1, data.col - 1];
82-
}
83-
84-
const msg = {
85-
type: data.type.charAt(0).toUpperCase() + data.type.slice(1),
86-
text: data.message,
87-
filePath,
88-
range: helpers.generateRange(textEditor, line, col),
89-
};
90-
91-
if (data.rule.id && data.rule.desc) {
92-
msg.trace = [{
93-
type: 'Trace',
94-
text: `[${data.rule.id}] ${data.rule.desc}`,
95-
}];
96-
}
97-
toReturn.push(msg);
98-
});
99-
return toReturn;
156+
toReturn.push(msg);
100157
});
158+
159+
return toReturn;
101160
},
102161
};
103162
},
163+
164+
determineExecPath(givenPath, projectPath) {
165+
let execPath = givenPath;
166+
if (execPath === '') {
167+
// Use the bundled copy of CSSLint
168+
let relativeBinPath = path.join('node_modules', '.bin', 'csslint');
169+
if (process.platform === 'win32') {
170+
relativeBinPath += '.cmd';
171+
}
172+
if (!bundledCsslintPath) {
173+
const packagePath = atom.packages.resolvePackagePath('linter-csslint');
174+
bundledCsslintPath = path.join(packagePath, relativeBinPath);
175+
}
176+
execPath = bundledCsslintPath;
177+
if (projectPath) {
178+
const localCssLintPath = path.join(projectPath, relativeBinPath);
179+
if (fs.existsSync(localCssLintPath)) {
180+
execPath = localCssLintPath;
181+
}
182+
}
183+
} else {
184+
// Normalize any usage of ~
185+
fs.normalize(execPath);
186+
}
187+
return execPath;
188+
},
104189
};

package.json

+15-12
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,29 @@
1313
"license": "MIT",
1414
"private": true,
1515
"configSchema": {
16-
"disableTimeout": {
17-
"type": "boolean",
18-
"description": "Disable the 10 second execution timeout",
19-
"default": false
16+
"executablePath": {
17+
"type": "string",
18+
"default": "",
19+
"description": "If unset a project local install of CSSLint is attempted to be used first, falling back to the bundled version. Requires a full path to `csslint` (e.g.: `/usr/bin/csslint` or `C:\\foo\\bar\\csslint.cmd`)."
2020
}
2121
},
2222
"engines": {
2323
"atom": ">=1.4.0 <2.0.0"
2424
},
2525
"dependencies": {
2626
"atom-linter": "^10.0.0",
27-
"atom-package-deps": "^4.0.1",
28-
"atomlinter-csslint": "0.10.1"
27+
"atom-package-deps": "^4.6.0",
28+
"csslint": "^1.0.5",
29+
"fs-plus": "^3.0.1"
2930
},
3031
"devDependencies": {
31-
"eslint": "^3.15.0",
32-
"eslint-config-airbnb-base": "^11.1.0",
33-
"eslint-plugin-import": "^2.2.0"
32+
"eslint": "^4.3.0",
33+
"eslint-config-airbnb-base": "^11.3.1",
34+
"eslint-plugin-import": "^2.7.0",
35+
"jasmine-fix": "^1.3.0"
3436
},
3537
"package-deps": [
36-
"linter"
38+
"linter:2.0.0"
3739
],
3840
"scripts": {
3941
"lint": "eslint .",
@@ -56,13 +58,14 @@
5658
"atom": true
5759
},
5860
"env": {
59-
"node": true
61+
"node": true,
62+
"browser": true
6063
}
6164
},
6265
"providedServices": {
6366
"linter": {
6467
"versions": {
65-
"1.0.0": "provideLinter"
68+
"2.0.0": "provideLinter"
6669
}
6770
}
6871
}

spec/.eslintrc.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
module.exports = {
22
env: {
33
jasmine: true,
4-
atomtest: true
4+
atomtest: true,
5+
},
6+
rules: {
7+
"import/no-extraneous-dependencies": [
8+
"error",
9+
{
10+
"devDependencies": true
11+
}
12+
]
513
}
614
};

spec/fixtures/execProject/node_modules/.bin/csslint

Whitespace-only changes.

spec/fixtures/execProject/node_modules/.bin/csslint.cmd

Whitespace-only changes.

0 commit comments

Comments
 (0)