Skip to content
This repository was archived by the owner on Feb 1, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions src/bootlint.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ var LocationIndex = _location.LocationIndex;
var NUM2SCREEN = ['xs', 'sm', 'md', 'lg'];
var IN_NODE_JS = !!(cheerio.load);
var MIN_JQUERY_VERSION = '1.9.1';// as of Bootstrap v3.3.0
var CURRENT_BOOTSTRAP_VERSION = '3.3.1';

function compareNums(a, b) {
return a - b;
Expand All @@ -43,6 +44,13 @@ var LocationIndex = _location.LocationIndex;
return node.type === 'directive' && node.name === '!doctype';
}

var tagNameOf = IN_NODE_JS ? function (element) {
return element.name.toUpperCase();
} : function (element) {
/* @covignore */
return element.tagName.toUpperCase();
};

function filenameFromUrl(url) {
var filename = url.replace(/[#?].*$/, ''); // strip querystring & fragment ID
var lastSlash = filename.lastIndexOf('/');
Expand Down Expand Up @@ -780,6 +788,82 @@ var LocationIndex = _location.LocationIndex;
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.', mediaPulls);
}
});
addLinter("W013", function lintOutdatedBootstrap($, reporter) {
var OUTDATED_BOOTSTRAP = "Bootstrap version might be outdated. Latest version is at least " + CURRENT_BOOTSTRAP_VERSION + " ; saw what appears to be usage of Bootstrap ";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the space before the semicolon in the message intended?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, although I'm happy to remove it if you wish

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's fine, just seemed a little odd.

var PLUGINS = [
'affix',
'alert',
'button',
'carousel',
'collapse',
'dropdown',
'modal',
'popover',
'scrollspy',
'tab',
'tooltip'
];
var theWindow = null;
try {
/*eslint-disable no-undef, block-scoped-var */
theWindow = window;// jshint ignore:line
/*eslint-enable no-undef, block-scoped-var */
}
catch (e) {
// deliberately do nothing
}
var globaljQuery = theWindow && (theWindow.$ || theWindow.jQuery);
/* @covignore */
if (globaljQuery) {
var versions = PLUGINS.map(function (pluginName) {
var plugin = globaljQuery.fn[pluginName];
if (!plugin) {
return undefined;
}
var constructor = plugin.Constructor;
if (!constructor) {
return undefined;
}
return constructor.VERSION;
}).filter(function (version) {
return version !== undefined;
}).sort(semver.compare);
if (versions.length) {
var minVersion = versions[0];
reporter(OUTDATED_BOOTSTRAP + minVersion);
return;
}
}
// check for Bootstrap <link>s and <script>s
var bootstraps = $([
'link[rel="stylesheet"][href$="/bootstrap.css"]',
'link[rel="stylesheet"][href="bootstrap.css"]',
'link[rel="stylesheet"][href$="/bootstrap.min.css"]',
'link[rel="stylesheet"][href="bootstrap.min.css"]',
'script[src$="/bootstrap.js"]',
'script[src="bootstrap.js"]',
'script[src$="/bootstrap.min.js"]',
'script[src="bootstrap.min.js"]'
].join(','));
bootstraps.each(function () {
var elem = $(this);
var urlAttr = (tagNameOf(this) === 'LINK') ? 'href' : 'src';
var pathSegments = parseUrl(elem.attr(urlAttr)).pathname.split('/');
var matches = pathSegments.map(function (segment) {
var match = segment.match(/^\d+\.\d+\.\d+$/);
return match ? match[0] : null;
}).filter(function (match) {
return match !== null;
});
if (!matches.length) {
return;
}
var version = matches[matches.length - 1];
if (semver.lt(version, CURRENT_BOOTSTRAP_VERSION, true)) {
reporter(OUTDATED_BOOTSTRAP + version, elem);
}
});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't this cause trouble with plugins/addons/whatevers again?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If their files are named something like foobar-bootstrap.css or /foobar/bootstrap.js, then yes.
Should be able to deal with the foobar-bootstrap.css cases by tweaking the selectors. Let me fix that...

});

