Repository: twbs/bootlint
Pull request #425 (2018-09-23 16:27:57)

[v1] Panels are cards now
Port E023, E024, E025, and E026

Basically the changes mentioned at https://getbootstrap.com/docs/4.1/migration/#panels but also the fact that `.card` does not need to be a direct parent anymore and also can be directly combined with `.card-body` on the same element (I can't remember what made me think that latter applies though, it has been a year).

What could be added in the future are tests for `.card-group`/`.card-deck`/`.card-columns` and making sure that `.card-title`/`.card-subtitle` are added to a `<h*>` and `.card-link` to `<a>` elements (#424).

- **Code**: Done but I am unsure about whether having both `.card-body` and `.card` is really a good idea and I still don't remember where I got the idea that it might be.
- **Tests**: Done.
- **Wiki**: Done.

Johann-S: Nice PR @Herst ! 👏 

Patch:
diff --git a/src/bootlint.js b/src/bootlint.js
index e5e0f2c..8d4decf 100644
--- a/src/bootlint.js
+++ b/src/bootlint.js
@@ -338,17 +338,6 @@ var LocationIndex = _location.LocationIndex;
     });
     */
     /*
-    addLinter('W002', function lintXUaCompatible($, reporter) {
-        var meta = $([
-            'head>meta[http-equiv="X-UA-Compatible"][content="IE=edge"]',
-            'head>meta[http-equiv="x-ua-compatible"][content="ie=edge"]'
-        ].join(','));
-        if (!meta.length) {
-            reporter('`<head>` is missing X-UA-Compatible `<meta>` tag that disables old IE compatibility modes');
-        }
-    });
-    */
-    /*
     addLinter('W003', function lintViewport($, reporter) {
         var meta = $('head>meta[name="viewport"][content]');
         if (!meta.length) {
@@ -496,14 +485,6 @@ var LocationIndex = _location.LocationIndex;
         });
     });
     /*
-    addLinter('W010', function lintMediaPulls($, reporter) {
-        var mediaPulls = $('.media>.pull-left, .media>.pull-right');
-        if (mediaPulls.length) {
-            reporter('Using `.pull-left` or `.pull-right` as part of the media object component is deprecated as of Bootstrap v3.3.0. Use `.media-left` or `.media-right` instead.');
-        }
-    });
-    */
-    /*
     addLinter('W012', function lintNavbarContainers($, reporter) {
         var navBars = $('.navbar');
         var containers = [
@@ -564,36 +545,6 @@ var LocationIndex = _location.LocationIndex;
     });
     */
     /*
-    addLinter('W015', function lintNewBootstrap($, reporter) {
-        var FUTURE_VERSION_ERROR = 'Detected what appears to be Bootstrap v4 or later. This version of Bootlint only supports Bootstrap v3.';
-        var theWindow = getBrowserWindowObject();
-
-        var globaljQuery = theWindow && (theWindow.$ || theWindow.jQuery);
-        // istanbul ignore if
-        if (globaljQuery) {
-            var versions = jqueryPluginVersions(globaljQuery);
-            if (versions.length) {
-                var minVersion = versions[0];
-                if (semver.gte(minVersion, BOOTSTRAP_VERSION_4, true)) {
-                    reporter(FUTURE_VERSION_ERROR);
-                    return;
-                }
-            }
-        }
-        // check for Bootstrap <link>s and <script>s
-        var bootstraps = $(BOOTSTRAP_FILES);
-        bootstraps.each(function () {
-            var version = versionInLinkedElement($, this);
-            if (version === null) {
-                return;
-            }
-            if (semver.gte(version, BOOTSTRAP_VERSION_4, true)) {
-                reporter(FUTURE_VERSION_ERROR, $(this));
-            }
-        });
-    });
-    */
-    /*
     addLinter('W016', function lintDisabledClassOnButton($, reporter) {
         var btnsWithDisabledClass = $('button.btn.disabled, input.btn.disabled');
         if (btnsWithDisabledClass.length) {
@@ -644,19 +595,6 @@ var LocationIndex = _location.LocationIndex;
         };
     })());
     /*
-    addLinter('E002', function lintBootstrapv2($, reporter) {
-        var columnClasses = [];
-        for (var n = 1; n <= 12; n++) {
-            columnClasses.push('.span' + n);
-        }
-        var selector = columnClasses.join(',');
-        var spanNs = $(selector);
-        if (spanNs.length) {
-            reporter('Found one or more uses of outdated Bootstrap v2 `.spanN` grid classes', spanNs);
-        }
-    });
-    */
-    /*
     addLinter('E003', function lintContainers($, reporter) {
         var notAnyColClass = COL_CLASSES.map(function (colClass) {
             return ':not(' + colClass + ')';
@@ -878,38 +816,38 @@ var LocationIndex = _location.LocationIndex;
         }
     });
     */
