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.

We'll thanks to the magic of bookmarklets we can instead:

Much better ya!

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.

W3C Markup Validation
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.

Optionally specify private hostnames and then drag the button above to your bookmark bar.

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!