Repository: sasstools/sass-lint (js)

Issue:
Allow configuring 'include' option as an array in sass-lint.yml
We have our SCSS files in two separate folders, one for global styles and another where it is co-located with Angular components. From what I've seen in projects at two different companies this is a pretty typical file layout. In order to configure sass-lint to only see the actual paths we need, the only possibility at the moment is to specify `include: '**/*.scss'` and add *everything else* to the `ignore` list - but that is counter-intuitive and not really best practice since it's prone to breaking if anything in the project structure changes.

IMHO this asymmetry between `include` and `ignore` should be eliminated. `include` should be specifiable as an array just like `ignore`, thus significantly reducing the configuration complexity (because `ignore` can in many cases simply be ignored). ;)

Pull request:
Allow multiple input sources
Allows you to add an array of globs/patterns to the include property of sass-iints config and also specify multiple patterns/paths from the CLI

You can still pass a string of one pattern to the files property but it's my feeling that this should have been removed when ignores were added as it creates an alternative way of including files. Something we should remove in 2.0 i believe.

Happy for feedback on any of the documentation changes here or on the approach.

Closes #668

`<DCO 1.1 Signed-off-by: Dan Purdy dan@danpurdy.co.uk>`

Patch:
diff --git a/README.md b/README.md
index 691d989..555a4a7 100644
--- a/README.md
+++ b/README.md
@@ -7,6 +7,12 @@ A Node-only Sass linter for both `sass` and `scss` syntax!
 ## Install
 You can get `sass-lint` from [NPM](https://www.npmjs.com/package/sass-lint):
 
+Install globally
+```
+npm install -g sass-lint
+```
+
+To save to a project as a dev dependency
 ```
 npm install sass-lint --save-dev
 ```
@@ -45,13 +51,26 @@ The following are options that you can use to config the Sass Linter.
 
 #### Files
 
-The `files` option can either be set to a [glob](https://github.com/isaacs/node-glob) or it can be set to an object, where the key `include` is set to the glob you want to include, and `ignore` set to either a glob string or an array of glob strings that you would like to ignore.
+The `files` option contains two properties, `include` and `ignore`. Both can be set to either a [glob](https://github.com/isaacs/node-glob) or an array of glob strings/file paths depending on your projects' needs and setup.
 
+For example below we are providing a singular glob string to our include property and an array of patterns to our ignore property:
 ```yml
 files:
   include: 'sass/**/*.s+(a|c)ss'
   ignore:
-    - 'sass/vendor/**/*.*'
+    - 'sass/vendor/**/*.scss'
+    - 'sass/tests/**/*.scss'
+```
+
+As mentioned you can also provide an array to the include property like so
+```yml
+files:
+  include:
+    - 'sass/blocks/*.s+(a|c)ss'
+    - 'sass/elements/*.s+(a|c)ss'
+  ignore:
+    - 'sass/vendor/**/*.scss'
+    - 'sass/tests/**/*.scss'
 ```
 
 #### Rules
@@ -102,6 +121,33 @@ or with long form flags
 sass-lint --config app/config/.sass-lint.yml '**/*.scss' --verbose --no-exit
 ```
 
+#### Including multiple source destinations
+By default when specifying a directory/file to lint from the CLI you would do something similar to the following
+
+```
+sass-lint 'myapp/**/*.scss' -v -q
+```
+
+or with long form flags
+
+```
+sass-lint 'myapp/**/*.scss' --verbose --no-exit
+```
+> Notice that you need to wrap glob patterns in quotation marks
+
+If you want to specify multiple input sources then you need to include a single comma and a space `, ` to separate each pattern as shown in the following
+```
+sass-lint 'myapp/dir1/**.*.scss, myapp/dir2/**/*.scss' -v -q
+```
+
+or with long form flags
+
+```
+sass-lint 'myapp/dir1/**.*.scss, myapp/dir2/**/*.scss' --verbose --no-exit
+```
+
+If you don't include the extra space after the comma then the multiple patterns will not be interpreted correctly and you could see `sass-lint` fail.
+
 #### Ignore files/patterns
 To add a list of files to ignore `tests/**/*.scss, dist/other.scss` into the mix you could do the following:
 ```
@@ -113,7 +159,7 @@ sass-lint --config app/config/.sass-lint.yml '**/*.scss' --verbose --no-exit --i
 ```
 
 