exports._lint = function ($, reporter, disabledIdList, html) {
var locationIndex = IN_NODE_JS ? new LocationIndex(html) : null;
Expand Down
20 changes: 20 additions & 0 deletions test/bootlint_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -611,5 +611,25 @@ exports.bootlint = {
'should not complain about .media-left or .media-right classes'
);
test.done();
},

'outdated version of Bootstrap': function (test) {
test.expect(5);
test.deepEqual(lintHtml(utf8Fixture('outdated/bootstrap-css.html')),
['Bootstrap version might be outdated. Latest version is at least 3.3.1 ; saw what appears to be usage of Bootstrap 3.2.0'],
'should complain about outdated bootstrap.css.');
test.deepEqual(lintHtml(utf8Fixture('outdated/bootstrap-min-css.html')),
['Bootstrap version might be outdated. Latest version is at least 3.3.1 ; saw what appears to be usage of Bootstrap 3.2.0'],
'should complain about outdated bootstrap.min.css.');
test.deepEqual(lintHtml(utf8Fixture('outdated/bootstrap-js.html')),
['Bootstrap version might be outdated. Latest version is at least 3.3.1 ; saw what appears to be usage of Bootstrap 3.2.0'],
'should complain about outdated bootstrap.js.');
test.deepEqual(lintHtml(utf8Fixture('outdated/bootstrap-min-js.html')),
['Bootstrap version might be outdated. Latest version is at least 3.3.1 ; saw what appears to be usage of Bootstrap 3.2.0'],
'should complain about outdated bootstrap.min.js.');
test.deepEqual(lintHtml(utf8Fixture('outdated/bootstrap-extensions-okay.html')),
[],
'should not complain about outdated libraries that just have "bootstrap" in their name.');
test.done();
}
};
26 changes: 26 additions & 0 deletions test/fixtures/outdated/bootstrap-css.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!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="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/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="../../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 id="qunit"></div>
<ol id="bootlint">
<li data-lint="Bootstrap version might be outdated. Latest version is at least 3.3.1 ; saw what appears to be usage of Bootstrap 3.2.0"></li>
</ol>
</body>
</html>
28 changes: 28 additions & 0 deletions test/fixtures/outdated/bootstrap-extensions-okay.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!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="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.css">
<link rel="stylesheet" href="other-library/1.0.0/plugin-for-bootstrap.css">
<link rel="stylesheet" href="other-library/1.0.0/plugin-for-bootstrap.min.css">
<script src="other-library/1.0.0/plugin-for-bootstrap.css"></script>
<script src="other-library/1.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="../../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 id="qunit"></div>
<ol id="bootlint"></ol>
</body>
</html>
26 changes: 26 additions & 0 deletions test/fixtures/outdated/bootstrap-js.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!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>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.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 id="qunit"></div>
<ol id="bootlint">
<li data-lint="Bootstrap version might be outdated. Latest version is at least 3.3.1 ; saw what appears to be usage of Bootstrap 3.2.0"></li>
</ol>
</body>
</html>
26 changes: 26 additions & 0 deletions test/fixtures/outdated/bootstrap-min-css.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!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="//maxcdn.bootstrapcdn.com/bootstrap/3.2.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="../../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 id="qunit"></div>
<ol id="bootlint">
<li data-lint="Bootstrap version might be outdated. Latest version is at least 3.3.1 ; saw what appears to be usage of Bootstrap 3.2.0"></li>
</ol>
</body>
</html>
26 changes: 26 additions & 0 deletions test/fixtures/outdated/bootstrap-min-js.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!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>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.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 id="qunit"></div>
<ol id="bootlint">
<li data-lint="Bootstrap version might be outdated. Latest version is at least 3.3.1 ; saw what appears to be usage of Bootstrap 3.2.0"></li>
</ol>
</body>
</html>