UNPKG

22.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
7As part of your project: `npm install stylint --save-dev`
8
9As a cli tool: `npm install stylint -g`
10
11[changelog](changelog.md)
12
13[known issues](https://github.com/rossPatton/stylint/issues)
14
15If you have any problems with the linter just create a ticket there and I will respond.
16
17Same thing if you have any feature requests.
18
19I will gladly accept pull requests if you want to do the work yourself.
20
21you can also ping me [here](https://gitter.im/rossPatton/stylint)
22
23
24## CLI
25`-h` or `--help` Display list of commands
26
27`-w` or `--watch` Watch file or directory and run lint on change
28
29`-c` or `--config` Pass in location of custom config file
30
31`-v` or `--version` Display current version
32
33
34## Example cli Usage:
35`stylint` Run stylint on cwd
36
37`stylint path/to/filename.styl` Run stylint on a file
38
39`stylint path/to/dir --watch` Watch dir, run stylint on file change
40
41`stylint --help` Get list of commands
42
43`stylint --version` Get version number
44
45`stylint --config path/to/config/.configrc` Run stylint with custom config settings
46
47`stylint --reporter stylint-reporter-module` Run stylint with [custom reporter](#custom-reporters) module
48
49`stylint styl/ --watch -c path/to/config/.configrc` Watch dir, use custom config
50
51
52## Non CLI Usage
53I'll be the first to admit that the syntax is a bit weird, but it works just fine.
54```javascript
55const stylint = require('stylint')('path/to/stylus/', {
56 brackets: 'always',
57 namingConvention: 'BEM',
58 semicolons: 'always'
59}, callbackFn).create();
60```
61
62API docs are in the docs/ folder
63
64
65## Gulp
66You can use the CLI with [gulp-shell](https://github.com/sun-zheng-an/gulp-shell) like below:
67```javascript
68gulp.task('stylint', shell.task([
69 'stylint path/to/styl/ -c .stylintrc'
70]));
71```
72
73Or just use [gulp-stylint](https://github.com/danielhusar/gulp-stylint)
74```javascript
75var gulp = require('gulp');
76var stylint = require('gulp-stylint');
77
78gulp.task('default', function () {
79 return gulp.src('src/*.styl')
80 .pipe(stylint())
81});
82```
83
84## Grunt
85You can use [grunt-stylint](https://github.com/xdissent/grunt-stylint)
86
87```javascript
88grunt.initConfig({
89 stylint: {
90 options: {
91 config: {
92 colons: 'never'
93 }
94 },
95 src: ['src/**/*.styl']
96 }
97});
98```
99
100## Webpack
101You can use [stylint-loader](https://github.com/guerrero/stylint-loader)
102
103```javascript
104module.exports = {
105 // ...
106 module: {
107 preLoaders: [
108 {
109 test: /\.styl$/,
110 loader: 'stylint'
111 }
112 ],
113 loaders: [
114 {
115 test: /\.styl$/,
116 loader: 'style!css!stylus'
117 }
118 ]
119 }
120 // ...
121}
122```
123
124
125## As Part of Your Workflow
126Stylint integrations with both Sublime Text 3 and Atom.io are available.
127
128[Atom linter-stylint](https://atom.io/packages/linter-stylint)
129
130[SublimeLinter-contrib-stylint](https://packagecontrol.io/packages/SublimeLinter-contrib-stylint)
131
132
133## Why Write This Tool?
134Stylus 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.
135
136
137## Why Use This Tool?
138To 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.
139
140
141## Options
142The following is a list of all options available to stylint.
143
144Note that customProperties and mixins are aliases
145```json
146{
147 "blocks": false,
148 "brackets": "never",
149 "colons": "always",
150 "colors": "always",
151 "commaSpace": "always",
152 "commentSpace": "always",
153 "cssLiteral": "never",
154 "customProperties": [],
155 "depthLimit": false,
156 "duplicates": true,
157 "efficient": "always",
158 "exclude": [],
159 "extendPref": false,
160 "globalDupe": false,
161 "groupOutputByFile": true,
162 "indentPref": false,
163 "leadingZero": "never",
164 "maxErrors": false,
165 "maxWarnings": false,
166 "mixed": false,
167 "mixins": [],
168 "namingConvention": false,
169 "namingConventionStrict": false,
170 "none": "never",
171 "noImportant": true,
172 "parenSpace": false,
173 "placeholders": "always",
174 "prefixVarsWithDollar": "always",
175 "quotePref": false,
176 "reporterOptions": {
177 "columns": ["lineData", "severity", "description", "rule"],
178 "columnSplitter": " ",
179 "showHeaders": false,
180 "truncate": true
181 },
182 "semicolons": "never",
183 "sortOrder": "alphabetical",
184 "stackedProperties": "never",
185 "trailingWhitespace": "never",
186 "universal": false,
187 "valid": true,
188 "zeroUnits": "never",
189 "zIndexNormalize": false
190}
191```
192
193
194#### Custom Configuration
195Stylint will try to find a custom configuration in many different places before it falls back to the default config (see above). It goes in this order of importance:
196
1971. Pass in via function parameter (ie, using stylint programmatically)
1982. Passed in via command line flag
1993. Passed in via package.json, either as an object or path to a `.stylintrc` file
2004. Via a `.stylintrc` file, starting from the cwd and working up to the home user directory
2015. If all of the above fails, use the default config
202
203You can also use the `-c` or `--config` flags to pass in the location of your custom `.stylintrc` config file if it resides somewhere else.
204
205You can use the `stylintrc` property in your package.json to point to a `.stylintrc` file, or just directly pass in your config
206
207If requiring Stylint ( as opposed to using it via the cli ), the 2nd param is the config object.
208
209
210#### Severity
211Stylint 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.
212
213Example:
214```json
215{
216 "brackets": {
217 "expect": "never",
218 "error": true
219 },
220 "colons": {
221 "expect": "always",
222 "error": true
223 }
224}
225```
226
227
228## Custom Reporters
229Stylint 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.
230
231[Stylint-stylish](https://github.com/SimenB/stylint-stylish)
232
233[stylint-json-reporter](https://github.com/sertae/stylint-json-reporter)
234
235
236## Excluding files, directories, and code blocks from the linter
237
238### .stylintignore
239Before 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`
240
241For reference, it looks like this:
242
243```
244path/to/file.styl
245path/to/directory/
246```
247
248
249### the package.json approach
250You can also exclude files/directories via your package.json by adding a stylintignore property.
251
252For reference:
253
254```json
255{
256 "stylintignore": ["path/to/file.styl", "path/to/directory/"],
257}
258```
259
260
261### the config approach
262see config documentation below for how to use the exclude option via `.stylintrc` or your passed in config object
263
264
265### stylint toggle ( inline comment: @stylint off || @stylint on )
266Disable 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.
267
268For 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.
269
270Example:
271```stylus
272.button_block {
273 background: silver;
274 padding: 4px;
275}
276// @stylint off
277.button_block .btn-default {
278 background-color: green;
279 color: white;
280}
281// @stylint on
282```
283
284
285### ignore line toggle ( inline comment: @stylint ignore )
286A toggle that works like `@stylint off`, but just for one line. Useful for cases where you want to include fallback css for browser support.
287
288Example:
289```stylus
290.button-zoom
291 background-image: url('path/to/png.png') // @stylint ignore
292 background-image: url('path/to/svg.svg')
293 cursor: pointer // @stylint ignore
294 cursor: zoom-in
295```
296
297
298### transparent mixins / custom properties ( Array<string> )
299In Stylus you have the option of using mixins transparently, like css properties. Because of how Stylus' syntax works, this rule also allows you to add adhoc support for custom properties as needed by just added the name of the property to this array.
300
301```javascript
302>>> config file
303 "customProperties": ['myCustomProperty']
304
305>>> example.styl
306.className
307 myCustomProperty: 5px
308```
309
310Where `myCustomProperty` is a mixin that takes a px val as it's parameter.
311
312If you use nib, `size`, `absolute`, and `fixed` are often used in this way. If you use css-modules, `composes` is another one.
313
314Because of nib's widespread use, and css-modules growing popularity, the above 4 custom properties are supported by Stylint by default.
315
316
317### blocks ( default: false, 'always' || 'never' || false )
318When 'always' expect the `@block` keyword when defining block variables.
319When 'never', expect no `@block` keyword when defining block variables.
320When false, do not check either way.
321
322Example if 'always': prefer `my-block = @block ` over `my-block = `
323
324Example if 'never': prefer `my-block = ` over `my-block = @block `
325
326
327### brackets ( default: 'never', 'always' || 'never' || false )
328When 'always', expect {} when declaring a selector.
329When 'never', expect no brackets when declaring a selector.
330
331Example if 'always': prefer `.some-class-name {` over `.some-class-name`
332
333Example if 'never': prefer `.some-class-name ` over `.some-class-name {`
334
335
336### colons ( default: 'always', 'always' || 'never' || false )
337When 'always', expect : when declaring a property.
338When 'never', expect no : when declaring a property.
339
340Example if 'always': prefer `margin: 0` over `margin 0`
341
342Example if 'never: prefer `margin 0` over `margin: 0`
343
344
345### colors ( default: 'always' || false )
346When 'always', enforce variables when defining hex values
347
348Example if true: prefer `color $red` over `color #f00`
349
350
351### commaSpace ( default: 'always', 'always' || 'never' || false )
352Enforce or disallow spaces after commas.
353
354Example if always: prefer `rgba(0, 0, 0, .18)` over `rgba(0,0,0,.18)`
355
356Example if never: prefer `rgba(0,0,0,.18)` over `rgba(0, 0, 0, .18)`
357
358
359### commentSpace ( default: 'always', 'always' || 'never' || false )
360Enforce or disallow spaces after line comments
361
362Example if always: prefer `// comment` over `//comment`
363
364Example if never: prefer `//comment` over `// comment`
365
366
367### cssLiteral ( default: 'never', 'never' || false )
368By default Stylint ignores `@css` blocks. If set to true however, it will throw a warning if `@css` is used.
369
370Example if 'never': `@css` will throw a warning
371
372
373### depthLimit ( default: false, number or false )
374Set 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.
375
376Set to false if you don't want to check for this.
377
378
379### duplicates ( default: true, true || false )
380Checks 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).
381
382Example if true: the following will throw a warning:
383```stylus
384.test
385 margin 0
386 margin 5px
387```
388
389
390### efficient ( default: 'always', 'always' || 'never' || false )
391Check for places where properties can be written more efficiently.
392
393Example if always: prefer `margin 0` over `margin 0 0`
394
395Example if never: prefer `margin 0 0` over `margin 0`
396
397
398### exclude ( default: [], array of strings )
399Exclude certain file patterns from linting.
400
401Example: `["vendor/**/*", "node_modules/**/*"]` will exclude all files in the `vendor` or `node_modules` directory.
402
403
404### extendPref ( default: false, '@extend' || '@extends' || false )
405Pass 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.
406
407Example if set to `@extends`: prefer `@extends $some-var` over `@extend $some-var`
408
409Example if set to `@extend`: prefer `@extend $some-var` over `@extend $some-var`
410
411
412### globalDupe ( default: false, true || false )
413Works 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.
414
415Example if true: the following will throw a warning
416```stylus
417>>> file1.styl
418.test
419 margin 0
420
421>>> file2.styl
422.test
423 margin 5px
424```
425
426
427### groupOutputByFile ( default: true, true || false )
428Stylint's default setting groups errors and warnings by file when outputting. You can disable this if you want
429
430Example if true:
431```javascript
432path/to/file.styl
433 73:32 warning mixed spaces and tabs mixed
434 78:30 error missing semicolon semicolons
435
436path/to/file2.styl
437 16 warning prefer alphabetical when sorting properties sortOrder
438```
439
440Example if false:
441```javascript
442path/to/file.styl
443 73:32 warning mixed spaces and tabs mixed
444
445path/to/file.styl
446 78:30 error missing semicolon semicolons
447
448path/to/file2.styl
449 16 warning prefer alphabetical when sorting properties sortOrder
450```
451
452
453### indentPref ( default: false, number or false )
454This 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.
455
456If you set this to a number, it will output warnings/errors if you the # of spaces used for indenting differs from the number set.
457
458By default this value is false, so if you indent with spaces you'll need to manually set this value in a custom `.stylintrc` file.
459
460Example if 2: prefer `/s/smargin: 0` over `/s/s/smargin: 0`
461
462
463### leadingZero ( default: 'never', 'always' || 'never' || false )
464Enforce or disallow unnecessary leading zeroes on decimal points.
465
466Example if always: prefer `rgba( 0, 0, 0, 0.5 )` over `rgba( 0, 0, 0, .5 )`
467
468Example if never: prefer `rgba( 0, 0, 0, .5 )` over `rgba( 0, 0, 0, 0.5 )`
469
470
471### maxErrors ( default: false, number || false )
472Set 'max' number of Errors.
473
474
475### maxWarnings ( default: false, number || false )
476Set 'max' number of Warnings.
477
478
479### mixed ( default: false, boolean, relies on indentPref )
480Returns 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.
481
482If soft tabs, outputs warning/error if hard tabs used. If hard tabs, outputs warning/error if unnecessary extra spaces found.
483
484Example if indentPref: 4 and mixed: true: prefer `\s\s\s\smargin\s0` over `\tmargin\s0`
485
486Example if indentPref: 2 and mixed: true: prefer `\s\smargin\s0` over `\tmargin\s0`
487
488Example if indentPref: false and mixed: true: prefer `\tmargin\s0` over `\s\s\s\smargin\s0`
489
490
491### namingConvention ( default: false, false | 'lowercase-dash' | 'lowercase_underscore' | 'camelCase' | 'BEM' )
492Enforce a particular naming convention when declaring classes, ids, and variables. Throws a warning if you don't follow the convention.
493
494Example if set to `'lowercase-dash'`: prefer `$var-name` over `$var_name` or `$varName`
495
496Example if set to `'lowercase_underscore'`: prefer `$var_name` over `$var-name` or `$varName`
497
498Example if set to `'camelCase'`: prefer `$varName` over `$var_name` or `$var-name`
499
500Example if set to `'BEM'`: prefer `$var__like--this` over `$var_name` or `$varName`
501
502
503### namingConventionStrict ( default: false, true || false )
504By default, namingConvention only looks at variable names. If namingConventionStrict is set to true, namingConvention will also look at class and id names.
505
506If you have a lot of 3rd party css you can't change you might want to leave this off.
507
508
509### none ( default: 'never'. options: 'always' || never' || false )
510If 'always' check for places where `none` used instead of `0`.
511If 'never' check for places where `0` could be used instead of `none`.
512
513Example if 'always': prefer `border none` over `border 0`
514
515Example if 'never': prefer `outline 0` over `outline none`
516
517
518### noImportant ( default: true, true || false )
519If true, show warning when `!important` is found.
520
521Example if true: the following will throw a warning
522
523```stylus
524div
525 color red !important
526```
527
528
529### parenSpace ( default: false, 'always' || 'never' || false )
530Enforce or disallow use of extra spaces inside parens.
531
532Example if always: prefer `my-mixin( $myParam )` over `my-mixin($myParam)`
533
534Example if never: prefer `my-mixin($myParam)` over `my-mixin( $myParam )`
535
536
537### placeholder ( default: 'always', 'always' || 'never' || false )
538Enforce extending placeholder vars when using `@extend(s)`
539
540Example if always: prefer `@extends $placeholder` over `$extends .some-class`
541
542Example if never: prefer `@extends .some-class` over `$extends $placeholder`
543
544
545### prefixVarsWithDollar ( default: 'always', 'always' || 'never' || false )
546Enforce 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`.
547
548Yes, `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 `$`.
549
550Example if always: prefer `$my-var = 0` over `my-var = 0`
551
552Example if never: prefer `my-var = 0` over `$my-var = 0`
553
554
555### quotePref ( default: false, 'single' || 'double' || false )
556Enforce consistent quotation style.
557
558Example if `'single'`: prefer `$var = 'some string'` over `$var = "some string"`
559
560Example if `'double'`: prefer `$var = "some string"` over `$var = 'some string'`
561
562
563### reporterOptions ( Object )
564If using the default reporter, Stylint uses columnify when outputting warnings and errors (only if you have groupOutputByFile set to true). See [columnify](https://www.npmjs.com/package/columnify) for more details. Using this option, you can easily customize the output (to an extent) without having to install a separate reporter.
565
566Default options:
567```
568{
569 columns: ['lineData', 'severity', 'description', 'rule'],
570 columnSplitter: ' ',
571 showHeaders: false,
572 truncate: true
573}
574```
575
576
577### semicolons ( default: 'never', 'always' || 'never' || false )
578Enforce or disallow semicolons
579
580Example if always: prefer `margin 0;` over `margin 0`
581
582Example if never: prefer `margin 0` over `margin 0;`
583
584
585### sortOrder ( default: 'alphabetical', 'alphabetical' || 'grouped' || [Array] || false )
586Enforce a particular sort order when declaring properties. Throws a warning if you don't follow the order. If set to false, allow any order.
587
588Example if `'alphabetical'`:
589
590prefer this:
591```stylus
592.some-class
593 display block
594 float left
595 position absolute
596 right 10px
597 top 0
598```
599
600over this:
601```stylus
602.some-class
603 position absolute
604 top 0
605 right 10px
606 display block
607 float left
608```
609
610Example if `'grouped'` ([based on predefined grouped ordering](src/data/ordering.json#L2)):
611
612prefer this:
613```stylus
614.some-class
615 position absolute
616 top 0
617 right 10px
618 display block
619 float left
620```
621
622over this:
623```stylus
624.some-class
625 display block
626 float left
627 position absolute
628 right 10px
629 top 0
630```
631
632Example if `[ 'margin', 'padding', 'float', 'position' ]`:
633
634prefer this:
635```stylus
636.some-class
637 margin 0
638 padding 0
639 float left
640 position absolute
641 right 10px
642 top 0
643 display block
644```
645
646over this:
647```stylus
648.some-class
649 display block
650 float left
651 position absolute
652 right 10px
653 top 0
654 margin 0
655 padding 0
656```
657
658When 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.
659
660
661### stackedProperties ( default: 'never', 'never' || false )
662No one-liners. Enforce putting properties on new lines.
663
664Example if `never`: prefer
665
666```stylus
667.className
668 padding 0
669```
670
671over
672
673`.className { padding 0 }`
674
675
676### trailingWhitespace ( default: 'never', 'never' || false )
677If false, ignores trailing white space. If 'never', trailing white space will throw a warning.
678
679
680### universal ( default: false, 'never' || false )
681Looks 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.
682
683Example if never, disallow the following:
684```stylus
685div *
686 margin 0
687```
688
689
690### valid ( default: true, true || false )
691Check that a property is valid CSS or HTML.
692
693Example if true: `marg 0` will throw a warning, prefer `margin 0`
694
695Example if true: `divv` will throw a warning, prefer `div`
696
697
698### zeroUnits ( default: 'never', 'always' || 'never' || false )
699Looks for instances of `0px`. You don't need the px. Checks all units, not just px.
700
701Example if always: prefer `margin-right 0px` over `margin-right 0`
702
703Example if never: prefer `margin-right 0` over `margin-right 0em`
704
705
706### zIndexNormalize ( default: false, number or false )
707Enforce 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.
708
709Example if set to 5: prefer `z-index 10` over `z-index 9`
710Example if set to 10: prefer `z-index 20` over `z-index 15`
711Example if set to 50: prefer `z-index 100` over `z-index 75`