From 6d0ac89c351a3307617d6bfecf4bfa779198590f Mon Sep 17 00:00:00 2001 From: Chris Rebert Date: Sun, 22 Feb 2015 15:33:15 -0800 Subject: [PATCH] Lint structure of Carousels; fixes #227 --- src/bootlint.js | 15 +++++++ test/bootlint_test.js | 25 +++++++++++ test/fixtures/carousel/controls.html | 3 ++ test/fixtures/carousel/indicators.html | 3 ++ .../carousel/missing-active-item.html | 39 ++++++++++++++++ test/fixtures/carousel/missing-inner.html | 34 ++++++++++++++ .../carousel/multiple-active-item.html | 45 +++++++++++++++++++ test/fixtures/carousel/multiple-inner.html | 44 ++++++++++++++++++ test/fixtures/carousel/valid.html | 3 ++ 9 files changed, 211 insertions(+) create mode 100644 test/fixtures/carousel/missing-active-item.html create mode 100644 test/fixtures/carousel/missing-inner.html create mode 100644 test/fixtures/carousel/multiple-active-item.html create mode 100644 test/fixtures/carousel/multiple-inner.html diff --git a/src/bootlint.js b/src/bootlint.js index e4a458f..c5ae10f 100644 --- a/src/bootlint.js +++ b/src/bootlint.js @@ -811,6 +811,21 @@ var LocationIndex = _location.LocationIndex; reporter('`.hide` should not be used on `.modal` in Bootstrap v3.', modalsWithHide); } }); + addLinter("E041", function lintCarouselStructure($, reporter) { + var carouselsWithWrongInners = $('.carousel').filter(function () { + return $(this).children('.carousel-inner').length !== 1; + }); + if (carouselsWithWrongInners.length) { + reporter('`.carousel` must have exactly one `.carousel-inner` child.', carouselsWithWrongInners); + } + + var innersWithWrongActiveItems = $('.carousel-inner').filter(function () { + return $(this).children('.item.active').length !== 1; + }); + if (innersWithWrongActiveItems.length) { + reporter('`.carousel-inner` must have exactly one `.item.active` child.', innersWithWrongActiveItems); + } + }); addLinter("W009", function lintEmptySpacerCols($, reporter) { var selector = COL_CLASSES.map(function (colClass) { return colClass + ':not(col):not(:last-child)'; diff --git a/test/bootlint_test.js b/test/bootlint_test.js index 70d7710..c2057f6 100644 --- a/test/bootlint_test.js +++ b/test/bootlint_test.js @@ -749,5 +749,30 @@ exports.bootlint = { 'should not complain about a modal without the .hide class.' ); test.done(); + }, + + 'carousel structure': function (test) { + test.expect(5); + test.deepEqual(lintHtml(utf8Fixture('carousel/valid.html')), + [], + 'should not complain about correctly structured carousels.' + ); + test.deepEqual(lintHtml(utf8Fixture('carousel/missing-inner.html')), + ['`.carousel` must have exactly one `.carousel-inner` child.'], + 'should complain about a carousel without a .carousel-inner.' + ); + test.deepEqual(lintHtml(utf8Fixture('carousel/multiple-inner.html')), + ['`.carousel` must have exactly one `.carousel-inner` child.'], + 'should complain about a carousel with multiple .carousel-inner children.' + ); + test.deepEqual(lintHtml(utf8Fixture('carousel/missing-active-item.html')), + ['`.carousel-inner` must have exactly one `.item.active` child.'], + 'should complain about a carousel without an active item.' + ); + test.deepEqual(lintHtml(utf8Fixture('carousel/multiple-active-item.html')), + ['`.carousel-inner` must have exactly one `.item.active` child.'], + 'should complain about a carousel with multiple active items.' + ); + test.done(); } }; diff --git a/test/fixtures/carousel/controls.html b/test/fixtures/carousel/controls.html index 3e3e1e8..bb6a16a 100644 --- a/test/fixtures/carousel/controls.html +++ b/test/fixtures/carousel/controls.html @@ -19,6 +19,9 @@