-> Notice that glob patterns need to be wrapped in quotation or single quote marks in order to be passed to sass-lint correctly and if you want to ignore multiple paths you also need to wrap it in quotation marks and seperate each pattern/file with a comma and a space `, `.
+> Notice that glob patterns need to be wrapped in quotation or single quote marks in order to be passed to sass-lint correctly and if you want to ignore multiple paths you also need to wrap it in quotation marks and separate each pattern/file with a comma and a space `, `.
 
 This will be revisited and updated in `sass-lint` v2.0.0.
 
diff --git a/docs/cli/readme.md b/docs/cli/readme.md
index 739124d..9c1511a 100644
--- a/docs/cli/readme.md
+++ b/docs/cli/readme.md
@@ -2,7 +2,7 @@
 
 Sass Lint can be run via its Command Line Interface (CLI). To do so, run `sass-lint` from the command line.
 
-By default, the command will run against the glob defined by a user's `file.include` option in their config, or a glob (or single file) can be passed as the last argument to the CLI to be explicitly run against.
+By default, the command will run against the glob / array of globs defined by a user's `file.include` option in their config, or a glob / array of globs (or single files) can be passed as the last argument to the CLI to be explicitly run against.
 
 > Please note that when using glob patterns such as `folder/**/*.scss` as a command line argument (files to be linted or ignored) you will need to wrap the pattern in quotes or escape the `*` characters to prevent bash/zsh from automatically expanding the glob pattern.
 
@@ -22,3 +22,5 @@ Command Line Flag        | Description
 `-s`,`--syntax`           | Syntax to evaluate the given file(s) with, either sass or scss. Use with care: overrides filename extension-based syntax detection.
 `-v`,`--verbose`          | Verbose output (fully formatted output)
 `-V`,`--version`          | Outputs the version number of Sass Lint