-    /*
-    addLinter('E023', function lintPanelBodyWithoutPanel($, reporter) {
-        var badPanelBody = $('.panel-body').parent(':not(.panel, .panel-collapse)');
-        if (badPanelBody.length) {
-            reporter('`.panel-body` must have a `.panel` or `.panel-collapse` parent', badPanelBody);
+    addLinter('E023', function lintCardBodyWithoutCard($, reporter) {
+        var badCardBody = $('.card-body').filter(function () {
+            return $(this).closest('.card').length !== 1;
+        });
+        if (badCardBody.length) {
+            reporter('`.card-body` must have `.card` or have it as an ancestor.', badCardBody);
         }
     });
-    */
-    /*
-    addLinter('E024', function lintPanelHeadingWithoutPanel($, reporter) {
-        var badPanelHeading = $('.panel-heading').parent(':not(.panel)');
-        if (badPanelHeading.length) {
-            reporter('`.panel-heading` must have a `.panel` parent', badPanelHeading);
+    addLinter('E024', function lintCardHeaderWithoutCard($, reporter) {
+        var badCardHeader = $('.card-header').filter(function () {
+            return $(this).parents('.card').length !== 1;
+        });
+        if (badCardHeader.length) {
+            reporter('`.card-header` must have a `.card` ancestor.', badCardHeader);
         }
     });
-    */
-    /*
-    addLinter('E025', function lintPanelFooterWithoutPanel($, reporter) {
-        var badPanelFooter = $('.panel-footer').parent(':not(.panel, .panel-collapse)');
-        if (badPanelFooter.length) {
-            reporter('`.panel-footer` must have a `.panel` or `.panel-collapse` parent', badPanelFooter);
+    addLinter('E025', function lintCardFooterWithoutCard($, reporter) {
+        var badCardFooter = $('.card-footer').filter(function () {
+            return $(this).parents('.card').length !== 1;
+        });
+        if (badCardFooter.length) {
+            reporter('`.card-footer` must have a `.card` ancestor.', badCardFooter);
         }
     });
-    */
-    /*
-    addLinter('E026', function lintPanelTitleWithoutPanelHeading($, reporter) {
-        var badPanelTitle = $('.panel-title').parent(':not(.panel-heading)');
-        if (badPanelTitle.length) {
-            reporter('`.panel-title` must have a `.panel-heading` parent', badPanelTitle);
+    addLinter('E026', function lintCardTitleWithoutCard($, reporter) {
+        var badCardTitle = $('.card-title').filter(function () {
+            return $(this).parents('.card').length !== 1;
+        });
+        if (badCardTitle.length) {
+            reporter('`.card-title` must have a `.card` ancestor.', badCardTitle);
         }
     });
-    */
     /*
     addLinter('E027', function lintTableResponsive($, reporter) {
         var badStructure = $('.table.table-responsive, table.table-responsive');
@@ -975,24 +913,6 @@ var LocationIndex = _location.LocationIndex;
         });
     });
     /*
-    addLinter('E030', function lintSoloGlyphiconClasses($, reporter) {
-        var missingGlyphiconClass = $('[class*="glyphicon-"]:not(.glyphicon):not(.glyphicon-class)').filter(function () {
-            return /\bglyphicon-([a-zA-Z]+)\b/.test($(this).attr('class'));
-        });
-        if (missingGlyphiconClass.length) {
-            reporter('Found elements with a `.glyphicon-*` class that were missing the additional required `.glyphicon` class.', missingGlyphiconClass);
-        }
-    });
-    */
-    /*
-    addLinter('E031', function lintGlyphiconOnNonEmptyElement($, reporter) {
-        var glyphiconNotEmpty = $('.glyphicon:not(:empty)');
-        if (glyphiconNotEmpty.length) {
-            reporter('Glyphicon classes must only be used on elements that contain no text content and have no child elements.', glyphiconNotEmpty);
-        }
-    });
-    */
-    /*
     addLinter('E032', function lintModalStructure($, reporter) {
         var elements;
 
@@ -1067,16 +987,6 @@ var LocationIndex = _location.LocationIndex;
         }
     });
     /*
-    addLinter('E038', function lintMediaPulls($, reporter) {
-        var mediaPullsOutsideMedia = $('.media-left, .media-right').filter(function () {
-            return !$(this).parent().closest('.media').length;
-        });
-        if (mediaPullsOutsideMedia.length) {
-            reporter('`.media-left` and `.media-right` should not be used outside of `.media` objects.', mediaPullsOutsideMedia);
-        }
-    });
-    */
-    /*
     addLinter('E039', function lintNavbarPulls($, reporter) {
         var navbarPullsOutsideNavbars = $('.navbar-left, .navbar-right').filter(function () {
             return !$(this).parent().closest('.navbar').length;


Test patch:
diff --git a/test/_old_fixtures/bs-v2.html b/test/_old_fixtures/bs-v2.html
deleted file mode 100644
index a7a5f8b..0000000
--- a/test/_old_fixtures/bs-v2.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!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>
-        <link rel="stylesheet" href="../../../node_modules/qunit/qunit/qunit.css">
-
-        <!--[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="../../node_modules/jquery/dist/jquery.min.js"></script>
-        <script src="../../node_modules/qunit/qunit/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="span12"></div>
-            </div>
-        </div>
-
-        <div id="qunit"></div>
-        <ol id="bootlint">
-            <li data-lint="Found one or more uses of outdated Bootstrap v2 `.spanN` grid classes"></li>
-            <li data-lint="Only columns (`.col-*-*`) may be children of `.row`s"></li>
-        </ol>
-    </body>
-</html>
diff --git a/test/_old_fixtures/glyphicons/missing-glyphicon-class.html b/test/_old_fixtures/glyphicons/missing-glyphicon-class.html
deleted file mode 100644
index 0f355bd..0000000
--- a/test/_old_fixtures/glyphicons/missing-glyphicon-class.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!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>
-        <link rel="stylesheet" href="../../../node_modules/qunit/qunit/qunit.css">
-
-        <!--[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="../../../node_modules/jquery/dist/jquery.min.js"></script>
-        <script src="../../../node_modules/qunit/qunit/qunit.js"></script>
-        <script src="../../../dist/browser/bootlint.js"></script>
-        <script src="../generic-qunit.js"></script>
-    </head>
-    <body>
-        <span class="glyphicon-asterisk"></span>
-
-        <div id="qunit"></div>
-        <ol id="bootlint">
-            <li data-lint="Found elements with a `.glyphicon-*` class that were missing the additional required `.glyphicon` class."></li>
-        </ol>
-    </body>
-</html>
diff --git a/test/_old_fixtures/glyphicons/on-elem-with-child.html b/test/_old_fixtures/glyphicons/on-elem-with-child.html
deleted file mode 100644
index 5483bc5..0000000
--- a/test/_old_fixtures/glyphicons/on-elem-with-child.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!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>
-        <link rel="stylesheet" href="../../../node_modules/qunit/qunit/qunit.css">
-
-        <!--[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="../../../node_modules/jquery/dist/jquery.min.js"></script>
-        <script src="../../../node_modules/qunit/qunit/qunit.js"></script>
-        <script src="../../../dist/browser/bootlint.js"></script>
-        <script src="../generic-qunit.js"></script>
-    </head>
-    <body>
-        <span class="glyphicon glyphicon-asterisk"><span id="bad-child"></span></span>
-
-        <div id="qunit"></div>
-        <ol id="bootlint">
-            <li data-lint="Glyphicon classes must only be used on elements that contain no text content and have no child elements."></li>
-        </ol>
-    </body>
-</html>
diff --git a/test/_old_fixtures/glyphicons/on-elem-with-text.html b/test/_old_fixtures/glyphicons/on-elem-with-text.html
deleted file mode 100644
index add8f8c..0000000
--- a/test/_old_fixtures/glyphicons/on-elem-with-text.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!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>
-        <link rel="stylesheet" href="../../../node_modules/qunit/qunit/qunit.css">
-
-        <!--[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="../../../node_modules/jquery/dist/jquery.min.js"></script>
-        <script src="../../../node_modules/qunit/qunit/qunit.js"></script>
-        <script src="../../../dist/browser/bootlint.js"></script>
-        <script src="../generic-qunit.js"></script>
-    </head>
-    <body>
-        <span class="glyphicon glyphicon-asterisk">This text is not allowed</span>
-
-        <div id="qunit"></div>
-        <ol id="bootlint">
-            <li data-lint="Glyphicon classes must only be used on elements that contain no text content and have no child elements."></li>
-        </ol>
-    </body>
-</html>
diff --git a/test/_old_fixtures/glyphicons/valid.html b/test/_old_fixtures/glyphicons/valid.html
deleted file mode 100644
index 86c189c..0000000
--- a/test/_old_fixtures/glyphicons/valid.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!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>
-        <link rel="stylesheet" href="../../../node_modules/qunit/qunit/qunit.css">
-
-        <!--[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="../../../node_modules/jquery/dist/jquery.min.js"></script>
-        <script src="../../../node_modules/qunit/qunit/qunit.js"></script>
-        <script src="../../../dist/browser/bootlint.js"></script>
-        <script src="../generic-qunit.js"></script>
-    </head>
-    <body>
-        <span class="glyphicon glyphicon-asterisk"></span>
-
-        <div id="qunit"></div>
-        <ol id="bootlint"></ol>
-    </body>
-</html>
diff --git a/test/_old_fixtures/media/deprecated-pull-classes.html b/test/_old_fixtures/media/deprecated-pull-classes.html
deleted file mode 100644
index d1cacba..0000000
--- a/test/_old_fixtures/media/deprecated-pull-classes.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!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>
-        <link rel="stylesheet" href="../../../node_modules/qunit/qunit/qunit.css">
-
-        <!--[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="../../../node_modules/jquery/dist/jquery.min.js"></script>
-        <script src="../../../node_modules/qunit/qunit/qunit.js"></script>
-        <script src="../../../dist/browser/bootlint.js"></script>
-        <script src="../generic-qunit.js"></script>
-    </head>
-    <body>
-        <div class="media">
-            <a class="pull-right" href="#">
-                <img src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHZpZXdCb3g9IjAgMCA2NCA2NCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGRlZnMvPjxyZWN0IHdpZHRoPSI2NCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0VFRUVFRSIvPjxnPjx0ZXh0IHg9IjE0LjUiIHk9IjMyIiBzdHlsZT0iZmlsbDojQUFBQUFBO2ZvbnQtd2VpZ2h0OmJvbGQ7Zm9udC1mYW1pbHk6QXJpYWwsIEhlbHZldGljYSwgT3BlbiBTYW5zLCBzYW5zLXNlcmlmLCBtb25vc3BhY2U7Zm9udC1zaXplOjEwcHQ7ZG9taW5hbnQtYmFzZWxpbmU6Y2VudHJhbCI+NjR4NjQ8L3RleHQ+PC9nPjwvc3ZnPg==" alt="">
-            </a>
-            <div class="media-body">
-                <h4 class="media-heading">Media heading</h4>
-            </div>
-        </div>
-        <div id="qunit"></div>
-        <ol id="bootlint">
-            <li data-lint="Using `.pull-left` or `.pull-right` as part of the media object component is deprecated as of Bootstrap v3.3.0. Use `.media-left` or `.media-right` instead."></li>
-        </ol>
-    </body>
-</html>
diff --git a/test/_old_fixtures/media/media-classes.html b/test/_old_fixtures/media/media-classes.html
deleted file mode 100644
index 24b3176..0000000
--- a/test/_old_fixtures/media/media-classes.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!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>
-        <link rel="stylesheet" href="../../../node_modules/qunit/qunit/qunit.css">
-
-        <!--[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="../../../node_modules/jquery/dist/jquery.min.js"></script>
-        <script src="../../../node_modules/qunit/qunit/qunit.js"></script>
-        <script src="../../../dist/browser/bootlint.js"></script>
-        <script src="../generic-qunit.js"></script>
-    </head>
-    <body>
-        <div class="media">
-            <a class="media-left" href="#">
-                <img src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHZpZXdCb3g9IjAgMCA2NCA2NCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGRlZnMvPjxyZWN0IHdpZHRoPSI2NCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0VFRUVFRSIvPjxnPjx0ZXh0IHg9IjE0LjUiIHk9IjMyIiBzdHlsZT0iZmlsbDojQUFBQUFBO2ZvbnQtd2VpZ2h0OmJvbGQ7Zm9udC1mYW1pbHk6QXJpYWwsIEhlbHZldGljYSwgT3BlbiBTYW5zLCBzYW5zLXNlcmlmLCBtb25vc3BhY2U7Zm9udC1zaXplOjEwcHQ7ZG9taW5hbnQtYmFzZWxpbmU6Y2VudHJhbCI+NjR4NjQ8L3RleHQ+PC9nPjwvc3ZnPg==" alt="">
-            </a>
-            <div class="media-body">
-                <h4 class="media-heading">Media heading</h4>
-            </div>
-        </div>
-        <div class="media">
-            <a class="media-right" href="#">
-                <img src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHZpZXdCb3g9IjAgMCA2NCA2NCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGRlZnMvPjxyZWN0IHdpZHRoPSI2NCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0VFRUVFRSIvPjxnPjx0ZXh0IHg9IjE0LjUiIHk9IjMyIiBzdHlsZT0iZmlsbDojQUFBQUFBO2ZvbnQtd2VpZ2h0OmJvbGQ7Zm9udC1mYW1pbHk6QXJpYWwsIEhlbHZldGljYSwgT3BlbiBTYW5zLCBzYW5zLXNlcmlmLCBtb25vc3BhY2U7Zm9udC1zaXplOjEwcHQ7ZG9taW5hbnQtYmFzZWxpbmU6Y2VudHJhbCI+NjR4NjQ8L3RleHQ+PC9nPjwvc3ZnPg==" alt="">
-            </a>
-            <div class="media-body">
-                <h4 class="media-heading">Media heading</h4>
-            </div>
-        </div>
-        <div id="qunit"></div>
-        <ol id="bootlint"></ol>
-    </body>
-</html>
diff --git a/test/_old_fixtures/media/media-pull-on-media.html b/test/_old_fixtures/media/media-pull-on-media.html
deleted file mode 100644
index 2797d3d..0000000
--- a/test/_old_fixtures/media/media-pull-on-media.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!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>
-        <link rel="stylesheet" href="../../../node_modules/qunit/qunit/qunit.css">
-
-        <!--[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="../../../node_modules/jquery/dist/jquery.min.js"></script>
-        <script src="../../../node_modules/qunit/qunit/qunit.js"></script>
-        <script src="../../../dist/browser/bootlint.js"></script>
-        <script src="../generic-qunit.js"></script>
-    </head>
-    <body>
-        <div class="media media-left">
-            <div class="media-body">
-                <h4 class="media-heading">Media heading</h4>
-            </div>
-        </div>
-        <div class="media media-right">
-            <div class="media-body">
-                <h4 class="media-heading">Media heading</h4>
-            </div>
-        </div>
-        <div id="qunit"></div>
-        <ol id="bootlint">
-            <li data-lint="`.media-left` and `.media-right` should not be used outside of `.media` objects."></li>
-        </ol>
-    </body>
-</html>
diff --git a/test/_old_fixtures/media/misplaced-media-left.html b/test/_old_fixtures/media/misplaced-media-left.html
deleted file mode 100644
index e6fd970..0000000
--- a/test/_old_fixtures/media/misplaced-media-left.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!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>
-        <link rel="stylesheet" href="../../../node_modules/qunit/qunit/qunit.css">
-
-        <!--[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="../../../node_modules/jquery/dist/jquery.min.js"></script>
-        <script src="../../../node_modules/qunit/qunit/qunit.js"></script>
-        <script src="../../../dist/browser/bootlint.js"></script>
-        <script src="../generic-qunit.js"></script>
-    </head>
-    <body>
-        <a class="media-left" href="#">Where is my media object?</a>
-        <div id="qunit"></div>
-        <ol id="bootlint">
-            <li data-lint="`.media-left` and `.media-right` should not be used outside of `.media` objects."></li>
-        </ol>
-    </body>
-</html>
diff --git a/test/_old_fixtures/media/misplaced-media-right.html b/test/_old_fixtures/media/misplaced-media-right.html
deleted file mode 100644
index 1ed04ce..0000000
--- a/test/_old_fixtures/media/misplaced-media-right.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!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>
-        <link rel="stylesheet" href="../../../node_modules/qunit/qunit/qunit.css">
-
-        <!--[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="../../../node_modules/jquery/dist/jquery.min.js"></script>
-        <script src="../../../node_modules/qunit/qunit/qunit.js"></script>
-        <script src="../../../dist/browser/bootlint.js"></script>
-        <script src="../generic-qunit.js"></script>
-    </head>
-    <body>
-        <a class="media-right" href="#">Where is my media object?</a>
-        <div id="qunit"></div>
-        <ol id="bootlint">
-            <li data-lint="`.media-left` and `.media-right` should not be used outside of `.media` objects."></li>
-        </ol>
-    </body>
-</html>
diff --git a/test/_old_fixtures/version-4/bootstrap-css.html b/test/_old_fixtures/version-4/bootstrap-css.html
deleted file mode 100644
index 1a9a959..0000000
--- a/test/_old_fixtures/version-4/bootstrap-css.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!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>
-        <link rel="stylesheet" href="../../../node_modules/qunit/qunit/qunit.css">
-
-        <link rel="stylesheet" href="css/4.0.0/bootstrap.css">
-        <!--[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="../../../node_modules/jquery/dist/jquery.min.js"></script>
-        <script src="../../../node_modules/qunit/qunit/qunit.js"></script>
-        <script src="../../../dist/browser/bootlint.js"></script>
-        <script src="../generic-qunit.js"></script>
-    </head>
-    <body>
-        <div id="qunit"></div>
-        <ol id="bootlint">
-            <li data-lint="Detected what appears to be Bootstrap v4 or later. This version of Bootlint only supports Bootstrap v3."></li>
-        </ol>
-    </body>
-</html>
diff --git a/test/_old_fixtures/version-4/bootstrap-extensions-okay.html b/test/_old_fixtures/version-4/bootstrap-extensions-okay.html
deleted file mode 100644
index f428e0c..0000000
--- a/test/_old_fixtures/version-4/bootstrap-extensions-okay.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!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>
-        <link rel="stylesheet" href="../../../node_modules/qunit/qunit/qunit.css">
-
-        <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.999.999/css/bootstrap.css">
-        <link rel="stylesheet" href="other-library/4.0.0/plugin-for-bootstrap.css">
-        <link rel="stylesheet" href="other-library/4.0.0/plugin-for-bootstrap.min.css">
-        <script src="other-library/4.0.0/plugin-for-bootstrap.css"></script>
-        <script src="other-library/4.0.0/plugin-for-bootstrap.min.css"></script>
-        <!--[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="../../../node_modules/jquery/dist/jquery.min.js"></script>
-        <script src="../../../node_modules/qunit/qunit/qunit.js"></script>
-        <script src="../../../dist/browser/bootlint.js"></script>
-        <script src="../generic-qunit.js"></script>
-    </head>
-    <body>
-        <div id="qunit"></div>
-        <ol id="bootlint"></ol>
-    </body>
-</html>
diff --git a/test/_old_fixtures/version-4/bootstrap-js.html b/test/_old_fixtures/version-4/bootstrap-js.html
deleted file mode 100644
index ec220ba..0000000
--- a/test/_old_fixtures/version-4/bootstrap-js.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!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>
-        <link rel="stylesheet" href="../../../node_modules/qunit/qunit/qunit.css">
-
-        <!--[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="../../../node_modules/jquery/dist/jquery.min.js"></script>
-        <script src="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.js"></script>
-        <script src="../../../node_modules/qunit/qunit/qunit.js"></script>
-        <script src="../../../dist/browser/bootlint.js"></script>
-        <script src="../generic-qunit.js"></script>
-    </head>
-    <body>
-        <div id="qunit"></div>
-        <ol id="bootlint">
-            <li data-lint="Detected what appears to be Bootstrap v4 or later. This version of Bootlint only supports Bootstrap v3."></li>
-        </ol>
-    </body>
-</html>
diff --git a/test/_old_fixtures/version-4/bootstrap-min-css.html b/test/_old_fixtures/version-4/bootstrap-min-css.html
deleted file mode 100644
index 3e7dd34..0000000
--- a/test/_old_fixtures/version-4/bootstrap-min-css.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!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>
-        <link rel="stylesheet" href="../../../node_modules/qunit/qunit/qunit.css">
-
-        <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
-        <!--[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="../../../node_modules/jquery/dist/jquery.min.js"></script>
-        <script src="../../../node_modules/qunit/qunit/qunit.js"></script>
-        <script src="../../../dist/browser/bootlint.js"></script>
-        <script src="../generic-qunit.js"></script>
-    </head>
-    <body>
-        <div id="qunit"></div>
-        <ol id="bootlint">
-            <li data-lint="Detected what appears to be Bootstrap v4 or later. This version of Bootlint only supports Bootstrap v3."></li>
-        </ol>
-    </body>
-</html>
diff --git a/test/_old_fixtures/version-4/bootstrap-min-js.html b/test/_old_fixtures/version-4/bootstrap-min-js.html
deleted file mode 100644
index 1f8790d..0000000
--- a/test/_old_fixtures/version-4/bootstrap-min-js.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!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>
-        <link rel="stylesheet" href="../../../node_modules/qunit/qunit/qunit.css">
-
-        <!--[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="../../../node_modules/jquery/dist/jquery.min.js"></script>
-        <script src="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
-        <script src="../../../node_modules/qunit/qunit/qunit.js"></script>
-        <script src="../../../dist/browser/bootlint.js"></script>
-        <script src="../generic-qunit.js"></script>
-    </head>
-    <body>
-        <div id="qunit"></div>
-        <ol id="bootlint">
-            <li data-lint="Detected what appears to be Bootstrap v4 or later. This version of Bootlint only supports Bootstrap v3."></li>
-        </ol>
-    </body>
-</html>
diff --git a/test/_old_fixtures/version-4/js-version-not-in-url-4.0.0.html b/test/_old_fixtures/version-4/js-version-not-in-url-4.0.0.html
deleted file mode 100644
index 369d665..0000000
--- a/test/_old_fixtures/version-4/js-version-not-in-url-4.0.0.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!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>
-        <link rel="stylesheet" href="../../../node_modules/qunit/qunit/qunit.css">
-
-        <!--[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="../../../node_modules/jquery/dist/jquery.min.js"></script>
-        <script>
-        (function () {
-            window.$.fn.modal = { Constructor: { VERSION: '4.0.0' } };
-        })();
-        </script>
-        <script src="../../../node_modules/qunit/qunit/qunit.js"></script>
-        <script src="../../../dist/browser/bootlint.js"></script>
-        <script src="../generic-qunit.js"></script>
-    </head>
-    <body>
-        <div id="qunit"></div>
-        <ol id="bootlint">
-            <li data-lint="Detected what appears to be Bootstrap v4 or later. This version of Bootlint only supports Bootstrap v3."></li>
-        </ol>
-    </body>
-</html>
diff --git a/test/_old_fixtures/x-ua-compatible/lowercase.html b/test/_old_fixtures/x-ua-compatible/lowercase.html
deleted file mode 100644
index 26b1381..0000000
--- a/test/_old_fixtures/x-ua-compatible/lowercase.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!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>
-        <link rel="stylesheet" href="../../../node_modules/qunit/qunit/qunit.css">
-
-        <!--[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="../../../node_modules/jquery/dist/jquery.min.js"></script>
-        <script src="../../../node_modules/qunit/qunit/qunit.js"></script>
-        <script src="../../../dist/browser/bootlint.js"></script>
-        <script src="../generic-qunit.js"></script>
-    </head>
-    <body>
-        <div id="qunit"></div>
-        <ol id="bootlint"></ol>
-    </body>
-</html>
diff --git a/test/_old_fixtures/x-ua-compatible/missing.html b/test/_old_fixtures/x-ua-compatible/missing.html
deleted file mode 100644
index abe26b1..0000000
--- a/test/_old_fixtures/x-ua-compatible/missing.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!doctype html>
-<html lang="en">
-    <head>
-        <meta charset="utf-8">
-        <meta name="viewport" content="width=device-width, initial-scale=1">
-        <title>Test</title>
-        <link rel="stylesheet" href="../../../node_modules/qunit/qunit/qunit.css">
-
-        <!--[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="../../../node_modules/jquery/dist/jquery.min.js"></script>
-        <script src="../../../node_modules/qunit/qunit/qunit.js"></script>
-        <script src="../../../dist/browser/bootlint.js"></script>
-        <script src="../generic-qunit.js"></script>
-    </head>
-    <body>
-        <div id="qunit"></div>
-        <ol id="bootlint">
-            <li data-lint="`&lt;head&gt;` is missing X-UA-Compatible `&lt;meta&gt;` tag that disables old IE compatibility modes"></li>
-        </ol>
-    </body>
-</html>
diff --git a/test/bootlint_test.js b/test/bootlint_test.js
index 760d8b3..77dc735 100644
--- a/test/bootlint_test.js
+++ b/test/bootlint_test.js
@@ -57,15 +57,6 @@ exports.bootlint = {
         test.done();
     },
     /*
-    'disabling lint checks': function (test) {
-        test.expect(1);
-        test.deepEqual(lintHtml(utf8Fixture('bs-v2.html'), ['E002', 'E013']),
-            [],
-            'should complain when Bootstrap v2 grid classes are present.');
-        test.done();
-    },
-    */
-    /*
     'UTF-8 charset meta tag': function (test) {
         test.expect(4);
         test.deepEqual(lintHtml(utf8Fixture('charset/utf8.html')),
@@ -84,33 +75,6 @@ exports.bootlint = {
     },
     */
     /*
-    'X-UA-Compatible': function (test) {
-        test.expect(3);
-        test.deepEqual(lintHtml(utf8Fixture('x-ua-compatible/present.html')),
-            [],
-            'should not complain when X-UA-Compatible <meta> tag is present.');
-        test.deepEqual(lintHtml(utf8Fixture('x-ua-compatible/lowercase.html')),
-            [],
-            'should not complain when X-UA-Compatible <meta> tag is present but lowercased.');
-        test.deepEqual(lintHtml(utf8Fixture('x-ua-compatible/missing.html')),
-            ['`<head>` is missing X-UA-Compatible `<meta>` tag that disables old IE compatibility modes'],
-            'should complain when X-UA-Compatible <meta> tag is missing.');
-        test.done();
-    },
-    */
-    /*
-    'Bootstrap v2': function (test) {
-        test.expect(1);
-        test.deepEqual(lintHtml(utf8Fixture('bs-v2.html')),
-            [
-                'Found one or more uses of outdated Bootstrap v2 `.spanN` grid classes',
-                'Only columns (`.col-*-*`) may be children of `.row`s'
-            ],
-            'should complain when Bootstrap v2 grid classes are present.');
-        test.done();
-    },
-    */
-    /*
     'rows outside containers': function (test) {
         test.expect(6);
         test.deepEqual(lintHtml(utf8Fixture('containers/fixed.html')),
@@ -460,27 +424,25 @@ exports.bootlint = {
         test.done();
     },
     */
