Repository: twbs/bootlint
Pull request #367 (2016-03-21 13:07:37)

#366 - 2 new lint checks: disallow pull-left/right on .row and .col-*-* classes
A fix for #366 which I created an issue for this morning.  Seemed easy enough to fix, so I made new rules for this.

New rule **E050** will disallow `.pull-right` and `.pull-left` on the same element as a `.col-*-*` class

```
<div class="col-sm-7 pull-right">
```

New rule **E051** will disallow `.pull-right` and `.pull-left` on the same element as a `.row` class

```
<div class="row pull-left">
```


chrismbarr: @XhmikosR I also fixed this one

Patch:
diff --git a/.gitignore b/.gitignore
index a02df4b..ebf2dfa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,23 +8,18 @@ pids
 *.seed
 
 # Directory for instrumented libs generated by jscoverage/JSCover
-lib-cov
+lib-cov/
 
-# Coverage directory used by tools like istanbul
-coverage
+coverage/
 *-cov
 
 # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
 .grunt
 
-# Compiled binary addons (http://nodejs.org/api/addons.html)
-build/Release
-
-# Dependency directory
-# Deployed apps should consider commenting this line out:
-# see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git
-node_modules
-
+node_modules/
+/bootstrap/
+.bundle/
+vendor/
 
 # Vim generated files
 *.swp
diff --git a/.travis.yml b/.travis.yml
index 0a2b9a2..5187687 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,37 +1,31 @@
-{
-    "sudo": false,
-    "dist": "trusty",
-    "language": "node_js",
-    "node_js": ["4", "8"],
-    "before_install": [
-        "if [[ `npm -v` != 5* ]]; then npm install -g npm@5; fi"
-    ],
-    "install": [
-        "npm install -g grunt-cli",
-        "npm install",
-        "bundle install --deployment --jobs=3 --retry=3"
-    ],
-    "before_script": [
-        "git clone --depth 1 https://github.com/twbs/bootstrap.git --branch v3-dev",
-        "pushd bootstrap && jekyll build; popd"
-    ],
-    "matrix": [
-        "fast_finish": true
-    ],
-    "script": [
-        "npm test",
-        "./src/cli-main.js bootstrap/_gh_pages/**/index.html",
-        "./src/cli-main.js --disable W003,E001 test/fixtures/doctype/missing.html test/fixtures/viewport/missing.html",
-        "./src/cli-main.js test/fixtures/x-ua-compatible/missing.html &> x-ua-compatible-missing.output.actual.txt || true",
-        "diff test/fixtures/cli/x-ua-compatible-missing.output.txt x-ua-compatible-missing.output.actual.txt"
-    ],
-    "after_script": [
-        "npm run coveralls"
-    ],
-    "cache": {
-        "directories": [
-            "node_modules",
-            "vendor/bundle"
-        ]
-    }
-}
+sudo: false
+dist: trusty
+language: node_js
+git:
+    depth: 10
+node_js:
+    - "4"
+    - "8"
+before_install:
+    - if [[ `npm -v` != 5* ]]; then npm install -g npm@5; fi
+install:
+    - npm install -g grunt-cli
+    - npm install
+before_script:
+    - git clone --depth 1 https://github.com/twbs/bootstrap.git --branch v3-dev
+    - bundle install --deployment --path "$(pwd)/vendor/bundle" --gemfile bootstrap/Gemfile --jobs=3 --retry=3
+    - pushd bootstrap && bundle exec jekyll build && popd
+script:
+    - npm test
+    - node ./src/cli-main.js --disable W003,W005 "bootstrap/_gh_pages/**/index.html"
+    - node ./src/cli-main.js --disable W003,E001 test/fixtures/doctype/missing.html test/fixtures/viewport/missing.html
+    - node ./src/cli-main.js test/fixtures/x-ua-compatible/missing.html &> x-ua-compatible-missing.output.actual.txt || true
+    - diff test/fixtures/cli/x-ua-compatible-missing.output.txt x-ua-compatible-missing.output.actual.txt
+after_script:
+    - npm run coveralls
+matrix:
+    fast_finish: true
+cache:
+    directories:
+        - node_modules
+        - vendor/bundle
diff --git a/Gemfile b/Gemfile
deleted file mode 100644
index 2270004..0000000
--- a/Gemfile
+++ /dev/null
@@ -1,5 +0,0 @@
-source 'https://rubygems.org'
-
-group :development, :test do
-    gem 'jekyll', '~> 3.4.5'
-end
diff --git a/Gemfile.lock b/Gemfile.lock
deleted file mode 100644
index ba0b6ec..0000000
--- a/Gemfile.lock
+++ /dev/null
@@ -1,53 +0,0 @@
-GEM
-  remote: https://rubygems.org/
-  specs:
-    addressable (2.5.1)
-      public_suffix (~> 2.0, >= 2.0.2)
-    colorator (1.1.0)
-    ffi (1.9.18)
-    ffi (1.9.18-x64-mingw32)
-    forwardable-extended (2.6.0)
-    jekyll (3.4.5)
-      addressable (~> 2.4)
-      colorator (~> 1.0)
-      jekyll-sass-converter (~> 1.0)
-      jekyll-watch (~> 1.1)
-      kramdown (~> 1.3)
-      liquid (~> 3.0)
-      mercenary (~> 0.3.3)
-      pathutil (~> 0.9)
-      rouge (~> 1.7)
-      safe_yaml (~> 1.0)
-    jekyll-sass-converter (1.5.0)
-      sass (~> 3.4)
-    jekyll-watch (1.5.0)
-      listen (~> 3.0, < 3.1)
-    kramdown (1.14.0)
-    liquid (3.0.6)
-    listen (3.0.8)
-      rb-fsevent (~> 0.9, >= 0.9.4)
-      rb-inotify (~> 0.9, >= 0.9.7)
-    mercenary (0.3.6)
-    pathutil (0.14.0)
-      forwardable-extended (~> 2.6)
-    public_suffix (2.0.5)
-    rb-fsevent (0.10.2)
-    rb-inotify (0.9.10)
-      ffi (>= 0.5.0, < 2)
-    rouge (1.11.1)
-    safe_yaml (1.0.4)
-    sass (3.5.1)
-      sass-listen (~> 4.0.0)
-    sass-listen (4.0.0)
-      rb-fsevent (~> 0.9, >= 0.9.4)
-      rb-inotify (~> 0.9, >= 0.9.7)
-
-PLATFORMS
-  ruby
-  x64-mingw32
-
-DEPENDENCIES
-  jekyll (~> 3.4.5)
-
-BUNDLED WITH
-   1.15.3
diff --git a/src/bootlint.js b/src/bootlint.js
index fa64d28..260fe2c 100644
--- a/src/bootlint.js
+++ b/src/bootlint.js
@@ -1105,6 +1105,38 @@ var LocationIndex = _location.LocationIndex;
             reporter('`.form-group`s should not be nested.', nestedFormGroups);
         }
     });
