Making/finding html5 validator bookmarklet
Asked Answered
T

4

5

I want to find or make a bookmarklet that will validate the html content of a currently viewed page using the W3C HTML 5 validator.

I have found two bookmarklets and am trying to get one to behave a bit like one and a bit like the other, however I am not sure how to do this.

Chris Coyier has an HTML5 validation bookmarklet that works well except it uses the page URI so does not work for locally tested sites:

javascript:(function(){%20function%20fixFileUrl(u)%20{%20var%20windows,u;%20windows%20=%20(navigator.platform.indexOf("Win")%20!=%20-1);%20%20/*%20chop%20off%20file:///,%20unescape%20each%20%hh,%20convert%20/%20to%20\%20and%20|%20to%20:%20*/%20%20u%20=%20u.substr(windows%20?%208%20:%207);%20u%20=%20unescape(u);%20if(windows)%20{%20u%20=%20u.replace(/\//g,"\");%20u%20=%20u.replace(/\|/g,":");%20}%20return%20u;%20}%20/*%20bookmarklet%20body%20*/%20var%20loc,fileloc;%20loc%20=%20document.location.href;%20if%20(loc.length%20>%209%20&&%20loc.substr(0,8)=="file:///")%20{%20fileloc%20=%20fixFileUrl(loc);%20if%20(prompt("Copy%20filename%20to%20clipboard,%20press%20enter,%20paste%20into%20validator%20form",%20fileloc)%20!=%20null)%20{%20document.location.href%20=%20"http://validator.w3.org/file-upload.html"%20}%20}%20else%20document.location.href%20=%20"http://validator.w3.org/check?uri="%20+%20escape(document.location.href);%20void(0);%20})();

I also found this one, which works by grabbing the html of the current page, but I can't figure out how to make it do html5... there is reference to doctype in the code and I have tried changing this to html5, html500 etc, and removing it entirely hoping it would autodetect.. but to no avail:

javascript:(function(){var h=document;var b=h.doctype;var e="<!DOCTYPE "+b.name.toLowerCase()+' PUBLIC "'+b.publicId+'" "'+b.systemId+'">\n';var g=h.documentElement.outerHTML;var f="http://validator.w3.org/check";var i={prefill_doctype:"html401",prefill:0,doctype:"inline",group:0,ss:1,st:1,outline:1,verbose:1,fragment:e+g};var a=h.createElement("form");a.setAttribute("method","post");a.setAttribute("target","_blank");a.setAttribute("action",f);for(var j in i){var c=h.createElement("input");c.setAttribute("type","hidden");c.setAttribute("name",j);c.setAttribute("value",i[j]);a.appendChild(c)}if(navigator.appCodeName=="Mozilla"){h.body.appendChild(a)}a.submit()})();
Tallahassee answered 30/4, 2012 at 2:25 Comment(0)
D
11

First, you need an exact copy of the HTML document (including Doctype etc). For this purpose, I have written the following function:

function DOMtoString(document_root) {
    var html = '',
        node = document_root.firstChild;
    while (node) {
        switch (node.nodeType) {
            case Node.ELEMENT_NODE:
                html += node.outerHTML;
            break;
            case Node.TEXT_NODE:
                html += node.nodeValue;
            break;
            case Node.CDATA_SECTION_NODE:
                html += '<![CDATA[' + node.nodeValue + ']]>';
            break;
            case Node.COMMENT_NODE:
                html += '<!--' + node.nodeValue + '-->';
            break;
            case Node.DOCUMENT_TYPE_NODE:
                // (X)HTML documents are identified by public identifiers
                html += "<!DOCTYPE "
                     + node.name
                     + (node.publicId ? ' PUBLIC "' + node.publicId + '"' : '')
                     + (!node.publicId && node.systemId ? ' SYSTEM' : '') 
                     + (node.systemId ? ' "' + node.systemId + '"' : '')
                     + '>\n';
            break;
        }
        node = node.nextSibling;
    }
    return html;
}

Then, a form has to be created and submitted. After inspecting the form submission to http://validator.w3.org/check, I've created the following function, which submits the significant key-value pairs:

javascript:(function() {
    var html_to_validate = DOMtoString(document);

    /* Paste the DOMtoString function here */

    function append(key, value) {
        var input = document.createElement('textarea');
        input.name = key;
        input.value = value;
        form.appendChild(input);
    }
    var form = document.createElement('form');
    form.method = 'POST';
    form.action = 'http://validator.w3.org/check';
    form.enctype = 'multipart/form-data';         // Required for this validator
    form.target = '_blank';                       // Open in new tab
    append('fragment', html_to_validate);         // <-- Code to validate
    append('doctype', 'HTML5');                   // Validate as HTML 5
    append('group', '0');
    document.body.appendChild(form);
    form.submit();
})();

Bookmarklet

Copy the previous two blocks to Google's closure compiler. Do not forget to prefix javascript: again.

javascript:(function(){function c(a,b){var c=document.createElement("textarea");c.name=a;c.value=b;d.appendChild(c)}var e=function(a){for(var b="",a=a.firstChild;a;){switch(a.nodeType){case Node.ELEMENT_NODE:b+=a.outerHTML;break;case Node.TEXT_NODE:b+=a.nodeValue;break;case Node.CDATA_SECTION_NODE:b+="<![CDATA["+a.nodeValue+"]]\>";break;case Node.COMMENT_NODE:b+="<\!--"+a.nodeValue+"--\>";break;case Node.DOCUMENT_TYPE_NODE:b+="<!DOCTYPE "+a.name+(a.publicId?' PUBLIC "'+a.publicId+'"':"")+(!a.publicId&&a.systemId? " SYSTEM":"")+(a.systemId?' "'+a.systemId+'"':"")+">\n"}a=a.nextSibling}return b}(document),d=document.createElement("form");d.method="POST";d.action="http://validator.w3.org/check";d.enctype="multipart/form-data";d.target="_blank";c("fragment",e);c("doctype","HTML5");c("group","0");document.body.appendChild(d);d.submit()})();
Deerhound answered 2/5, 2012 at 19:29 Comment(8)
Thank you! Especially for the explanation of how you went about making it. Very useful. I may look into if it can be made to auto-detect the doctypeTallahassee
@Tallahassee If you want to auto-detect the document type, use "Inline" instead of "HTML5".Deerhound
I'm finding certain pages are having a 'Sorry! This document cannot be checked.' error. for instance: designswan.com. It usually comes up after a long load time. Any idea what might be causing this?Tallahassee
@Tallahassee Currently, I see no errors at Chrome and Firefox. I guess that you attempted to use the service when it was overloaded. Side note: Keep in mind that the rendered HTML is validated. Missing close tags/attributes are automatically added by the browser. If the page is fully static, it might be a better option to validate the URL (or, use a XHR to fetch the raw data, for local pages).Deerhound
xhr? sounds intriguing. i'm getting some weird errors.. like ` 500 Can't connect to localhost:8888 (connect: Connection refused)'` on non-local websites (frex: www.milliontrees.ca)Tallahassee
@Tallahassee These errors are not related to the web service. Using the steps in my answer, you can use validator.nu. Unrelated note: The XHR suggestion in the previous post does not have anything to do with the error you get. I only mentioned it, to make you aware of the fact that the rendered HTML does not necessarily have to be equal to the downloaded page.Deerhound
ah.. i just couldn't imagine why it'd be trying to connect to localhost for a non local site..Tallahassee
when I use this with bookmarklet I see the temporarily created form is remained on the page . Maybe need to add some code to delete that form?Reinaldoreinaldos
S
1

I was also getting the 'Sorry! This document cannot be checked.' error, resolved it by adding an accept-charset "utf-8" to the form attributes.

In the function that creates the form element add the following line: form.acceptCharset = "utf-8";

It worked for me.

Splanchnic answered 7/1, 2013 at 14:58 Comment(0)
L
1

Marta's answer helped me out. Here is the updated bookmarklet.

javascript:(function(){function c(a,b){var c=document.createElement("textarea");c.name=a;c.value=b;d.appendChild(c)}var e=function(a){for(var b="",a=a.firstChild;a;){switch(a.nodeType){case Node.ELEMENT_NODE:b+=a.outerHTML;break;case Node.TEXT_NODE:b+=a.nodeValue;break;case Node.CDATA_SECTION_NODE:b+="<![CDATA["+a.nodeValue+"]]\>";break;case Node.COMMENT_NODE:b+="<\!--"+a.nodeValue+"--\>";break;case Node.DOCUMENT_TYPE_NODE:b+="<!DOCTYPE "+a.name+(a.publicId?' PUBLIC "'+a.publicId+'"':"")+(!a.publicId&&a.systemId? " SYSTEM":"")+(a.systemId?' "'+a.systemId+'"':"")+">\n"}a=a.nextSibling}return b}(document),d=document.createElement("form");d.method="POST";d.action="http://validator.w3.org/check";d.enctype="multipart/form-data";d.target="_blank";d.acceptCharset="utf-8";c("fragment",e);c("doctype","HTML5");c("group","0");document.body.appendChild(d);d.submit()})();
Lynching answered 16/5, 2013 at 15:57 Comment(0)
L
1

The previous answers didn't work form me. I'm using the "Check serialized DOM of Current Page" bookmarklet at https://validator.w3.org/nu/about.html. This seems to work wonderfully, picking up dynamically generated HTML.

Lenlena answered 16/7, 2015 at 19:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.