Merge pull request #55 from zacechola/btn_dropdown_after_btn

Warn about split-button dropdowns
This commit is contained in:
Chris Rebert 2014-08-20 17:20:59 -07:00
Родитель a38f955a42 e91385a4ea
Коммит 3d72ff9214
7 изменённых файлов: 168 добавлений и 11 удалений

50
dist/browser/bootlint.js поставляемый
Просмотреть файл

@ -1,4 +1,4 @@
/*! bootlint - v0.1.1 - 2014-07-31 */
/*! bootlint - v0.1.1 - 2014-08-20 */
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
/*!
@ -9199,6 +9199,7 @@ return jQuery;
* Copyright (c) 2014 Christopher Rebert
* Licensed under the MIT License.
*/
/*eslint-env node */
var cheerio = require('cheerio');
@ -9236,14 +9237,17 @@ var cheerio = require('cheerio');
};
}
else {
return function ($) {
if (document.doctype === null) {
return function () {
/*eslint-disable no-undef */
var doc = window.document;
/*eslint-enable un-undef */
if (doc.doctype === null) {
return MISSING_DOCTYPE;
}
if (document.doctype.publicId) {
if (doc.doctype.publicId) {
return NON_HTML5_DOCTYPE;
}
if (document.doctype.systemId && document.doctype.systemId !== "about:legacy-compat") {
if (doc.doctype.systemId && doc.doctype.systemId !== "about:legacy-compat") {
return NON_HTML5_DOCTYPE;
}
};
@ -9295,7 +9299,10 @@ var cheerio = require('cheerio');
}
};
exports.lintRowAndColOnSameElem = function ($) {
var selector = COL_CLASSES.map(function (col) { return ".row" + col; }).join(',');
var selector = COL_CLASSES.map(function (col) {
return ".row" + col;
}).join(',');
var rowCols = $(selector);
if (rowCols.length) {
return "Found both `.row` and `.col-*-*` used on the same element";
@ -9310,13 +9317,15 @@ var cheerio = require('cheerio');
exports.lintJquery = function ($) {
var theWindow = null;
try {
/*eslint-disable no-undef */
theWindow = window;
/*eslint-enable no-undef */
}
catch (e) {
// deliberately do nothing
}
if (theWindow && (theWindow.$ || theWindow.jQuery)) {
return;
return undefined;
}
var jqueries = $('script[src*="jquery"],script[src*="jQuery"]');
if (!jqueries.length) {
@ -9375,7 +9384,10 @@ var cheerio = require('cheerio');
}
};
exports.lintGridClassMixedWithInputGroup = function ($) {
var selector = COL_CLASSES.map(function (colClass) { return '.input-group' + colClass; }).join(',');
var selector = COL_CLASSES.map(function (colClass) {
return '.input-group' + colClass;
}).join(',');
var badMixes = $(selector);
if (badMixes.length) {
return ".input-group and .col-*-* cannot be used directly on the same element. Instead, nest the .input-group within the .col-*-*";
@ -9383,7 +9395,10 @@ var cheerio = require('cheerio');
};
exports.lintRowChildrenAreCols = function ($) {
var ALLOWED_CHILD_CLASSES = COL_CLASSES.concat(['.clearfix', '.bs-customizer-input']);
var selector = '.row>*' + ALLOWED_CHILD_CLASSES.map(function (colClass) { return ':not(' + colClass + ')'; }).join('');
var selector = '.row>*' + ALLOWED_CHILD_CLASSES.map(function (colClass) {
return ':not(' + colClass + ')';
}).join('');
var nonColRowChildren = $(selector);
if (nonColRowChildren.length) {
return "Only columns (.col-*-*) may be children of `.row`s";
@ -9403,6 +9418,12 @@ var cheerio = require('cheerio');
return "Having multiple add-ons on a single side of an input group is not supported";
}
};
exports.lintBtnToggle = function ($) {
var badBtnToggle = $('.btn.dropdown-toggle ~ .btn');
if (badBtnToggle.length) {
return "`.btn.dropdown-toggle` must be the last button in a button group.";
}
};
exports.lintBlockCheckboxes = function ($) {
var badCheckboxes = $('.checkbox').filter(function (i, div) {
return $(div).filter(':has(>label>input[type="checkbox"])').length <= 0;
@ -9485,6 +9506,7 @@ var cheerio = require('cheerio');
errs.push(this.lintFormGroupMixedWithInputGroup($));
errs.push(this.lintGridClassMixedWithInputGroup($));
errs.push(this.lintInputGroupsWithMultipleAddOnsPerSide($));
errs.push(this.lintBtnToggle($));
errs.push(this.lintBlockCheckboxes($));
errs.push(this.lintBlockRadios($));
errs.push(this.lintButtonsCheckedActive($));
@ -9492,7 +9514,9 @@ var cheerio = require('cheerio');
errs = errs.concat(this.lintInputGroupFormControlTypes($));
errs = errs.concat(this.lintInlineCheckboxes($));
errs = errs.concat(this.lintInlineRadios($));
errs = errs.filter(function (item) { return item !== undefined; });
errs = errs.filter(function (item) {
return item !== undefined;
});
return errs;
};
if (IN_NODE_JS) {
@ -9527,18 +9551,22 @@ var cheerio = require('cheerio');
exports.showLintReportForCurrentDocument = function () {
var errs = this.lintCurrentDocument();
if (errs.length) {
/*eslint-disable no-alert, no-undef */
window.alert("bootlint found errors in this document! See the JavaScript console for details.");
/*eslint-enable no-alert, no-undef */
errs.forEach(function (err) {
console.warn("bootlint:", err);
});
}
};
/*eslint-disable no-undef */
window.bootlint = exports;
/*eslint-enable no-undef */
$(function () {
exports.showLintReportForCurrentDocument();
});
})();
}
}(typeof exports === 'object' && exports || this));
})(typeof exports === 'object' && exports || this);
},{"cheerio":1}]},{},[2]);