+    addLinter('E051', function lintColumnsNoFloats($, reporter) {
+        var pullSelector = COL_CLASSES.map(function (col) {
+            return '.pull-left' + col + ',.pull-right' + col;
+        }).join(',');
+        var pulledCols = $(pullSelector);
+        if (pulledCols.length) {
+            reporter('`.pull-right` and `.pull-left` must not be used on `.col-*-*` elements', pulledCols);
+        }
+        var styledSelector = COL_CLASSES.map(function (col) {
+            return col + '[style]';
+        }).join(',');
+        var styledCols = $(styledSelector).filter(function (i, el) {
+            //test for `float:*` in the style attribute
+            return /float\s*:\s*[a-z]+/i.test($(el).attr('style'));
+        });
+        if (styledCols.length) {
+            reporter('Manually added `float` styles must not be added on `.col-*-*` elements', styledCols);
+        }
+    });
+    addLinter('E052', function lintRowsNoFloats($, reporter) {
+        var pulledRows = $('.row.pull-right, .row.pull-left');
+        if (pulledRows.length) {
+            reporter('`.pull-right` and `.pull-left` must not be used on `.row` elements', pulledRows);
+        }
+        var styledRows = $('.row[style]').filter(function (i, el) {
+            //test for `float:*` in the style attribute
+            return /float\s*:\s*[a-z]+/i.test($(el).attr('style'));
+        });
+        if (styledRows.length) {
+            reporter('Manually added `float` styles must not be added on `.row` elements', styledRows);
+        }
+    });
     exports._lint = function ($, reporter, disabledIdList, html) {
         var locationIndex = IN_NODE_JS ? new LocationIndex(html) : null;
         var reporterWrapper = IN_NODE_JS ? function (problem) {


Test patch:
diff --git a/test/bootlint_test.js b/test/bootlint_test.js
index 31ffbb1..2900aef 100644
--- a/test/bootlint_test.js
+++ b/test/bootlint_test.js
@@ -955,5 +955,27 @@ exports.bootlint = {
             'should complain when form-groups are nested'
         );
         test.done();
+    },
+    '.pull-right/left classes and manual float styles not allowed on .col-*-*': function (test) {
+        test.expect(1);
+        test.deepEqual(lintHtml(utf8Fixture('grid/col-no-float.html')),
+            [
+                '`.pull-right` and `.pull-left` must not be used on `.col-*-*` elements',
+                'Manually added `float` styles must not be added on `.col-*-*` elements'
+            ],
+            'should complain about a `.pull-right/.pull-left` classes on `.col-*-*` AND manual `style="float:left;"/style="float:right;"` on a `.col-*-*`'
+        );
+        test.done();
+    },
+    '.pull-right/left classes and manual float styles not allowed on .row': function (test) {
+        test.expect(1);
+        test.deepEqual(lintHtml(utf8Fixture('grid/row-no-float.html')),
+            [
+                '`.pull-right` and `.pull-left` must not be used on `.row` elements',
+                'Manually added `float` styles must not be added on `.row` elements'
+            ],
+            'should complain about a `.pull-right/.pull-left` classes on `.row` AND manual `style="float:left;"/style="float:right;"` on a `.row`'
+        );
+        test.done();
     }
 };
