Validating Comments
Update:
The plugin has a new home page. Look there for the most up-to-date installation instructions.I actually got a couple of emails about my previous post on implementing Comment Validation in a MovableType blog. Evidently, there’s some interest out there. So here is the first in an occasional series of “How-To” articles on MovableType.
Alexei Kosut wrapped the W3C Validator in an MT plugin. I extended his plugin by adding some more MT Template tags, correcting some errors where the Validator was sending invalid output and customized the Validator’s output templates to make them more suitable for inclusion in a weblog comment preview window. More recently (5/26/2004), I updated the plugin to incorporate the newer, more user-friendly error-reporting in the new W3C Validator and added (6/22/2004) some portability fixes. Since Alexei seems to have lost interest, and since my changes are now quite substantial, you can now get my revised plugin with all the changes rolled in.
The plugin has a bunch of prerequisites. You may need to install or update several Perl modules:
Config::General
(version 2.06 or later)File::Spec
(version 0.8 or later)HTML::Entities
HTML::Parser
(version 3.25 or later)HTML::Template
(version 2.6 or later)IO::File
IPC::Open3
Set::IntSpan
Text::Iconv
Text::Wrap
If you’re not already using the CPAN module, then perhaps now would be a good time. With CPAN, you can install the whole lot with a single command,
install HTML::Template Bundle::W3C::Validator
or, if you have most of what you need already, you can install just the missing modules with an appropriate “install ...
” command.
“But wait!” I hear you cry, “I don’t have root on my webhost. How can I use CPAN?” Well, the folks who designed it were helpful enough to design it so that you can also install files locally (in your MT/extlib
directory):
perl -MCPAN -e shell o conf makepl_arg "LIB=/your/path/to/MT/extlib \ INSTALLMAN1DIR=/dev/null \ INSTALLMAN3DIR=/dev/null" install HTML::Template Bundle::W3C::Validator
CPAN puts the modules through a rigorous set of self-test before installing them. Even if a module passes every single self-test but one, CPAN will err on the side of caution and not install it. For your purposes, this is way more conservative than you need. If a module fails a couple of tests, but passes almost all of the rest, just do a
force install ModuleName
That is pretty sure to be safe.
You may also need a copy of the onsgmls
program from the OpenSP Project. It comes pre-installed with most flavours of Linux. For MacOSX, I got mine from Fink (“fink install opensp3
”). If worst comes to worst, you can download and compile the OpenSP source. In any case, you may have to edit /plugins/validator/config/validator.conf
to point to the location of the onsgmls
executable. In my case, it reads
SGML_Parser = /sw/bin/onsgmls
Now that you have the SGML parser installed, you need a set of DTDs for it to work with. Download and unpack sgml-lib and install it as plugins/validator/sgml-lib
.
One more gotcha has to do with whether, in Perl, $0
returns just the filename or the full path on your operating system. If the Validator complains about being unable to find its configuration files, set the path to your plugins directory
PluginPath /full/path/to/plugins
in mt.cfg
and the error will go away.
The output of the Validator is controlled by a bunch of template files in plugins/validator/templates/
. The relevant ones are probably results.html
(the main template controlling the output), valid.html
(included if the page validated) and invalid.html
(included if there were errors). You’ll want to tweak them so that the output looks like what you want. And you’re free to use CSS to style them as you wish.
But first, we need to modify our MovableType templates. The key one will be the Comment Preview Template. Let me step you through mine.
<$MTInclude module="DTD"$> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title><$MTBlogName$>: Comment Preview</title> <$MTInclude module="HeaderLinks"$> </head> <body> <$MTInclude module="SmallBanner"$> <div class="blog"> <h2 class="comments-head">Preview Your Comment</h2>
As you can see, a lot of stuff in my templates is abstracted into modules. I can change the DTD of all the pages of my blog by editing one template module. That module currently reads:
<?xml version='1.0' encoding='iso-8859-1'?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN" "http://www.w3.org/TR/MathML2/dtd/xhtml-math11-f.dtd" >
Being able to change something by editing one template module and having the change reflected blog-wide is a very good thing.
<MTValidate> <$MTInclude module="DTD"$> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Your Comment</title> </head> <body> <h3 class="title"><$MTCommentPreviewSubject strip_controlchars="2" remove_html="1"$></h3> <$MTCommentPreviewBody safe_urls="1" smarty_pants="2"$> <p class="comments-post">Submitted by <$MTCommentPreviewAuthorLink spam_protect="1"$> at <$MTCommentPreviewDate$></p> </body> </html> </MTValidate> <form method="post" action="<$MTCGIPath$><$MTCommentScript$>">
The contents of the <MTValidate>...</MTValidate>
gets passed to the Validator. Note that the Validator expects a fully-formed (X)HTML document, right down to the DTD. Also, I happen to be using the SmartyPants and
safe_href plugins.
If the comment had errors, we’ll get a sad message listing the errors. If it was valid XHTML, we’ll get a happy message and then we’ll want to present the user with a preview of his comment and an opportunity to post it. The contents of <MTValidateIfValid>...</MTValidateIfValid>
only appear if the Validator found no errors.
<MTValidateIfValid> <div class="blogbody"> <$MTCommentPreviewBody safe_urls="1" smarty_pants="2"$> <span class="comments-post">Submitted by <$MTCommentPreviewAuthorLink spam_protect="1"$> at <$MTCommentPreviewDate$></span> </div> <fieldset class="blogbody"> <input type="submit" name="post" value=" POST " /> </fieldset> </MTValidateIfValid>
We only want to display the comment preview if the comment was valid XHTML, and the same goes for the “POST” button.
Next, we present the user with the opportunity to edit the comment and preview it again. Note that there are some additional form fields, because we’re using Alexei’s most excellent MTThreadedComments plugin.
<h2 class="comments-head">Edit Your Comment</h2> <fieldset class="blogbody"> <input type="hidden" name="entry_id" value="<$MTEntryID$>" /> <input type="hidden" name="static" value="<$MTCommentPreviewIsStatic$>" /> <label for="author">Name:</label><br /> <input id="author" name="author" value="<$MTCommentPreviewAuthor encode_html="1"$>" /><br /> <label for="email">Email Address:</label><br /> <input id="email" name="email" size="30" value="<$MTCommentPreviewEmail encode_html="1"$>" /><br /> <label for="url">URL:</label><br /> <input id="url" name="url" size="50" value="<$MTCommentPreviewURL encode_html="1"$>" /><br /> <input type="hidden" name="parent_id" value="<$MTCommentPreviewParentID$>" /> <label for="subject">Subject: </label><br /> <input id="subject" name="subject" size="30" value="<$MTCommentPreviewSubject encode_html="1"$>" /><br /> <label for="text">Comments:</label><br /> <textarea id="text" name="text" rows="10" cols="48"><$MTCommentPreviewBody convert_breaks="0" encode_html="1"$> </textarea><br /> <input type="submit" name="preview" value=" PREVIEW " /> </fieldset> </form>
Note, again, that there’s only a “PREVIEW” button here. We want the commenter to preview the comment again, if it’s been edited.
Finally, if there are any, we’ll present the user with a listing of previous comments and trackbacks (using the MTSimpleComments plugin) on this post. The same template module used to provide this listing is used to list the comments and trackbacks on the individual archive page. To get the conditional display, we use the Compare plugin.
<MTIfGreater a="[MTSimpleCommentCount]" b="0"> <h2 class="comments-head">Previous Comments & Trackbacks</h2> <MTInclude module="FollowupList> </MTIfGreater> </div> </body> </html>
Now all we need to do is remove the “POST” button from the Comment Listing Template and the Comment Error Template, so that people need to preview their comment (and, in so doing, run it through the Validator) before they can post it.
Try it out! Type a comment and preview it. Try seeing what happens if you stick in some invalid HTML. Nifty, huh?
Update (11/27/2006): More Checks
Version 0.4 of the plugin incorporates a new configuration option in /plugins/validator/config/validator.conf
. The onsgmls
parser doesn’t really check XHTML documents for well-formedness. To get an extra layer of protection, you can set
XHTML_Check = 1
which runs the comment through a real XML parser, ensuring that it is well-formed. To use this option, you’ll need the XML::LibXML
Perl Module.
The new version also incorporates yet more user-friendly error messages from version 0.74 of the W3C Validator.
Re: Validating Comments
Hmmm… Don’t mind me, I find this interesting and I’d like to try it out… so below will be some badly formated HTML…
bad formating with bold and italic…
Thanks for the test :)
———————–>
OH WOW! It works even better than I dreamed… maybe when I have a few hours I’ll implement this :)