Просмотреть файл

@ -223,6 +223,12 @@ var cheerio = require('cheerio');
return "Having multiple add-ons on a single side of an input group is not supported";
}
};
exports.lintBtnToggle = function ($) {
var badBtnToggle = $('.btn.dropdown-toggle ~ .btn');
if (badBtnToggle.length) {
return "`.btn.dropdown-toggle` must be the last button in a button group.";
}
};
exports.lintBlockCheckboxes = function ($) {
var badCheckboxes = $('.checkbox').filter(function (i, div) {
return $(div).filter(':has(>label>input[type="checkbox"])').length <= 0;
@ -305,6 +311,7 @@ var cheerio = require('cheerio');
errs.push(this.lintFormGroupMixedWithInputGroup($));
errs.push(this.lintGridClassMixedWithInputGroup($));
errs.push(this.lintInputGroupsWithMultipleAddOnsPerSide($));
errs.push(this.lintBtnToggle($));
errs.push(this.lintBlockCheckboxes($));
errs.push(this.lintBlockRadios($));
errs.push(this.lintButtonsCheckedActive($));

Просмотреть файл

@ -232,6 +232,16 @@ exports['bootlint'] = {
'should complain when both a normal add-on and a button add-on are on the left side of an input group.');
test.done();
},
'dropdown-toggle comes before btn': function (test) {
test.expect(2);
test.deepEqual(bootlint.lintHtml(utf8Fixture('buttons/btn-toggle.html')),
[],
'should not complain when correct .dropdown-toggle markup is used.');
test.deepEqual(bootlint.lintHtml(utf8Fixture('buttons/btn-toggle-after-btn.html')),
["`.btn.dropdown-toggle` must be the last button in a button group."],
'should complain when `.dropdown-toggle` is on the left side of a btn');
test.done();
},
'incorrect markup for .checkbox, .radio, .checkbox-inline, and .radio-inline classes': function (test) {
test.expect(7);

Двоичные данные
test/fixtures/buttons/.btn-toggle-after-btn.html.swp поставляемый Normal file

Двоичный файл не отображается.

Двоичные данные
test/fixtures/buttons/.btn-toggle.html.swp поставляемый Normal file

Двоичный файл не отображается.

41
test/fixtures/buttons/btn-toggle-after-btn.html поставляемый Normal file
Просмотреть файл

@ -0,0 +1,41 @@
<!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-1.14.0.css">
<script src="../../lib/qunit-1.14.0.js"></script>
<script src="../../../dist/browser/bootlint.js"></script>
<script src="../generic-qunit.js"></script>
</head>
<body>
<div class="btn-group">
<button type="button" class="btn btn-danger dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu" role="menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
<button type="button" class="btn btn-danger">Action</button>
</div>
<div id="qunit"></div>
<ol id="bootlint">
<li data-lint="`.btn.dropdown-toggle` must be the last button in a button group."></li>
</ol>
</body>
</html>

71
test/fixtures/buttons/btn-toggle.html поставляемый Normal file
Просмотреть файл

@ -0,0 +1,71 @@
<!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-1.14.0.css">
<script src="../../lib/qunit-1.14.0.js"></script>
<script src="../../../dist/browser/bootlint.js"></script>
<script src="../generic-qunit.js"></script>
</head>
<body>
<!-- Split btn dropdowns -->
<div class="btn-group">
<button type="button" class="btn btn-danger">Action</button>
<button type="button" class="btn btn-danger dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu" role="menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
</div>
<!-- nested btn groups with dropdown -->
<div class="btn-group">
<button type="button" class="btn btn-default">1</button>
<button type="button" class="btn btn-default">2</button>
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
Dropdown
<span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li><a href="#">Dropdown link</a></li>
<li><a href="#">Dropdown link</a></li>
</ul>
</div>
</div>
<!-- Single button -->
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
Action <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
</div>
<div id="qunit"></div>
<ol id="bootlint"></ol>
</body>
</html>