Repository: sasstools/sass-lint (js)

Issue:
Bug: clean-import-paths errors on CSS import
Running gulp task with Sass Lint 1.1.0

The following code
```
@if variable-exists(google-fonts-url) {
  @import url($google-fonts-url);
}
```

throws this error
```
/Users/minamarkham/fooBar/node_modules/gulp-sass-lint/node_modules/sass-lint/lib/rules/clean-import-paths.js:36
          var importPath = stripQuotes(parent.first('string').content),
                                                             ^
TypeError: Cannot read property 'content' of undefined
    at /Users/minamarkham/fooBar/node_modules/gulp-sass-lint/node_modules/sass-lint/lib/rules/clean-import-paths.js:36:62
    at Node.traverse (/Users/minamarkham/fooBar/node_modules/gulp-sass-lint/node_modules/sass-lint/node_modules/gonzales-pe/lib/node/basic-node.js:1:3265)
    at Node.traverse (/Users/minamarkham/fooBar/node_modules/gulp-sass-lint/node_modules/sass-lint/node_modules/gonzales-pe/lib/node/basic-node.js:1:3407)
    at /Users/minamarkham/fooBar/node_modules/gulp-sass-lint/node_modules/sass-lint/lib/rules/clean-import-paths.js:33:15
    at RootNode.traverseByType (/Users/minamarkham/fooBar/node_modules/gulp-sass-lint/node_modules/sass-lint/node_modules/gonzales-pe/lib/node/root-node.js:1:1739)
    at Object.module.exports.detect (/Users/minamarkham/fooBar/node_modules/gulp-sass-lint/node_modules/sass-lint/lib/rules/clean-import-paths.js:32:9)
    at /Users/minamarkham/fooBar/node_modules/gulp-sass-lint/node_modules/sass-lint/index.js:30:25
    at Array.forEach (native)
    at Function.sassLint.lintText (/Users/minamarkham/fooBar/node_modules/gulp-sass-lint/node_modules/sass-lint/index.js:29:9)
    at DestroyableTransform._transform (/Users/minamarkham/fooBar/node_modules/gulp-sass-lint/index.js:32:27)
```

Pull request:
Fix Clean Import Path bug when concerning CSS
Update rule to ignore @import when concerning CSS files

Fixes #95 

DCO 1.1 Signed-off-by: Ben Griffith <gt11687@gmail.com>

Patch:
diff --git a/lib/rules/clean-import-paths.js b/lib/rules/clean-import-paths.js
index 3faea5b..282e245 100644
--- a/lib/rules/clean-import-paths.js
+++ b/lib/rules/clean-import-paths.js
@@ -20,6 +20,17 @@ var getExtension = function (filename) {
   return filename.substr(lastIndex + 1);
 };
 