+
+To see more on how to use the CLI you can view the examples included within sass-lint's [readme](https://github.com/sasstools/sass-lint/blob/develop/README.md#cli)
diff --git a/index.js b/index.js
index 252646f..cb1d540 100644
--- a/index.js
+++ b/index.js
@@ -156,31 +156,52 @@ sassLint.lintText = function (file, options, configPath) {
 sassLint.lintFiles = function (files, options, configPath) {
   var that = this,
       results = [],
+      includes = [],
       ignores = '';
 
+  // Files passed as a string on the command line
   if (files) {
     ignores = this.getConfig(options, configPath).files.ignore || '';
-    files = glob.sync(files, {ignore: ignores});
+    if (files.indexOf(', ') !== -1) {
+      files.split(', ').forEach(function (pattern) {
+        includes = includes.concat(glob.sync(pattern, {ignore: ignores}));
+      });
+    }
+    else {
+      includes = glob.sync(files, {ignore: ignores});
+    }
   }
+  // If not passed in then we look in the config file
   else {
     files = this.getConfig(options, configPath).files;
+    // A glob pattern of files can be just a string
     if (typeof files === 'string') {
-      files = glob.sync(files);
+      includes = glob.sync(files);
     }
+    // Look into the include property of files and check if there's an array of files
+    else if (files.include && files.include instanceof Array) {
+      files.include.forEach(function (pattern) {
+        includes = includes.concat(glob.sync(pattern, {ignore: files.ignore}));
+      });
+    }
+    // Or there is only one pattern in the include property of files
     else {
-      files = glob.sync(files.include, {
+      includes = glob.sync(files.include, {
         'ignore': files.ignore
       });
     }
   }
 
-  files.forEach(function (file) {
-    var lint = that.lintText({
-      'text': fs.readFileSync(file),
-      'format': options.syntax ? options.syntax : path.extname(file).replace('.', ''),
-      'filename': file
-    }, options, configPath);
-    results.push(lint);
+  includes.forEach(function (file, index) {
+    // Only lint non duplicate files from our glob results
+    if (includes.indexOf(file) === index) {
+      var lint = that.lintText({
+        'text': fs.readFileSync(file),
+        'format': options.syntax ? options.syntax : path.extname(file).replace('.', ''),
+        'filename': file
+      }, options, configPath);
+      results.push(lint);
+    }
   });
 
   return results;


Test patch:
diff --git a/tests/cli.js b/tests/cli.js
index ecb4a05..c873eae 100644
--- a/tests/cli.js
+++ b/tests/cli.js
@@ -34,6 +34,85 @@ describe('cli', function () {
     });
   });
 
+  it('Should accept multiple input paths', function (done) {
+    var command = 'sass-lint "tests/cli/cli-error.scss, tests/cli/cli-error.sass" --no-exit --verbose';
+
+    exec(command, function (err, stdout) {
+
+      if (err) {
+        return done(err);
+      }
+
+      assert(stdout.indexOf('.scss') !== -1);
+      assert(stdout.indexOf('.sass') !== -1);
+
+      return done();
+    });
+  });
+
+  it('Should accept multiple input globs', function (done) {
+    var command = 'sass-lint "tests/cli/*.scss, tests/cli/*.sass" --no-exit --verbose';
+
+    exec(command, function (err, stdout) {
+
+      if (err) {
+        return done(err);
+      }
+
+      assert(stdout.indexOf('.scss') !== -1);
+      assert(stdout.indexOf('.sass') !== -1);
+
+      return done();
+    });
+  });
+
+  it('Should accept multiple input paths from a config file', function (done) {
+    var command = 'sass-lint -c tests/yml/.multiple-inputs.yml --no-exit --verbose';
+
+    exec(command, function (err, stdout) {
+
+      if (err) {
+        return done(err);
+      }
+
+      assert(stdout.indexOf('.scss') !== -1);
+      assert(stdout.indexOf('.sass') !== -1);
+
+      return done();
+    });
+  });
+
+  it('Should accept multiple input paths and multiple ignore paths', function (done) {
+    var command = 'sass-lint "tests/cli/cli-error.scss, tests/cli/cli-error.sass" -i "tests/cli/cli-error.scss, tests/cli/cli-error.sass" --no-exit --verbose';
+
+    exec(command, function (err, stdout) {
+
+      if (err) {
+        return done(err);
+      }
+
+      assert(stdout.indexOf('.scss') === -1);
+      assert(stdout.indexOf('.sass') === -1);
+
+      return done();
+    });
+  });
+
+  it('Should accept multiple input paths and multiple ignores from a config file', function (done) {
+    var command = 'sass-lint -c tests/yml/.multiple-ignores.yml --no-exit --verbose';
+
+    exec(command, function (err, stdout) {
+
+      if (err) {
+        return done(err);
+      }
+      assert(stdout.indexOf('.scss') === -1);
+      assert(stdout.indexOf('.sass') === -1);
+
+      return done();
+    });
+  });
+
   it('CLI format option should output JSON', function (done) {
     var command = 'sass-lint -c tests/yml/.stylish-output.yml tests/cli/cli.scss --verbose --format json';
 
@@ -236,7 +315,7 @@ describe('cli', function () {
   });
 
   it('should not include ignored paths', function (done) {
-    var command = 'sass-lint -i **/*.scss -v -q --format json **/cli/*.scss';
+    var command = 'sass-lint -i "**/*.scss" -v -q --format json "**/cli/*.scss"';
 
     exec(command, function (err, stdout) {
 
@@ -251,7 +330,7 @@ describe('cli', function () {
   });
 
   it('should not include multiple ignored paths', function (done) {
-    var command = 'sass-lint -i \'**/*.scss, **/*.sass\' -q -v --format json';
+    var command = 'sass-lint -i "**/*.scss, **/*.sass" -q -v --format json';
 
     exec(command, function (err, stdout) {
 
diff --git a/tests/config.js b/tests/config.js
index f77906d..d00f838 100644
--- a/tests/config.js
+++ b/tests/config.js
@@ -139,30 +139,6 @@ describe('config', function () {
     done();
   });
 
-  it('should not merge custom option rules when `merge-default-rules` is false', function (done) {
-    var defaultConfig = yaml.safeLoad(fs.readFileSync(path.join(__dirname, '..', 'lib', 'config', 'sass-lint.yml'), 'utf8')),
-        tempOptions = custOptions(),
-        conf,
-        merged;
-
-    tempOptions.options['merge-default-rules'] = false;
-    conf = config(tempOptions);
-    merged = merge.recursive(tempOptions, defaultConfig);
-    merged.rules = tempOptions.rules;
-
-    assert(
-      equal(
-        conf,
-        merged,
-        {
-          'strict': true
-        }
-      )
-    );
-
-    done();
-  });
-
   it('should load a cached version of the config', function (done) {
     var tempOptions = {
           'options': {}
@@ -191,4 +167,30 @@ describe('config', function () {
 
     done();
   });
+
+  it('should not merge custom option rules when `merge-default-rules` is false', function (done) {
+    var defaultConfig = yaml.safeLoad(fs.readFileSync(path.join(__dirname, '..', 'lib', 'config', 'sass-lint.yml'), 'utf8')),
+        tempOptions = custOptions(),
+        conf,
+        merged;
+
+    tempOptions.options['merge-default-rules'] = false;
+    conf = config(tempOptions);
+    merged = merge.recursive(tempOptions, defaultConfig);
+    merged.rules = tempOptions.rules;
+
+    assert(
+      equal(
+        conf,
+        merged,
+        {
+          'strict': true
+        }
+      )
+    );
+
+    done();
+  });
+
+
 });
diff --git a/tests/main.js b/tests/main.js
index 4aed580..27a89bf 100644
--- a/tests/main.js
+++ b/tests/main.js
@@ -12,6 +12,13 @@ var lintFile = function lintFile (file, options, cb) {
   cb(results[0]);
 };
 
+var lintFiles = function lintFiles (files, options, configPath, cb) {
+  options = options || {};
+  var results = lint.lintFiles(files, options, configPath);
+
+  cb(results);
+};
+
 var resultsObj = [{
   filePath: 'app/scss/echo-base/defaults/utilities/_mixins.scss',
   warningCount: 3,
@@ -54,10 +61,49 @@ var resultsObj = [{
   }]
 }];
 
+var multiInputResults = [{
+  filePath: 'tests/cli/cli-error.sass',
+  warningCount: 1,
+  errorCount: 0,
+  messages: [{
+    ruleId: 'no-ids',
+    line: 1,
+    column: 1,
+    message: 'ID selectors not allowed',
+    severity: 1
+  }]
+}, {
+  filePath: 'tests/cli/cli-error.scss',
+  warningCount: 1,
+  errorCount: 0,
+  messages: [{
+    ruleId: 'no-ids',
+    line: 1,
+    column: 1,
+    message: 'ID selectors not allowed',
+    severity: 1
+  }]
+}];
+
+var stringInputResults = [{
+  filePath: 'tests/cli/cli-error.sass',
+  warningCount: 1,
+  errorCount: 0,
+  messages: [{
+    ruleId: 'no-ids',
+    line: 1,
+    column: 1,
+    message: 'ID selectors not allowed',
+    severity: 1
+  }]
+}];
+
 describe('sass lint', function () {
-  //////////////////////////////
-  // Not Error on Empty Files
-  //////////////////////////////
+
+  // ==============================================================================
+  //  Not Error on Empty Files
+  // ==============================================================================
+
   it('should not error if a file is empty', function (done) {
     lintFile('empty-file.scss', function (data) {
       assert.equal(0, data.warningCount);
@@ -67,9 +113,10 @@ describe('sass lint', function () {
     });
   });
 
-  //////////////////////////////
-  // Parse Errors should return as lint errors
-  //////////////////////////////
+  // ==============================================================================
+  //  Parse Errors should return as lint errors
+  // ==============================================================================
+
   it('Parse Errors should return as lint errors', function (done) {
     lintFile('parse.scss', function (data) {
       assert.equal(1, data.errorCount);
@@ -112,36 +159,77 @@ describe('sass lint', function () {
       done();
     });
   });
-});
 
-describe('sassLint detect counts', function () {
-  //////////////////////////////
-  // Error count
-  //////////////////////////////
-  it('should equal 2 errors', function (done) {
-    var result = lint.errorCount(resultsObj);
+  // ==============================================================================
+  //  Lint files with config path
+  // ==============================================================================
 
-    assert.equal(2, result.count);
-    done();
-  });
+  describe('sassLint Config load', function () {
+    it('should accept multiple input sources in a config', function (done) {
+      lintFiles(null, {options: {'cache-config': false}}, 'tests/yml/.multiple-inputs.yml', function (data) {
+        assert.deepEqual(data, multiInputResults);
+        done();
+      });
+    });
 
-  //////////////////////////////
-  // Warning count
-  //////////////////////////////
-  it('should equal 3 warnings', function (done) {
-    var result = lint.warningCount(resultsObj);
+    it('should accept multiple input sources and ignores in a config', function (done) {
+      lintFiles(null, {options: {'cache-config': false}}, 'tests/yml/.multiple-ignores.yml', function (data) {
+        assert.deepEqual(data, []);
+        done();
+      });
+    });
 
-    assert.equal(3, result.count);
-    done();
+    it('should accept singular string input sources', function (done) {
+      lintFiles(null, {options: {'cache-config': false}}, 'tests/yml/.single-input-include-string.yml', function (data) {
+        assert.deepEqual(data, stringInputResults);
+        done();
+      });
+    });
+
+    it('should accept singular string input sources and ignores in a config file', function (done) {
+      lintFiles(null, {options: {'cache-config': false}}, 'tests/yml/.multiple-ignore-strings.yml', function (data) {
+        assert.deepEqual(data, []);
+        done();
+      });
+    });
   });
 
-  //////////////////////////////
-  // Result count
-  //////////////////////////////
-  it('should equal 5 overall detects', function (done) {
-    var result = lint.resultCount(resultsObj);
+  // ==============================================================================
+  //  Counters
+  // ==============================================================================
+
+  describe('sassLint detect counts', function () {
+    // ==============================================================================
+    //  Error Count
+    // ==============================================================================
 
-    assert.equal(5, result);
-    done();
+    it('should equal 2 errors', function (done) {
+      var result = lint.errorCount(resultsObj);
+
+      assert.equal(2, result.count);
+      done();
+    });
+
+    // ==============================================================================
+    //  Warning count
+    // ==============================================================================
+
+    it('should equal 3 warnings', function (done) {
+      var result = lint.warningCount(resultsObj);
+
+      assert.equal(3, result.count);
+      done();
+    });
+
+    // ==============================================================================
+    //  Result count
+    // ==============================================================================
+
+    it('should equal 5 overall detects', function (done) {
+      var result = lint.resultCount(resultsObj);
+
+      assert.equal(5, result);
+      done();
+    });
   });
 });
diff --git a/tests/yml/.multiple-ignore-strings.yml b/tests/yml/.multiple-ignore-strings.yml
new file mode 100644
index 0000000..1fb0a5f
--- /dev/null
+++ b/tests/yml/.multiple-ignore-strings.yml
@@ -0,0 +1,60 @@
+options:
+  formatter: stylish
+  cache-config: false
+  merge-default-rules: false
+files:
+  include: 'tests/cli/cli-error.sass'
+  ignore: 'tests/cli/cli-error.sass'
+rules:
+  # Extends
+  extends-before-mixins: 0
+  extends-before-declarations: 0
+  placeholder-in-extend: 0
+
+  # Mixins
+  mixins-before-declarations: 0
+
+  # Line Spacing
+  one-declaration-per-line: 0
+  empty-line-between-blocks: 0
+  single-line-per-selector: 0
+
+  # Disallows
+  no-debug: 0
+  no-duplicate-properties: 0
+  no-empty-rulesets: 0
+  no-extends: 0
+  no-ids: 1
+  no-important: 0
+  no-warn: 0
+  no-color-keywords: 0
+  no-invalid-hex: 0
+  no-css-comments: 0
+  no-color-literals: 0
+
+  # Style Guide
+  border-zero: 0
+  clean-import-paths: 0
+  empty-args: 0
+  hex-length: 0
+  hex-notation: 0
+  indentation: 0
+  leading-zero: 0
+  nesting-depth: 0
+  property-sort-order: 0
+  quotes: 0
+  variable-for-property: 0
+  zero-unit: 0
+
+  # Inner Spacing
+  space-after-comma: 0
+  space-before-colon: 0
+  space-after-colon: 0
+  space-before-brace: 0
+  space-before-bang: 0
+  space-after-bang: 0
+  space-between-parens: 0
+
+  # Final Items
+  trailing-semicolon: 0
+  final-newline: 0
diff --git a/tests/yml/.multiple-ignores.yml b/tests/yml/.multiple-ignores.yml
new file mode 100644
index 0000000..310a007
--- /dev/null
+++ b/tests/yml/.multiple-ignores.yml
@@ -0,0 +1,64 @@
+options:
+  formatter: stylish
+  cache-config: false
+  merge-default-rules: false
+files:
+  include:
+    - 'tests/cli/cli-error.sass'
+    - 'tests/cli/cli-error.scss'
+  ignore:
+    - 'tests/cli/cli-error.sass'
+    - 'tests/cli/cli-error.scss'
+rules:
+  # Extends
+  extends-before-mixins: 0
+  extends-before-declarations: 0
+  placeholder-in-extend: 0
+
+  # Mixins
+  mixins-before-declarations: 0
+
+  # Line Spacing
+  one-declaration-per-line: 0
+  empty-line-between-blocks: 0
+  single-line-per-selector: 0
+
+  # Disallows
+  no-debug: 0
+  no-duplicate-properties: 0
+  no-empty-rulesets: 0
+  no-extends: 0
+  no-ids: 1
+  no-important: 0
+  no-warn: 0
+  no-color-keywords: 0
+  no-invalid-hex: 0
+  no-css-comments: 0
+  no-color-literals: 0
+
+  # Style Guide
+  border-zero: 0
+  clean-import-paths: 0
+  empty-args: 0
+  hex-length: 0
+  hex-notation: 0
+  indentation: 0
+  leading-zero: 0
+  nesting-depth: 0
+  property-sort-order: 0
+  quotes: 0
+  variable-for-property: 0
+  zero-unit: 0
+
+  # Inner Spacing
+  space-after-comma: 0
+  space-before-colon: 0
+  space-after-colon: 0
+  space-before-brace: 0
+  space-before-bang: 0
+  space-after-bang: 0
+  space-between-parens: 0
+
+  # Final Items
+  trailing-semicolon: 0
+  final-newline: 0
diff --git a/tests/yml/.multiple-inputs.yml b/tests/yml/.multiple-inputs.yml
new file mode 100644
index 0000000..d6162ba
--- /dev/null
+++ b/tests/yml/.multiple-inputs.yml
@@ -0,0 +1,61 @@
+options:
+  formatter: stylish
+  cache-config: false
+  merge-default-rules: false
+files:
+  include:
+    - 'tests/cli/cli-error.sass'
+    - 'tests/cli/cli-error.scss'
+rules:
+  # Extends
+  extends-before-mixins: 0
+  extends-before-declarations: 0
+  placeholder-in-extend: 0
+
+  # Mixins
+  mixins-before-declarations: 0
+
+  # Line Spacing
+  one-declaration-per-line: 0
+  empty-line-between-blocks: 0
+  single-line-per-selector: 0
+
+  # Disallows
+  no-debug: 0
+  no-duplicate-properties: 0
+  no-empty-rulesets: 0
+  no-extends: 0
+  no-ids: 1
+  no-important: 0
+  no-warn: 0
+  no-color-keywords: 0
+  no-invalid-hex: 0
+  no-css-comments: 0
+  no-color-literals: 0
+
+  # Style Guide
+  border-zero: 0
+  clean-import-paths: 0
+  empty-args: 0
+  hex-length: 0
+  hex-notation: 0
+  indentation: 0
+  leading-zero: 0
+  nesting-depth: 0
+  property-sort-order: 0
+  quotes: 0
+  variable-for-property: 0
+  zero-unit: 0
+
+  # Inner Spacing
+  space-after-comma: 0
+  space-before-colon: 0
+  space-after-colon: 0
+  space-before-brace: 0
+  space-before-bang: 0
+  space-after-bang: 0
+  space-between-parens: 0
+
+  # Final Items
+  trailing-semicolon: 0
+  final-newline: 0
diff --git a/tests/yml/.single-input-include-string.yml b/tests/yml/.single-input-include-string.yml
new file mode 100644
index 0000000..57693d3
--- /dev/null
+++ b/tests/yml/.single-input-include-string.yml
@@ -0,0 +1,59 @@
+options:
+  formatter: stylish
+  cache-config: false
+  merge-default-rules: false
+files:
+  include: 'tests/cli/cli-error.sass'
+rules:
+  # Extends
+  extends-before-mixins: 0
+  extends-before-declarations: 0
+  placeholder-in-extend: 0
+
+  # Mixins
+  mixins-before-declarations: 0
+
+  # Line Spacing
+  one-declaration-per-line: 0
+  empty-line-between-blocks: 0
+  single-line-per-selector: 0
+
+  # Disallows
+  no-debug: 0
+  no-duplicate-properties: 0
+  no-empty-rulesets: 0
+  no-extends: 0
+  no-ids: 1
+  no-important: 0
+  no-warn: 0
+  no-color-keywords: 0
+  no-invalid-hex: 0
+  no-css-comments: 0
+  no-color-literals: 0
+
+  # Style Guide
+  border-zero: 0
+  clean-import-paths: 0
+  empty-args: 0
+  hex-length: 0
+  hex-notation: 0
+  indentation: 0
+  leading-zero: 0
+  nesting-depth: 0
+  property-sort-order: 0
+  quotes: 0
+  variable-for-property: 0
+  zero-unit: 0
+
+  # Inner Spacing
+  space-after-comma: 0
+  space-before-colon: 0
+  space-after-colon: 0
+  space-before-brace: 0
+  space-before-bang: 0
+  space-after-bang: 0
+  space-between-parens: 0
+
+  # Final Items
+  trailing-semicolon: 0
+  final-newline: 0