diff --git a/test/fixtures/grid/col-no-float.html b/test/fixtures/grid/col-no-float.html
new file mode 100644
index 0000000..95c0fdf
--- /dev/null
+++ b/test/fixtures/grid/col-no-float.html
@@ -0,0 +1,38 @@
+﻿<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8" />
+        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+        <meta name="viewport" content="width=device-width, initial-scale=1" />
+        <title>Test</title>
+        <!--[if lt IE 9]>
+            <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
+            <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
+        <![endif]-->
+        <script src="../../lib/jquery.min.js"></script>
+
+        <link rel="stylesheet" href="../../lib/qunit.css">
+        <script src="../../lib/qunit.js"></script>
+        <script src="../../../dist/browser/bootlint.js"></script>
+        <script src="../generic-qunit.js"></script>
+    </head>
+    <body>
+        <div class="container">
+            <div class="row">
+                <div class="col-xs-6 pull-right">Content</div>
+                <div class="col-md-6 pull-left">Content</div>
+            </div>
+            
+            <div class="row">
+                <div class="col-xs-6" style="float:left">Content</div>
+                <div class="col-md-6" style="float:right">Content</div>
+            </div>
+        </div>
+
+        <div id="qunit"></div>
+        <ol id="bootlint">
+            <li data-lint="`.pull-right` and `.pull-left` must not be used on `.col-*-*` elements"></li>
+            <li data-lint="Manually added `float` styles must not be added on `.col-*-*` elements"></li>
+        </ol>
+    </body>
+</html>
diff --git a/test/fixtures/grid/row-no-float.html b/test/fixtures/grid/row-no-float.html
new file mode 100644
index 0000000..c209031
--- /dev/null
+++ b/test/fixtures/grid/row-no-float.html
@@ -0,0 +1,44 @@
+﻿<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8" />
+        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+        <meta name="viewport" content="width=device-width, initial-scale=1" />
+        <title>Test</title>
+        <!--[if lt IE 9]>
+            <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
+            <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
+        <![endif]-->
+        <script src="../../lib/jquery.min.js"></script>
+
+        <link rel="stylesheet" href="../../lib/qunit.css">
+        <script src="../../lib/qunit.js"></script>
+        <script src="../../../dist/browser/bootlint.js"></script>
+        <script src="../generic-qunit.js"></script>
+    </head>
+    <body>
+        <div class="container">
+            <div class="row pull-right">
+                <div class="col-xs-6">Content</div>
+            </div>
+            
+            <div class="row pull-left">
+                <div class="col-md-6">Content</div>
+            </div>
+            
+            <div class="row" style="float: left;">
+                <div class="col-md-6">Content</div>
+            </div>
+            
+            <div class="row" style="float: right;">
+                <div class="col-md-6">Content</div>
+            </div>
+        </div>
+
+        <div id="qunit"></div>
+        <ol id="bootlint">
+            <li data-lint="`.pull-right` and `.pull-left` must not be used on `.row` elements"></li>
+            <li data-lint="Manually added `float` styles must not be added on `.row` elements"></li>
+        </ol>
+    </body>
+</html>