Skip to content

Instantly share code, notes, and snippets.

@ttscoff

ttscoff/linkchecker.js

Last active Feb 8, 2021
Embed
What would you like to do?
if ((/^localhost/).test(document.location.host)) {
var linkChecker = (function() {
"use strict";
let links, errors = [], completed = [], errorCounter = 0;
function addStyle(styleString) {
const style = document.createElement("style");
style.textContent = styleString;
document.head.append(style);
}
function finished(counter) {
completed.push(counter);
if (completed.length === links.length) {
errors = errors.filter(e => typeof e === "object");
if (errors.length > 0) {
let errorNav = `${errors.length} Link Errors: <a href="javascript:linkChecker.prevError()">&#9650;</a><a href="javascript:linkChecker.nextError()">&#9660;</a>`;
addStyle(
`
#linkCheckerErrorDialog {
background-color: rgba(255,0,0,.9);
border-radius: 5px;
color: white;
display: flex;
font-weight: bolder;
padding: 5px;
position: fixed;
left: 5px;
top: 5px;
z-index: 10000;
}
#linkCheckerErrorDialog a {
background: none;
color: white;
display: inline-block;
padding: 0 .5em;
text-decoration: none;
}
.linkError {
border: solid 1px rgba(255,0,0,.6);
border-radius: 1em;
padding: 0 5px;
background: rgba(255,0,0,.02);
}
.linkError:target {
background: rgba(255,0,0,.5);
color: #fff;
}
.linkError:target::after {
content: attr(href);
color: #fff;
position: fixed;
bottom: 5px;
left: 5px;
background: rgba(0,0,0,.5);
height: 2em;
line-height: 2;
padding: 0 5px;
border-radius: 5px;
}
`
);
let errorDialog = document.createElement("div");
errorDialog.id = "linkCheckerErrorDialog";
errorDialog.innerHTML = errorNav;
document.body.appendChild(errorDialog);
}
}
}
var linkChecker = {
currentError: -1,
errors: [],
nextError: function() {
let err = linkChecker.currentError;
if (err >= errors.length - 1) {
err = 0;
} else {
err += 1;
}
let target = "#" + errors[err][0];
document.location.hash = target;
linkChecker.currentError = err;
},
prevError: function() {
let err = linkChecker.currentError;
if (err <= 0) {
err = errors.length - 1;
} else {
err -= 1;
}
let target = "#" + errors[err][0];
document.location.hash = target;
linkChecker.currentError = err;
},
check: function() {
links = document.querySelectorAll("a[href]");
links.forEach((i, idx) => {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 400) {
i.classList += " linkError";
i.id = "error-" + errorCounter;
errors[idx] = [i.id, i.href];
errorCounter += 1;
}
finished(idx);
}
};
xhr.open("HEAD", i.href);
xhr.send();
});
}
};
return linkChecker;
})();
document.addEventListener("DOMContentLoaded", (event) => {
linkChecker.check();
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment