Skip to content
This repository has been archived by the owner on Feb 1, 2022. It is now read-only.

Commit

Permalink
Merge pull request #254 from twbs/tweaked-250
Browse files Browse the repository at this point in the history
Warn if version 4 of Bootstrap is detected
  • Loading branch information
cvrebert committed Mar 2, 2015
2 parents b16d614 + 6d65112 commit cd05e3c
Show file tree
Hide file tree
Showing 12 changed files with 451 additions and 141 deletions.
217 changes: 148 additions & 69 deletions dist/browser/bootlint.js
Original file line number Diff line number Diff line change
Expand Up @@ -10379,6 +10379,31 @@ if (typeof define === 'function' && define.amd)
);

},{}],4:[function(require,module,exports){
/**
* This file automatically generated from `pre-publish.js`.
* Do not manually edit.
*/

module.exports = {
"area": true,
"base": true,
"br": true,
"col": true,
"embed": true,
"hr": true,
"img": true,
"input": true,
"keygen": true,
"link": true,
"menuitem": true,
"meta": true,
"param": true,
"source": true,
"track": true,
"wbr": true
};

},{}],5:[function(require,module,exports){
/*!
* Bootlint - an HTML linter for Bootstrap projects
* https://github.com/twbs/bootlint
Expand All @@ -10391,6 +10416,7 @@ if (typeof define === 'function' && define.amd)
var cheerio = require('cheerio');
var parseUrl = require('url').parse;
var semver = require('semver');
var voidElements = require('void-elements');
var _location = require('./location');
var LocationIndex = _location.LocationIndex;

Expand All @@ -10416,6 +10442,30 @@ var LocationIndex = _location.LocationIndex;
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.2';
var BOOTSTRAP_VERSION_4 = '4.0.0';
var PLUGINS = [
'affix',
'alert',
'button',
'carousel',
'collapse',
'dropdown',
'modal',
'popover',
'scrollspy',
'tab',
'tooltip'
];
var BOOTSTRAP_FILES = [
'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(',');

function compareNums(a, b) {
return a - b;
Expand Down Expand Up @@ -10542,6 +10592,62 @@ var LocationIndex = _location.LocationIndex;
return runs;
}

/**
* This function returns the browser window object, or null if this is not running in a browser environment.
* @returns {(Window|null)}
*/
function getBrowserWindowObject() {
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
}

return theWindow;
}

function versionsIn(strings) {
return strings.map(function (str) {
var match = str.match(/^\d+\.\d+\.\d+$/);
return match ? match[0] : null;
}).filter(function (match) {
return match !== null;
});
}

function versionInLinkedElement($, element) {
var elem = $(element);
var urlAttr = (tagNameOf(element) === 'LINK') ? 'href' : 'src';
var pathSegments = parseUrl(elem.attr(urlAttr)).pathname.split('/');
var versions = versionsIn(pathSegments);
if (!versions.length) {
return null;
}
var version = versions[versions.length - 1];
return version;
}

function jqueryPluginVersions(jQuery) {
/* @covignore */
return PLUGINS.map(function (pluginName) {
var plugin = jQuery.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);
}

function bootstrapScriptsIn($) {
var longhands = $('script[src*="bootstrap.js"]').filter(function (i, script) {
var url = $(script).attr('src');
Expand Down Expand Up @@ -10796,16 +10902,11 @@ var LocationIndex = _location.LocationIndex;
if (!/^j[qQ]uery(\.min)?\.js$/.test(filename)) {
return;
}
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) {
var versions = versionsIn(pathSegments);
if (!versions.length) {
return;
}
var version = matches[matches.length - 1];
var version = versions[versions.length - 1];
if (!semver.gte(version, MIN_JQUERY_VERSION, true)) {
reporter(OLD_JQUERY, script);
}
Expand Down Expand Up @@ -11209,15 +11310,16 @@ var LocationIndex = _location.LocationIndex;
});
addLinter("W009", function lintEmptySpacerCols($, reporter) {
var selector = COL_CLASSES.map(function (colClass) {
return colClass + ':not(col):not(:last-child)';
return colClass + ':not(:last-child)';
}).join(',');
var columns = $(selector);
columns.each(function (_index, col) {
var column = $(col);
var isVoidElement = voidElements[col.tagName.toLowerCase()];
// can't just use :empty because :empty excludes nodes with all-whitespace text content
var hasText = !!column.text().trim().length;
var hasChildren = !!column.children(':first-child').length;
if (hasChildren || hasText) {
if (hasChildren || hasText || isVoidElement) {
return;
}

Expand Down Expand Up @@ -11255,44 +11357,11 @@ var LocationIndex = _location.LocationIndex;
});
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 ";
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 theWindow = getBrowserWindowObject();
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);
var versions = jqueryPluginVersions(globaljQuery);
if (versions.length) {
var minVersion = versions[0];
if (semver.lt(minVersion, CURRENT_BOOTSTRAP_VERSION, true)) {
Expand All @@ -11302,32 +11371,14 @@ var LocationIndex = _location.LocationIndex;
}
}
// 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(','));
var bootstraps = $(BOOTSTRAP_FILES);
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) {
var version = versionInLinkedElement($, this);
if (version === null) {
return;
}
var version = matches[matches.length - 1];
if (semver.lt(version, CURRENT_BOOTSTRAP_VERSION, true)) {
reporter(OUTDATED_BOOTSTRAP + version, elem);
reporter(OUTDATED_BOOTSTRAP + version, $(this));
}
});
});
Expand All @@ -11343,6 +11394,34 @@ 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);
/* @covignore */
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));
}
});
});

exports._lint = function ($, reporter, disabledIdList, html) {
var locationIndex = IN_NODE_JS ? new LocationIndex(html) : null;
Expand Down Expand Up @@ -11458,7 +11537,7 @@ var LocationIndex = _location.LocationIndex;
}
})(typeof exports === 'object' && exports || this);

},{"./location":1,"cheerio":2,"semver":3,"url":5}],5:[function(require,module,exports){
},{"./location":1,"cheerio":2,"semver":3,"url":6,"void-elements":4}],6:[function(require,module,exports){
/*eslint-env node, browser */
/* jshint browser: true */
/**
Expand Down Expand Up @@ -11498,4 +11577,4 @@ var LocationIndex = _location.LocationIndex;
exports.parse = parse;
})();

},{}]},{},[4]);
},{}]},{},[5]);
Loading

0 comments on commit cd05e3c

Please sign in to comment.