Last active
October 18, 2017 19:48
-
-
Save drmercer/7da5b9dbe1a3e0b3ccc43c7fff8a1ec5 to your computer and use it in GitHub Desktop.
A jQuery plugin for tracking HTML "coverage" of jQuery selectors - it helps you figure out which selectors aren't actually selecting any elements, which may signify dead code.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Include using | |
<script type="text/javascript" src="https://cdn.rawgit.com/drmercer/7da5b9dbe1a3e0b3ccc43c7fff8a1ec5/raw/86dba4b108a0ac3f1889f06c9db9454d88f770b1/jQuery-coverage.js"></script> | |
Be sure to include it after you've loaded jQuery. | |
*/ | |
window.jqcoverage = (function ($) { | |
"use strict"; | |
function log(...args) { | |
console.log("%c[jQuery-coverage]", "color:aqua", ...args); | |
} | |
// Configuration stuff (stores settings in localStorage) | |
const KEY_SELECTORS = "jQuery-coverage-badSelectors"; | |
const badSelectors = JSON.parse(localStorage.getItem(KEY_SELECTORS)) || []; | |
const KEY_BLACKLIST = "jQuery-coverage-blacklist"; | |
const blacklistedSelectors = JSON.parse(localStorage.getItem(KEY_BLACKLIST)) || []; | |
function saveBlacklist() { | |
localStorage.setItem(KEY_BLACKLIST, JSON.stringify(blacklistedSelectors)); | |
} | |
const KEY_LOG_ENABLED = "jQuery-coverage-logEnabled"; | |
var logBadSelectors = JSON.parse(localStorage.getItem(KEY_LOG_ENABLED) || "true"); | |
function saveLogEnabledSetting() { | |
localStorage.setItem(KEY_LOG_ENABLED, JSON.stringify(logBadSelectors)); | |
} | |
if (badSelectors.length) { | |
log("Loaded " + badSelectors.length + " bad selectors from a previous run"); | |
if (!logBadSelectors) { | |
log("(Logging disabled. Call jqcoverage.enableBadSelectorLogging() to enable)"); | |
} | |
} | |
// This object is made global, so you can use it from the dev console. More functions below. | |
const jqcoverage = { | |
disableBadSelectorLogging: function () { | |
logBadSelectors = false; | |
saveLogEnabledSetting(); | |
log("Bad selector logging disabled"); | |
}, | |
enableBadSelectorLogging: function () { | |
logBadSelectors = true; | |
saveLogEnabledSetting(); | |
log("Bad selector logging enabled"); | |
}, | |
}; | |
// Create proxy jQuery function: | |
const coverageMap = {}; | |
const new$ = function (...args) { | |
const $res = $(...args); | |
const key = args.join(); | |
const prevCount = coverageMap[key] || 0; | |
const newCount = Math.max($res.length, prevCount); | |
coverageMap[key] = newCount; | |
// Warn when bad selectors are used again, to give the dev a stack trace | |
if (logBadSelectors && | |
newCount === 0 && | |
badSelectors.includes(key) && | |
!blacklistedSelectors.includes(key)) { | |
console.warn("Bad selector used: ", ...args); | |
} | |
return $res; | |
}; | |
$.extend(new$, $); | |
window.jQuery = new$; | |
if (window.$ === $) { | |
window.$ = new$; | |
} | |
//============================================== | |
// Coverage report tools | |
// Call this to get a coverage report | |
jqcoverage.getCoverage = function () { | |
const summary = {}; | |
$.each(coverageMap, function (key, val) { | |
summary[val] || (summary[val] = []); | |
summary[val].push(key); | |
}); | |
return summary; | |
}; | |
jqcoverage.getCoverageOf = function(selector) { | |
selector = "" + selector; | |
var useCount = coverageMap[selector] || 0; | |
return selector + " selected at most " + useCount + " element(s)"; | |
}; | |
// Call this to save the list of bad selectors to localStorage | |
jqcoverage.saveBadSelectors = function () { | |
const badSelectors = jqcoverage.getCoverage()[0] || []; | |
localStorage.setItem(KEY_SELECTORS, JSON.stringify(badSelectors)); | |
const badSelectorCount = badSelectors.length; | |
log("Saved " + badSelectorCount + " bad selectors to analyze on a later run"); | |
}; | |
// Call this to clear the list of bad selectors inlocalStorage and memory | |
jqcoverage.clearBadSelectors = function () { | |
localStorage.removeItem(KEY_SELECTORS); | |
badSelectors.splice(0); | |
}; | |
//============================================== | |
// Key blacklisting tools | |
jqcoverage.blacklistSelector = function (selector) { | |
if (typeof selector !== "string") { | |
throw new Error("Selector must be a string"); | |
} | |
if (!blacklistedSelectors.includes(selector)) { | |
blacklistedSelectors.push(selector); | |
} | |
saveBlacklist(); | |
}; | |
jqcoverage.unblacklistSelector = function (selector) { | |
var idx = blacklistedSelectors.indexOf(selector); | |
if (idx !== -1) { | |
blacklistedSelectors.splice(idx, 1); | |
return "Selector removed from blacklist"; | |
} else { | |
return "Selector not found in blacklist"; | |
} | |
saveBlacklist(); | |
}; | |
log("jQuery-coverage loaded"); | |
return jqcoverage; | |
}(window.jQuery)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment