HTML validation using Web Design Group's HTML validator.


import os

from WebUtils.Funcs import htmlEncode
from MiscUtils import StringIO

def encodeWithIndentation(html):
    """Encode HTML and create indentation from tab characters."""
    html = htmlEncode(html).replace('  ', '  ')
    return html.replace('\t', '    ')

def validateHTML(html):
    """Validate the given html.

    Validate the input using Web Design Group's HTML validator
    available at http://www.htmlhelp.com/tools/validator/

    Make sure you install the offline validator (called "validate")
    which can be called from the command-line.
    The "validate" script must be in your path.

    If no errors are found, an empty string is returned.
    Otherwise, the HTML with the error messages is returned.


    input, output = os.popen4('validate')
    out = output.readlines()

    errorLines = {}
    for line in out:
        if line[0:5] == 'Line ':
            i = line.find(',')
            if i >= 0:
                linenum = int(line[5:i])
                errorLines[linenum] = line

    # Be quiet if all's well
    if not errorLines:
        return ''

    result = StringIO()
    result.write('<table style="background-color: #ffffff">'
        '<tr><td colspan="2">\n')
    result.write("<pre>%s</pre>" % "".join(out))

    goodColors = ['#d0d0d0', '#e0e0e0']
    badColor = '#ffd0d0'
    lines = html.splitlines(True)
    i = 1
    for line in lines:
        if i in errorLines:
            result.write('<tr style="background-color: %s">'
                '<td rowspan="2">%d</td><td>%s</td></tr>\n'
                % (badColor, i, encodeWithIndentation(errorLines[i])))
            result.write('<tr style="background-color: %s">'
                % (badColor, encodeWithIndentation(line)))
            color = goodColors[i % 2]
            result.write('<tr style="background-color: %s">'
                % (color, i, encodeWithIndentation(line)))
        i += 1
    return result.getvalue()