W3C Markup Validation Bookmarklet
August 5, 2013
April 10, 2016 - The W3C Markup Validation Bookmarklet is now open source and on GitHub. Please refer to the open source repository for the most up to date code.
I love the W3C Markup Validation Service but I was growing tired of the following process.
- Open Validator
- Switch tabs
- Copy URL
- Switch tabs
- Paste URL
- Click check
We'll thanks to the magic of bookmarklets we can instead:
- Click bookmarklet
What's a bookmarklet?
A bookmarklet (or favelet) is a special kind of bookmark that uses JavaScript.
The W3C actually has some nice ones listed on their Favelets For The Validator page. They are perfect for publicly accessible resources but do not work for password protected pages, localhost servers or other private locations.
Speaking of which...
Is is possible to check private pages with a bookmarklet?
Almost... almost... in fact my first version of a bookmarklet did exactly this. Unfortunately there seems to be no way to get at the raw HTML source. This means the code that gets sent to the Validator is already parsed and cleaned up. Normally a good thing but when looking for mistakes... not so much.
I'm pretty sure there are browser extensions out there that can do this but I like to keep my browser light and that means bookmarklets.
Feel free to copy the code below if pulling the currently parsed HTML is useful for something you are working on.
/* Validate by Direct Input */
var doctype = document.doctype,
html,
quote = unescape('%22'),
form = document.createElement('form'),
input = document.createElement('input');
if (doctype !== null) {
html = '<!DOCTYPE ';
html += doctype.name;
html += (doctype.publicId ? ' PUBLIC ' + quote + doctype.publicId + quote : '');
html += (!doctype.publicId && doctype.systemId ? ' SYSTEM' : '');
html += (doctype.systemId ? ' ' + quote + doctype.systemId + quote : '');
html += '>\n';
}
html += document.getElementsByTagName('html')[0].outerHTML;
/* Chrome extensions use chrome-extension: */
html = html.replace(/<link.*?chrome-extension:.*?>/ig, '');
html = html.replace(/<script.*?chrome-extension:.*?>.*?>/ig, '');
/* Firefox add-ons use chrome: */
/* Safari extensions use safari-extension: */
form.method = 'post';
form.action = validator + 'check';
form.target = '_blank';
form.style.cssText = 'display: none !important';
input.setAttribute('name', 'fragment');
input.setAttribute('value', html);
form.appendChild(input);
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);
The Solution
In order of increasing convenience; here is the how the bookmarklet works.
- If the site being viewed is not http or https then open the Validator like a regular bookmark would do.
- If the site being viewed is private then open directly to Validate by Direct Input for some human copy/paste assistance.
- If the site being viewed is not private then send the URL directly to Validate by URI for instant results.
Drag the button above to your bookmark bar.
Private locations have to be checked a more manually by using the Validate by Direct Input method instead of Validate by URI. The default private locations are localhost, 127.0.0.1 and ::1 although you can add to this list using the input box below.
The bookmarklet will try to emulate a regular bookmark if you click on it while viewing a non-http or https page. The keyword is try though. It does not work from new tab page in Chrome or Firefox for example.
Compatibility
Chrome, Firefox 11+, Safari and IE9+
Bookmarklet Code
Feel free to peruse and use for anything you like. Go crazy!
javascript:(function() {
/*
W3C Markup Validation Bookmarklet
By Daniel Gagan of ForestMist.org
Version 2013-08-05
Chrome, Firefox 11+, Safari and IE9+
*/
var validator = 'https://validator.w3.org/',
direct_input = ['localhost', '127.0.0.1', '::1'],
direct_input_additional = [];
direct_input = direct_input.concat(direct_input_additional);
if (window.location.protocol.indexOf('http') === 0) {
if (direct_input.indexOf(window.location.hostname.toLowerCase()) >= 0) {
/* Validate by Direct Input */
window.open(validator + '#validate_by_input');
} else {
/* Validate by URI */
window.open(validator + 'check?uri=' + encodeURIComponent(window.location.href));
}
} else {
window.open(validator);
}
})();
Code improvements, issue reports, questions, suggestions or anything else related are welcome.
Cheers!