-    /*
-    'panel structure': function (test) {
+    'card structure': function (test) {
         test.expect(5);
-        test.deepEqual(lintHtml(utf8Fixture('panels/panels.html')),
-            [],
-            'should not complain when panel is structured correctly.');
-        test.deepEqual(lintHtml(utf8Fixture('panels/panel-body-missing-parent.html')),
-            ['`.panel-body` must have a `.panel` or `.panel-collapse` parent'],
-            'should complain when .panel-body is missing .panel or .panel-collapse parent');
-        test.deepEqual(lintHtml(utf8Fixture('panels/panel-footer-missing-parent.html')),
-            ['`.panel-footer` must have a `.panel` or `.panel-collapse` parent'],
-            'should complain when .panel-footer is missing .panel parent');
-        test.deepEqual(lintHtml(utf8Fixture('panels/panel-title-missing-parent.html')),
-            ['`.panel-title` must have a `.panel-heading` parent'],
-            'should complain when .panel-title is missing .panel-heading parent');
-        test.deepEqual(lintHtml(utf8Fixture('panels/panel-heading-missing-parent.html')),
-            ['`.panel-heading` must have a `.panel` parent'],
-            'should complain when .panel-heading is missing .panel parent');
+        test.deepEqual(lintHtml(utf8Fixture('cards/cards.html')),
+            [],
+            'should not complain when card is structured correctly.');
+        test.deepEqual(lintHtml(utf8Fixture('cards/card-body-missing-ancestor.html')),
+            ['`.card-body` must have `.card` or have it as an ancestor.'],
+            'should complain when .card-body is missing .card ancestor');
+        test.deepEqual(lintHtml(utf8Fixture('cards/card-footer-missing-ancestor.html')),
+            ['`.card-footer` must have a `.card` ancestor.'],
+            'should complain when .card-footer is missing .card ancestor');
+        test.deepEqual(lintHtml(utf8Fixture('cards/card-title-missing-ancestor.html')),
+            ['`.card-title` must have a `.card` ancestor.'],
+            'should complain when .card-title is missing .card ancestor');
+        test.deepEqual(lintHtml(utf8Fixture('cards/card-header-missing-ancestor.html')),
+            ['`.card-header` must have a `.card` ancestor.'],
+            'should complain when .card-header is missing .card ancestor');
         test.done();
     },
-    */
     'columns outside of rows and form groups': function (test) {
         test.expect(3);
         test.deepEqual(lintHtml(utf8Fixture('grid/cols-within-row.html')),
@@ -595,38 +557,6 @@ exports.bootlint = {
     },
     */
     /*
-    'Glyphicons on non-empty elements': function (test) {
-        test.expect(3);
-        test.deepEqual(lintHtml(utf8Fixture('glyphicons/valid.html')),
-            [],
-            'should not complain when the .glyphicon element has no text content or children.'
-        );
-        test.deepEqual(lintHtml(utf8Fixture('glyphicons/on-elem-with-text.html')),
-            ['Glyphicon classes must only be used on elements that contain no text content and have no child elements.'],
-            'should complain when Glyphicon is used on an element with text content.'
-        );
-        test.deepEqual(lintHtml(utf8Fixture('glyphicons/on-elem-with-child.html')),
-            ['Glyphicon classes must only be used on elements that contain no text content and have no child elements.'],
-            'should complain when Glyphicon is used on an element with child element(s).'
-        );
-        test.done();
-    },
-    */
-    /*
-    'Glyphicons missing the .glyphicon class': function (test) {
-        test.expect(2);
-        test.deepEqual(lintHtml(utf8Fixture('glyphicons/valid.html')),
-            [],
-            'should not complain when Glyphicon is used correctly.'
-        );
-        test.deepEqual(lintHtml(utf8Fixture('glyphicons/missing-glyphicon-class.html')),
-            ['Found elements with a `.glyphicon-*` class that were missing the additional required `.glyphicon` class.'],
-            'should complain when .glyphicon-* class is used without the .glyphicon class.'
-        );
-        test.done();
-    },
-    */
-    /*
     'modal structure': function (test) {
         test.expect(7);
         test.deepEqual(lintHtml(utf8Fixture('modal/valid.html')),
@@ -701,20 +631,6 @@ exports.bootlint = {
     },
     */
     /*
-    'pull classes inside media': function (test) {
-        test.expect(2);
-        test.deepEqual(lintHtml(utf8Fixture('media/deprecated-pull-classes.html')),
-            ['Using `.pull-left` or `.pull-right` as part of the media object component is deprecated as of Bootstrap v3.3.0. Use `.media-left` or `.media-right` instead.'],
-            'should complain about .pull-* classes in .media'
-        );
-        test.deepEqual(lintHtml(utf8Fixture('media/media-classes.html')),
-            [],
-            'should not complain about .media-left or .media-right classes.'
-        );
-        test.done();
-    },
-    */
-
     'invalid nonexistent .col*-0 classes': function (test) {
         test.expect(4);
         test.deepEqual(lintHtml(utf8Fixture('grid/col-sm-0.html')),
@@ -769,27 +685,6 @@ exports.bootlint = {
     },
     */
     /*
-    'version 4 of Bootstrap': function (test) {
-        test.expect(5);
-        test.deepEqual(lintHtml(utf8Fixture('version-4/bootstrap-css.html')),
-            ['Detected what appears to be Bootstrap v4 or later. This version of Bootlint only supports Bootstrap v3.'],
-            'should complain about version 4 of bootstrap.css.');
-        test.deepEqual(lintHtml(utf8Fixture('version-4/bootstrap-min-css.html')),
-            ['Detected what appears to be Bootstrap v4 or later. This version of Bootlint only supports Bootstrap v3.'],
-            'should complain about version 4 of bootstrap.min.css.');
-        test.deepEqual(lintHtml(utf8Fixture('version-4/bootstrap-js.html')),
-            ['Detected what appears to be Bootstrap v4 or later. This version of Bootlint only supports Bootstrap v3.'],
-            'should complain about version 4 of bootstrap.js.');
-        test.deepEqual(lintHtml(utf8Fixture('version-4/bootstrap-min-js.html')),
-            ['Detected what appears to be Bootstrap v4 or later. This version of Bootlint only supports Bootstrap v3.'],
-            'should complain about version 4 of bootstrap.min.js.');
-        test.deepEqual(lintHtml(utf8Fixture('version-4/bootstrap-extensions-okay.html')),
-            [],
-            'should not complain about v4.0.0+ libraries that just have "bootstrap" in their name.');
-        test.done();
-    },
-    */
-    /*
     'carousel control target': function (test) {
         test.expect(3);
         test.deepEqual(lintHtml(utf8Fixture('carousel/indicators.html')),
@@ -812,28 +707,6 @@ exports.bootlint = {
     },
     */
     /*
-    'media pulls outside of media objects': function (test) {
-        test.expect(4);
-        test.deepEqual(lintHtml(utf8Fixture('media/media-classes.html')),
-            [],
-            'should not complain about media pulls inside media objects.'
-        );
-        test.deepEqual(lintHtml(utf8Fixture('media/misplaced-media-left.html')),
-            ['`.media-left` and `.media-right` should not be used outside of `.media` objects.'],
-            'should complain about .media-left outside of a media object.'
-        );
-        test.deepEqual(lintHtml(utf8Fixture('media/misplaced-media-right.html')),
-            ['`.media-left` and `.media-right` should not be used outside of `.media` objects.'],
-            'should complain about .media-right outside of a media object.'
-        );
-        test.deepEqual(lintHtml(utf8Fixture('media/media-pull-on-media.html')),
-            ['`.media-left` and `.media-right` should not be used outside of `.media` objects.'],
-            'should complain about media pulls on .media itself.'
-        );
-        test.done();
-    },
-    */
-    /*
     'navbar pulls outside of navbars': function (test) {
         test.expect(4);
         test.deepEqual(lintHtml(utf8Fixture('navbar/navbar-left-bad.html')),
diff --git a/test/_old_fixtures/panels/panel-body-missing-parent.html b/test/fixtures/cards/card-body-missing-ancestor.html
similarity index 88%
rename from test/_old_fixtures/panels/panel-body-missing-parent.html
rename to test/fixtures/cards/card-body-missing-ancestor.html
index 1f3653b..1ab6157 100644
--- a/test/_old_fixtures/panels/panel-body-missing-parent.html
+++ b/test/fixtures/cards/card-body-missing-ancestor.html
@@ -19,14 +19,14 @@
     <body>
 
       <div>
-          <div class="panel-body">
+          <div class="card-body">
             <p>Something</p>
           </div>
       </div>
 
         <div id="qunit"></div>
         <ol id="bootlint">
-          <li data-lint="`.panel-body` must have a `.panel` or `.panel-collapse` parent"> </li>
+          <li data-lint="`.card-body` must have `.card` or have it as an ancestor."> </li>
         </ol>
     </body>
 </html>
diff --git a/test/_old_fixtures/panels/panel-heading-missing-parent.html b/test/fixtures/cards/card-footer-missing-ancestor.html
similarity index 89%
rename from test/_old_fixtures/panels/panel-heading-missing-parent.html
rename to test/fixtures/cards/card-footer-missing-ancestor.html
index 3d3117a..26d8100 100644
--- a/test/_old_fixtures/panels/panel-heading-missing-parent.html
+++ b/test/fixtures/cards/card-footer-missing-ancestor.html
@@ -19,14 +19,14 @@
     <body>
 
       <div>
-          <div class="panel-heading">
+          <div class="card-footer">
             <p>Something</p>
           </div>
       </div>
 
         <div id="qunit"></div>
         <ol id="bootlint">
-          <li data-lint="`.panel-heading` must have a `.panel` parent"></li>
+          <li data-lint="`.card-footer` must have a `.card` ancestor."></li>
         </ol>
     </body>
 </html>
diff --git a/test/_old_fixtures/panels/panel-footer-missing-parent.html b/test/fixtures/cards/card-header-missing-ancestor.html
similarity index 88%
rename from test/_old_fixtures/panels/panel-footer-missing-parent.html
rename to test/fixtures/cards/card-header-missing-ancestor.html
index e34687e..aead878 100644
--- a/test/_old_fixtures/panels/panel-footer-missing-parent.html
+++ b/test/fixtures/cards/card-header-missing-ancestor.html
@@ -19,14 +19,14 @@
     <body>
 
       <div>
-          <div class="panel-footer">
+          <div class="card-header">
             <p>Something</p>
           </div>
       </div>
 
         <div id="qunit"></div>
         <ol id="bootlint">
-          <li data-lint="`.panel-footer` must have a `.panel` or `.panel-collapse` parent"></li>
+          <li data-lint="`.card-header` must have a `.card` ancestor."></li>
         </ol>
     </body>
 </html>
diff --git a/test/_old_fixtures/panels/panel-title-missing-parent.html b/test/fixtures/cards/card-title-missing-ancestor.html
similarity index 85%
rename from test/_old_fixtures/panels/panel-title-missing-parent.html
rename to test/fixtures/cards/card-title-missing-ancestor.html
index 009163f..7cfefad 100644
--- a/test/_old_fixtures/panels/panel-title-missing-parent.html
+++ b/test/fixtures/cards/card-title-missing-ancestor.html
@@ -18,13 +18,13 @@
     </head>
     <body>
 
-      <div class="panel">
-          <h2 class="panel-title">Panel title</h2>
+      <div>
+          <h2 class="card-title">Card title</h2>
       </div>
 
         <div id="qunit"></div>
         <ol id="bootlint">
-          <li data-lint="`.panel-title` must have a `.panel-heading` parent"></li>
+          <li data-lint="`.card-title` must have a `.card` ancestor."></li>
         </ol>
     </body>
 </html>
diff --git a/test/_old_fixtures/panels/panels.html b/test/fixtures/cards/cards.html
similarity index 75%
rename from test/_old_fixtures/panels/panels.html
rename to test/fixtures/cards/cards.html
index 55793fb..beeba29 100644
--- a/test/_old_fixtures/panels/panels.html
+++ b/test/fixtures/cards/cards.html
@@ -18,73 +18,74 @@
     </head>
     <body>
 
-        <!-- Basic Panel -->
-        <div class="panel">
-          <div class="panel-heading">
-            <h1 class="panel-title">Title</h1>
+
+        <!-- Basic Card -->
+        <div class="card">
+          <div class="card-header">
+            <h1 class="card-title">Title</h1>
           </div>
-          <div class="panel-body">
+          <div class="card-body">
             <p>Something</p>
           </div>
-          <div class="panel-footer">
+          <div class="card-footer">
             <p>Footer</p>
           </div>
         </div>
 
-        <!-- Panel accordion example -->
-        <div class="panel-group" id="accordion">
-          <div class="panel panel-default">
-            <div class="panel-heading">
-              <h4 class="panel-title">
+        <!-- Card accordion example -->
+        <div class="accordion" id="accordion">
+          <div class="card">
+            <div class="card-header">
+              <h4 class="card-title">
                 <a data-toggle="collapse" data-parent="#accordion" href="#collapseOne">
                   Collapsible Group Item #1
                 </a>
               </h4>
             </div>
-            <div id="collapseOne" class="panel-collapse collapse in">
-              <div class="panel-body">
+            <div id="collapseOne" class="collapse in">
+              <div class="card-body">
                 Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.
               </div>
             </div>
           </div>
-          <div class="panel panel-default">
-            <div class="panel-heading">
-              <h4 class="panel-title">
+          <div class="card">
+            <div class="card-header">
+              <h4 class="card-title">
                 <a data-toggle="collapse" data-parent="#accordion" href="#collapseTwo">
                   Collapsible Group Item #2
                 </a>
               </h4>
             </div>
-            <div id="collapseTwo" class="panel-collapse collapse">
-              <div class="panel-body">
+            <div id="collapseTwo" class="collapse">
+              <div class="card-body">
                 Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.
               </div>
             </div>
           </div>
-          <div class="panel panel-default">
-            <div class="panel-heading">
-              <h4 class="panel-title">
+          <div class="card">
+            <div class="card-header">
+              <h4 class="card-title">
                 <a data-toggle="collapse" data-parent="#accordion" href="#collapseThree">
                   Collapsible Group Item #3
                 </a>
               </h4>
             </div>
-            <div id="collapseThree" class="panel-collapse collapse">
-              <div class="panel-body">
+            <div id="collapseThree" class="collapse">
+              <div class="card-body">
                 Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.
               </div>
             </div>
           </div>
-          <div class="panel panel-default">
-            <div class="panel-heading">
-              <h4 class="panel-title">
+          <div class="card">
+            <div class="card-header">
+              <h4 class="card-title">
                 <a data-toggle="collapse" data-parent="#accordion" href="#collapseFour">
                   Collapsible Group Item #3
                 </a>
               </h4>
             </div>
-            <div id="collapseFour" class="panel-collapse collapse">
-              <div class="panel-footer">Footer</div>
+            <div id="collapseFour" class="collapse">
+              <div class="card-footer">Footer</div>
             </div>
           </div>
         </div>