UNPKG

20.3 kBMarkdownView Raw
1## stylint - the stylus linter.
2
3[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/rossPatton/stylint?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Code Climate](https://codeclimate.com/github/rossPatton/stylint/badges/gpa.svg)](https://codeclimate.com/github/rossPatton/stylint) [![Test Coverage](https://codeclimate.com/github/rossPatton/stylint/badges/coverage.svg)](https://codeclimate.com/github/rossPatton/stylint/coverage) [![Build Status](https://travis-ci.org/rossPatton/stylint.svg?branch=master)](https://travis-ci.org/rossPatton/stylint)
4
5[![NPM](https://nodei.co/npm/stylint.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/stylint/)
6
7[changelog](changelog.md)
8
9[known issues](https://github.com/rossPatton/stylint/issues)
10
11If you have any problems with the linter just create a ticket there and I will respond.
12
13Same thing if you have any feature requests.
14
15I will gladly accept pull requests if you want to do the work yourself.
16
17you can also ping me [here](https://gitter.im/rossPatton/stylint)
18
19
20## CLI
21`-h` or `--help` Display list of commands
22
23`-w` or `--watch` Watch file or directory and run lint on change
24
25`-c` or `--config` Pass in location of custom config file
26
27`-v` or `--version` Display current version
28
29
30## Example cli Usage:
31`stylint` Run stylint on cwd
32
33`stylint path/to/filename.styl` Run stylint on a file
34
35`stylint path/to/dir --watch` Watch dir, run stylint on file change
36
37`stylint --help` Get list of commands
38
39`stylint --version` Get version number
40
41`stylint --config path/to/config/.configrc` Run stylint with custom config settings
42
43`stylint --reporter stylint-reporter-module` Run stylint with [custom reporter](#custom-reporters) module
44
45`stylint styl/ --watch -c path/to/config/.configrc` Watch dir, use custom config
46
47
48## Non CLI Usage
49I'll be the first to admit that the syntax is a bit weird, but it works just fine.
50```javascript
51const stylint = require('stylint')('path/to/stylus/', {
52 brackets: 'always',
53 namingConvention: 'BEM',
54 semicolons: 'always'
55}, callbackFn).create();
56```
57
58API docs are in the docs/ folder
59
60
61## Gulp
62You can use the CLI with [gulp-shell](https://github.com/sun-zheng-an/gulp-shell) like below:
63```javascript
64gulp.task('stylint', shell.task([
65 'stylint path/to/styl/ -c .stylintrc'
66]));
67```
68
69Or just use [gulp-stylint](https://github.com/danielhusar/gulp-stylint)
70```javascript
71var gulp = require('gulp');
72var stylint = require('gulp-stylint');
73
74gulp.task('default', function () {
75 return gulp.src('src/*.styl')
76 .pipe(stylint())
77});
78```
79
80## Grunt
81You can use [grunt-stylint](https://github.com/xdissent/grunt-stylint)
82
83```javascript
84grunt.initConfig({
85 stylint: {
86 options: {
87 config: {
88 colons: 'never'
89 }
90 },
91 src: ['src/**/*.styl']
92 }
93});
94```
95
96## Webpack
97You can use [stylint-loader](https://github.com/guerrero/stylint-loader)
98
99```javascript
100module.exports = {
101 // ...
102 module: {
103 preLoaders: [
104 {
105 test: /\.styl$/,
106 loader: 'stylint'
107 }
108 ],
109 loaders: [
110 {
111 test: /\.styl$/,
112 loader: 'style!css!stylus'
113 }
114 ]
115 }
116 // ...
117}
118```
119
120
121## As Part of Your Workflow
122Stylint integrations with both Sublime Text 3 and Atom.io are available.
123
124[Atom linter-stylint](https://atom.io/packages/linter-stylint)
125
126[SublimeLinter-contrib-stylint](https://packagecontrol.io/packages/SublimeLinter-contrib-stylint)
127
128
129## Why Write This Tool?
130Stylus is my CSS pre-processor of choice and the lack of a decent linter (or really, any linter) was an annoying pain point. So I thought I'd try my hand at writing what I thought my ideal linter would look like.
131
132
133## Why Use This Tool?
134To catch little mistakes (duplication of rules for instance) and to enforce a code style guide. This is particularly important with Stylus, which is unopinionated when it comes to syntax. Like Stylus itself, this linter opts for flexibility over rigidity.
135
136
137## Options
138The following is a list of all options available to stylint.
139```json
140{
141 "blocks": false,
142 "brackets": "never",
143 "colons": "always",
144 "colors": "always",
145 "commaSpace": "always",
146 "commentSpace": "always",
147 "cssLiteral": "never",
148 "customProperties"|"mixins": false,
149 "depthLimit": false,
150 "duplicates": true,
151 "efficient": "always",
152 "exclude": [],
153 "extendPref": false,
154 "globalDupe": false,
155 "indentPref": false,
156 "leadingZero": "never",
157 "maxErrors": false,
158 "maxWarnings": false,
159 "mixed": false,
160 "namingConvention": false,
161 "namingConventionStrict": false,
162 "none": "never",
163 "noImportant": true,
164 "parenSpace": false,
165 "placeholders": "always",
166 "prefixVarsWithDollar": "always",
167 "quotePref": false,
168 "semicolons": "never",
169 "sortOrder": "alphabetical",
170 "stackedProperties": "never",
171 "trailingWhitespace": "never",
172 "universal": false,
173 "valid": true,
174 "zeroUnits": "never",
175 "zIndexNormalize": false
176}
177```
178
179#### Custom Configuration
180By default, Stylint attempts to use the .stylintrc file in your working directory. If not, the above is what it falls back to.
181
182You can also use the `-c` or `--config` flags to pass in the location of your custom `.stylintrc` config file if it resides somewhere else.
183
184If requiring Stylint ( as opposed to using it via the cli ), the 2nd param is the config object.
185
186
187#### Severity
188Stylint has 2 levels of output, Warnings and Errors. All Stylint rules optionally take an object, allowing you to set it to be an Error. Combined with the maxWarnings and maxErrors properties, you can be very flexible about say, code style but strict on things like code duplication.
189
190Example:
191```json
192{
193 "brackets": {
194 "expect": "never",
195 "error": true
196 },
197 "colons": {
198 "expect": "always",
199 "error": true
200 }
201}
202```
203
204
205## Custom Reporters
206Stylint console output can be modified with the use of a reporter. Feel free to write your own (no matter how outlandish) and I'll add it here.
207
208[Stylint-stylish](https://github.com/SimenB/stylint-stylish)
209
210[stylint-json-reporter](https://github.com/sertae/stylint-json-reporter)
211
212
213## Excluding files, directories, and code blocks from the linter
214
215### .stylintignore
216Before linting, Stylint will look for a `.stylintignore` file in the current working directory, and will ignore files listed there. The files should be formatted in the same way you would use `.gitignore` or `.eslintignore`
217
218For reference, it looks like this:
219
220```
221path/to/file.styl
222path/to/directory/
223```
224
225
226### the package.json approach
227You can also exclude files/directories via your package.json by adding a stylintignore property.
228
229For reference:
230
231```json
232{
233 "stylintignore": ["path/to/file.styl", "path/to/directory/"],
234}
235```
236
237
238### the config approach
239see config documentation below for how to use the exclude option via `.stylintrc` or your passed in config object
240
241
242### warning toggle ( inline comment: @stylint off || @stylint on )
243Disable linting for a particular block of code by placing `@stylint off` in a line comment. Re-enable by placing `@stylint on` in a line comment further down. Stylint will not test any lines until turned back on. Use this to suppress warnings on a case-by-case basis. By default the linter will check every line except for @css blocks or places where certain rules have exceptions.
244
245For example, let's say you want to enforce `namingConvention: "lowercase_underscore"`, but you're also styling elements from the Bootstrap framework. You can use the `@stylint off` toggle to prevent warnings in places where you're referencing Bootstrap classes.
246
247Example:
248```stylus
249.button_block {
250 background: silver;
251 padding: 4px;
252}
253// @stylint off
254.button_block .btn-default {
255 background-color: green;
256 color: white;
257}
258// @stylint on
259```
260
261
262### ignore toggle ( inline comment: @stylint ignore )
263A toggle that works like the block comment, but just for one line. Useful for cases where you want to include fallback css for browser support.
264
265Example:
266```stylus
267.button-zoom
268 cursor pointer // @stylint ignore
269 cursor zoom-in
270```
271
272
273### transparent mixin use ( Array<string> )
274In Stylus you have the option of using mixins transparently, like css properties.
275
276Example: prefer `mySpecialTransition: 5px`
277
278Where `mySpecialTransition` is a previously defined mixin that takes a px val as it's parameter.
279
280If you use nib, `size`, `absolute`, and `fixed` are often used in this way.
281
282Because of nib's widespread use, the above 3 are supported by default. But any custom transparent mixin will cause the valid property check to fail. If you want to use the valid check with transparent mixins, you can do so by passing in the name of your transparent mixin to the `mixins` property of your config object.
283
284Example: `mixins: ['mySpecialTransition']` will tell Stylint that mySpecialTransition exists and is not an error.
285
286
287### blocks ( default: false, 'always' || 'never' || false )
288When 'always' expect the `@block` keyword when defining block variables.
289When 'never', expect no `@block` keyword when defining block variables.
290When false, do not check either way.
291
292Example if 'always': prefer `my-block = @block ` over `my-block = `
293
294Example if 'never': prefer `my-block = ` over `my-block = @block `
295
296
297### brackets ( default: 'never', 'always' || 'never' || false )
298When 'always', expect {} when declaring a selector.
299When 'never', expect no brackets when declaring a selector.
300
301Example if 'always': prefer `.some-class-name {` over `.some-class-name`
302
303Example if 'never': prefer `.some-class-name ` over `.some-class-name {`
304
305
306### colons ( default: 'always', 'always' || 'never' || false )
307When 'always', expect : when declaring a property.
308When 'never', expect no : when declaring a property.
309
310Example if 'always': prefer `margin: 0` over `margin 0`
311
312Example if 'never: prefer `margin 0` over `margin: 0`
313
314
315### colors ( default: 'always' || false )
316When 'always', enforce variables when defining hex values
317
318Example if true: prefer `color $red` over `color #f00`
319
320
321### commaSpace ( default: 'always', 'always' || 'never' || false )
322Enforce or disallow spaces after commas.
323
324Example if always: prefer `rgba(0, 0, 0, .18)` over `rgba(0,0,0,.18)`
325
326Example if never: prefer `rgba(0,0,0,.18)` over `rgba(0, 0, 0, .18)`
327
328
329### commentSpace ( default: 'always', 'always' || 'never' || false )
330Enforce or disallow spaces after line comments
331
332Example if always: prefer `// comment` over `//comment`
333
334Example if never: prefer `//comment` over `// comment`
335
336
337### cssLiteral ( default: 'never', 'never' || false )
338By default Stylint ignores `@css` blocks. If set to true however, it will throw a warning if `@css` is used.
339
340Example if 'never': `@css` will throw a warning
341
342
343### depthLimit ( default: false, number or false )
344Set the max selector depth. If set to 4, max selector depth will be 4 indents. Pseudo selectors like `&:first-child` or `&:hover` won't count towards the limit.
345
346Set to false if you don't want to check for this.
347
348
349### duplicates ( default: true, true || false )
350Checks if selector or property duplicated unnecessarily. By default, only checks on a file-by-file basis, but if `globalDupes: true` is set, then it will also check for duplicates globally (for root values only).
351
352Example if true: the following will throw a warning:
353```stylus
354.test
355 margin 0
356 margin 5px
357```
358
359
360### efficient ( default: 'always', 'always' || 'never' || false )
361Check for places where properties can be written more efficiently.
362
363Example if always: prefer `margin 0` over `margin 0 0`
364
365Example if never: prefer `margin 0 0` over `margin 0`
366
367
368### exclude ( default: [], array of strings )
369Exclude certain file patterns from linting.
370
371Example: `["vendor/**/*", "node_modules/**/*"]` will exclude all files in the `vendor` or `node_modules` directory.
372
373
374### extendPref ( default: false, '@extend' || '@extends' || false )
375Pass in either `@extend` or `@extends` and then enforce that. Both are valid in Stylus. It doesn't really matter which one you use. I prefer `@extends` myself.
376
377Example if set to `@extends`: prefer `@extends $some-var` over `@extend $some-var`
378
379Example if set to `@extend`: prefer `@extend $some-var` over `@extend $some-var`
380
381
382### globalDupe ( default: false, true || false )
383Works in conjunction with duplicates. Does nothing on its own. If false, duplicates will check for dupes within individual files only. If true, duplicates will check for dupes across all files.
384
385Example if true: the following will throw a warning
386```stylus
387>>> file1.styl
388.test
389 margin 0
390
391>>> file2.styl
392.test
393 margin 5px
394```
395
396
397### indentPref ( default: false, number or false )
398This works in conjunction with depthLimit. If you indent with spaces this is the number of spaces you indent with. If you use hard tabs, set this value to false.
399
400If you set this to a number, it will output warnings/errors if you the # of spaces used for indenting differs from the number set.
401
402By default this value is false, so if you indent with spaces you'll need to manually set this value in a custom `.stylintrc` file.
403
404Example if 2: prefer `/s/smargin: 0` over `/s/s/smargin: 0`
405
406
407### leadingZero ( default: 'never', 'always' || 'never' || false )
408Enforce or disallow unnecessary leading zeroes on decimal points.
409
410Example if always: prefer `rgba( 0, 0, 0, 0.5 )` over `rgba( 0, 0, 0, .5 )`
411
412Example if never: prefer `rgba( 0, 0, 0, .5 )` over `rgba( 0, 0, 0, 0.5 )`
413
414
415### maxErrors ( default: false, number || false )
416Set 'max' number of Errors.
417
418
419### maxWarnings ( default: false, number || false )
420Set 'max' number of Warnings.
421
422
423### mixed ( default: false, boolean, relies on indentPref )
424Returns true if mixed spaces and tabs are found. If a number is passed to indentPref, it assumes soft tabs (ie, spaces), and if false is passed to indentPref it assumes hard tabs.
425
426If soft tabs, outputs warning/error if hard tabs used. If hard tabs, outputs warning/error if unnecessary extra spaces found.
427
428Example if indentPref: 4 and mixed: true: prefer `\s\s\s\smargin\s0` over `\tmargin\s0`
429
430Example if indentPref: 2 and mixed: true: prefer `\s\smargin\s0` over `\tmargin\s0`
431
432Example if indentPref: false and mixed: true: prefer `\tmargin\s0` over `\s\s\s\smargin\s0`
433
434
435### namingConvention ( default: false, false | 'lowercase-dash' | 'lowercase_underscore' | 'camelCase' | 'BEM' )
436Enforce a particular naming convention when declaring classes, ids, and variables. Throws a warning if you don't follow the convention.
437
438Example if set to `'lowercase-dash'`: prefer `$var-name` over `$var_name` or `$varName`
439
440Example if set to `'lowercase_underscore'`: prefer `$var_name` over `$var-name` or `$varName`
441
442Example if set to `'camelCase'`: prefer `$varName` over `$var_name` or `$var-name`
443
444Example if set to `'BEM'`: prefer `$var__like--this` over `$var_name` or `$varName`
445
446
447### namingConventionStrict ( default: false, true || false )
448By default, namingConvention only looks at variable names. If namingConventionStrict is set to true, namingConvention will also look at class and id names.
449
450If you have a lot of 3rd party css you can't change you might want to leave this off.
451
452
453### none ( default: 'never'. options: 'always' || never' || false )
454If 'always' check for places where `none` used instead of `0`.
455If 'never' check for places where `0` could be used instead of `none`.
456
457Example if 'always': prefer `border none` over `border 0`
458
459Example if 'never': prefer `outline 0` over `outline none`
460
461
462### noImportant ( default: true, true || false )
463If true, show warning when `!important` is found.
464
465Example if true: the following will throw a warning
466
467```stylus
468div
469 color red !important
470```
471
472
473### parenSpace ( default: false, 'always' || 'never' || false )
474Enforce or disallow use of extra spaces inside parens.
475
476Example if always: prefer `my-mixin( $myParam )` over `my-mixin($myParam)`
477
478Example if never: prefer `my-mixin($myParam)` over `my-mixin( $myParam )`
479
480
481### placeholder ( default: 'always', 'always' || 'never' || false )
482Enforce extending placeholder vars when using `@extend(s)`
483
484Example if always: prefer `@extends $placeholder` over `$extends .some-class`
485
486Example if never: prefer `@extends .some-class` over `$extends $placeholder`
487
488
489### prefixVarsWithDollar ( default: 'always', 'always' || 'never' || false )
490Enforce use of `$` when defining a variable. In Stylus using a `$` when defining a variable is optional, but is a good idea if you want to prevent ambiguity. Not including the `$` sets up situations where you wonder: "Is this a variable or a value?" For instance: `padding $default` is easier to understand than `padding default`.
491
492Yes, `default` isn't an acceptable value for `padding`, but at first glance you might not catch that since it just looks like a value. And now if you try to set `cursor default`, it's not going to behave the way you expect. All this pain and heartache could've been avoided if you just used a `$`.
493
494Example if always: prefer `$my-var = 0` over `my-var = 0`
495
496Example if never: prefer `my-var = 0` over `$my-var = 0`
497
498
499### quotePref ( default: false, 'single' || 'double' || false )
500Enforce consistent quotation style.
501
502Example if `'single'`: prefer `$var = 'some string'` over `$var = "some string"`
503
504Example if `'double'`: prefer `$var = "some string"` over `$var = 'some string'`
505
506
507### semicolons ( default: 'never', 'always' || 'never' || false )
508Enforce or disallow semicolons
509
510Example if always: prefer `margin 0;` over `margin 0`
511
512Example if never: prefer `margin 0` over `margin 0;`
513
514
515### sortOrder ( default: 'alphabetical', 'alphabetical' || 'grouped' || [Array] || false )
516Enforce a particular sort order when declaring properties. Throws a warning if you don't follow the order. If set to false, allow any order.
517
518Example if `'alphabetical'`:
519
520prefer this:
521```stylus
522.some-class
523 display block
524 float left
525 position absolute
526 right 10px
527 top 0
528```
529
530over this:
531```stylus
532.some-class
533 position absolute
534 top 0
535 right 10px
536 display block
537 float left
538```
539
540Example if `'grouped'` ([based on predefined grouped ordering](src/data/ordering.json#L2)):
541
542prefer this:
543```stylus
544.some-class
545 position absolute
546 top 0
547 right 10px
548 display block
549 float left
550```
551
552over this:
553```stylus
554.some-class
555 display block
556 float left
557 position absolute
558 right 10px
559 top 0
560```
561
562Example if `[ 'margin', 'padding', 'float', 'position' ]`:
563
564prefer this:
565```stylus
566.some-class
567 margin 0
568 padding 0
569 float left
570 position absolute
571 right 10px
572 top 0
573 display block
574```
575
576over this:
577```stylus
578.some-class
579 display block
580 float left
581 position absolute
582 right 10px
583 top 0
584 margin 0
585 padding 0
586```
587
588When set to `'grouped'` or `{Array}` throws a warning if properties that are not defined in the ordering array are not after those that should be ordered.
589
590
591### stackedProperties ( default: 'never', 'never' || false )
592No one-liners. Enforce putting properties on new lines.
593
594Example if `never`: prefer
595
596```stylus
597.className
598 padding 0
599```
600
601over
602
603`.className { padding 0 }`
604
605
606### trailingWhitespace ( default: 'never', 'never' || false )
607If false, ignores trailing white space. If 'never', trailing white space will throw a warning.
608
609
610### universal ( default: false, 'never' || false )
611Looks for instances of the inefficient * selector. Lots of resets use this, for good reason (resetting box model), but past that you really don't need this selector, and you should avoid it if possible.
612
613Example if never, disallow the following:
614```stylus
615div *
616 margin 0
617```
618
619
620### valid ( default: true, true || false )
621Check that a property is valid CSS or HTML.
622
623Example if true: `marg 0` will throw a warning, prefer `margin 0`
624
625Example if true: `divv` will throw a warning, prefer `div`
626
627
628### zeroUnits ( default: 'never', 'always' || 'never' || false )
629Looks for instances of `0px`. You don't need the px. Checks all units, not just px.
630
631Example if always: prefer `margin-right 0px` over `margin-right 0`
632
633Example if never: prefer `margin-right 0` over `margin-right 0em`
634
635
636### zIndexNormalize ( default: false, number or false )
637Enforce some (very) basic z-index sanity. Any number passed in will be used as the base for your z-index values. Throws an error if your value is not normalized.
638
639Example if set to 5: prefer `z-index 10` over `z-index 9`
640Example if set to 10: prefer `z-index 20` over `z-index 15`
641Example if set to 50: prefer `z-index 100` over `z-index 75`