+var getImportPath = function (parent) {
+  if (parent.first('string')) {
+    return parent.first('string');
+  }
+  else if (parent.first('uri')) {
+    return parent.first('uri');
+  }
+
+  return false;
+};
+
 module.exports = {
   'name': 'import-path',
   'defaults': {
@@ -32,54 +43,59 @@ module.exports = {
     ast.traverseByType('atkeyword', function (keyword, i, parent) {
       keyword.traverse(function (item) {
         if (item.content === 'import') {
+          var importPathNode = getImportPath(parent);
 
-          var importPath = stripQuotes(parent.first('string').content),
-              filename = getFilename(importPath),
-              fileExtension = getExtension(filename);
+          if (importPathNode && importPathNode.type === 'string') {
+            var importPath = stripQuotes(importPathNode.content),
+                filename = getFilename(importPath),
+                fileExtension = getExtension(filename);
 
-          if (filename.charAt(0) === '_') {
-            if (!parser.options['leading-underscore']) {
-              result = helpers.addUnique(result, {
-                'ruleId': parser.rule.name,
-                'line': item.start.line,
-                'column': item.start.column,
-                'message': 'Leading underscores are not allowed',
-                'severity': parser.severity
-              });
-            }
-          }
-          else {
-            if (parser.options['leading-underscore']) {
-              result = helpers.addUnique(result, {
-                'ruleId': parser.rule.name,
-                'line': item.start.line,
-                'column': item.start.column,
-                'message': 'Leading underscores are required',
-                'severity': parser.severity
-              });
-            }
-          }
+            if (fileExtension !== 'css') {
+              if (filename.charAt(0) === '_') {
+                if (!parser.options['leading-underscore']) {
+                  result = helpers.addUnique(result, {
+                    'ruleId': parser.rule.name,
+                    'line': item.start.line,
+                    'column': item.start.column,
+                    'message': 'Leading underscores are not allowed',
+                    'severity': parser.severity
+                  });
+                }
+              }
+              else {
+                if (parser.options['leading-underscore']) {
+                  result = helpers.addUnique(result, {
+                    'ruleId': parser.rule.name,
+                    'line': item.start.line,
+                    'column': item.start.column,
+                    'message': 'Leading underscores are required',
+                    'severity': parser.severity
+                  });
+                }
+              }
 
-          if (fileExtension) {
-            if (!parser.options['filename-extension']) {
-              result = helpers.addUnique(result, {
-                'ruleId': parser.rule.name,
-                'line': item.start.line,
-                'column': item.start.column,
-                'message': 'File extensions are not allowed',
-                'severity': parser.severity
-              });
-            }
-          }
-          else {
-            if (parser.options['filename-extension']) {
-              result = helpers.addUnique(result, {
-                'ruleId': parser.rule.name,
-                'line': item.start.line,
-                'column': item.start.column,
-                'message': 'File extensions are required',
-                'severity': parser.severity
-              });
+              if (fileExtension) {
+                if (!parser.options['filename-extension']) {
+                  result = helpers.addUnique(result, {
+                    'ruleId': parser.rule.name,
+                    'line': item.start.line,
+                    'column': item.start.column,
+                    'message': 'File extensions are not allowed',
+                    'severity': parser.severity
+                  });
+                }
+              }
+              else {
+                if (parser.options['filename-extension']) {
+                  result = helpers.addUnique(result, {
+                    'ruleId': parser.rule.name,
+                    'line': item.start.line,
+                    'column': item.start.column,
+                    'message': 'File extensions are required',
+                    'severity': parser.severity
+                  });
+                }
+              }
             }
           }
         }


Test patch:
diff --git a/tests/main.js b/tests/main.js
index 48a5870..43826a1 100644
--- a/tests/main.js
+++ b/tests/main.js
@@ -834,4 +834,81 @@ describe('rule', function () {
       done();
     });
   });
+
+  //////////////////////////////
+  // Clean Import Paths
+  //////////////////////////////
+
+  // Default
+  it('clean import paths - [leading-underscore: false, filename-extension: false]', function (done) {
+    lintFile('clean-import-paths.scss', {
+      'options': {
+        'merge-default-rules': false
+      },
+      'rules': {
+        'clean-import-paths': 1
+      }
+    }, function (data) {
+      assert.equal(8, data.warningCount);
+      done();
+    });
+  });
+
+  it('clean import paths - [leading-underscore: true, filename-extension: false]', function (done) {
+    lintFile('clean-import-paths.scss', {
+      'options': {
+        'merge-default-rules': false
+      },
+      'rules': {
+        'clean-import-paths': [
+          1,
+          {
+            'leading-underscore': true
+          }
+        ]
+      }
+    }, function (data) {
+      assert.equal(8, data.warningCount);
+      done();
+    });
+  });
+
+  it('clean import paths - [leading-underscore: false, filename-extension: true]', function (done) {
+    lintFile('clean-import-paths.scss', {
+      'options': {
+        'merge-default-rules': false
+      },
+      'rules': {
+        'clean-import-paths': [
+          1,
+          {
+            'filename-extension': true
+          }
+        ]
+      }
+    }, function (data) {
+      assert.equal(8, data.warningCount);
+      done();
+    });
+  });
+
+  it('clean import paths - [leading-underscore: true, filename-extension: true]', function (done) {
+    lintFile('clean-import-paths.scss', {
+      'options': {
+        'merge-default-rules': false
+      },
+      'rules': {
+        'clean-import-paths': [
+          1,
+          {
+            'leading-underscore': true,
+            'filename-extension': true
+          }
+        ]
+      }
+    }, function (data) {
+      assert.equal(8, data.warningCount);
+      done();
+    });
+  });
 });
diff --git a/tests/sass/clean-import-paths.scss b/tests/sass/clean-import-paths.scss
index 6d6126f..bcc4ad1 100644
--- a/tests/sass/clean-import-paths.scss
+++ b/tests/sass/clean-import-paths.scss
@@ -13,3 +13,15 @@
 // Both leading underscores and filename extensions
 @import '_foo.scss';
 @import 'bar/_foo.scss';
+
+// CSS imports - ignore
+@import url('fineprint.css');
+@import url('bluish.css') projection, tv;
+@import 'custom.css';
+@import url('chrome://communicator/skin/');
+@import 'common.css' screen, projection;
+@import url('landscape.css') screen and (orientation: landscape);
+
+@if variable-exists(google-fonts-url) {
+  @import url($google-fonts-url);
+}