summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--paste/wdg_validate.py75
1 files changed, 75 insertions, 0 deletions
diff --git a/paste/wdg_validate.py b/paste/wdg_validate.py
new file mode 100644
index 0000000..b7bdeff
--- /dev/null
+++ b/paste/wdg_validate.py
@@ -0,0 +1,75 @@
+"""
+Middleware that checks HTML and appends messages about the validity of
+the HTML. Uses: http://www.htmlhelp.com/tools/validator/ -- interacts
+with the command line client. Use the configuration ``wdg_path`` to
+override the path (default: looks for ``validate`` in $PATH).
+
+To install, in your web context's __init__.py::
+
+ def urlparser_wrap(environ, start_response, app):
+ return wdg_validate.WDGValidateMiddleware(app)(
+ environ, start_response)
+"""
+
+from cStringIO import StringIO
+import subprocess
+from paste import wsgilib
+import re
+import cgi
+
+class WDGValidateMiddleware(object):
+
+ _end_body_regex = re.compile(r'</body>', re.I)
+
+ def __init__(self, app):
+ self.app = app
+
+ def __call__(self, environ, start_response):
+ output = StringIO()
+ response = []
+ def writer_start_response(status, headers):
+ response.extend((status, headers))
+ start_response(status, headers)
+ return output.write
+ app_iter = self.app(environ, writer_start_response)
+ try:
+ for s in app_iter:
+ output.write(s)
+ finally:
+ if hasattr(app_iter, 'close'):
+ app_iter.close()
+ page = output.getvalue()
+ status, headers = response
+ v = wsgilib.header_value(headers, 'content-type')
+ if (not v.startswith('text/html')
+ and not v.startswith('text/xhtml+xml')):
+ # Can't validate
+ # @@: Should validate CSS too... but using what?
+ return [page]
+ ops = []
+ if v.startswith('text/xhtml+xml'):
+ ops.append('--xml')
+ # @@: Should capture encoding too
+ conf = environ['paste.config']
+ wdg_path = conf.get('wdg_path', 'validate')
+ proc = subprocess.Popen([wdg_path] + ops,
+ shell=False,
+ close_fds=True,
+ stdout=subprocess.PIPE,
+ stdin=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ stdout = proc.communicate(page)[0]
+ proc.wait()
+ if not stdout:
+ return [page]
+ add_text = '<pre style="background-color: #ffd; color: #600; border: 1px solid #000;">%s</pre>' % cgi.escape(stdout)
+ match = self._end_body_regex.search(page)
+ if match:
+ page = page[:match.start()] + add_text + page[match.end():]
+ else:
+ page += add_text
+ return [page]
+
+
+
+