<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Ardamis &#187; xhtml</title>
	<atom:link href="http://www.ardamis.com/tag/xhtml/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ardamis.com</link>
	<description>Ardamis is a blog about web development and technology in general.</description>
	<lastBuildDate>Thu, 02 Feb 2012 07:07:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Ardamis in 2012 &#8211; new look, more microdata, faster code</title>
		<link>http://www.ardamis.com/2012/01/22/ardamis-2012/</link>
		<comments>http://www.ardamis.com/2012/01/22/ardamis-2012/#comments</comments>
		<pubDate>Mon, 23 Jan 2012 05:50:02 +0000</pubDate>
		<dc:creator>ardamis</dc:creator>
				<category><![CDATA[Google]]></category>
		<category><![CDATA[Web Site Dev]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[comment spam]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[themes]]></category>
		<category><![CDATA[xhtml]]></category>

		<guid isPermaLink="false">http://www.ardamis.com/?p=1863</guid>
		<description><![CDATA[Ardamis.com is starting out 2012 with a new look, better structured data markup, and a revamped anti-spam system.]]></description>
			<content:encoded><![CDATA[<p>Just a few weeks behind schedule, but a long time in the works, I&#8217;ve finally pushed the new WordPress theme for Ardamis live.  Basic and elegant (I&#8217;m trying to establish a trend here), the theme also should outperform its predecessors in both page load times and SEO-potential.  The index and archive pages should appear more consistent, and all pages should provide more complete structured data markup (<a href="http://schema.org/">schema.org</a> as well as <a href="http://microformats.org/wiki/existing-classes">microformats.org</a>).  The comment form has been outfitted with <a href="http://www.ardamis.com/2011/08/27/a-cache-proof-method-for-reducing-comment-spam/">an improved approach to reducing comment spam</a>.</p>
<p>The new theme is pretty light on the graphics, due to increased browser support for and subsequently greater use of CSS3 goodness for box shadows and gradients.  I&#8217;ve reduced the number of image files to two: a background and a sprites file.</p>
<p>Only half-implemented in the previous theme, the new look, &#8220;Joy&#8221;, makes much better use of structured data markup, or <a href="http://en.wikipedia.org/wiki/Microdata_(HTML)">microdata</a>.  Google is absolutely looking for ways to display your pages&#8217; semantic markup in its results, so you may as well get on board.</p>
<p>The frequency of spam comments increased dramatically over the past two months, according to my Akismet stats, so I&#8217;ve gone back to the drawing board and developed a better front-line defense against them.  The new method should be more opaque to bots that parse JavaScript while still being invisible to human visitors leaving legitimate comments.</p>
<p>In sum, I think Ardamis should be leaner, faster, and smarter (and maybe prettier) in 2012 than ever before.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ardamis.com/2012/01/22/ardamis-2012/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A cache-friendly method for reducing WordPress comment spam</title>
		<link>http://www.ardamis.com/2011/08/27/a-cache-proof-method-for-reducing-comment-spam/</link>
		<comments>http://www.ardamis.com/2011/08/27/a-cache-proof-method-for-reducing-comment-spam/#comments</comments>
		<pubDate>Sat, 27 Aug 2011 08:34:53 +0000</pubDate>
		<dc:creator>ardamis</dc:creator>
				<category><![CDATA[Nonsense]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web Site Dev]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[application]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[comment spam]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[spam]]></category>
		<category><![CDATA[templates]]></category>
		<category><![CDATA[themes]]></category>
		<category><![CDATA[web app]]></category>
		<category><![CDATA[xhtml]]></category>

		<guid isPermaLink="false">http://www.ardamis.com/?p=1673</guid>
		<description><![CDATA[A safe-for-cached-pages method of filtering out spam comments by requiring at least some time to have passed between the time the page is loaded and the form is submitted.]]></description>
			<content:encoded><![CDATA[<p>In the endless battle against WordPress comment spam, I&#8217;ve developed and then refined a few different methods for preventing spam from getting to the database to begin with.  My philosophy has always been that a human visitor and a spam bot behave differently (after all, we&#8217;re not dealing with <a href="http://en.wikipedia.org/wiki/Do_Androids_Dream_of_Electric_Sheep%3F#Androids">Nexus-6 model androids</a> here), and an effective spam-prevention method should be able to recognize the differences.  I also have a dislike for CAPTCHA methods that require a human visitor to <em>prove</em>, via an intentionally difficult test, that they aren&#8217;t a bot.  The ideal method, I feel, would be invisible to a human visitor, but still accurately identify comments submitted by bots.</p>
<h2>A history of spam fighting</h2>
<p>The most successful and simple method I found was a server-side system for <a href="http://www.ardamis.com/2007/12/15/using-timestamps-to-reduce-wordpress-comment-spam/">reducing comment spam by using a handshake method involving timestamps</a> on hidden form fields.  The general idea was that a bot would submit a comment more quickly than a human visitor, so if the comment was submitted too soon after the page was loaded, it was rejected.  A human caught in this trap would be able to click the Back button on the browser to resubmit.  This had proven to be very effective on ardamis.com, cutting the number of <a href="http://www.ardamis.com/2010/08/09/reducing-wordpress-spam-comments/">spam comments intercepted by Akismet per day to nearly zero</a>.  For a long time, the only problem was that it required modifying a core WordPress file, <strong>wp-comments-post.php</strong>.  Each time WordPress was updated, the core file was replaced.  If I didn&#8217;t then go back and make my modifications again, <a href="http://www.ardamis.com/2011/01/18/a-chart-illustrating-the-reduction-in-comment-spam-at-ardamis-com/">I would lose the spam protection</a> until I made the changes.  As it became easier to update WordPress (via the admin panel) and I updated it more frequently, editing the core file became more of a nuisance.</p>
<h2>A huge facepalm</h2>
<p>When Google began weighting page load times as part of its ranking algorithm, I implemented the <a href="http://wordpress.org/extend/plugins/wp-super-cache/" title="WP Super Cache">WP Super Cache</a> caching plugin on ardamis.com and configured it to use .htaccess and mod_rewrite to serve cache files.  Page load times certainly decreased, but the amount of spam detected by Akismet increased.  After a while, I realized that this was because the spam bots were submitting comments from static, cached pages, and the timestamps on those pages, which had been generated server-side with PHP, were already minutes old when the page was requested.  The form processing script, which normally rejects comments that are submitted too quickly to be written by a human visitor, happily accepted the timestamps.  Even worse, a second function of my anti-spam method also rejected comments that were submitted 10 minutes or more after the page was loaded.  Of course, most of the visitors were being served cached pages that were already more than 10 minutes old, so even legitimate comments were being rejected.  Using PHP to generate my timestamps obviously was not going to work if I wanted to keep serving cached pages.</p>
<h2>JavaScript to the rescue</h2>
<p>Generating real-time timestamps on cached pages requires JavaScript.  But instead of a reliable server clock setting the timestamp, the time is coming from the visitor&#8217;s system, which can&#8217;t be trusted to be accurate.  Merely changing the comment form to use JavaScript to generate the first timestamp wouldn&#8217;t work, because verifying a timestamp generated on the client-side against one generated with a server-side language would be disastrous.</p>
<p>Replacing the PHP-generated timestamps with JavaScript-generated timestamps would require substantial changes to the system.</p>
<p>Traditional client-side form validation using JavaScript happens when the form is submitted.  If the validation fails, the form is not submitted, and the visitor typically gets an alert with suggestions on how to make the form acceptable.  If the validation passes, the form submission continues without bothering the visitor.  To get our two timestamps, we can generate a first timestamp when the page loads and compare it to a second timestamp generated when the form is submitted.  If the visitor submits the form too quickly, we can display an alert showing the number of seconds remaining until the form can be successfully submitted.  This should hopefully be invisible to most visitors who choose to leave comments, but at the very least, far less irritating than a CAPTCHA system.</p>
<p>It took me two tries to get it right, but I&#8217;m going to discuss the less successful method first to point out its flaws.</p>
<h3>Method One (not good enough)</h3>
<p>Here&#8217;s how the original system flowed.</p>
<ol>
<li>Generate a first JS timestamp when the page is loaded.</li>
<li>Generate a second JS timestamp when the form is submitted.</li>
<li>Before the form is submitted, compare the two, and if enough time has passed, write a pre-determined passcode to a hidden INPUT element, then submit the form.</li>
<li>On the form processing page, use server-side logic to verify that the passcode is present and valid.</li>
</ol>
<p>The problem was that it seemed that certain bots could parse JavaScript enough to drop the pre-determined passcode into the hidden form field before submitting the form, circumventing the timestamps completely and defeating the system.  </p>
<p>It also failed to adhere to one of the basic tenants of form validation &#8211; that the input must be checked on both the client-side and the server-side.</p>
<h3>Method Two (better)</h3>
<p>Rather than having the server-side validation be merely a check to confirm that the passcode is present, method two goes back to comparing the timestamps a second time on the server side. Instead of a single hidden input, we now have two &#8211; one for each timestamp.  This is intended to prevent a bot from figuring out the ultimate validation mechanism by simply parsing the JavaScript.  Finally, the hidden fields are added to the form via jQuery, which makes it easier to implement and may act as another layer of obfuscation. </p>
<ol>
<li>Generate a first JS timestamp when the page is loaded and write it to a hidden form field.</li>
<li>Generate a second JS timestamp when the form is submitted and write it to a hidden form field.</li>
<li>Before the form is submitted, compare the two, and if enough time has passed, submit the form (client-side validation).</li>
<li>On the form processing page, use server-side logic to compare the timestamps a second time (server-side validation).</li>
</ol>
<p>The timestamp handshake works more like it did in the server-side-only method.  We still have to pass something from the comment form to the processing script, but it&#8217;s not too obvious from the HTML what is being done with it.</p>
<h2>The same downside plagues me</h2>
<p>Unfortunately, if we want to have any server-side validation at all, and we do, the core file <strong>wp-comments-post.php</strong> will still have to be modified.  In my experience, the system is not sufficiently effective using just client-side validation.  </p>
<h2>The code</h2>
<p>Two files must be modified to implement the validation.</p>
<p><strong>File 1: The theme&#8217;s comments.php file (older themes) or wp-includes\comment-template.php (newer themes)</strong></p>
<p>Your comment form lives somewhere.  My theme is based on Kubrick, the old default WordPress theme, and my comment form is in my theme folder, in a file named <strong>comments.php</strong>.  If your theme is newer and based on the current default theme, twentyeleven, the form is in <strong>wp-includes\comment-template.php</strong>.  If your theme isn&#8217;t based on either of these, all bets are off.  I know it&#8217;s confusing.  Sorry.</p>
<p>Add the JavaScript that creates and populates the timestamp fields.  Be sure to confirm that your comment form has an ID of <strong>commentform</strong>.  I&#8217;m using jQuery to help fire functions when the page loads.</p>
<pre class="brush: jscript; title: ; notranslate">
&lt;script type=&quot;text/javascript&quot; src=&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
$(document).ready(function(){
	ardGenTS1();
});

function ardGenTS1() {
	// prepare the form
	$('#commentform').append('&lt;input type=&quot;hidden&quot; name=&quot;ardTS1&quot; id=&quot;ardTS1&quot; value=&quot;1&quot; /&gt;');
	$('#commentform').append('&lt;input type=&quot;hidden&quot; name=&quot;ardTS2&quot; id=&quot;ardTS2&quot; value=&quot;1&quot; /&gt;');
	$('#commentform').attr('onsubmit', 'return validate()');
	// set a first timestamp when the page loads
	var ardTS1 = (new Date).getTime();
	document.getElementById(&quot;ardTS1&quot;).value = ardTS1;
}

function validate() {
	// read the first timestamp
	var ardTS1 = document.getElementById(&quot;ardTS1&quot;).value;
//	alert ('ardTS1: ' + ardTS1);
	// generate the second timestamp
	var ardTS2 = (new Date).getTime();
	document.getElementById(&quot;ardTS2&quot;).value = ardTS2;
//	alert ('ardTS2: ' + document.getElementById(&quot;ardTS2&quot;).value);
	// find the difference
	var diff = ardTS2 - ardTS1;
	var elapsed = Math.round(diff / 1000);
	var remaining = 10 - elapsed;
//	alert ('diff: ' + diff + '\n\nelapsed:' + elapsed);
	// check whether enough time has elapsed
	if (diff &gt; 10000) {
		// submit the form
		return true;
	}else{
		// display an alert if the form is submitted within 10 seconds
		alert(&quot;This site is protected by an anti-spam feature that requires 10 seconds to have elapsed between the page load and the form submission.\n\nPlease close this alert window.  The form may be resubmitted successfully in &quot; + remaining + &quot; seconds.&quot;);
		// prevent the form from being submitted
		return false;
	}
}
&lt;/script&gt;
</pre>
<p><strong>File 2: The wp-comments-post.php file</strong></p>
<p>The wp-comments-post.php file lives in the root of WordPress and handles the form processing.  We need to add a few lines that check the contents of our new validation input field.</p>
<p>Somewhere after line 53 or so (where <em>$comment_content</em> is defined), insert the following code.</p>
<pre class="brush: php; title: ; notranslate">
$ardTS1 = ( isset($_POST['ardTS1']) ) ? trim($_POST['ardTS1']) : 1;
$ardTS2 = ( isset($_POST['ardTS2']) ) ? trim($_POST['ardTS2']) : 2;
$ardTS = $ardTS2 - $ardTS1;

if ( $ardTS &lt; 10000 ) {
// If the difference of the timestamps is not more than 10 seconds, exit
    wp_die( __('&lt;strong&gt;ERROR&lt;/strong&gt;:  This site uses JavaScript validation to reduce comment spam.  Either your browser has JavaScript disabled, or the comment was not legitimately submitted.') );
}
</pre>
<p>That&#8217;s it.  Not so bad, right?</p>
<h2>Final thoughts</h2>
<p>One advantage to this method over the old PHP-only method is that even if the core file is replaced and the server-side validation is lost, the client-side validation continues to work, perhaps providing some measure of protection.</p>
<p>The method is safe for use with caching systems that create purely static, HTML pages.  I&#8217;ll follow up later and report on how effective it seems to be at stopping spam comments before they get to Akismet (and into the WordPress database).</p>
<p>Now, for a little extra protection, you can rename the <strong>wp-comments-post.php</strong> file and change the path in the comment form&#8217;s action attribute.  I&#8217;ve <a href="http://www.ardamis.com/2010/08/09/reducing-wordpress-spam-comments/">posted logs</a> showing that some bots just try to post spam directly to the <strong>wp-comments-post.php</strong> file, so renaming that file is an easy way to cut down on spam.  Just remember to come back and delete the <strong>wp-comments-post.php</strong> file each time you update WordPress.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ardamis.com/2011/08/27/a-cache-proof-method-for-reducing-comment-spam/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Jealous of The Social Network</title>
		<link>http://www.ardamis.com/2011/06/12/jealous-of-the-social-network/</link>
		<comments>http://www.ardamis.com/2011/06/12/jealous-of-the-social-network/#comments</comments>
		<pubDate>Mon, 13 Jun 2011 02:46:50 +0000</pubDate>
		<dc:creator>ardamis</dc:creator>
				<category><![CDATA[Nonsense]]></category>
		<category><![CDATA[Web Site Dev]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[application]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[downloads]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[web app]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[xhtml]]></category>

		<guid isPermaLink="false">http://www.ardamis.com/?p=1467</guid>
		<description><![CDATA[A short list of my programming accomplishments.]]></description>
			<content:encoded><![CDATA[<p>So I finally watched <a href="http://en.wikipedia.org/wiki/The_Social_Network"><em>The Social Network</em></a> over the weekend, and it&#8217;s made me feel jealous and a bit guilty.</p>
<p>In a meager effort to console myself for so far failing to be a billionaire, I&#8217;m assembling the short list of web-application type things I&#8217;ve built here.</p>
<ol>
<li>A dice roller: <a href="http://alephstudios.com/rollforit/">rollforit</a>. Enter a name, create a room, invite your friends, and start rolling dice.  For people who want to play pen and paper, table-top RPG dice games with their distant friends.</li>
<li>A URL shortener: <a href="http://minifi.de/">Minifi.de</a>.  Minifi.de comes with an API and a bookmarklet.  It really works, too!  The <a href="http://minifi.de/technical.php">technical explanation</a> has more details.</li>
<li>A social networking site: <a href="http://alephstudios.com/snapbase/">Snapbase</a>.  Snapbase is a social site that shows you what&#8217;s going on in your city or anywhere in the world as pictures are uploaded by your friends and neighbors.  The application extracts location information from the EXIF data embedded in images and displays recent images taken near your present location.</li>
<li>A <a href="http://alephstudios.com/helpdesk/">trouble-ticketing system</a> for an IT help desk or technical support center.  It&#8217;s really pretty extensive, with asset management, user accounts, salted encrypted passwords, and all sorts of nifty things.  I really must write a full description of it at some point, but until then, the <a href="http://alephstudios.com/helpdesk/documentation/">documentation</a> is the next best thing.</li>
<li>An <a href="http://alephstudios.com/ias/">account-based invoice tracking and access system</a> for grouping invoices according to clients, then sharing invoice history with those clients and allowing them to easily pay outstanding invoices via Paypal.</li>
<li>An <a href="http://alephstudios.com/ias/">account-based invoice access system</a> where clients can view paid and unpaid invoices, and even easily pay an outstanding invoice via Paypal. I actually use this almost every day.</li>
<li>A simple method for <a href="http://www.ardamis.com/2008/06/11/protecting-a-download-using-a-unique-url/">protecting a download using a unique URL</a> that can be emailed to authorized users. The URL can be set to expire after a certain amount of time or any number of downloads.</li>
<li>An update to the above download protection script to <a href="http://www.ardamis.com/2009/06/26/protecting-multiple-downloads-using-unique-urls/">protect multiple downloads</a>, generate batches of keys, leave notes about who received the key, the ability to specify per-key the allowable number of downloads and age, and some basic reporting.</li>
<li>An HTML auction template generator called <a href="http://simpleauctionwizard.com/">Simple Auction Wizard</a>.  It helps you create HTML auction templates for eBay, and uses SWFUpload and tinyMCE.</li>
</ol>
<p>I have another project in the works that promises to be more financially viable, but the most clever thing on that list is Snapbase.  It&#8217;s in something akin to alpha right now; barely usable.  I really wish I had the time to pursue it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ardamis.com/2011/06/12/jealous-of-the-social-network/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>W3C Link Checker fails with an Error: 406 Not Acceptable</title>
		<link>http://www.ardamis.com/2011/04/08/w3c-link-checker-fails-with-an-error-406-not-acceptable/</link>
		<comments>http://www.ardamis.com/2011/04/08/w3c-link-checker-fails-with-an-error-406-not-acceptable/#comments</comments>
		<pubDate>Fri, 08 Apr 2011 18:50:06 +0000</pubDate>
		<dc:creator>ardamis</dc:creator>
				<category><![CDATA[Nonsense]]></category>
		<category><![CDATA[Web Site Dev]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[troubleshooting]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[xhtml]]></category>

		<guid isPermaLink="false">http://www.ardamis.com/?p=1192</guid>
		<description><![CDATA[Attempting to run the W3C Link Checker against http://www.ardamis.com/ returns a 406 error message.]]></description>
			<content:encoded><![CDATA[<p>Attempting to run the <a href="http://validator.w3.org/checklink">W3C Link Checker</a> against http://www.ardamis.com/ returns an error message.</p>
<blockquote><p>Error: 406 Not Acceptable</p></blockquote>
<p>This is what the W3C says about the 406 HTTP status header:</p>
<blockquote><p><strong>406 Not Acceptable</strong><br />The resource identified by the request is only capable of generating response entities which have content characteristics not acceptable according to the accept headers sent in the request.<br />
<br /><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html</a></p></blockquote>
<p>In other words, the W3C Link Checker requests the web page, and tells the web server that, by the way, it can only accept a responses in a certain format.  The web server then regrets to inform the requestor that it cannot fulfill this request, because it cannot return a response that would be acceptable to the requestor.  It does this in the form of a 406 Not Acceptable HTTP header.  The W3C Link Checker then outputs this error.</p>
<p>Other W3C apps, like <a href="http://validator.w3.org/unicorn/">Unicorn &#8211; W3C&#8217;s Unified Validator</a> and the <a href="http://validator.w3.org/">W3C HTML Validator</a> don&#8217;t seem to be sending the same HTTP headers.  (But I did note that there were a few small issues preventing the home page from passing the test, which I then fixed.) </p>
<p>Ardamis runs on WordPress, with a custom theme originally developed years ago from the Kubrick theme and a handful of plugins (as more completely described at the <a href="http://www.ardamis.com/colophon/">colophon</a> page).  I tinker with the site, from time to time, trying to speed it up or what-have-you.  But no amount of tinkering seemed to resolve this problem.  Over the course of a few months, I&#8217;d try various changes to the site to see if there was something I could do to fix this problem.  I had pretty much convinced myself that it was going to be an issue for my web host when, miraculously, after making some changes to the .htaccess file, my theme and disabling one of the plugins (which I can&#8217;t see how would possibly affect the HTTP headers) the Link Checker began working.</p>
<p>In the <a href="http://validator.w3.org/checklink?uri=http%3A%2F%2Fwww.ardamis.com%2F&#038;hide_type=all&#038;depth=&#038;check=Check">results page for www.ardamis.com</a>, it lists some of the headers used:</p>
<blockquote><p>Settings used:</p>
<ul>
<li><tt><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1">Accept</a></tt>: text/html, application/xhtml+xml;q=0.9, application/vnd.wap.xhtml+xml;q=0.6, */*;q=0.5</li>
<li><tt><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4">Accept-Language</a></tt>: en-US,en;q=0.8</li>
<li><tt><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.36">Referer</a></tt>: sending</li>
<li>Sleeping 1 second between requests to each server</li>
</ul>
</blockquote>
<p>I&#8217;m not sure what I did to make this work, or even if it was something I did.  But further troubleshooting would have involved disabling all plugins, trying a different theme, and then ruling out WordPress entirely.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ardamis.com/2011/04/08/w3c-link-checker-fails-with-an-error-406-not-acceptable/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Web development tools</title>
		<link>http://www.ardamis.com/2010/08/15/web-development-tools/</link>
		<comments>http://www.ardamis.com/2010/08/15/web-development-tools/#comments</comments>
		<pubDate>Mon, 16 Aug 2010 03:39:17 +0000</pubDate>
		<dc:creator>ardamis</dc:creator>
				<category><![CDATA[Web Site Dev]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[script.aculo.us]]></category>
		<category><![CDATA[templates]]></category>
		<category><![CDATA[themes]]></category>
		<category><![CDATA[web app]]></category>
		<category><![CDATA[xhtml]]></category>

		<guid isPermaLink="false">http://www.ardamis.com/?p=842</guid>
		<description><![CDATA[A collection of web development tools for building better sites more easily.]]></description>
			<content:encoded><![CDATA[<p>A collection of web development tools for building better sites more easily.</p>
<h3>Frameworks and scripts</h3>
<p><a href="http://html5boilerplate.com/">HTML5 Boilerplate</a> is the professional badass&#8217;s base HTML/CSS/JS template for a fast, robust and future-proof site.</p>
<p><a href="http://scriptsrc.net/">scriptsrc.net</a> is a collection of script tags of the latest versions of a range of JavaScript libraries.</p>
<p><a href="http://www.modernizr.com/">Modernizr</a> adds classes to the &lt;html&gt; element which allow you to target specific browser functionality in your stylesheet. You don&#8217;t actually need to write any Javascript to use it.</p>
<h3>Images</h3>
<p><a href="http://placehold.it/">placehold.it</a> is a quick and simple image placeholder service.</p>
<h3>Text manipulation</h3>
<p><a href="http://www.textfixer.com/tools/">TextFixer</a> is a collection of online text tools. Remove line breaks from text, alphabetize text, capitalize the first letter of sentences, remove whitespaces, and uppercase text or lowercase text.</p>
<h3>XHTML</h3>
<p><a href="http://willpeavy.com/minifier/">HTML Minifier</a> will minify HTML (or XHTML), and any CSS or JS included in your markup.</p>
<h3>CSS</h3>
<p><a href="http://css3generator.com/">CSS3 Generator</a> is an awesome code generator for CSS3 snippets, and shows the minimum browser versions required to display the effects.</p>
<p><a href="http://procssor.com/">proCSSor</a> is an advanced CSS prettifier with tons of formatting options.</p>
<h3>JavaScript</h3>
<p><a href="http://jsbeautifier.org/">Online javascript beautifier</a> will reformat and reindent bookmarklets, ugly javascript, unpack scripts packed by the popular <a href="http://dean.edwards.name/packer/">Dean Edward&#8217;s packer,</a> as well as deobfuscate scripts processed by javascriptobfuscator.com.  The source code for the latest version is always available on <a href="http://github.com/einars/js-beautify">github</a>, and you can download the beautifier for local use (<a href="http://github.com/einars/js-beautify/zipball/master">zip</a>, <a href="http://github.com/einars/js-beautify/tarball/master">tar.gz</a>) as well.</p>
<h3>Fonts and Typography</h3>
<p>Fontshop.com has written <a href="http://www.fontshop.com/education/">A Field Guide to Typography</a> to get you excited about fonts and typography.</p>
<p><a href="http://www.typetester.org/">Typetester</a> is an online app for comparing different fonts for the screen, you can test up to three fonts at a time and choose the one you like. Its primary role is to make web designer’s life easier.</p>
<p>A quick chart of the <a href="http://www.ampsoft.net/webdesign-l/WindowsMacFonts.html">fonts common to all versions of Windows and the Mac equivalents</a>, or a more extensive <a href="http://media.24ways.org/2007/17/fontmatrix.html">matrix of fonts bundled with Mac and Windows operating systems, Microsoft Office and Adobe Creative Suite</a>.</p>
<p><a href="http://html-ipsum.com/">&lt;html&gt;ipsum</a> has Lorem ipsum already wrapped in HTML tags.  Pre-made paragraphs, lists, etc&#8230;</p>
<p>More resources at: <a href="http://www.smashingmagazine.com/2009/01/27/css-typographic-tools-and-techniques/">50 Useful Design Tools For Beautiful Web Typography</a> and <a href="http://speckyboy.com/2009/01/12/21-typography-and-font-web-apps-you-cant-live-without/">21 Typography and Font Web Apps You Can&#8217;t Live Without</a>.</p>
<h3>Colors</h3>
<p><a href="http://colorschemedesigner.com/">Color Scheme Designer</a>.</p>
<h3>Markup</h3>
<p>Google Webmaster Tools&#8217; <a href="http://www.google.com/webmasters/tools/richsnippets">Rich Snippets Testing Tool</a>.</p>
<p>Use the Rich Snippets Testing Tool to check that Google can correctly parse your structured data markup and display it in search results.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ardamis.com/2010/08/15/web-development-tools/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How to speed up WordPress</title>
		<link>http://www.ardamis.com/2010/08/03/how-to-speed-up-wordpress/</link>
		<comments>http://www.ardamis.com/2010/08/03/how-to-speed-up-wordpress/#comments</comments>
		<pubDate>Tue, 03 Aug 2010 05:35:14 +0000</pubDate>
		<dc:creator>ardamis</dc:creator>
				<category><![CDATA[Web Site Dev]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[xhtml]]></category>

		<guid isPermaLink="false">http://www.ardamis.com/?p=811</guid>
		<description><![CDATA[How to speed up WordPress by reducing HTTP requests and database look ups, using a faster mod_rewrite code, and shrinking the size of the database.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve written a few posts on how to speed up web sites by <a href="http://www.ardamis.com/2010/07/17/sending-headers-to-leverage-browser-caching/">sending the correct headers to leverage browser caching</a> and <a href="http://www.ardamis.com/2010/07/11/compress-files-without-mod_gzip-or-mod_deflate/">compressing .php, .css and .js files without mod_gzip or mod_deflate</a>.</p>
<p>The intended audience for this post is developers who have already applied most or all of Google&#8217;s <a href="http://code.google.com/speed/page-speed/docs/rules_intro.html">Web Performance Best Practices</a> and Yahoo&#8217;s <a href="http://developer.yahoo.com/performance/rules.html">Best Practices for Speeding Up Your Web Site</a> and are wondering how to speed up WordPress sites in particular.</p>
<p>I assume you&#8217;re familiar with <a href="http://codex.wordpress.org/WordPress_Optimization/Caching">WordPress caching</a> and are already using a caching plugin, such as <a href="http://wordpress.org/extend/plugins/wp-super-cache/">WP Super Cache</a>, <a href="http://wordpress.org/extend/plugins/w3-total-cache/">W3 Total Cache</a> or the like.  </p>
<h2>Reduce HTTP requests</h2>
<p>Reducing HTTP requests should be the very first thing step in speeding up any site.  If you are using plugins, watch them carefully for inefficiencies like added CSS and JavaScript files.  Combine, minify and compress these files.  Some plugins allow you to turn off their bundled CSS in the plugin&#8217;s settings page.  Where possible, copy the plugin&#8217;s CSS into the current theme&#8217;s style.css and turn off the extra file.</p>
<h2>Delete deactivated plugins</h2>
<p>Remove any plugins you&#8217;re not using.  Deactivated plugins can be deleted from the Plugins page.</p>
<h2>Speed up the mod_rewrite code</h2>
<p><a href="http://www.webmasterworld.com/profilev4.cgi?action=view&#038;member=jdMorgan">jdMorgan</a> from WebmasterWorld.com has written a replacement for the .htaccess rewrite rule used by WordPress.  This will speed up the WordPress mod_rewrite code by a factor of more than two.</p>
<blockquote><p>This is a total replacement for the code supplied with WP as bounded by the &#8220;Begin WP&#8221; and &#8220;End WP&#8221; comments, and fixes several performance-affecting problems. Notably, the unnecessary and potentially-problematic <IfModule> container is completely removed, and code is added and re-structured to both prevent completely-unnecessary file- and directory- exists checks and to reduce the number of necessary -exists checks to one-half the original count (due to the way mod_rewrite behaves recursively in .htaccess context).</p>
<p><a href="http://www.webmasterworld.com/apache/4053973.htm">http://www.webmasterworld.com/apache/4053973.htm</a>
</p></blockquote>
<p>The following code is adapted from the original to add png, flv and swf to the list of static file formats:</p>
<pre class="brush: plain; title: ; notranslate">
# BEGIN WordPress
# adapted from http://www.webmasterworld.com/apache/4053973.htm
#
RewriteEngine on
#
# Unless you have set a different RewriteBase preceding this point,
# you may delete or comment-out the following RewriteBase directive
# RewriteBase /
#
# if this request is for &quot;/&quot; or has already been rewritten to WP
RewriteCond $1 ^(index\.php)?$ [OR]
# or if request is for image, css, or js file
RewriteCond $1 \.(gif|jpg|png|ico|css|js|flv|swf)$ [NC,OR]
# or if URL resolves to existing file
RewriteCond %{REQUEST_FILENAME} -f [OR]
# or if URL resolves to existing directory
RewriteCond %{REQUEST_FILENAME} -d
# then skip the rewrite to WP
RewriteRule ^(.*)$ - [S=1]
# else rewrite the request to WP
RewriteRule . /index.php [L]
#
# END wordpress
</pre>
<h2>Only load the comment-reply.js when needed</h2>
<p>In the default WordPress template, the <strong>comment-reply.js</strong> script is included on all single post pages, regardless of whether nested/threaded comments is enabled.  A simple tweak changes the theme to only include <strong>comment-reply.js</strong> on single post pages only when it makes sense to do so: if threaded comments are enabled, commenting on that post is allowed, and a comment already exists.</p>
<p>Remove the following line from your theme&#8217;s <strong>header.php</strong>:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php if ( is_singular() ) wp_enqueue_script( 'comment-reply' ); ?&gt;
</pre>
<p>Add the following lines to your theme&#8217;s <strong>functions.php</strong>.</p>
<pre class="brush: php; title: ; notranslate">
// Don't add the wp-includes/js/comment-reply.js?ver=20090102 script to single post pages unless threaded comments are enabled
// adapted from http://bigredtin.com/behind-the-websites/including-wordpress-comment-reply-js/
function theme_queue_js(){
  if (!is_admin()){
    if (is_singular() &amp;&amp; (get_option('thread_comments') == 1) &amp;&amp; comments_open() &amp;&amp; have_comments())
      wp_enqueue_script('comment-reply');
  }
}
add_action('wp_print_scripts', 'theme_queue_js');
</pre>
<h2>Only load the l10n.js when needed</h2>
<p>In WordPress 3.1, a <strong>l10n.js</strong> script is loaded.  It is &#8220;mostly used for scripts that send over localization data from PHP to the JS side using <em>wp_localize_script()</em>.&#8221; Whether it&#8217;s safe to remove this file seems to be a matter of debate, but should you decide you want to remove it&#8230;</p>
<p>Add the following lines to your theme&#8217;s <strong>functions.php</strong>.</p>
<pre class="brush: php; title: ; notranslate">
// Don't add the wp-includes/js/l10n.js?ver=20101110 script to non-admin pages
// adapted from http://wordpress.stackexchange.com/questions/5451/what-does-l10n-js-do-in-wordpress-3-1-and-how-do-i-remove-it
function remove_l10n_js(){
  if (!is_admin()){
    wp_deregister_script('l10n');
  }
}
add_action('wp_print_scripts', 'remove_l10n_js');
</pre>
<h2>Replace unecessary code executions and database queries</h2>
<p>WordPress saves settings specific to your blog in the database.  These settings include what language your blog is written in, whether text is read left-to-right or vice versa, the path to the template directory, etc.</p>
<p>The default WordPress theme contains a number of database queries in order to figure out these things and build the correct page.  The default theme needs this flexibility, but your theme does not.  Joost de Valk recommends replacing these database queries with static text in your theme files in his post <a href="http://yoast.com/speed-up-wordpress/">Speed up WordPress, and clean it up too!</a></p>
<p>An easy way to do this is to browse to your web site and then view the source code.  Copy the content that won&#8217;t change from page to page and paste it into your theme, overwriting the PHP with the generated HTML.</p>
<p>For example, my theme&#8217;s header.php file contains this line:</p>
<pre class="brush: php; title: ; notranslate">
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; &lt;?php language_attributes(); ?&gt;&gt;
</pre>
<p>The source code of the rendered page displays this line:</p>
<pre class="brush: php; title: ; notranslate">
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; dir=&quot;ltr&quot; lang=&quot;en-US&quot;&gt;
</pre>
<p>On my blog, this HTML output is never going to be anything different, so why make WordPress look these settings up in the database each time a page is loaded?  This line is an excellent candidate for replacement.  The footer.php file contains a handful more opportunities for replacement, but go through each of your theme&#8217;s files and look for references to the template directory and other data that won&#8217;t change as long as you&#8217;re using the theme.  All told, I was able to replace 12 database queries with static HTML.</p>
<p>Joost also recommends checking for unnecessary or slow database queries, and installing a helpful debugging plugin, in his post on <a href="http://yoast.com/wordpress-performance-optimization/">Optimizing WordPress database performance</a>.</p>
<h2>Clean out your MySQL database</h2>
<h3>Delete spam comments</h3>
<p>From the Dashboard, click Comments, then click on Empty Spam.</p>
<h3>Delete post revisions</h3>
<p>If you don&#8217;t use post revisions, you may want to delete them from the <code>wp_posts</code> table.  Back up your database, then run the following SQL query:</p>
<pre class="brush: sql; title: ; notranslate">
DELETE FROM wp_posts WHERE post_type = &quot;revision&quot;;
</pre>
<p>Before: 683 records<br />
After: 165 records</p>
<p>This does not delete the latest draft of unpublished posts.  It&#8217;s a good idea to optimize the table after deleting the revisions.</p>
<p>You can stop WordPress from saving post revisions by adding the following code to wp-config.php:</p>
<pre class="brush: php; title: ; notranslate">
define('WP_POST_REVISIONS', false );
</pre>
<h2>Optimize your MySQL database</h2>
<p>Optimizing your MyISAM tables is comparable to defragmenting your hard drive.  It&#8217;s probably been a while since you&#8217;ve done that, too.</p>
<p>If you&#8217;re using phpMyAdmin, browse to your WordPress database.  Under the Structure tab, at the bottom of the list of tables, click on the link &#8220;Check all&#8221;.  In the &#8220;With selected&#8221; menu, choose &#8220;Optimize table&#8221;.  (I would have recommended just optimizing tables that have overhead, but the <code>wp_posts</code> table can be optimized even when it doesn&#8217;t show any overhead.</p>
<blockquote><p>For MyISAM tables, OPTIMIZE TABLE works as follows:</p>
<ul>
<li>If the table has deleted or split rows, repair the table.</li>
<li>If the index pages are not sorted, sort them.</li>
<li>If the table&#8217;s statistics are not up to date (and the repair could not be accomplished by sorting the index), update them.</li>
</ul>
<p><a href="http://dev.mysql.com/doc/refman/5.1/en/optimize-table.html">http://dev.mysql.com/doc/refman/5.1/en/optimize-table.html</a></p></blockquote>
<h2>Flush the Buffer Early</h2>
<blockquote><p>When users request a page, it can take anywhere from 200 to 500ms for the backend server to stitch together the HTML page. During this time, the browser is idle as it waits for the data to arrive. In PHP you have the function <code><a href="http://php.net/flush">flush()</a></code>. It allows you to send your partially ready HTML response to the browser so that the browser can start fetching components while your backend is busy with the rest of the HTML page. The benefit is mainly seen on busy backends or light frontends.</p>
<p><a href="http://developer.yahoo.com/performance/rules.html#flush">http://developer.yahoo.com/performance/rules.html#flush</a></p></blockquote>
<p>Add <code>flush()</code> between the closing <code></head></code> tag and the opening <code><body></code> tag in <strong>header.php</strong>.</p>
<pre class="brush: php; title: ; notranslate">
&lt;/head&gt;
&lt;?php flush(); // http://developer.yahoo.com/performance/rules.html#flush ?&gt;
&lt;body&gt;
</pre>
<p>OK, so this isn&#8217;t technically a WordPress-specific tweak, but it&#8217;s a good idea.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ardamis.com/2010/08/03/how-to-speed-up-wordpress/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Ardamis.com is HTML5</title>
		<link>http://www.ardamis.com/2010/07/21/ardamis-com-is-html5/</link>
		<comments>http://www.ardamis.com/2010/07/21/ardamis-com-is-html5/#comments</comments>
		<pubDate>Wed, 21 Jul 2010 18:51:50 +0000</pubDate>
		<dc:creator>ardamis</dc:creator>
				<category><![CDATA[Nonsense]]></category>
		<category><![CDATA[Web Site Dev]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[xhtml]]></category>

		<guid isPermaLink="false">http://www.ardamis.com/?p=823</guid>
		<description><![CDATA[Ardamis.com is now being served as valid HTML5.]]></description>
			<content:encoded><![CDATA[<p>It required only a few small changes to move from XHTML 1.0 Strict to HTML5, but as of today, ardamis.com is being served as valid HTML5.  For some time, I&#8217;ve been waiting for HTML5 to get closer to becoming a W3C recommendation, and for better support from user agents, but I&#8217;ve gotten caught up with other improvements to the site and decided to make the transition now.</p>
<p>Over the next few weeks, I&#8217;ll be updating the HTML to incorporate some of the new tags.  I&#8217;m pretty excited about replacing divs with new semantic elements like <code>&lt;header&gt;</code>, <code>&lt;article&gt;</code>, and <code>&lt;footer&gt;</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ardamis.com/2010/07/21/ardamis-com-is-html5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Word 2007 macros for converting symbols to HTML entities</title>
		<link>http://www.ardamis.com/2010/03/02/word-2007-macros-for-converting-symbols-to-html-entities/</link>
		<comments>http://www.ardamis.com/2010/03/02/word-2007-macros-for-converting-symbols-to-html-entities/#comments</comments>
		<pubDate>Wed, 03 Mar 2010 03:24:08 +0000</pubDate>
		<dc:creator>ardamis</dc:creator>
				<category><![CDATA[Nonsense]]></category>
		<category><![CDATA[Web Site Dev]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Office]]></category>
		<category><![CDATA[xhtml]]></category>

		<guid isPermaLink="false">http://www.ardamis.com/?p=443</guid>
		<description><![CDATA[A few Word macros that will replace the symbols commonly found in documents with html entities.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m often given copy for web sites as Word documents.  As one would expect, these documents contain all sorts of symbols that should be converted to entities before they can be used in a web page.</p>
<p>For example, &#8216;smart quotes&#8217; (curly quotes), trademark and registered symbols, em-dashes, and other symbols look great, but can cause problems if you just drop them into a page and don&#8217;t use the corresponding character encoding.</p>
<p>Rather than do a global find-and-replace in my HTML editor, I&#8217;ve written a few Word macros that replace these symbols.</p>
<p>The first macro, CleanupHTML, replaces smart quotes with straight quotes.  The second macro, PrettyHTML, replaces smart quotes with the correct pretty quote, ala <strong>&rsquo;</strong>.</p>
<p>At some point, I want to extend the macro to replace accented characters, such as <strong>&egrave;</strong>, and also to wrap bold and italics in <strong>strong</strong> and <em>em</em> tags.  Ideally, I&#8217;d also find a way of converting lists in Word to straight text wrapped in unordered list items, as lists seem to require the most cleanup when copying and pasting.</p>
<pre class="brush: plain; title: ; notranslate">
Sub CleanupHTML()
'
' CleanupHTML Macro
' Cleanup document for HTML by replacing special characters with entities.
'
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = &quot;&amp;&quot;
        .Replacement.Text = &quot;&amp;amp;&quot;
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = &quot;©&quot;
        .Replacement.Text = &quot;&amp;copy;&quot;
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = &quot;®&quot;
        .Replacement.Text = &quot;&amp;reg;&quot;
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = &quot;™&quot;
        .Replacement.Text = &quot;&amp;#8482;&quot;
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = &quot;--&quot;
        .Replacement.Text = &quot;&amp;#8212;&quot;
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = &quot;—&quot;
        .Replacement.Text = &quot;&amp;#8212;&quot;
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = &quot;–&quot;
        .Replacement.Text = &quot;&amp;#8211;&quot;
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = &quot;…&quot;
        .Replacement.Text = &quot;...&quot;
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = &quot;'&quot;
        .Replacement.Text = &quot;'&quot;
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
    With Selection.Find
        .Text = &quot;&quot;&quot;&quot;
        .Replacement.Text = &quot;&quot;&quot;&quot;
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
End Sub

Sub PrettyHTML()
'
' PrettyHTML Macro
'
'
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = &quot;&amp;&quot;
        .Replacement.Text = &quot;&amp;amp;&quot;
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = &quot;©&quot;
        .Replacement.Text = &quot;&amp;copy;&quot;
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = &quot;®&quot;
        .Replacement.Text = &quot;&amp;reg;&quot;
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = &quot;™&quot;
        .Replacement.Text = &quot;&amp;#8482;&quot;
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = &quot;--&quot;
        .Replacement.Text = &quot;&amp;#8212;&quot;
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = &quot;—&quot;
        .Replacement.Text = &quot;&amp;#8212;&quot;
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = &quot;–&quot;
        .Replacement.Text = &quot;&amp;#8211;&quot;
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = &quot;…&quot;
        .Replacement.Text = &quot;...&quot;
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = ChrW(8220)
        .Replacement.Text = &quot;&amp;ldquo;&quot;
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = ChrW(8221)
        .Replacement.Text = &quot;&amp;rdquo;&quot;
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = &quot;'&quot;
        .Replacement.Text = &quot;&amp;rsquo;&quot;
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = &quot;è&quot;
        .Replacement.Text = &quot;&amp;egrave;&quot;
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
End Sub
</pre>
<p>Many thanks to<br />
<a href="http://celebritycola.blogspot.com/2004/09/preserving-formatting-when-posting.html">http://celebritycola.blogspot.com/2004/09/preserving-formatting-when-posting.html</a> for getting me started on this.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ardamis.com/2010/03/02/word-2007-macros-for-converting-symbols-to-html-entities/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Aleph Studios Is Launched</title>
		<link>http://www.ardamis.com/2009/09/21/aleph-studios-is-launched/</link>
		<comments>http://www.ardamis.com/2009/09/21/aleph-studios-is-launched/#comments</comments>
		<pubDate>Mon, 21 Sep 2009 05:33:34 +0000</pubDate>
		<dc:creator>ardamis</dc:creator>
				<category><![CDATA[Nonsense]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Web Site Dev]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[xhtml]]></category>

		<guid isPermaLink="false">http://www.ardamis.com/?p=371</guid>
		<description><![CDATA[I'm excited to announce a new site of mine - Aleph Studios - which will be the new home for my web development freelance work.]]></description>
			<content:encoded><![CDATA[<p>For some time, I&#8217;ve felt that Ardamis.com was being pulled in two directions.  It started out as something of a business card, then it landed me a job, and so the focus changed and it became more of a personal blog.  A few years later, I found myself posting mainly code snippets from personal projects and announcements of new site launches.</p>
<p>So, I&#8217;ve determined that I&#8217;ll keep Ardamis.com as a place for experimentation and create a new site to handle the web development business &#8211; <a href="http://alephstudios.com">Aleph Studios</a>.  It&#8217;s so new that I have to think sometimes about how Aleph is spelled as I type it.</p>
<p>I&#8217;ll be migrating some of the pages away from Ardamis over the next week or two.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ardamis.com/2009/09/21/aleph-studios-is-launched/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HTML auction template generator</title>
		<link>http://www.ardamis.com/2009/07/09/an-online-html-template-generator-for-auctions/</link>
		<comments>http://www.ardamis.com/2009/07/09/an-online-html-template-generator-for-auctions/#comments</comments>
		<pubDate>Fri, 10 Jul 2009 03:18:20 +0000</pubDate>
		<dc:creator>ardamis</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[Web Site Dev]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[themes]]></category>
		<category><![CDATA[web app]]></category>
		<category><![CDATA[xhtml]]></category>

		<guid isPermaLink="false">http://www.ardamis.com/?p=294</guid>
		<description><![CDATA[Simple Auction Wizard is an online HTML template generator for auction websites like eBay.  It's fast, free, and easy to use.]]></description>
			<content:encoded><![CDATA[<p>A friend who does a lot of selling on eBay asked me to develop a web application for generating HTML templates that could be copied and pasted into his auctions.  He wanted to be able to add a title, a description, and some terms and conditions, and also to be able to upload images so the auction template would display thumbnails that could be clicked to display full-sized versions in a new window or tab.  The more we talked, the more it sounded like something that would be both useful for a good number of people, and potentially a source of ad revenue for us.  And so was born <a href="http://simpleauctionwizard.com/">Simple Auction Wizard</a>, an online HTML template generator for auction websites like eBay.</p>
<p>I was looking for just this kind of a project because I wanted a reason to play with <a href="http://tinymce.moxiecode.com/">TinyMCE</a>, an Open Source, platform independent, web-based JavaScript HTML WYSIWYG editor control, and <a href="http://swfupload.org/">SWFUpload</a>, a small JavaScript/Flash library that does very neat things with file uploads.</p>
<p>The most difficult part was actually getting the templates to look good in a variety of browsers.  Because the template HTML appears inside of a larger page, I couldn&#8217;t rely on Doctype switching to place IE into standards mode.  This meant the templates would have to be developed so that they would look approximately the same in standards-compliant browsers like Firefox, Chrome, and Safari, as well as horrible browsers like IE6 in quirks-mode.  I tried very hard to minimize the use of tables, but they eventually crept in.  I was able to use CSS, for the most part, though if any more issues come up, I&#8217;m going to throw in the towel and just do inline styles.</p>
<p>The web app is open to the public, but realize that it&#8217;s very early in its development and I intend to continue making changes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ardamis.com/2009/07/09/an-online-html-template-generator-for-auctions/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

