Configurable tool for writing clean, consistent SCSS
scss-lintis a tool to help keep your SCSS files clean and readable by running it against a collection of configurable linter rules. You can run it manually from the command line, or integrate it into your SCM hooks.
The Sass core team is now building Sass in Dart instead of Ruby, and will no longer be maintaining the Ruby implementation unless a maintainer steps up to help. Since the SCSS-Lint project relies on the Ruby Sass implementation, this means it will eventually not support the latest Sass features and bug fixes.
One alternative worthy of consideration is stylelint, which supports SCSS natively. If you want to use SCSS-specific rules in addition to stylelint core rules, you need to configure stylelint plugins like stylelint-scss or stylelint-order.
The SCSS-Lint project will continue to accept pull requests and provide basic support on the issue tracker.
gem install scss_lint
...or add the following to your
Gemfileand run
bundle install:
gem 'scss_lint', require: false
The
require: falseis necessary because
scss-lintmonkey patches Sass in order to properly traverse the parse tree created by the Sass parser. This can interfere with other applications that invoke the Sass parser after
scss-lintlibraries have been loaded at runtime, so you should only require it in the context in which you are linting, nowhere else.
Run
scss-lintfrom the command line by passing in a directory (or multiple directories) to recursively scan:
scss-lint app/assets/stylesheets/
You can also specify a list of files explicitly:
scss-lint app/assets/stylesheets/**/*.css.scss
...or you can lint a file passed via standard input (note the
--stdin-file-pathflag is required when passing via standard input):
cat some-file | scss-lint --stdin-file-path=path/to/treat/stdin/as/having.scss
scss-lintwill output any problems with your SCSS, including the offending filename and line number (if available).
Command Line Flag |
Description |
---|
-c/
--config| Specify a configuration file to use
-e/
--exclude| Exclude one or more files from being linted
-f/
--format| Output format (see Formatters)
-o/
--out| Write output to a file instead of STDOUT
-r/
--require| Require file/library (mind
$LOAD_PATH, uses
Kernel.require)
-i/
--include-linter| Specify which linters you specifically want to run
-x/
--exclude-linter| Specify which linters you don't want to run
--stdin-file-path| When linting a file passed via standard input, treat it as having the specified path to apply the appropriate configuration
--[no-]color| Whether to output in color
-h/
--help| Show command line flag documentation
--show-formatters| Show all available formatters
--show-linters| Show all available linters
-v/
--version| Show version
When running
scss-lintwith JRuby, using JRuby's
--devflag will probably improve performance.
scss-lintloads configuration in the following order of precedence:
--configflag
.scss-lint.ymlin the current working directory, if it exists
.scss-lint.ymlin the user's home directory, if it exists
All configurations extend the default configuration.
Note: The first configuration file found is the one that is loaded, e.g. the
.scss-lint.ymlfile in the current working directory is loaded instead of the one in the user's home directory—they are not merged with each other.
Here's an example configuration file:
scss_files: 'app/assets/stylesheets/**/*.css.scss'exclude: 'app/assets/stylesheets/plugins/**'
linters: BorderZero: enabled: false
Indentation: exclude: - 'path/to/file.scss' - 'path/to/directory/**' severity: warning width: 2
All linters have an
enabledoption which can be
trueor
false, which controls whether the linter is run, along with linter-specific options. The defaults are defined in
config/default.yml.
The
severitylinter option allows you to specify whether the lint should be treated as a
warningor an
error. Warnings cause
scss-lintto exit with a different error code than errors (unless both warnings and errors are present, in which case the
errorexit code is returned). This is useful when integrating
scss-lintwith build systems or other executables, as you can rely on its exit status code to indicate whether a lint actually requires attention.
You can also define the default severity for all linters by setting the global
severityoption.
The
excludedirective allows you to specify a glob pattern of files that should not be linted by
scss-lint. Paths are relative to the location of the config file itself if they are not absolute paths. If an inherited file specifies the
excludedirective, the two exclusion lists are combined. Any additional exclusions specified via the
--excludeflag are also combined. If you need to exclude files for a single linter you can specify the list of files using the linter's
excludeconfiguration option.
To start using
scss-lintyou can use the
ConfigFormatter, which will generate an
.scss-lint.ymlconfiguration file with all linters which caused a lint disabled. Starting with this as your configuration you can slowly enable each linter and fix any lints one by one.
For special cases where a particular lint doesn't make sense in a specific area of a file, special inline comments can be used to enable/disable linters. Some examples are provided below:
Disable for the entire file
scss // scss-lint:disable BorderZero p { border: none; // No lint reported }
Disable a few linters
scss // scss-lint:disable BorderZero, StringQuotes p { border: none; // No lint reported content: "hello"; // No lint reported }
Disable all lints within a block (and all contained blocks) ```scss p { // scss-lint:disable BorderZero border: none; // No lint reported }
a { border: none; // Lint reported } ```
Disable and enable again ```scss // scss-lint:disable BorderZero p { border: none; // No lint reported } // scss-lint:enable BorderZero
a { border: none; // Lint reported } ```
Disable for just one line ```scss p { // No lint reported: border: none; // scss-lint:disable BorderZero
a { border: none; // Lint reported } } ```
Disable/enable all linters ```scss // scss-lint:disable all p { border: none; // No lint reported } // scss-lint:enable all
a { border: none; // Lint reported } ```
The default formatter is intended to be easy to consume by both humans and external tools.
scss-lint [scss-files...]
test.scss:2:1 [W] StringQuotes: Prefer single quoted strings test.scss:2:1 [W] Indentation: Line should be indented 0 spaces, but was indented 1 space test.scss:5:1 [W] StringQuotes: Prefer single quoted strings test.scss:6:8 [W] UrlQuotes: URLs should be enclosed in quotes
Displays a list of all files that were free of lints.
Returns a valid
.scss-lint.ymlconfiguration where all linters which caused a lint are disabled. Starting with this as your configuration, you can slowly enable each linter and fix any lints one by one.
scss-lint --format=Config [scss-files...]
linters: Indentation: enabled: false StringQuotes: enabled: false UrlQuotes: enabled: false
Useful when you just want to open all offending files in an editor. This will just output the names of the files so that you can execute the following to open them all:
scss-lint --format=Files [scss-files...] | xargs vim
Outputs JSON with filenames and an array of issue objects.
{ "test.css": [ {"line": 2, "column": 1, "length": 2, "severity": "warning", "reason": "Prefer single quoted strings", "linter": "StringQuotes"}, {"line": 2, "column": 1, "length": 1, "severity": "warning", "reason": "Line should be indented 0 spaces, but was indented 1 spaces", "linter": "Indentation"}, {"line": 5, "column": 5, "length": 2, "severity": "warning", "reason": "Prefer single quoted strings", "linter": "StringQuotes"}, {"line": 6, "column": 4, "length": 9, "severity": "warning", "reason": "URLs should be enclosed in quotes", "linter": "UrlQuotes"} ] }
Outputs TAP version 13 format.
TAP version 13 1..5 ok 1 - ok1.scss not ok 2 - not-ok1.scss:123:10 SCSSLint::Linter::PrivateNamingConvention --- message: Description of lint 1 severity: warning data: file: not-ok1.scss line: 123 column: 10 --- not ok 3 - not-ok2.scss:20:2 SCSSLint::Linter::PrivateNamingConvention --- message: Description of lint 2 severity: error data: file: not-ok2.scss line: 20 column: 2 --- not ok 4 - not-ok2.scss:21:3 SCSSLint::Linter::PrivateNamingConvention --- message: Description of lint 3 severity: warning data: file: not-ok2.scss line: 21 column: 3 --- ok 5 - ok2.scss
Outputs statistics about how many lints of each type were found, and across how many files. This reporter can help in cleaning up a large codebase, allowing you to fix and then enable one lint type at a time.
15 ColorKeyword (across 1 files) 15 ColorVariable (across 1 files) 11 StringQuotes (across 11 files) 11 EmptyLineBetweenBlocks (across 11 files) 5 Indentation (across 1 files) 5 QualifyingElement (across 2 files) 4 MergeableSelector (across 1 files) -- ---------------------- ----------------- 66 total (across 12 files)
There are also formatters that integrate with third-party tools which are available as plugins.
Outputs an XML document with
, , and tags. Suitable for consumption by tools like Jenkins with the Checkstyle plugin.gem install scss_lint_reporter_checkstyle scss-lint --require=scss_lint_reporter_checkstyle --format=Checkstyle [scss-files...]
scss-linttries to use semantic exit statuses wherever possible, but the full list of codes and the conditions under which they are returned is listed here for completeness.
Exit Status |
Description |
---|
0| No lints were found
1| Lints with a severity of
warningwere reported (no errors)
2| One or more errors were reported (and any number of warnings)
64| Command line usage error (invalid flag, etc.)
66| One or more files specified were not found
69| Required library specified via
-r/
--requireflag was not found
70| Unexpected error (i.e. a bug); please report it
78| Invalid configuration file; your YAML is likely incorrect
80| Files glob patterns specified did not match any files.
scss-lintis a customizable tool with opinionated defaults that helps you enforce a consistent style in your SCSS. For these opinionated defaults, we've had to make calls about what we think are the "best" style conventions, even when there are often reasonable arguments for more than one possible style.
Should you want to customize the checks run against your code, you can do so by editing your configuration file to match your preferred style.
scss-lintallows you to create custom linters specific to your project. By default, it will load linters from the
.scss-lintersin the root of your repository. You can customize which directories to load from via the
plugin_directoriesoption in your
.scss-lint.ymlconfiguration file. See the linters directory for examples of how to write linters. All linters loaded from directories in
plugin_directoriesare enabled by default, and you can set their configuration in your
.scss-lint.yml.
# .scss-linters/another_linter.rbmodule SCSSLint class Linter::AnotherLinter < Linter include LinterRegistry
...
end end
# .scss-lint.yml plugin_directories: ['.scss-linters', '.another_directory']linters: AnotherLinter: enabled: true some_option: [1, 2, 3]
You can also load linters packaged as gems by specifying the gems via the
plugin_gemsconfiguration option. See the
scss_lint_plugin_examplefor an example of how to structure these plugins.
If the gem is packaged with an
.scss-lint.ymlfile in its root directory then this will be merged with your configuration. This provides a convenient way for organizations to define a single repo with their
scss-lintconfiguration and custom linters and use them across multiple projects. You can always override plugin configuration with your repo's
.scss-lint.ymlfile.
# .scss-lint.yml plugin_gems: ['scss_lint_plugin_example']
Note that you don't need to publish a gem to Rubygems to take advantage of this feature. Using Bundler, you can specify your plugin gem in your project's
Gemfileand reference its git repository instead:
# Gemfile gem 'scss_lint_plugin_example', git: 'git://github.com/cih/scss_lint_plugin_example'
As long as you execute
scss-lintvia
bundle exec scss-lint, it should be able to load the gem.
Sometimes SCSS files need to be preprocessed before being linted. This is made possible with two options that can be specified in your configuration file.
The
preprocess_commandoption specifies the command to run once per SCSS file. The command can be specified with arguments. The contents of a SCSS file will be written to STDIN, and the processed SCSS contents must be written to STDOUT. If the process exits with a code other than 0, scss-lint will immediately exit with an error.
For example,
preprocess_command: "cat"specifies a simple no-op preprocessor (on Unix-like systems).
catsimply writes the contents of STDIN back out to STDOUT.
Metadata codeblocks like Jekyll Front Matter at the beginning of SCSS files can cause a syntax error when SCSS-Lint does not encounter Sass at the first line of the file, e.g.
Invalid CSS after "@charset "utf-8"": expected "{", was ";". To search the first line for front matter's triple dash delimiter
---, strip out the YAML codeblock and pass the result to SCSS-Lint with line numbers preserved, you can use
preprocess_command: "sed '1{/^---$/{:a N;/---$/!ba;d}}'"-- please note this sed command is valid for gnu-sed. If you are using the FreeBSD version of sed that ships with Mac OS X by default, it will throw an EOF error. You may solve this error by installing Homebrew, running
brew install gnu-sed, and then substituting
gsedfor
sedin the
preprocess_command.
If only some SCSS files need to be preprocessed, you may use the
preprocess_filesoption to specify a list of file globs that need preprocessing. Preprocessing only a subset of files should make scss-lint more performant.
Codacy automates code reviews and monitors code quality on every commit and pull request. With Codacy you have scss-lint analysis out-of-the-box, and it is free for open source projects. It gives visibility into the technical debt and it can track code style and security issues, code coverage, code duplication, cyclomatic complexity and enforce best practices.
You can have
scss-lintautomatically run against your SCSS files after saving by using the Syntastic plugin. If you already have the plugin, just add
let g:syntastic_scss_checkers = ['scss_lint']to your
.vimrc.
Install the SCSS Lint plugin for IntelliJ
Install the Sublime scss-lint plugin.
Install the Atom scss-lint plugin. It is a part of the
atomlinterproject, so if you are already using other linter plugins, you can keep them in one place.
Install and enable both scss-mode and flycheck-mode. You can enable automatic linting for scss-mode buffers with
(add-hook 'scss-mode-hook 'flycheck-mode)in your
init.el.
If you use
TextMate 2, you can install the SCSS-Lint.tmbundle bundle.
If you use
Visual Studio Code, you can install the scss-lint extension
If you'd like to integrate
scss-lintinto your Git workflow, check out our Git hook manager, overcommit.
To execute
scss-lintvia a Rake task, ensure you have
rakein your gem path (e.g. by adding to your
Gemfile), and add the following to your
Rakefile:
require 'scss_lint/rake_task'SCSSLint::RakeTask.new
When you execute
rake scss_lint, the above configuration is equivalent to just running
scss-lint, which will lint all
.scssfiles in the current working directory and its descendants.
You can customize the task by writing:
require 'scss_lint/rake_task'SCSSLint::RakeTask.new do |t| t.config = 'custom/config.yml' t.args = ['--format', 'JSON', '--out', 'results.txt'] t.files = Dir.glob(['app/assets', 'custom/*.scss']) end
You can specify any command line arguments in the
argsattribute that are allowed by the
scss-lintRuby binary script. Each argument must be passed as an Array element, rather than one String with spaces.
You can also use this custom configuration with a set of files specified via the command line (note that this will not expand glob patterns):
# Single quotes prevent shell glob expansion rake 'scss_lint[app/assets, custom/file-with-a-literal-asterisk-*.scss]'
Files specified in this manner take precedence over the
filesattribute initialized in the configuration above.
Maven integration is available as part of the Sass maven plugin
scss-lintsince version 2.3 Check out the plugin documentation.
The Maven plugin comes with the necessary libraries included, a separate installation of
rubyor
scss-lintis not required.
Code documentation is generated with YARD and hosted by RubyDoc.info.
We love getting feedback with or without pull requests. If you do add a new feature, please add tests so that we can avoid breaking it in the future.
Speaking of tests, we use
rspec, which can be run like so:
bundle exec rspec
After you get the unit tests passing, you probably want to see your version of
scss-lintin action. You can use Bundler to execute your binary locally from within your project's directory:
bundle exec bin/scss-lint
All major discussion surrounding SCSS-Lint happens on the GitHub issues page.
You can also follow @scss_lint on Twitter.
If you're interested in seeing the changes and bug fixes between each version of
scss-lint, read the SCSS-Lint Changelog.
This project adheres to the Open Code of Conduct. By participating, you are expected to honor this code.
This project is released under the MIT license.