<?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/"
	xmlns:media="http://search.yahoo.com/mrss/"
>

<channel>
	<title>Meta &#8211; Wade Tregaskis</title>
	<atom:link href="https://wadetregaskis.com/categories/meta/feed/" rel="self" type="application/rss+xml" />
	<link>https://wadetregaskis.com</link>
	<description></description>
	<lastBuildDate>Fri, 21 Jun 2024 17:50:13 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://wadetregaskis.com/wp-content/uploads/2016/03/Stitch-512x512-1-256x256.png</url>
	<title>Meta &#8211; Wade Tregaskis</title>
	<link>https://wadetregaskis.com</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">226351702</site>	<item>
		<title>cloudinit breaks connections from localhost to Plesk-operated web servers</title>
		<link>https://wadetregaskis.com/cloudinit-breaks-connections-from-localhost-to-plesk-operated-web-servers/</link>
					<comments>https://wadetregaskis.com/cloudinit-breaks-connections-from-localhost-to-plesk-operated-web-servers/#respond</comments>
		
		<dc:creator><![CDATA[]]></dc:creator>
		<pubDate>Tue, 23 Jan 2024 01:03:08 +0000</pubDate>
				<category><![CDATA[Howto]]></category>
		<category><![CDATA[Meta]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[Broken Link Checker]]></category>
		<category><![CDATA[CDN]]></category>
		<category><![CDATA[cloud-init]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[Nginx]]></category>
		<category><![CDATA[Plesk]]></category>
		<category><![CDATA[Plesk Obsidian]]></category>
		<category><![CDATA[Wordpress]]></category>
		<guid isPermaLink="false">https://wadetregaskis.com/?p=7491</guid>

					<description><![CDATA[I don&#8217;t know how or why it is even installed &#8211; perhaps part of the provided Ubuntu image from my VPS host &#8211; but cloud-init (a.k.a &#8220;cloud-config&#8221;) is a bit obnoxious. At [re]boot time (best I can tell), it resets /etc/hosts based on some random template it has (/etc/cloud/templates/hosts.debian.tmpl in my case, even though that&#8230; <a class="read-more-link" href="https://wadetregaskis.com/cloudinit-breaks-connections-from-localhost-to-plesk-operated-web-servers/" data-wpel-link="internal">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>I don&#8217;t know how or why it is even installed &#8211; perhaps part of the provided Ubuntu image from my VPS host &#8211; but <a href="https://github.com/canonical/cloud-init" data-wpel-link="external" target="_blank" rel="external noopener">cloud-init</a> (a.k.a &#8220;cloud-config&#8221;) is a bit obnoxious.  At [re]boot time (best I can tell), it resets <code>/etc/hosts</code> based on some random template it has (<code>/etc/cloud/templates/hosts.debian.tmpl</code> in my case, even though that makes no sense as I&#8217;m not using Debian).  That template has a very weird entry:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><code>127.0.1.1 {{fqdn}} {{hostname}}</code></p>
</blockquote>



<p>I have no idea what it&#8217;s even trying to do with that.</p>



<p>What it <em>does</em> do is break a lot of things, because while 127.0.1.1 is a valid address (albeit weird to use instead of the canonical 127.0.0.1), in a standard <a href="https://www.plesk.com" data-wpel-link="external" target="_blank" rel="external noopener">Plesk</a> system <a href="https://nginx.org" data-wpel-link="external" target="_blank" rel="external noopener">Nginx</a> (that sits in front of <a href="https://httpd.apache.org" data-wpel-link="external" target="_blank" rel="external noopener">Apache</a> typically) is configured to listen only on the network interface(s) associated with your web server&#8217;s public IP address(es), not localhost<sup data-fn="f02da440-1755-49a0-b849-7989472e1805" class="fn"><a href="#f02da440-1755-49a0-b849-7989472e1805" id="f02da440-1755-49a0-b849-7989472e1805-link">1</a></sup>.  So if you try e.g. <code>curl mydomain.com</code> from inside your server hosting that very domain, you get a connection refused error (or it just times out with no response, depending on firewall settings).</p>



<p>The way <a href="https://talk.plesk.com/threads/can-no-longer-connect-to-nginx-from-localhost.372659/" data-wpel-link="external" target="_blank" rel="external noopener">I found out about this</a> was when WordPress&#8217;s &#8220;cron&#8221; system silently stopped running tasks (because I use a real cron job to trigger it periodically, rather than relying on WordPress&#8217;s flaky built-in system).  I subsequently also noticed that <a href="https://wordpress.org/plugins/broken-link-checker/" data-wpel-link="external" target="_blank" rel="external noopener">Broken Link Checker</a> mistakenly reported <em>every</em> link within my own site as broken.</p>



<h2 class="wp-block-heading">The solution</h2>



<p>…is fairly simple &#8211; modify the template to remove the offending line.  You then have to either reboot or similarly manually modify <code>/etc/hosts</code> to actually apply the fix.</p>



<p>If for some reason you cannot do that, there are potentially workarounds.  For example, for <code>curl</code> commands you can make <code>curl</code> navigate around the problem this like:</p>



<figure class="wp-block-pullquote"><blockquote><p><code>curl --header 'Host: mydomain.com' https://&lt;your server's external IP></code></p></blockquote></figure>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<p>☝️ If you have a CDN or similar in front of your server, e.g. <a href="https://www.cloudflare.com/" data-wpel-link="external" target="_blank" rel="external noopener">Cloudflare</a>, this will potentially behave differently to connecting from another host; it&#8217;ll bypass the CDN and connect directly to your web server (effectively the same as if you did connect to 127.0.0.1).</p>



<p>Depending on your needs, this could be desirable (e.g. no need to send WordPress cron invocations through a CDN) or undesirable (broken link checking probably should go through the CDN, just like all real traffic, to test that the CDN doesn&#8217;t cause a problem).</p>
</div></div>



<p>In a non-Plesk environment you might also be able to just change the Nginx configuration (somewhere under <code>/etc/nginx</code>).  That&#8217;s ill-advised for Plesk-operated servers as Plesk will inevitably revert your changes (and as far as I can tell there is no configuration option, or workaround otherwise, to make Plesk configure Nginx to listen on localhost as well 😕).</p>


<ol class="wp-block-footnotes"><li id="f02da440-1755-49a0-b849-7989472e1805">I suspect this is more a side-effect than intentional.  Plesk chooses the interface only implicitly, when it specifies that it listens on specific addresses &#8211; those assigned to the website in question (Nginx can host multiple otherwise unrelated websites, and each is configured independently within its settings).  Since Plesk supports hosting multiple websites, each with potentially <em>different</em> IP addresses, it makes sense that it would want to keep them separate.  Otherwise, in a shared hosting situation you could connect to the IP address for somehost.com yet issue a HTTP request for unrelatedhost.com and actually get a response, which is weird, at least. <a href="#f02da440-1755-49a0-b849-7989472e1805-link" aria-label="Jump to footnote reference 1">↩︎</a></li></ol>]]></content:encoded>
					
					<wfw:commentRss>https://wadetregaskis.com/cloudinit-breaks-connections-from-localhost-to-plesk-operated-web-servers/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">7491</post-id>	</item>
		<item>
		<title>How to install ImageMagick 7 for WordPress under Plesk Obsidian on Ubuntu 22.04</title>
		<link>https://wadetregaskis.com/how-to-install-imagemagick-7-for-wordpress-under-plesk-obsidian-on-ubuntu-22-04/</link>
					<comments>https://wadetregaskis.com/how-to-install-imagemagick-7-for-wordpress-under-plesk-obsidian-on-ubuntu-22-04/#comments</comments>
		
		<dc:creator><![CDATA[]]></dc:creator>
		<pubDate>Mon, 22 Jan 2024 02:29:08 +0000</pubDate>
				<category><![CDATA[Howto]]></category>
		<category><![CDATA[Meta]]></category>
		<category><![CDATA[AVIF]]></category>
		<category><![CDATA[ImageMagick]]></category>
		<category><![CDATA[Imagick]]></category>
		<category><![CDATA[JXL]]></category>
		<category><![CDATA[Plesk]]></category>
		<category><![CDATA[Plesk Obsidian]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[Wordpress]]></category>
		<guid isPermaLink="false">https://wadetregaskis.com/?p=7457</guid>

					<description><![CDATA[Why should I do this? WordPress relies on either ImageMagick or GD for its ability to read &#38; write images. It prefers ImageMagick, as ImageMagick supports a much wider range of files, tends to be faster, and some assert that it produces higher quality files. ImageMagick 6 was superseded by ImageMagick 7 nearly a decade&#8230; <a class="read-more-link" href="https://wadetregaskis.com/how-to-install-imagemagick-7-for-wordpress-under-plesk-obsidian-on-ubuntu-22-04/" data-wpel-link="internal">Read more</a>]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading no-clear-thanks">Why should I do this?</h2>



<p><a href="https://wordpress.org" data-wpel-link="external" target="_blank" rel="external noopener">WordPress</a> relies on either <a href="https://imagemagick.org" data-wpel-link="external" target="_blank" rel="external noopener">ImageMagick</a> or <a href="https://libgd.github.io" data-wpel-link="external" target="_blank" rel="external noopener">GD</a> for its ability to read &amp; write images.  It prefers ImageMagick, as ImageMagick supports a much wider range of files, tends to be faster, and some assert that it produces higher quality files.</p>



<p>ImageMagick 6 was superseded by ImageMagick 7 nearly a decade ago.  <a href="https://legacy.imagemagick.org" data-wpel-link="external" target="_blank" rel="external noopener">Version 6 is officially in legacy mode</a> and while still technically supported (in a <a href="https://en.wikipedia.org/wiki/Long-term_support" data-wpel-link="external" target="_blank" rel="external noopener">long term support</a> sense) it generally receives only bug fixes &#8211; it fundamentally lacks many features, and most crucially it doesn&#8217;t support modern image formats correctly, such as AVIF<sup data-fn="39baf781-8a25-40c7-8128-a093b1008184" class="fn"><a href="#39baf781-8a25-40c7-8128-a093b1008184" id="39baf781-8a25-40c7-8128-a093b1008184-link">1</a></sup>.</p>



<p>Additionally, <a href="https://www.cvedetails.com/vulnerability-list/vendor_id-1749/Imagemagick.html?page=1&amp;cvssscoremin=9&amp;order=7&amp;trc=646&amp;sha=65fdcf32523abd445121e3eeede4072f9b2e0164" data-wpel-link="external" target="_blank" rel="external noopener">ImageMagick is a common source of serious security exploits</a>.  It&#8217;s very important to run the latest version (or very close to) at all times, to have as many critical bug fixes as possible.</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<p>I recall when I was at Google there was &#8211; very begrudging &#8211; use of ImageMagick &#8211; it <em>is</em> the premier library for converting images when you really need to accept just about anything &#8211; but there were heroic efforts taken to isolate it and compartmentalise it, because it was taken as a given that it would be successfully exploited all the time<sup data-fn="dd7bbb45-83b3-427f-b78e-2e7899711d0f" class="fn"><a href="#dd7bbb45-83b3-427f-b78e-2e7899711d0f" id="dd7bbb45-83b3-427f-b78e-2e7899711d0f-link">2</a></sup>.  Buffer overflows, memory corruption, etc &#8211; ImageMagick is written in plain old C &amp; C++, and as such is inherently very prone to these kinds of problems.</p>
</div></div>



<p>Note that, depending on how you operate your WordPress site(s), you may or may not be seriously exposed to ImageMagick security problems.  For simple single-author sites, where only the admin can upload anything to the site (images or otherwise), it&#8217;s arguably not a huge concern.  But for more complex sites with multiple contributors &#8211; or worse, sites which accept images from general users or the public &#8211; using an outdated ImageMagick release is a serious risk.</p>



<h2 class="wp-block-heading">Why isn&#8217;t this easy?</h2>



<p>On some Linux distros, and when Plesk isn&#8217;t involved, it <em>is</em> easy &#8211; you just <code>apt install imagemagick</code> or <code>yum install ImageMagick</code> or at worst <a href="https://imagemagick.org/script/download.php" data-wpel-link="external" target="_blank" rel="external noopener">download the RPM</a> and install that.  Generally that installs ImageMagick 7 (and if not the very latest release, at least a recent one).  You subsequently just run <code>update</code> on your package manager periodically and ImageMagick is kept reasonably up to date.</p>



<p>Ubuntu does not like ImageMagick 7, for some reason.  No version of Ubuntu supports it officially, in the sense that it is not in any of the official package repos.  If you <code>apt install imagemagick</code>, you&#8217;ll get version 6 &#8211; and not even a recent version 6, but 6.9.11-60 which is over three years old!  That&#8217;s <em>three years</em> of well-known bugs &#8211; some of them potential security exploits.</p>



<p>So, unfortunately, the only way to install a modern version of ImageMagick on Ubuntu is manually.</p>



<p>Consequently, you have to manually install a suitable version of <a href="https://github.com/Imagick/imagick" data-wpel-link="external" target="_blank" rel="external noopener">Imagick</a> as well, and you have to do it into Plesk&#8217;s special PHP installation(s).</p>



<p>It took me several hours to figure all of this out, which is why I&#8217;ve written this post &#8211; so that nobody else ever has to.</p>



<h2 class="wp-block-heading">The procedure</h2>



<p>If you run into any issues, please let me know in the comments section at the bottom of the page.  I endeavour to correct any mistakes, oversights, or confusion.</p>



<p>Note that most of these commands must be run as <em>root</em>.  Either run them inside a root shell (e.g. <code>su</code>, or <code>sudo bash</code>) or prefix them with <code>sudo</code>.</p>



<h3 class="wp-block-heading">Install ImageMagick 7</h3>



<p>Fortunately, <a href="https://github.com/SoftCreatR/imei" data-wpel-link="external" target="_blank" rel="external noopener">ImageMagick Easy Install (IMEI)</a> exists to greatly simplify this step.</p>



<p>First, as a precaution IMEI insists you remove any existing ImageMagick installation(s).  Manually installing a build of ImageMagick over the formally-packaged Ubuntu version could cause problems.</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<div class="wp-block-group warning is-horizontal is-content-justification-center is-layout-flex wp-container-core-group-is-layout-00ace616 wp-block-group-is-layout-flex">
<p style="font-size:100px">⚠️</p>



<p class="wp-container-content-9cfa9a5a">Be mindful that as soon as you run this command, things on your server that rely on ImageMagick will no longer work!  Fortunately this whole process takes less than half an hour, so it might go unnoticed (WordPress itself will continue working fine, serving up all existing media, but you probably won&#8217;t be able to upload new images until you finish this procedure).<br><br>If you do not finish the installation successfully, your server will likely be left in a bad, partly-broken state.  In principle you can revert back to the standard system versions of things, with e.g. <code>apt install imagemagick</code> or perhaps through Plesk, but I haven&#8217;t tested it and I make no promises.</p>
</div>
</div></div>



<figure class="wp-block-pullquote"><blockquote><p><code>apt remove "*imagemagick*" --purge -y &amp;&amp; apt autoremove --purge -y</code></p></blockquote></figure>



<p>Next, download and install ImageMagick:</p>



<figure class="wp-block-pullquote"><blockquote><p><code>pushd /tmp &amp;&amp; git clone https://github.com/SoftCreatR/imei &amp;&amp; cd imei &amp;&amp; chmod +x imei.sh &amp;&amp; ./imei.sh</code></p></blockquote></figure>



<p>By default it&#8217;ll install a very recent version &#8211; usually the very latest release &#8211; but you can customise it if you wish with the <code>--imagemagick-version</code> argument to <code>imei.sh</code>.</p>



<p>Note: I had to use the <code>--force</code> argument to get <code>imei.sh</code> to actually build &amp; install <em>all</em> the components &#8211; for some reason it skipped the dependent libraries (for AVIF &amp; JXL support) and just installed ImageMagick, <em>without</em> AVIF and JXL support.  Try it without first, since that&#8217;s supposed to be the happy path, but check that it says <code>[<span style="color: green">OK</span>]</code> for every item; that nothing is <code>[<span style="color: green">SKIPPED</span>]</code>.</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<p>Building libaom (for AVIF support) requires CMake 3.6 or later.  Ubuntu 22.04 comes with a suitable version, so you shouldn&#8217;t have any issues.  But if you&#8217;re installing on an older Ubuntu, a different distro, or you&#8217;ve messed with CMake otherwise, check that you have a suitable version with <code>cmake --version</code>.</p>
</div></div>



<p>Once it&#8217;s completed successfully &#8211; which can take tens of minutes if you have a wimpy server such as is often used for WordPress hosting &#8211; double-check that you have a good version installed:</p>



<figure class="wp-block-pullquote"><blockquote><p><code>identify --version</code></p></blockquote></figure>



<p>At time of writing that says 7.1.1-26 for me, but of course for you it&#8217;ll probably be something newer.  You can consult <a href="https://imagemagick.org/script/download.php" data-wpel-link="external" target="_blank" rel="external noopener">ImageMagick&#8217;s download page</a> to find out what the newest version is.</p>



<h3 class="wp-block-heading">Install Imagick</h3>



<p>First, download Imagick:</p>



<figure class="wp-block-pullquote"><blockquote><p><code>pushd /tmp &amp;&amp; git clone https://github.com/Imagick/imagick &amp;&amp; cd imagick</code></p></blockquote></figure>



<p>Next, you need to set the version string to the actual version &#8211; otherwise, at the very end of this process, you&#8217;ll find that WordPress quietly refuses to use ImageMagick / Imagick!  Do that by editing the <code>php_imagick.h</code> file.  You should see, somewhere near the top of the file, something like:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-disabled" data-code-block-pro-font-family="" style="font-size:.875rem;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><pre class="shiki light-plus" style="background-color: #FFFFFF" tabindex="0"><code><span class="line"><span style="color: #AF00DB">#define</span><span style="color: #0000FF"> PHP_IMAGICK_VERSION    </span><span style="color: #A31515">&quot;@PACKAGE_VERSION@&quot;</span></span>
<span class="line"><span style="color: #AF00DB">#define</span><span style="color: #0000FF"> PHP_IMAGICK_EXTNUM     </span><span style="color: #098658">30700</span></span></code></pre></div>



<p>You need to change that first string to the version declared on that second line.  30700 means version 3.7.0.  So in my case I replaced <code>"@PACKAGE_VERSION@"</code> with <code>"3.7.0"</code>.</p>



<p>Now you need to determine where the relevant PHP installation is &#8211; the version that Plesk is using to run WordPress for your website(s).  You can find that out in various ways, perhaps the simplest being to log in to your Plesk dashboard, open the &#8220;Websites &amp; Domains&#8221; section, and look at the PHP version listed for each website of interest.</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<p>☝️If you have multiple sites and they&#8217;re not all running the same version of PHP, you&#8217;ll need to repeat all the following steps for each PHP version.</p>
</div></div>



<p>In my case I&#8217;m using PHP 8.2. So now I know that the PHP install of interest is located at <code>/opt/plesk/php/8.2/</code> (Plesk installs all its versions of PHP in <code>/opt/plesk/php</code>). I&#8217;ll use that in the subsequent commands shown here, but make sure to adjust that to suit whatever version of PHP you&#8217;re using.</p>



<p>To build Imagick, you need the PHP developer tools &#8211; for your particular Plesk PHP installation(s).  e.g. in my case I&#8217;m using PHP 8.2, so I need to run:</p>



<figure class="wp-block-pullquote"><blockquote><p><code>apt install plesk-php82-dev</code></p></blockquote></figure>



<p>Now you need to configure the Imagick build:</p>



<figure class="wp-block-pullquote"><blockquote><p><code>/opt/plesk/php/8.2/bin/phpize &amp;&amp; ./configure --prefix=/opt/plesk/php/8.2/ --exec-prefix=/opt/plesk/php/8.2/ --datadir=/opt/plesk/php/8.2/ --with-php-config=/opt/plesk/php/8.2/bin/php-config &amp;&amp; make -j `nproc --all` install</code></p></blockquote></figure>



<p>Don&#8217;t forget to change &#8220;8.2&#8221; to your version of PHP, if it&#8217;s different!</p>



<p>It should only take ten seconds or so to configure, build, &amp; install Imagick.</p>



<p>Now, rename the built library so that Plesk updates won&#8217;t clobber it:</p>



<figure class="wp-block-pullquote"><blockquote><p><code>mv /opt/plesk/php/8.2/lib/php/modules/imagick{,_custom}.so</code></p></blockquote></figure>



<p>Lastly, although it&#8217;s technically optional, it&#8217;s nice to fix the permissions of the installed library:</p>



<figure class="wp-block-pullquote"><blockquote><p><code>chmod 644 /opt/plesk/php/8.2/lib/php/modules/imagick_custom.so</code></p></blockquote></figure>



<h3 class="wp-block-heading">Load Imagick into PHP</h3>



<p>Annoyingly, PHP won&#8217;t automatically notice Imagick is installed &#8211; you have to tell it so, manually.  Though this is pretty easy to do.  There are a few ways to do it, the easiest being through Plesk:  go to the &#8220;Tools &amp; Settings&#8221; section of your Plesk dashboard, click &#8220;PHP Settings&#8221; (from the &#8220;General Settings&#8221; category), then click on the relevant handler in the list (e.g. &#8220;FPM application&#8221;).  If you&#8217;re not sure which is relevant, look for a non-zero number in the &#8220;Domains&#8221; column.</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<p>☝️If you use different handlers for different websites &#8211; as will be shown in the &#8220;Domains&#8221; column by a number greater than zero for multiple rows &#8211; then you might need to repeat the following steps for each one of them.  Start with any one of them, then when editing the <code>php.ini</code> file (as explained below) check which handlers are listed as also covered by that same file.  If any are missing, those are the ones you&#8217;ll need to repeat these steps on.</p>
</div></div>



<p>Click on &#8220;php.ini&#8221; to switch to that tab, and you should see a text field containing the contents of the relevant <code>php.ini</code> file.  Somewhere in this file &#8211; technically anywhere, but I like to scroll down to the section where all the other extensions are listed &#8211; you need to add the line:</p>



<pre class="wp-block-preformatted">extension=imagick_custom.so</pre>



<p>Then, click the &#8220;OK&#8221; button to save your changes.</p>



<p>In <em>theory</em> Plesk will now restart the relevant server daemons, to have them pick up the change, but if you subsequently find that WordPress doesn&#8217;t seem to see the new ImageMagick installation (or you edited <code>php.ini</code> directly from the command line), you can give it a more forceful shove:</p>



<figure class="wp-block-pullquote"><blockquote><p><code>service plesk-php82-fpm restart</code></p></blockquote></figure>



<p>You should now be set &#8211; you can test your upgrade in a variety of ways, such as:</p>



<ul class="wp-block-list">
<li>Try uploading an image in a format, or using features such as animation or transparency, that wasn&#8217;t previously supported.  e.g. AVIFs.  Note that you might need additional WordPress plug-ins to enable use of the new formats, e.g. <a href="https://wordpress.org/plugins/avif-support/" data-wpel-link="external" target="_blank" rel="external noopener">AVIF Support</a> or any of the <a href="https://wordpress.org/plugins/search/svg/" data-wpel-link="external" target="_blank" rel="external noopener">numerous SVG support plug-ins</a>.<br><br>See also <a href="https://wadetregaskis.com/image-workflow-for-wordpress/" data-wpel-link="internal">my earlier post on my Image workflow for WordPress</a> &#8211; particularly <a href="https://wadetregaskis.com/image-workflow-for-wordpress/#AVIF_Support" data-wpel-link="internal">the section on AVIF</a>.</li>



<li>Check phpinfo &#8211; in your Plesk dashboard, go to your website(s) in the &#8220;Websites &amp; Domains&#8221; section, click &#8220;PHP&#8221; (under the &#8220;Dev Tools&#8221; category), then click the subtle &#8220;View the phpinfo() page&#8221; link to the right of the first pop-up menus.  Search for &#8220;imagick&#8221; &#8211; you should find an entry for it, with a table of plug-in information such as its version, the version of ImageMagick being used, and the file formats supported.</li>
</ul>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img fetchpriority="high" decoding="async" width="946" height="480" src="https://wadetregaskis.com/wp-content/uploads/2024/01/imagick-section-of-phpinfo.webp" alt="Screenshot of the &quot;imagick&quot; section of the phpinfo page." class="wp-image-7465" srcset="https://wadetregaskis.com/wp-content/uploads/2024/01/imagick-section-of-phpinfo.webp 946w, https://wadetregaskis.com/wp-content/uploads/2024/01/imagick-section-of-phpinfo-256x130.webp 256w, https://wadetregaskis.com/wp-content/uploads/2024/01/imagick-section-of-phpinfo-512x260.webp 512w, https://wadetregaskis.com/wp-content/uploads/2024/01/imagick-section-of-phpinfo@2x.webp 1892w" sizes="(max-width: 946px) 100vw, 946px" /></figure>
</div>


<h2 class="wp-block-heading">Addendum: updating ImageMagick &amp; Magick</h2>



<p>You can of course just repeat all the above steps to perform a fresh install, incorporating any updates since you last installed everything.  But you can save a little time by keeping the <code>imei</code> and <code>imagick</code> folders around, and just doing:</p>



<ol class="wp-block-list">
<li><code>git pull --rebase</code> in each, then re-run their respective build commands.  For Imagick you&#8217;ll probably have to <code>git stash</code> first, in order to do the <code>git pull</code>, and then restore your version string patch with <code>git stash apply</code>.<br><br>Don&#8217;t forget to check if you need to update the version string in <code>php_imagick.h</code>.</li>



<li>Rename the built <code>imagick.so</code> again, and fix its permissions.</li>



<li>Restart the PHP daemon.</li>
</ol>


<ol class="wp-block-footnotes"><li id="39baf781-8a25-40c7-8128-a093b1008184">Some versions &amp; builds nominally support AVIF, but this support is almost by accident &#8211; what they actually support formally is <a href="https://en.wikipedia.org/wiki/High_Efficiency_Image_File_Format" data-wpel-link="external" target="_blank" rel="external noopener">HEIF</a>, for which they use <a href="https://github.com/strukturag/libheif" data-wpel-link="external" target="_blank" rel="external noopener">libheif</a>, which <em>can</em> be built with AVIF support as well, but in my experience that support is buggy and incomplete &#8211; e.g. <a href="https://alexwlchan.net/2023/check-for-transparency/" data-wpel-link="external" target="_blank" rel="external noopener">alpha channels are not supported</a>. <a href="#39baf781-8a25-40c7-8128-a093b1008184-link" aria-label="Jump to footnote reference 1">↩︎</a></li><li id="dd7bbb45-83b3-427f-b78e-2e7899711d0f">Alas I don&#8217;t actually know if / how often it was successfully exploited, as far as Google saw.  I have to imagine it was not uncommon, though, given the large attack surface that is ImageMagick&#8217;s APIs and image plug-ins, not to mention how lucrative a target Google is. <a href="#dd7bbb45-83b3-427f-b78e-2e7899711d0f-link" aria-label="Jump to footnote reference 2">↩︎</a></li></ol>]]></content:encoded>
					
					<wfw:commentRss>https://wadetregaskis.com/how-to-install-imagemagick-7-for-wordpress-under-plesk-obsidian-on-ubuntu-22-04/feed/</wfw:commentRss>
			<slash:comments>12</slash:comments>
		
		
			<media:content url="https://wadetregaskis.com/wp-content/uploads/2024/01/ImageMagick-logo.avif" medium="image" />
<post-id xmlns="com-wordpress:feed-additions:1">7457</post-id>	</item>
		<item>
		<title>No more Dark Mode support</title>
		<link>https://wadetregaskis.com/no-more-dark-mode-support/</link>
					<comments>https://wadetregaskis.com/no-more-dark-mode-support/#respond</comments>
		
		<dc:creator><![CDATA[]]></dc:creator>
		<pubDate>Mon, 01 Jan 2024 03:45:56 +0000</pubDate>
				<category><![CDATA[Meta]]></category>
		<category><![CDATA[Bloated]]></category>
		<category><![CDATA[Dark mode]]></category>
		<category><![CDATA[Dark Mode for Safari]]></category>
		<category><![CDATA[Dark Reader]]></category>
		<category><![CDATA[Dracula Dark Mode]]></category>
		<category><![CDATA[Noir]]></category>
		<category><![CDATA[Perfect Images]]></category>
		<category><![CDATA[Sad]]></category>
		<category><![CDATA[Wordpress]]></category>
		<category><![CDATA[WP Dark Mode]]></category>
		<category><![CDATA[WP Fastest Cache]]></category>
		<guid isPermaLink="false">https://wadetregaskis.com/?p=7255</guid>

					<description><![CDATA[For about a month I was using WP Dark Mode. I don&#8217;t really recall how I thought upon it to begin with, but I vaguely recall choosing to install it because it seemed kind to support dark mode. Even though I don&#8217;t use it myself, it does seem to have a non-trivial following. And I&#8230; <a class="read-more-link" href="https://wadetregaskis.com/no-more-dark-mode-support/" data-wpel-link="internal">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>For about a month I was using <a href="https://wordpress.org/plugins/wp-dark-mode/" data-wpel-link="external" target="_blank" rel="external noopener">WP Dark Mode</a>.  I don&#8217;t really recall how I thought upon it to begin with, but I vaguely recall choosing to install it because it seemed kind to support dark mode.  Even though I don&#8217;t use it myself, it does seem to have a non-trivial following.  And I remember being obsessively into it &#8211; and OS theming in general &#8211; when I was a child.</p>



<p>WP Dark Mode had &#8216;flashing&#8217; problems, though &#8211; where the page loads first in normal, &#8216;light&#8217; mode and only then re-renders into dark mode.  Possibly just a result of interference by <a href="https://www.wpfastestcache.com" data-wpel-link="external" target="_blank" rel="external noopener">WP Fastest Cache</a>, which I later realised was probably deferring WP Dark Mode&#8217;s JavaScript files past initial page load.  Irrespective, I found that <a href="https://wordpress.org/plugins/dracula-dark-mode/" data-wpel-link="external" target="_blank" rel="external noopener">Dracula Dark Mode</a> worked better &#8211; though still not flawlessly in this regard &#8211; so I switched to that.</p>



<p>However, I eventually noticed that Dracula Dark Mode adds <em>415 KiB</em> to every single page load, with its JavaScript and CSS files.  That <em>doubles</em> the total size for some pages, even with WordPress &amp; Jetpack bloating the baseline.  Its own analytics suggested that basically nobody uses dark mode, at least amongst people that browse my website.  So that does not seem like a reasonable trade-off.</p>



<p>Thus, with a bit of sadness, I&#8217;ve disabled the plug-in.  Maybe in future the plug-in&#8217;s authors can find a way to optimise things such that its JS &amp; CSS is only loaded if dark mode is actually in use.</p>



<p>Turns out, though, that almost no websites support dark mode anyway &#8211; I discovered as much while having dark mode enabled during my own testing.  So it doesn&#8217;t seem like I&#8217;m an odd one out, and my tiny website is not going to start any trends.  From the looks of it the way most people actually tackle the web in dark mode is through browser plug-ins which basically do the same thing as the WordPress plug-ins, but for <em>every</em> website.  And only users actually interested in dark mode have to pay their price.</p>



<p>I haven&#8217;t tried any of them, but there&#8217;s numerous Safari plug-ins for dark mode, e.g. <a href="https://darkreader.org" data-wpel-link="external" target="_blank" rel="external noopener">Dark Reader</a>, <a href="https://getnoir.app" data-wpel-link="external" target="_blank" rel="external noopener">Noir</a>, <a href="https://alexdenk.eu/mywork/darkmode.html" data-wpel-link="external" target="_blank" rel="external noopener">Dark Mode for Safari</a>, etc.</p>



<p>It does mean I can&#8217;t do image substitutions for dark mode users, but I couldn&#8217;t find any dark mode WordPress plug-in that works correctly in that regard anyway (they seem to do naive URL substitutions, without accounting for images having various replicas of different sizes per WordPress standard practice, and certainly without supporting <a href="https://meowapps.com/wp-retina-2x/" data-wpel-link="external" target="_blank" rel="external noopener">Perfect Images</a>).  It&#8217;s also rare that I have a dark mode version of an image available &#8211; though I can at least be better about using actual alpha channels rather than fixed white backgrounds, going forward.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wadetregaskis.com/no-more-dark-mode-support/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">7255</post-id>	</item>
		<item>
		<title>Image workflow for WordPress</title>
		<link>https://wadetregaskis.com/image-workflow-for-wordpress/</link>
					<comments>https://wadetregaskis.com/image-workflow-for-wordpress/#respond</comments>
		
		<dc:creator><![CDATA[]]></dc:creator>
		<pubDate>Sun, 31 Dec 2023 01:41:49 +0000</pubDate>
				<category><![CDATA[Howto]]></category>
		<category><![CDATA[Meta]]></category>
		<category><![CDATA[AVIF]]></category>
		<category><![CDATA[AVIF Support]]></category>
		<category><![CDATA[Enable Media Replace]]></category>
		<category><![CDATA[Image Regenerate & Select Crop]]></category>
		<category><![CDATA[Image Tool+]]></category>
		<category><![CDATA[ImageOptim]]></category>
		<category><![CDATA[JPEG 2000]]></category>
		<category><![CDATA[JPEG XL]]></category>
		<category><![CDATA[Perfect Images]]></category>
		<category><![CDATA[PNG]]></category>
		<category><![CDATA[WebP]]></category>
		<category><![CDATA[Wordpress]]></category>
		<guid isPermaLink="false">https://wadetregaskis.com/?p=7146</guid>

					<description><![CDATA[These are the main tools and procedures I use for publishing images through WordPress. In case it&#8217;s helpful to others. My input images generally fall into three categories: Some of these formats can be published directly into WordPress &#8211; mainly PNG and JPEG &#8211; but not all, and neither PNG nor JPEG are the best&#8230; <a class="read-more-link" href="https://wadetregaskis.com/image-workflow-for-wordpress/" data-wpel-link="internal">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>These are the main tools and procedures I use for publishing images through WordPress.  In case it&#8217;s helpful to others.</p>



<p>My input images generally fall into three categories:</p>



<ol class="wp-block-list">
<li>Screenshots, as PNGs.</li>



<li>Random 3rd party images, typically as JPEGs but sometimes PNGs or other formats.</li>



<li>Photos, as Nikon NEFs.</li>
</ol>



<p>Some of these formats <em>can</em> be published directly into WordPress &#8211; mainly PNG and JPEG &#8211; but not all, and neither PNG nor JPEG are the best file formats for anything these days.  In terms of compression efficiency, there are numerous superior formats &#8211; JPEG 2000, JPEG XL, HEIF<sup data-fn="ce19f9a1-4b3d-427c-b205-ec8684b1e5ae" class="fn"><a href="#ce19f9a1-4b3d-427c-b205-ec8684b1e5ae" id="ce19f9a1-4b3d-427c-b205-ec8684b1e5ae-link">1</a></sup>, WebP, AVIF, etc.</p>



<p>Using an appropriate and efficient format &#8211; and suitable compression quality settings &#8211; is important to me to save disk space, save bandwidth, minimise page load times, and ensure images are seen the way I want them to be (re. lossless vs lossy).</p>



<h1 class="wp-block-heading">Best image codecs</h1>



<h2 class="wp-block-heading">Legacy options</h2>



<p>PNG and JPEG are supported in practically any &amp; every web browser still in real use today.  As is GIF, technically, although it&#8217;s strictly inferior to PNG [for static images] and actual video formats [for moving images].  It certainly <em>is</em> possible to still use them, but it wastes storage space &amp; bandwidth, and hurts page load times.</p>



<p>That said, PNG is not the worst option <em>if</em> you use appropriate tooling to maximise the compression.  The level of compression you achieve &#8216;out of the box&#8217; with most applications &#8211; e.g. Photoshop, Apple&#8217;s apps, etc &#8211; is actually quite poor.  There are numerous specialised tools which can greatly improve the compression.  I recommend <a href="https://imageoptim.com/mac" data-wpel-link="external" target="_blank" rel="external noopener">ImageOptim</a> &#8211; it&#8217;s free and open source.  It typically reduces PNG files sizes by a further 20% to 50% (depending on how much fine detail or noise the image contains) without any loss of image quality.  It actually makes PNG competitive with the modern formats to a degree, although ultimately still not the best.</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<p>⚠️ ImageOptim does not work correctly with <em>animated</em> PNGs &#8211; it silently removes the animation!</p>
</div></div>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" width="664" height="559" src="https://wadetregaskis.com/wp-content/uploads/2023/12/ImageOptim.webp" alt="" class="wp-image-7150" style="width:664px;height:auto" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/ImageOptim.webp 664w, https://wadetregaskis.com/wp-content/uploads/2023/12/ImageOptim-256x216.webp 256w, https://wadetregaskis.com/wp-content/uploads/2023/12/ImageOptim-512x431.webp 512w, https://wadetregaskis.com/wp-content/uploads/2023/12/ImageOptim@2x.webp 1328w" sizes="(max-width: 664px) 100vw, 664px" /></figure>
</div>


<p>It&#8217;s quite configurable, including with regard to stripping metadata or not &#8211; although, alas, it offers no nuance in this, such as keeping copyright metadata but removing spurious camera metadata, or geolocations.</p>



<div class="alignnormal"><div id="metaslider-id-7155" style="max-width: 775px; margin: 0 auto;" class="ml-slider-3-107-0 metaslider metaslider-flex metaslider-7155 ml-slider ms-theme-default nav-hidden" role="region" aria-label="ImageOptim Preferences" data-height="510" data-width="775">
    <div id="metaslider_container_7155">
        <div id="metaslider_7155" class="flexslider">
            <ul class='slides'>
                <li style="display: block; width: 100%;" class="slide-7157 ms-image " aria-roledescription="slide" data-date="2023-12-30 12:03:47" data-filename="ImageOptim-Settings-General.webp" data-slide-type="image"><img decoding="async" width="775" height="510" src="https://wadetregaskis.com/wp-content/uploads/2023/12/ImageOptim-Settings-General.webp" class="slider-7155 slide-7157 msDefaultImage" alt="Screenshot of the ImageOptim Preferences window, showing the General tab" rel="" title="ImageOptim Settings - General" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/ImageOptim-Settings-General.webp 775w, https://wadetregaskis.com/wp-content/uploads/2023/12/ImageOptim-Settings-General-256x168.webp 256w, https://wadetregaskis.com/wp-content/uploads/2023/12/ImageOptim-Settings-General-512x337.webp 512w, https://wadetregaskis.com/wp-content/uploads/2023/12/ImageOptim-Settings-General@2x.webp 1550w" sizes="(max-width: 775px) 100vw, 775px" /><div class="caption-wrap"><div class="caption">You have full control over which libraries are used.  Not all the libraries are enabled by default - Guetzli in particular is off by default because it can make the recompression process take a particularly long time.  But in my opinion, if you're going to the trouble of using specialised tools to improve your image compression, you might as well use them to their fullest.</div></div></li>
                <li style="display: none; width: 100%;" class="slide-7158 ms-image " aria-roledescription="slide" data-date="2023-12-30 12:03:47" data-filename="ImageOptim-Settings-Quality.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="775" height="510" src="https://wadetregaskis.com/wp-content/uploads/2023/12/ImageOptim-Settings-Quality.webp" class="slider-7155 slide-7158 msDefaultImage" alt="Screenshot of the ImageOptim Preferences window, showing the Quality tab" rel="" title="ImageOptim Settings - Quality" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/ImageOptim-Settings-Quality.webp 775w, https://wadetregaskis.com/wp-content/uploads/2023/12/ImageOptim-Settings-Quality-256x168.webp 256w, https://wadetregaskis.com/wp-content/uploads/2023/12/ImageOptim-Settings-Quality-512x337.webp 512w, https://wadetregaskis.com/wp-content/uploads/2023/12/ImageOptim-Settings-Quality@2x.webp 1550w" sizes="auto, (max-width: 775px) 100vw, 775px" /><div class="caption-wrap"><div class="caption">By default ImageOptim preserves your images exactly as they appear (lossless recompression), but it does give you the option of using lossy compression.  Just beware of significant and unpredictable compression artefacts, particularly with PNGs.</div></div></li>
                <li style="display: none; width: 100%;" class="slide-7156 ms-image " aria-roledescription="slide" data-date="2023-12-30 12:03:46" data-filename="ImageOptim-Settings-Optimisation-level.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="775" height="510" src="https://wadetregaskis.com/wp-content/uploads/2023/12/ImageOptim-Settings-Optimisation-level.webp" class="slider-7155 slide-7156 msDefaultImage" alt="Screenshot of the ImageOptim Preferences window, showing the Optimisation level tab" rel="" title="ImageOptim Settings - Optimisation level" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/ImageOptim-Settings-Optimisation-level.webp 775w, https://wadetregaskis.com/wp-content/uploads/2023/12/ImageOptim-Settings-Optimisation-level-256x168.webp 256w, https://wadetregaskis.com/wp-content/uploads/2023/12/ImageOptim-Settings-Optimisation-level-512x337.webp 512w, https://wadetregaskis.com/wp-content/uploads/2023/12/ImageOptim-Settings-Optimisation-level@2x.webp 1550w" sizes="auto, (max-width: 775px) 100vw, 775px" /><div class="caption-wrap"><div class="caption">I haven't really played with this 'Optimisation level' setting, I just set it to maximum.  Why use a tool like this if you're not going to use it to its fullest?</div></div></li>
            </ul>
        </div>
        
    </div>
</div></div>



<p>It&#8217;s also possible to use such specialised tools for <em>lossy</em> PNG compression.  PNG is not inherently lossy, but by manipulating the image before compression it is possible to greatly improve its compressibility.  e.g. by reducing the colour palette, adding or removing dithering, or simply removing fine detail.  Various tools &#8211; including ImageOptim &#8211; will do this for you if you wish, although be warned that the resulting image quality is unpredictable and sometimes very poor (exhibiting obvious colour changes, banding, or visual artefacts otherwise).</p>



<p>The example below is a fairly typical &#8220;good&#8221; result &#8211; the file size is cut by 70%, but the lossy PNG compression has introduced noticeable banding and dithering.  You might consider it worth the trade-off but consider that a lossy WebP version, <em>also</em> saving 70% on file size, doesn&#8217;t have any noticeable image degradation.  And an AVIF version with similar image quality cuts the file size by <em>80%</em>.  So while you might think it&#8217;s neat to use a &#8216;lossy&#8217; PNG and get &#8211; by PNG standards &#8211; dramatically higher compression, you&#8217;re probably better off just using WebP or AVIF.</p>



<div class="alignnormal"><div id="metaslider-id-7178" style="max-width: 1000px; margin: 0 auto;" class="ml-slider-3-107-0 metaslider metaslider-flex metaslider-7178 ml-slider ms-theme-default nav-hidden nav-hidden" role="region" aria-label="Lossy PNG warning" data-height="597" data-width="1000">
    <div id="metaslider_container_7178">
        <div id="metaslider_7178" class="flexslider">
            <ul class='slides'>
                <li style="display: block; width: 100%;" class="slide-7183 ms-image " aria-roledescription="slide" data-date="2023-12-30 16:01:23" data-filename="Swift-on-Raspberry-Pi-lossless.png" data-slide-type="image"><img loading="lazy" decoding="async" width="2000" height="1194" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Swift-on-Raspberry-Pi-lossless.png" class="slider-7178 slide-7183 msDefaultImage" alt="" rel="" title="Swift on Raspberry Pi (lossless)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Swift-on-Raspberry-Pi-lossless.png 2000w, https://wadetregaskis.com/wp-content/uploads/2023/12/Swift-on-Raspberry-Pi-lossless-256x153.png 256w, https://wadetregaskis.com/wp-content/uploads/2023/12/Swift-on-Raspberry-Pi-lossless-512x306@2x.png 1024w, https://wadetregaskis.com/wp-content/uploads/2023/12/Swift-on-Raspberry-Pi-lossless-512x306.png 512w" sizes="auto, (max-width: 2000px) 100vw, 2000px" /><div class="caption-wrap"><div class="caption">Lossless PNG (1,956 KB)</div></div></li>
                <li style="display: none; width: 100%;" class="slide-7184 ms-image " aria-roledescription="slide" data-date="2023-12-30 16:01:23" data-filename="Swift-on-Raspberry-Pi-lossy.png" data-slide-type="image"><img loading="lazy" decoding="async" width="2000" height="1194" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Swift-on-Raspberry-Pi-lossy.png" class="slider-7178 slide-7184 msDefaultImage" alt="" rel="" title="Swift on Raspberry Pi (lossy)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Swift-on-Raspberry-Pi-lossy.png 2000w, https://wadetregaskis.com/wp-content/uploads/2023/12/Swift-on-Raspberry-Pi-lossy-256x153.png 256w, https://wadetregaskis.com/wp-content/uploads/2023/12/Swift-on-Raspberry-Pi-lossy-512x306@2x.png 1024w, https://wadetregaskis.com/wp-content/uploads/2023/12/Swift-on-Raspberry-Pi-lossy-512x306.png 512w" sizes="auto, (max-width: 2000px) 100vw, 2000px" /><div class="caption-wrap"><div class="caption">Lossy PNG (587 KB)</div></div></li>
            </ul>
        </div>
        
    </div>
</div></div>



<h2 class="wp-block-heading">Non-options</h2>



<p>Despite its age JPEG 2000 is surprisingly good in my experience &#8211; I used it many years ago on this website for my <a href="https://wadetregaskis.com/raw-converter-comparison/" data-wpel-link="internal">Raw converter comparison</a> as an alternative to TIFF and PNG, as it yielded file sizes about half that of PNG.  It&#8217;s competitive even with newer formats like WebP and AVIF.  JPEG XL is purportedly even better again.  Alas, no browser other than Safari supports either of them.</p>



<p>HEIF exists and is &#8220;modern&#8221; but isn&#8217;t really in the same ballpark &#8211; while it <em>is</em> better than JPEG, that&#8217;s a low bar; it achieves worse results even than JPEG 2000, a codec that&#8217;s <em>twenty years</em> older.  Its only claim to any fame is that it&#8217;s the native source format for many photos today, thanks to its use on Apple iDevices.  In any case, the only current-version web browser which supports it is Safari.</p>



<h2 class="wp-block-heading">Viable options</h2>



<p>The only modern format which is universally supported<sup data-fn="42530c0c-bed1-4a7a-bff8-2c27f0a337bd" class="fn"><a href="#42530c0c-bed1-4a7a-bff8-2c27f0a337bd" id="42530c0c-bed1-4a7a-bff8-2c27f0a337bd-link">2</a></sup> is WebP.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="1158" height="746" src="https://wadetregaskis.com/wp-content/uploads/2023/12/caniuse-com-for-WebP.webp" alt="Screenshot of caniuse.com showing the web browser compatibility matrix for the WebP image format" class="wp-image-7147" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/caniuse-com-for-WebP.webp 1158w, https://wadetregaskis.com/wp-content/uploads/2023/12/caniuse-com-for-WebP-256x165.webp 256w, https://wadetregaskis.com/wp-content/uploads/2023/12/caniuse-com-for-WebP-512x330@2x.webp 1024w, https://wadetregaskis.com/wp-content/uploads/2023/12/caniuse-com-for-WebP-512x330.webp 512w, https://wadetregaskis.com/wp-content/uploads/2023/12/caniuse-com-for-WebP@2x.webp 2316w" sizes="auto, (max-width: 1158px) 100vw, 1158px" /><figcaption class="wp-element-caption">Source: <a href="https://caniuse.com/webp" data-wpel-link="external" target="_blank" rel="external noopener">caniuse.com</a></figcaption></figure>
</div>


<p>AVIF is <em>nearly</em> universally supported, with the unfortunately notable exception of Edge.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="1158" height="879" src="https://wadetregaskis.com/wp-content/uploads/2023/12/caniuse-com-for-AVIF.webp" alt="Screenshot of caniuse.com showing the web browser compatibility matrix for the AVIF image format" class="wp-image-7148" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/caniuse-com-for-AVIF.webp 1158w, https://wadetregaskis.com/wp-content/uploads/2023/12/caniuse-com-for-AVIF-256x194.webp 256w, https://wadetregaskis.com/wp-content/uploads/2023/12/caniuse-com-for-AVIF-512x389@2x.webp 1024w, https://wadetregaskis.com/wp-content/uploads/2023/12/caniuse-com-for-AVIF-512x389.webp 512w, https://wadetregaskis.com/wp-content/uploads/2023/12/caniuse-com-for-AVIF@2x.webp 2316w" sizes="auto, (max-width: 1158px) 100vw, 1158px" /><figcaption class="wp-element-caption">Source: <a href="https://caniuse.com/avif" data-wpel-link="external" target="_blank" rel="external noopener">caniuse.com</a></figcaption></figure>
</div>


<p>I choose to use AVIF nonetheless, as my audience are unlikely to be using Edge anyway, since they&#8217;re unlikely to be using Windows at all.  I also like to assume that Edge <em>will</em>, eventually, get with the program &#8211; although the fact that AVIF support was apparently incorporated in versions 114 to 117, but then <em>removed</em>, is concerning.</p>



<p>So those are the two options, basically.  For better or worse, neither one is strictly superior to the other.</p>



<figure class="wp-block-pullquote"><blockquote><p>WebP is best for lossless compression, and AVIF is usually the best for lossy compression (especially at lower qualities).</p></blockquote></figure>



<p>It is case-dependent and a little subjective as they have noticeably different methodologies:</p>



<ul class="wp-block-list">
<li>AVIF tends to be heavy-handed with &#8216;noise&#8217; removal, which seems to be a significant part of how it achieves better compression.</li>



<li>WebP will more faithfully preserve noise (and artefacts from earlier lossy compressions), which can be counter-productive.</li>
</ul>



<p>AVIF really excels &#8211; compared to WebP and earlier codecs &#8211; with more aggressive compression settings.  It&#8217;s much better under tight file size constraints.  It also performs particularly well for images which <em>aren&#8217;t</em> so clean to begin with &#8211; where they do have some actual image noise, or visible compression artefacts from an earlier lossy compression stage, or otherwise fine details that aren&#8217;t important to preserve.</p>



<p>WebP behaves more &#8220;traditionally&#8221; &#8211; like JPEG &#8211; with regard to increase blockiness and banding as you crank up the compression.  AVIF does a much better job of degrading image quality more &#8216;smoothly&#8217; across the image &#8211; so that particularly bad, noticeable artefacts don&#8217;t develop as easily.  Even while it preserves more genuine detail.</p>



<div class="alignnormal"><div id="metaslider-id-7171" style="max-width: 1024px; margin: 0 auto;" class="ml-slider-3-107-0 metaslider metaslider-flex metaslider-7171 ml-slider ms-theme-default nav-hidden nav-hidden nav-hidden" role="region" aria-label="Noisy Echo (WebP vs AVIF high-compression comparison)" data-height="1024" data-width="1024">
    <div id="metaslider_container_7171">
        <div id="metaslider_7171" class="flexslider">
            <ul class='slides'>
                <li style="display: block; width: 100%;" class="slide-7174 ms-image " aria-roledescription="slide" data-date="2023-12-30 15:40:08" data-filename="Noisy-Echo-10.avif" data-slide-type="image"><img loading="lazy" decoding="async" width="2048" height="2048" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Noisy-Echo-10.avif" class="slider-7171 slide-7174 msDefaultImage" alt="" rel="" title="Noisy-Echo (10)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Noisy-Echo-10-1024x1024@2x.avif 2048w, https://wadetregaskis.com/wp-content/uploads/2023/12/Noisy-Echo-10-256x256.avif 256w, https://wadetregaskis.com/wp-content/uploads/2023/12/Noisy-Echo-10-512x512@2x.avif 1024w, https://wadetregaskis.com/wp-content/uploads/2023/12/Noisy-Echo-10-512x512.avif 512w" sizes="auto, (max-width: 2048px) 100vw, 2048px" /><div class="caption-wrap"><div class="caption">AVIF (188 KB)</div></div></li>
                <li style="display: none; width: 100%;" class="slide-7175 ms-image " aria-roledescription="slide" data-date="2023-12-30 15:40:09" data-filename="Noisy-Echo-22.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="2048" height="2048" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Noisy-Echo-22.webp" class="slider-7171 slide-7175 msDefaultImage" alt="" rel="" title="Noisy-Echo (22)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Noisy-Echo-22-1024x1024@2x.webp 2048w, https://wadetregaskis.com/wp-content/uploads/2023/12/Noisy-Echo-22-256x256.webp 256w, https://wadetregaskis.com/wp-content/uploads/2023/12/Noisy-Echo-22-512x512@2x.webp 1024w, https://wadetregaskis.com/wp-content/uploads/2023/12/Noisy-Echo-22-512x512.webp 512w" sizes="auto, (max-width: 2048px) 100vw, 2048px" /><div class="caption-wrap"><div class="caption">WebP (185 KB)</div></div></li>
            </ul>
        </div>
        
    </div>
</div></div>



<p>WebP is more competitive with high quality settings or high quality, &#8216;smooth&#8217; images (e.g. screenshots or computer renderings).  In lossless mode WebP universally outperforms AVIF, often by a significant margin.  In fact even PNG typically outperforms AVIF for lossless compression!</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img loading="lazy" decoding="async" width="1208" height="566" src="https://wadetregaskis.com/wp-content/uploads/2019/03/Dialog-screenshot.webp" alt="" class="wp-image-4352" style="width:604px" srcset="https://wadetregaskis.com/wp-content/uploads/2019/03/Dialog-screenshot.webp 1208w, https://wadetregaskis.com/wp-content/uploads/2019/03/Dialog-screenshot-512x240@2x.webp 1024w, https://wadetregaskis.com/wp-content/uploads/2019/03/Dialog-screenshot-256x120.webp 256w, https://wadetregaskis.com/wp-content/uploads/2019/03/Dialog-screenshot-512x240.webp 512w" sizes="auto, (max-width: 1208px) 100vw, 1208px" /><figcaption class="wp-element-caption">82 KB as WebP, 119 KB as PNG, and a whopping 284 KB as AVIF!</figcaption></figure>
</div>


<p>I&#8217;ve also noticed that WebP is <em>substantially</em> better at compressing repetitive patterns (even if they&#8217;re not perfectly identical).</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="1024" height="1024" src="https://wadetregaskis.com/wp-content/uploads/2023/12/WebP-repetitive-tiling-example.webp" alt="" class="wp-image-7151" style="object-fit:cover" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/WebP-repetitive-tiling-example-512x512@2x.webp 1024w, https://wadetregaskis.com/wp-content/uploads/2023/12/WebP-repetitive-tiling-example-256x256.webp 256w, https://wadetregaskis.com/wp-content/uploads/2023/12/WebP-repetitive-tiling-example-512x512.webp 512w, https://wadetregaskis.com/wp-content/uploads/2023/12/WebP-repetitive-tiling-example@2x.webp 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Using high-quality (but <em>lossy</em>) compression, this conglomerate image comparing four different RAW converters is 2.3 MB as WebP, 3.8 MB as AVIF (and 12.6 MB as an uncompressed TIFF, for reference).  Yet if you compress any one of the quarters individually, AVIF outperforms WebP.  Even though each quarter is significantly different, there&#8217;s enough repetition between them that WebP can extract significant compression gains, that AVIF apparently cannot.  And in cases with more verbatim repetition, WebP&#8217;s advantage increases even further.</figcaption></figure>
</div>


<p>AVIF seems particularly good at reducing visible artefacts resulting from JPEG over-compression, and in avoiding prominent compression artefacts in general &#8211; such as in the example below, where the file sizes are very similar (14 KB for AVIF, 13 KB for WebP) but AVIF does more with it &#8211; preserving more genuine detail such as in the camera lens and IR sensor even while doing a better job of removing the JPEG artefacts (noise, blockiness, and banding).</p>



<div class="alignnormal"><div id="metaslider-id-7188" style="max-width: 849px; margin: 0 auto;" class="ml-slider-3-107-0 metaslider metaslider-flex metaslider-7188 ml-slider ms-theme-default nav-hidden nav-hidden nav-hidden nav-hidden" role="region" aria-label="AVIF vs WebP for reducing JPEG artefacts" data-height="538" data-width="849">
    <div id="metaslider_container_7188">
        <div id="metaslider_7188" class="flexslider">
            <ul class='slides'>
                <li style="display: block; width: 100%;" class="slide-7196 ms-image " aria-roledescription="slide" data-date="2023-12-30 16:52:16" data-filename="Blink-XT.png" data-slide-type="image"><img loading="lazy" decoding="async" width="849" height="538" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Blink-XT.png" class="slider-7188 slide-7196 msDefaultImage" alt="" rel="" title="Blink-XT" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Blink-XT.png 849w, https://wadetregaskis.com/wp-content/uploads/2023/12/Blink-XT-256x162.png 256w, https://wadetregaskis.com/wp-content/uploads/2023/12/Blink-XT-512x324.png 512w" sizes="auto, (max-width: 849px) 100vw, 849px" /><div class="caption-wrap"><div class="caption">Original, full of JPEG artefacts</div></div></li>
                <li style="display: none; width: 100%;" class="slide-7195 ms-image " aria-roledescription="slide" data-date="2023-12-30 16:52:16" data-filename="Blink-XT-60.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="849" height="538" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Blink-XT-60.webp" class="slider-7188 slide-7195 msDefaultImage" alt="" rel="" title="Blink-XT (60)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Blink-XT-60.webp 849w, https://wadetregaskis.com/wp-content/uploads/2023/12/Blink-XT-60-256x162.webp 256w, https://wadetregaskis.com/wp-content/uploads/2023/12/Blink-XT-60-512x324.webp 512w" sizes="auto, (max-width: 849px) 100vw, 849px" /><div class="caption-wrap"><div class="caption">WebP</div></div></li>
                <li style="display: none; width: 100%;" class="slide-7194 ms-image " aria-roledescription="slide" data-date="2023-12-30 16:52:15" data-filename="Blink-XT-30.avif" data-slide-type="image"><img loading="lazy" decoding="async" width="849" height="538" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Blink-XT-30.avif" class="slider-7188 slide-7194 msDefaultImage" alt="" rel="" title="Blink-XT (30)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Blink-XT-30.avif 849w, https://wadetregaskis.com/wp-content/uploads/2023/12/Blink-XT-30-256x162.avif 256w, https://wadetregaskis.com/wp-content/uploads/2023/12/Blink-XT-30-512x324.avif 512w" sizes="auto, (max-width: 849px) 100vw, 849px" /><div class="caption-wrap"><div class="caption">AVIF</div></div></li>
            </ul>
        </div>
        
    </div>
</div></div>



<p>While generally I avoid re-compressing from an already lossy source since it tends to just compound the compression artefacts, AVIF can be useful for replacing low-quality JPEGs when you don&#8217;t have a quality original available.  It can actually <em>improve</em> subjective image quality &#8211; by correcting JPEG artefacts &#8211; even while substantially shrinking the file size.</p>



<h1 class="wp-block-heading">Image format conversion</h1>



<p>There&#8217;s basically two schools of thought on converting images to their serving format &#8211; do it in advance of uploading the image to WordPress, or have WordPress do it (via one or more plug-ins).  I prefer the former as:</p>



<ol class="wp-block-list">
<li>I have more control over the images by doing the conversion myself.
<ul class="wp-block-list">
<li>I can pick the best format for each situation.</li>



<li>I can customise compression settings to suit the situation (e.g. use more aggressive compression if the source image isn&#8217;t high quality to begin with) and use (e.g. use lossless for images which are about comparing image formats, RAW converters, or other such situations where viewers need to see the image <em>exactly</em>).</li>
</ul>
</li>



<li>I have more reliably-available computing horsepower locally; I can run pretty much any conversion or optimisation process and it&#8217;ll just work.  In contrast, WordPress-hosted processing is subject to various limits on runtime and RAM usage, which can cause things to fail in all sorts of ways both obvious and nefarious.  Most web servers [used for WordPress sites] have <em>way</em> less RAM available than even an entry-level personal computer.  Processing of &#8220;large&#8221; images, such as photos from a camera, <em>will</em> fail with default WordPress &amp; PHP settings.</li>



<li>Every additional WordPress plug-in increases the possibility of problems, whether due to bugs in the plug-in, the possibility of incompatibilities between plug-ins, etc.</li>



<li>WordPress plug-ins don&#8217;t always age well; each one I adopt is yet another plug-in which I might have to migrate off of in future.</li>



<li>WordPress plug-ins for image format conversion &amp; optimisation tend, in my experience, to be both buggy and money-grubbing.  Many are tied to 3rd party services like CDNs or &#8220;Cloud&#8221;-based image processing, and try to lock you into pricey and unnecessary paid subscriptions.</li>
</ol>



<p>Nominally having WordPress do it means you can just upload any random image without care for its format or compression, <em>and</em> that over time you can easily adopt new image formats just by installing new plug-ins, with all existing images converted retroactively.  In reality, new image formats come along very rarely and popular ones &#8211; like PNG, JPEG and WebP &#8211; are supported basically forever.</p>



<p>You do have to be a little careful, however, to not over-compress your original uploads (or, retain higher-quality versions locally).  Especially if you&#8217;re churning through image conversions &amp; uploads rapidly, you might not immediately notice compression artefacts.  Having the original available in order to redo the compression is valuable.</p>



<h2 class="wp-block-heading">Advance conversion</h2>



<p>There&#8217;s a further choice as to whether you do the processing locally or use a website.  I prefer to just do it locally, for some of the same reasons as not using WordPress, and <em>also</em> because in my experience I can achieve better results &#8211; websites that do image conversion / recompression, <em>especially</em> those that do it for free, use weak compression in order to minimise processing time, and consequently do not achieve the best results.</p>



<p>The best tool I&#8217;ve found for local image processing is <a href="https://apps.apple.com/us/app/image-tool/id1524216218" data-wpel-link="external" target="_blank" rel="external noopener">Image Tool+</a>.  It supports all the formats you&#8217;ll likely need and is designed for easy batch conversions.</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<p>⚠️ While Image Tool+ <em>mostly</em> supports animated images, it does <em>not</em> support animated AVIFs.  It will silently remove animation from any AVIFs it creates.</p>



<p>Beyond that, though, I&#8217;ve found that it does a surprisingly poor job of producing animated images, no matter what format you use &#8211; the resulting files are <em>huge</em>.  You can get <em>much</em> better results with other tools (e.g. <a href="https://ezgif.com/gif-to-avif" data-wpel-link="external" target="_blank" rel="external noopener">EZGIF</a> albeit with no control over the quality).</p>
</div></div>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="1277" height="832" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Image-Tool.webp" alt="Screenshot of the Image Tool+ main window, showing a bunch of image format conversions in progress" class="wp-image-7149" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Image-Tool.webp 1277w, https://wadetregaskis.com/wp-content/uploads/2023/12/Image-Tool-256x167.webp 256w, https://wadetregaskis.com/wp-content/uploads/2023/12/Image-Tool-512x334@2x.webp 1024w, https://wadetregaskis.com/wp-content/uploads/2023/12/Image-Tool-512x334.webp 512w, https://wadetregaskis.com/wp-content/uploads/2023/12/Image-Tool@2x.webp 2554w" sizes="auto, (max-width: 1277px) 100vw, 1277px" /><figcaption class="wp-element-caption">The user interface is a little clunky &#8211; with some odd but harmless rendering issues occasionally, as seen in the left hand column &#8211; but ultimately it&#8217;s functional, and does a better job than any other apps I&#8217;ve found.</figcaption></figure>
</div>


<p>In years gone by I used <a href="https://www.lemkesoft.de/en/products/graphicconverter/" data-wpel-link="external" target="_blank" rel="external noopener">GraphicConverter</a>, but it doesn&#8217;t support AVIF.</p>



<p>It&#8217;s important to note that the PNG files produced by Image Tool+ are not very efficiently compressed &#8211; you should run them through ImageOptim if you actually intend to use them.</p>



<h1 class="wp-block-heading">Publishing images in WordPress</h1>



<p>WordPress supports <em>some</em> image formats natively, and does a passable job of handling them by default.  So you don&#8217;t <em>have</em> to do anything additional, necessarily.  However, there&#8217;s several plug-ins I recommend which significantly improve its capabilities.</p>



<h2 class="wp-block-heading" id="avif-support"><a href="https://wordpress.org/plugins/avif-support/" data-wpel-link="external" target="_blank" rel="external noopener">AVIF Support</a></h2>



<p>As it says on the tin, it adds support for AVIF to WordPress, which sadly lacks support otherwise.  Without this plug-in, WordPress will simply refuse to accept AVIF uploads.</p>



<p>It&#8217;s free, <a href="https://plugins.trac.wordpress.org/browser/avif-support/" data-wpel-link="external" target="_blank" rel="external noopener">open source</a>, and works pretty seamlessly, as long as your web server and WordPress installation are sufficiently modern.  The easiest way to determine if that&#8217;s the case it to simply install the plug-in &#8211; its Settings page will tell you if AVIF is supported or not.  If it&#8217;s not, only then will you need to do some package upgrading.  In particular, you need (as best I can tell from experience and what I&#8217;ve read online):</p>



<ul class="wp-block-list">
<li><a href="https://grandplugins.com/how-to-upload-avif-images-in-wordpress/" data-wpel-link="external" target="_blank" rel="external noopener">PHP 8.2 (or later)</a>.</li>



<li><a href="https://php.watch/versions/8.1/gd-avif" data-wpel-link="external" target="_blank" rel="external noopener">libavif and suitably-compiled versions of GD and PHP</a>.</li>



<li><a href="https://web.archive.org/web/20240104012918/https://avif.io/blog/tutorials/imagemagick/" data-wpel-link="external" target="_blank" rel="external noopener">ImageMagick 7.0.25 (or later)</a><br><br>…<em>or</em> <a href="https://legacy.imagemagick.org" data-wpel-link="external" target="_blank" rel="external noopener">ImageMagick 6</a> with a suitably new and compiled <a href="https://github.com/strukturag/libheif" data-wpel-link="external" target="_blank" rel="external noopener">libheif</a> w/ AVIF support.  I haven&#8217;t been able to pin down specific version numbers, and it might vary by package repo (as libheif has to be compiled with certain flags to include the AVIF support).  In a nutshell you can tell if your system has it by following the dependency graph from your libmagickcore-6… library (via <code>apt info &lt;package></code> or similar) and seeing if it includes libheifN with in turn an [installed] dependency on svt-av1 or libaomN.  Where &#8216;N&#8217; may be any number.<br><br>Note: ImageMagick 6 doesn&#8217;t support alpha channels in AVIF images (see <a href="#avif-bug-alpha-channels">Bug: Alpha channels</a>, below).  So use ImageMagick 7 if possible.</li>
</ul>



<p>Even though all those versions are quite old, <a href="https://wadetregaskis.com/migrated-hosts-out-of-the-subdomain/" data-wpel-link="internal">I actually had to switch web hosts in order to get them</a>, as you&#8217;d be sadly surprised how many WordPress hosting services are running wildly ancient versions of Linux (kernel &amp; distro) and PHP.  Now that I have my own Linux VPS, however, it was quite trivial &#8211; I basically just used <code>apt</code> and <a href="https://www.plesk.com" data-wpel-link="external" target="_blank" rel="external noopener">Plesk</a> to install the latest versions of all the relevant software (which you should be frequently doing anyway, for security patches and bug fixes).  Although sadly that still only gets me ImageMagick 6 (and an outdated GD that doesn&#8217;t support AVIF) &#8211; Plesk PHP builds are pretty far behind, and Ubuntu doesn&#8217;t officially support ImageMagick 7 at all! 😠</p>



<p>Note that you only need <em>one</em> of GD or ImageMagick to have the necessary AVIF support, which is fortunate in case one of the two is difficult to upgrade with your particular system (such as if you use Plesk).</p>



<p>ImageMagick is apparently superior:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>It&#8217;s recommended though to use Imagick lib. It gives way better results in terms of speed, quality and size.</p>
<cite>AVIF Support author (<a href="https://grandplugins.com" data-wpel-link="external" target="_blank" rel="external noopener">GrandPlugins</a>)</cite></blockquote>



<p>I haven&#8217;t tested that claim myself, but you&#8217;ll find it repeated in numerous places online, and not just in the context of AVIF.  It sounds like the common wisdom is that GD just isn&#8217;t very good<sup data-fn="416556d8-6d2c-4a41-9401-e301838a8bb7" class="fn"><a href="#416556d8-6d2c-4a41-9401-e301838a8bb7" id="416556d8-6d2c-4a41-9401-e301838a8bb7-link">3</a></sup>.</p>



<h3 class="wp-block-heading"><s>Bug: AVIF over-compression</s></h3>



<p><s>At time of writing, it has a bug whereby it doesn&#8217;t respect image quality settings, neither the WordPress defaults nor any customisation you might do with other plug-ins.  Instead, it always uses a 30% quality setting for AVIF compression (e.g. for thumbnails) which often results in noticeable visual artefacts from the over-compression.  I&#8217;ve reported this to the developer and 🤞 they address this soon, as it looks like a trivial one-line patch.</s></p>



<p><em>Update</em>: the plug-in author fixed this in version 1.0.5, January 2nd 2024.  As a bonus they also added plug-in settings for specifying the desired image quality and (for GD) &#8216;speed&#8217; (how hard the AVIF encoder tries, trading off compression speed for effectiveness).</p>



<h3 class="wp-block-heading" id="avif-bug-alpha-channels">Bug: Alpha channels</h3>



<p><a href="https://alexwlchan.net/2023/check-for-transparency/" data-wpel-link="external" target="_blank" rel="external noopener">AVIFs with alpha channels don&#8217;t work with ImageMagick 6</a>, at time of writing &#8211; any time WordPress re-encodes the image, such as for thumbnail generation, it removes the alpha channel.  Typically this results in the transparent sections turning black instead.</p>



<p><s>For now, I use WebP when transparency is involved, as I&#8217;m hamstrung by Plesk&#8217;s lack of support for ImageMagick 7 in their PHP packages. 😕</s></p>



<p>I ultimately upgraded to ImageMagick 7 to fix this bug.  See <a href="https://wadetregaskis.com/how-to-install-imagemagick-7-for-wordpress-under-plesk-obsidian-on-ubuntu-22-04/" data-wpel-link="internal">my upgrade guide</a> if you&#8217;re on Ubuntu or using Plesk, or otherwise can&#8217;t seem to get ImageMagick 7 from your normal package management process.</p>



<h3 class="wp-block-heading">CDN incompatibility</h3>



<p>Note that some CDNs <em>still</em> don&#8217;t support AVIF, and there&#8217;s nothing the AVIF Support plug-in can do about that.  You might be using such a CDN without even realising it &#8211; e.g. the popular <a href="https://wordpress.org/plugins/jetpack/" data-wpel-link="external" target="_blank" rel="external noopener">Jetpack</a> plug-in secretly uses the wp.com CDN, so AVIF images don&#8217;t work in some places, such as Jetpack&#8217;s &#8220;Related posts&#8221; feature.  Alas there&#8217;s not much you can do other than not use such broken CDNs &#8211; nor plug-ins that rely on them, like Jetpack.</p>



<p>In general you don&#8217;t want to use such CDNs anyway, because their lack of support for AVIF &#8211; or any other content format &#8211; is usually only a result of them mucking with your images in some way.  Not all CDNs are bad, though &#8211; e.g. <a href="https://www.cloudflare.com/" data-wpel-link="external" target="_blank" rel="external noopener">Cloudflare</a> has no issues with AVIF because they don&#8217;t try to mess with your files.</p>



<h2 class="wp-block-heading" id="enable-media-replace"><a href="https://wordpress.org/plugins/enable-media-replace/" data-wpel-link="external" target="_blank" rel="external noopener">Enable Media Replace</a></h2>



<p>This lets you replace an existing image without breaking any use of it in existing posts, pages, etc.  <em>Including with a different file format</em>.  That latter detail is something most competing image replacement plug-ins do <em>not</em> support [reliably], but it&#8217;s crucial if you want to upgrade any existing images on your website.</p>



<p>It&#8217;s free and <a href="https://github.com/short-pixel-optimizer/enable-media-replace" data-wpel-link="external" target="_blank" rel="external noopener">open source</a>.</p>



<h2 class="wp-block-heading" id="image-regenerate-and-select-crop"><a href="https://iuliacazan.ro/image-regenerate-select-crop/" data-wpel-link="external" target="_blank" rel="external noopener">Image Regenerate &amp; Select Crop</a></h2>



<p>This lets you perform a bunch of helpful little things, including:</p>



<ul class="wp-block-list">
<li>You can define custom image &#8220;thumbnail&#8221; sizes (and modify WordPress&#8217;s defaults), which can be handy for tailoring your images to your actual presentation sizes.  The WordPress defaults are pretty arbitrary and typically don&#8217;t match what your theme desires, let-alone any other plug-ins&#8217; needs (such as for galleries, slideshows, etc).</li>



<li>You can adjust the default image compression quality setting (for each thumbnail size individually).<br><br>Note however that this doesn&#8217;t always apply, e.g. currently the <a href="#avif-support">AVIF Support</a> plug-in has a bug whereby it ignores this setting.  The setting seems to work for the built-in-supported image formats, though, like JPEG and WebP.</li>



<li>You can manually delete or [re]generate thumbnails in each of the possible sizes, for images both individually or en masse.  This can be handy if you change relevant settings (like compression quality, above) or in debugging situations (such as if you&#8217;re experimenting with other image plug-ins and they muck up your thumbnails).</li>
</ul>



<p>It&#8217;s free (albeit with optional paid &#8216;advanced&#8217; features).</p>



<h2 class="wp-block-heading"><a href="https://meowapps.com/wp-retina-2x/" data-wpel-link="external" target="_blank" rel="external noopener">Perfect Images</a></h2>



<p>It&#8217;s baffling that <em>to this day</em> WordPress doesn&#8217;t support modern displays &#8211; and I use &#8216;modern&#8217; in a very liberal sense, since we&#8217;re talking circa 2010 onwards.  That is, displays designed with a high pixel density that use a non-1-to-1 ratio of points to pixels.  i.e. any smartphone or quality computer display in the last decade.</p>



<p>The result is images that render at a quarter (or worse) of full resolution, looking pixelated or soft.</p>



<p>If you care enough about image quality to even consider what image formats or compression settings you&#8217;re using, you absolutely should be using Perfect Images.</p>



<p>Basically it fixes &amp; extends WordPress&#8217;s image support to &#8211; mostly automagically and invisibly &#8211; just work with full-resolution images.  It&#8217;s particularly noticeable and essential for things like screenshots, or any images containing text, as those are especially obvious if rendered incorrectly.</p>



<p>Its core functionality is free &#8211; and you can get a fair way with just the free version &#8211; but <a href="https://meowapps.com/products/wp-retina-2x-pro/" data-wpel-link="external" target="_blank" rel="external noopener">the pro version</a> is worth it, even if a bit pricey.</p>



<h3 class="wp-block-heading">Usage tips</h3>



<h4 class="wp-block-heading">Fix WordPress&#8217;s image size limit</h4>



<p>Make sure to check the &#8220;Image Threshold … Disable&#8221; checkbox in the General settings.  This fixes a truly obnoxious WordPress bug whereby it mangles uploads of large images.</p>



<h4 class="wp-block-heading">Upload &#8216;Retina&#8217; images specially</h4>



<p>For images which are explicitly &#8220;2x&#8221; &#8211; such as screenshots &#8211; it&#8217;s important to upload them &#8216;manually&#8217; using Media &gt; Add New Media File, as opposed to e.g. just drag-and-dropping them into a post.  The plug-in adds an &#8220;Upload New Retina Image&#8221; option to the dedicated upload page, which registers the uploaded image with WordPress at technically a quarter of its actual size.  That basically tricks WordPress into using the <em>correct</em> dimensions for the image &#8211; otherwise, WordPress mistakes the <em>pixel</em> dimensions for the <em>point</em> dimensions, and will naively try to display the image at four times its natural size.</p>



<p>Don&#8217;t worry, Perfect Images preserves the real, full-resolution version as the &#8220;2x&#8221; version of the upload, and will display that instead to your visitors.</p>



<p>This particular upload method is the <em>only</em> way to get images to render correctly in all cases.  In some places &#8211; e.g. embedded in posts &#8211; you can manually specify the correct image dimensions, but that&#8217;s both tedious and error-prone, and not possible in all uses.</p>



<p>The only caveat is that those images will look ugly and blurry in the post &amp; page editors.  Don&#8217;t worry, they&#8217;ll render correctly in the actual published (and preview) version of your posts &amp; pages.</p>



<p>For images which don&#8217;t have an intrinsic pixel density &#8211; such as photos &#8211; you typically don&#8217;t have to worry about this, as you&#8217;ll usually just let them render at whatever size the viewport &amp; layout permit, up to their natural full size.</p>



<h3 class="wp-block-heading">Limitations</h3>



<p>The core functionality works reliably in my experience (over <em>many</em> years now), but some of the peripheral features are broken or notably buggy:</p>



<ul class="wp-block-list">
<li>Image replacement will <em>not</em> work correctly if the file format changes &#8211; and it won&#8217;t even recognise this case and prevent it, instead leaving you with broken images.  Use <a href="#enable-media-replace">Enable Media Replace</a> for this instead.</li>



<li>Batch regeneration of thumbnails doesn&#8217;t work reliably &#8211; it will silently fail midway if an error occurs, such as it encountering a video file.  Use <a href="#image-regenerate-and-select-crop">Image Regenerate &amp; Select Crop</a> for this instead.</li>



<li>Custom Image Sizes don&#8217;t work correctly &#8211; they <em>always</em> force cropping of the image (&#8220;resize to fill&#8221;), rather than resizing to fit.  This is almost never what you want.  Use <a href="#image-regenerate-and-select-crop">Image Regenerate &amp; Select Crop</a> for this instead.</li>



<li>For the Pro version [only], auto-update doesn&#8217;t work.  You have to periodically check the website for new versions.</li>



<li>It sometimes reports &#8220;issues&#8221; for images, in its special dashboard under the Media section, when there aren&#8217;t any.  This is of course pretty insignificant &#8211; you can just ignore it &#8211; although it might hide any <em>actual</em> issues if they occur.  I did find a way to clear these bogus issues, but it involved manually deleting all thumbnails for all my images and regenerating them, which was a bit of an ordeal due to other, aforementioned bugs.  So I don&#8217;t recommend mucking with it.</li>
</ul>


<ol class="wp-block-footnotes"><li id="ce19f9a1-4b3d-427c-b205-ec8684b1e5ae">Note that <a href="https://nokiatech.github.io/heif/technical.html" data-wpel-link="external" target="_blank" rel="external noopener">HEIF <em>does</em> support lossless encoding</a> but support for this amongst actual encoding applications is poor to non-existent.  As such it&#8217;s generally not a suitable replacement for PNG in practice. <a href="#ce19f9a1-4b3d-427c-b205-ec8684b1e5ae-link" aria-label="Jump to footnote reference 1">↩︎</a></li><li id="42530c0c-bed1-4a7a-bff8-2c27f0a337bd">As the matrix shows, no version of <a href="https://en.wikipedia.org/wiki/Internet_Explorer" data-wpel-link="external" target="_blank" rel="external noopener">Internet Explorer</a> supports WebP.  But &#8211; though there apparently <em>is</em> some non-trivial number of people still using it &#8211; I don&#8217;t consider Internet Explorer a browser of concern anymore, given it has an official and straightforward successor in <a href="https://en.wikipedia.org/wiki/Microsoft_Edge" data-wpel-link="external" target="_blank" rel="external noopener">Edge</a>, and <a href="https://en.wikipedia.org/wiki/Internet_Explorer#Internet_Explorer_11" data-wpel-link="external" target="_blank" rel="external noopener">its last version was released <em>a decade ago</em> in 2013</a>. <a href="#42530c0c-bed1-4a7a-bff8-2c27f0a337bd-link" aria-label="Jump to footnote reference 2">↩︎</a></li><li id="416556d8-6d2c-4a41-9401-e301838a8bb7">Although for image compression, specifically, this is odd, since there&#8217;s only a couple of underlying libraries they could possibly be using, and while <a href="https://github.com/strukturag/libheif/wiki/AVIF-Encoder-Benchmark" data-wpel-link="external" target="_blank" rel="external noopener">they do vary significantly in speed</a> they should produce very similar outputs. <a href="#416556d8-6d2c-4a41-9401-e301838a8bb7-link" aria-label="Jump to footnote reference 3">↩︎</a></li></ol>]]></content:encoded>
					
					<wfw:commentRss>https://wadetregaskis.com/image-workflow-for-wordpress/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			<media:content url="https://wadetregaskis.com/wp-content/uploads/2023/12/Image-Tool.webp" medium="image" />
<post-id xmlns="com-wordpress:feed-additions:1">7146</post-id>	</item>
		<item>
		<title>Swift code syntax highlighting in WordPress</title>
		<link>https://wadetregaskis.com/swift-code-syntax-highlighting-in-wordpress/</link>
					<comments>https://wadetregaskis.com/swift-code-syntax-highlighting-in-wordpress/#comments</comments>
		
		<dc:creator><![CDATA[]]></dc:creator>
		<pubDate>Sat, 30 Dec 2023 02:34:43 +0000</pubDate>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Meta]]></category>
		<category><![CDATA[Reviews]]></category>
		<category><![CDATA[Code Block Pro]]></category>
		<category><![CDATA[Code Syntax Block]]></category>
		<category><![CDATA[CodeColorer]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Dark mode]]></category>
		<category><![CDATA[Dracula Dark Mode]]></category>
		<category><![CDATA[Enlighter]]></category>
		<category><![CDATA[EnlighterJS]]></category>
		<category><![CDATA[GeSHi]]></category>
		<category><![CDATA[highlight.js]]></category>
		<category><![CDATA[highlight.php]]></category>
		<category><![CDATA[Highlighting Code Block]]></category>
		<category><![CDATA[Prism.js]]></category>
		<category><![CDATA[Prismatic]]></category>
		<category><![CDATA[Shiki]]></category>
		<category><![CDATA[syntax highlighting]]></category>
		<category><![CDATA[Syntax-highlighting Code Block (with Server-side Rendering)]]></category>
		<category><![CDATA[SyntaxHighlighter Evolved]]></category>
		<category><![CDATA[Tested]]></category>
		<category><![CDATA[TextMate]]></category>
		<category><![CDATA[Urvanov Syntax Highlighter]]></category>
		<category><![CDATA[Visual Studio Code]]></category>
		<category><![CDATA[WP Dark Mode]]></category>
		<category><![CDATA[Xcode]]></category>
		<guid isPermaLink="false">https://blog.wadetregaskis.com/?p=5561</guid>

					<description><![CDATA[The built-in &#8220;code&#8221; block for WordPress (the CMS I use for this site) is virtually useless &#8211; it&#8217;s just a &#60;pre&#62; block, essentially. The appearance may vary depending on WordPress theme, but will virtually always be bland. In fact, it&#8217;s not even guaranteed to use a monospaced font &#8211; the example I&#8217;ve shown here is&#8230; <a class="read-more-link" href="https://wadetregaskis.com/swift-code-syntax-highlighting-in-wordpress/" data-wpel-link="internal">Read more</a>]]></description>
										<content:encoded><![CDATA[



<div class="alignnormal"><div id="metaslider-id-6572" style="max-width: 611px;" class="ml-slider-3-107-0 metaslider metaslider-flex metaslider-6572 ml-slider ms-theme-default nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden" role="region" aria-label="Syntax highlighting: WordPress default" data-height="1158" data-width="611">
    <div id="metaslider_container_6572">
        <div id="metaslider_6572" class="flexslider">
            <ul class='slides'>
                <li style="display: block; width: 100%;" class="slide-6575 ms-image " aria-roledescription="slide" data-date="2023-12-12 11:07:27" data-filename="WordPress-default-Light.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="1222" height="2316" src="https://wadetregaskis.com/wp-content/uploads/2023/12/WordPress-default-Light.webp" class="slider-6572 slide-6575 msDefaultImage" alt="" rel="" title="WordPress default (Light)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/WordPress-default-Light.webp 1222w, https://wadetregaskis.com/wp-content/uploads/2023/12/WordPress-default-Light-135x256.webp 135w, https://wadetregaskis.com/wp-content/uploads/2023/12/WordPress-default-Light-270x512@2x.webp 540w, https://wadetregaskis.com/wp-content/uploads/2023/12/WordPress-default-Light-1081x2048.webp 1081w, https://wadetregaskis.com/wp-content/uploads/2023/12/WordPress-default-Light-270x512.webp 270w, https://wadetregaskis.com/wp-content/uploads/2023/12/WordPress-default-Light-540x1024@2x.webp 1080w" sizes="auto, (max-width: 1222px) 100vw, 1222px" /><div class="caption-wrap"><div class="caption">Light mode</div></div></li>
                <li style="display: none; width: 100%;" class="slide-6576 ms-image " aria-roledescription="slide" data-date="2023-12-12 11:07:28" data-filename="WordPress-default-Dark.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="1222" height="2316" src="https://wadetregaskis.com/wp-content/uploads/2023/12/WordPress-default-Dark.webp" class="slider-6572 slide-6576 msDefaultImage" alt="" rel="" title="WordPress default (Dark)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/WordPress-default-Dark.webp 1222w, https://wadetregaskis.com/wp-content/uploads/2023/12/WordPress-default-Dark-135x256.webp 135w, https://wadetregaskis.com/wp-content/uploads/2023/12/WordPress-default-Dark-270x512@2x.webp 540w, https://wadetregaskis.com/wp-content/uploads/2023/12/WordPress-default-Dark-1081x2048.webp 1081w, https://wadetregaskis.com/wp-content/uploads/2023/12/WordPress-default-Dark-270x512.webp 270w, https://wadetregaskis.com/wp-content/uploads/2023/12/WordPress-default-Dark-540x1024@2x.webp 1080w" sizes="auto, (max-width: 1222px) 100vw, 1222px" /><div class="caption-wrap"><div class="caption">Dark mode</div></div></li>
            </ul>
        </div>
        
    </div>
</div></div>



<p>The built-in &#8220;code&#8221; block for <a href="https://wordpress.org" data-wpel-link="external" target="_blank" rel="external noopener">WordPress</a> (the <a href="https://en.wikipedia.org/wiki/Content_management_system" data-wpel-link="external" target="_blank" rel="external noopener">CMS</a> I use for this site) is virtually useless &#8211; it&#8217;s just a &lt;pre&gt; block, essentially.</p>



<p>The appearance may vary depending on WordPress theme, but will virtually always be bland.</p>



<p>In fact, it&#8217;s not even guaranteed to use a monospaced font &#8211; the example I&#8217;ve shown here is what you&#8217;ll <em>probably</em> get with any given WordPress theme, but it&#8217;s not actually the default for the theme I use (<a href="https://generatepress.com" data-wpel-link="external" target="_blank" rel="external noopener">GeneratePress</a>) due to <a href="https://github.com/tomusborne/generatepress/issues/395" data-wpel-link="external" target="_blank" rel="external noopener">a known bug in GeneratePress</a> (which the theme authors outright refuse to fix!).</p>



<p class="wp-container-content-9cfa9a5a">In any case, you have to use <a href="https://wordpress.org/plugins/search/code+syntax+highlighter/" data-wpel-link="external" target="_blank" rel="external noopener">WordPress plug-ins</a> to extend or replace it with something that actually looks in any way decent.</p>



<p class="wp-container-content-9cfa9a5a">Unfortunately, Swift is a complicated language, even just at the &#8220;superficial&#8221; level of syntax highlighting.  And most generally-popular syntax highlighting tools are both:</p>



<ol class="wp-block-list">
<li>Focused on languages like JavaScript and HTML, not Swift.</li>



<li>Written in JavaScript or Ruby, with no access to standard tooling like the <a href="https://github.com/apple/sourcekit-lsp" data-wpel-link="external" target="_blank" rel="external noopener">Swift Language Server Protocol</a>.</li>
</ol>



<p>Since I&#8217;m using WordPress for this site, Ruby&#8217;s not a good option (and I didn&#8217;t find any relevant WordPress plug-ins which rely on it, anyway).  Hypothetically I could add a Ruby environment to my server and do static generation through it, but, ugh.  It&#8217;s annoying enough dealing with JavaScript and PHP.  If you&#8217;re going to go to that much trouble, you&#8217;d probably be better off actually using Swift (e.g. <a href="https://github.com/apple/swift-syntax" data-wpel-link="external" target="_blank" rel="external noopener">SwiftSyntax</a>).  And while I&#8217;d welcome a WordPress plug-in which does exactly that, alas no such plug-in exists today.</p>



<p>So, I spent <em>way</em> too much of my time trying out a <em>bunch</em> of the available WordPress plug-ins, and now I shall report the results so others don&#8217;t have to suffer [as much].</p>



<p>I&#8217;ve presented previews for both light and dark modes (but my apologies to dark-mode viewers that all the samples default to light mode &#8211; an unfortunate limitation of my CMS).</p>



<h1 class="wp-block-heading">Baseline: Xcode</h1>



<div class="alignnormal"><div id="metaslider-id-6568" style="max-width: 492px;" class="ml-slider-3-107-0 metaslider metaslider-flex metaslider-6568 ml-slider ms-theme-default nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden" role="region" aria-label="Syntax highlighting: Xcode [Default]" data-height="1100" data-width="492">
    <div id="metaslider_container_6568">
        <div id="metaslider_6568" class="flexslider">
            <ul class='slides'>
                <li style="display: block; width: 100%;" class="slide-6570 ms-image " aria-roledescription="slide" data-date="2023-12-12 10:47:45" data-filename="Xcode-Default-Light.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="984" height="2200" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Xcode-Default-Light.webp" class="slider-6568 slide-6570 msDefaultImage" alt="" rel="" title="Xcode [Default] (Light)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Xcode-Default-Light.webp 984w, https://wadetregaskis.com/wp-content/uploads/2023/12/Xcode-Default-Light-115x256.webp 115w, https://wadetregaskis.com/wp-content/uploads/2023/12/Xcode-Default-Light-229x512@2x.webp 458w, https://wadetregaskis.com/wp-content/uploads/2023/12/Xcode-Default-Light-916x2048.webp 916w, https://wadetregaskis.com/wp-content/uploads/2023/12/Xcode-Default-Light-229x512.webp 229w, https://wadetregaskis.com/wp-content/uploads/2023/12/Xcode-Default-Light-115x256@2x.webp 230w" sizes="auto, (max-width: 984px) 100vw, 984px" /><div class="caption-wrap"><div class="caption">Light mode</div></div></li>
                <li style="display: none; width: 100%;" class="slide-6569 ms-image " aria-roledescription="slide" data-date="2023-12-12 10:47:45" data-filename="Xcode-Default-Dark.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="984" height="2200" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Xcode-Default-Dark.webp" class="slider-6568 slide-6569 msDefaultImage" alt="" rel="" title="Xcode [Default] (Dark)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Xcode-Default-Dark.webp 984w, https://wadetregaskis.com/wp-content/uploads/2023/12/Xcode-Default-Dark-115x256.webp 115w, https://wadetregaskis.com/wp-content/uploads/2023/12/Xcode-Default-Dark-229x512@2x.webp 458w, https://wadetregaskis.com/wp-content/uploads/2023/12/Xcode-Default-Dark-916x2048.webp 916w, https://wadetregaskis.com/wp-content/uploads/2023/12/Xcode-Default-Dark-229x512.webp 229w, https://wadetregaskis.com/wp-content/uploads/2023/12/Xcode-Default-Dark-115x256@2x.webp 230w" sizes="auto, (max-width: 984px) 100vw, 984px" /><div class="caption-wrap"><div class="caption">Dark mode</div></div></li>
            </ul>
        </div>
        
    </div>
</div></div>



<p>Syntax highlighting theming is a very subjective and somewhat personal preference.  I really must stress this, as something to keep in mind as I critique these plug-ins based on <em>my</em> preference, which is pretty close to Xcode&#8217;s default theme.</p>



<p>I&#8217;ve tried to focus mostly on how well the plug-ins understand Swift syntax &amp; grammar and what functionality they offer broadly, rather than which ones look prettier out of the box.  Most have at least some degree of custom theming support, or at least permit unofficial theming through straightforward CSS overrides.</p>



<p>It is unsurprising that Xcode does by <em>far</em> the best job of understanding and correctly syntax-highlighting Swift code, of anything tested here.  It has the advantage of being able to actually compile and analyse the code with full context &#8211; the example shown here has supporting type and function definitions &#8220;off-screen&#8221; &#8211; which WordPress plug-ins do not<sup data-fn="f5cd2d93-b8e5-4773-8838-26add7d33f48" class="fn"><a href="#f5cd2d93-b8e5-4773-8838-26add7d33f48" id="f5cd2d93-b8e5-4773-8838-26add7d33f48-link">1</a></sup>.  While I set out on this exploration hoping to find something effectively as good as Xcode, I wasn&#8217;t really expecting to (and spoiler: I did not).</p>



<p>Allow me to call out a particular few things Xcode does right, that (as you&#8217;ll see) few if any of the WordPress plug-ins do:</p>



<ul class="wp-block-list">
<li>In short, it supports <em>all</em> Swift syntax.  It correctly identifies all the keywords (<em>and</em> things that are <em>not</em> keywords but happen to be the same word, such as static properties called <code>default</code> as in the example code).</li>



<li>It utilises not just colour but font and font weight.  This permits it to effectively delineate things without having to use an excessive variety of hues.<br><br>Some might finds its results comparatively bland with the default theme as shown here, in light mode especially, but it has other themes for those that want a more hue-centric approach, and supports a very good degree of theme customisation.<br><br>The default theme doesn&#8217;t &#8220;demo&#8221; well (in light mode), in the same way that colour-accurate TVs look rather bland and unattractive in the showroom but are actually great in real-world use in your home.</li>



<li>Even though it uses multiple font weights, it still preserves correct letter spacing.</li>



<li>It understands DocC&#8217;s limited Markdown-like markup within documentation comments (and can even render them as properly styled text, although that&#8217;s not shown here).</li>
</ul>



<p>I&#8217;ll also call out one thing which &#8211; in my opinion &#8211; it gets <em>wrong</em>, which is essentially not recognising custom type names.  It renders them as plain text &#8211; no highlighting at all &#8211; yet gives special treatment to &#8220;built-in&#8221; types (from the Swift standard library) like <code>String</code>.  It&#8217;s fine if it wants to distinguish between those two sets of type names, but it should use some kind of highlighting for <em>both</em> of them.  Many of the WordPress plug-ins actually do a better job in this respect.</p>



<h1 class="wp-block-heading">Common limitation: no Light/Dark mode support</h1>



<p>One thing that <em>none</em> of these plug-ins do, that you would think they could and reasonably should, is explicitly support light / dark mode &#8211; even though most include both light and dark themes (some plug-ins even include light and dark variations of the <em>same</em> theme &#8211; so close!).</p>



<p>Instead, you have to pick just one theme.  Furthermore, if you want proper light <em>and</em> dark mode support you have to pick a light theme specifically, to match WordPress&#8217;s default mode of light.  This limits your control over the appearance in dark mode &#8211; and may make it difficult for you to find a theme which suits your aesthetic preferences in <em>both</em> modes.</p>



<p>WordPress itself doesn&#8217;t support light/dark mode &#8211; you have to<sup data-fn="395a26f7-0a74-4647-ae97-e770481a032a" class="fn"><a href="#395a26f7-0a74-4647-ae97-e770481a032a" id="395a26f7-0a74-4647-ae97-e770481a032a-link">2</a></sup> use 3rd-party plug-ins.  Depending on which one you use, you might get viable automatic switching anyway.  The several that I experimented with were all able to make my theme adapt actually quite well.</p>



<p>I initially used <a href="https://wordpress.org/plugins/wp-dark-mode/" data-wpel-link="external" target="_blank" rel="external noopener">WP Dark Mode</a>, but discovered it was buggy in that it would load pages in light mode first and only after the initial render would it switch them to dark, making browsing my site in dark mode very uncomfortable.  It also didn&#8217;t work properly with <a href="#syntaxhighlighter-evolved" data-type="internal" data-id="#syntaxhighlighter-evolved">SyntaxHighlighter Evolved</a>.  I consequently switched to <a href="https://wordpress.org/plugins/dracula-dark-mode/" data-wpel-link="external" target="_blank" rel="external noopener">Dracula Dark Mode</a> which is a <em>very</em> similar plug-in but doesn&#8217;t have those bugs.</p>



<p>Note that most of the dark-mode screenshots shown here were taken while using WP Dark Mode.  There may be slight differences in colours with Dracula Dark Mode (or some other dark mode plug-in), but in my brief experimentation the results are virtually indistinguishable.</p>



<h1 class="wp-block-heading">The contestants</h1>



<h2 class="wp-block-heading" id="code-block-pro"><a href="https://code-block-pro.com" data-wpel-link="external" target="_blank" rel="external noopener">Code Block Pro</a></h2>



<div class="alignnormal"><div id="metaslider-id-6687" style="max-width: 572px;" class="ml-slider-3-107-0 metaslider metaslider-flex metaslider-6687 ml-slider ms-theme-default nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden" role="region" aria-label="Syntax highlighting: Code Block Pro [Light Plus]" data-height="1284" data-width="572">
    <div id="metaslider_container_6687">
        <div id="metaslider_6687" class="flexslider">
            <ul class='slides'>
                <li style="display: block; width: 100%;" class="slide-6690 ms-image " aria-roledescription="slide" data-date="2023-12-13 20:22:37" data-filename="Code-Block-Pro-Light-Plus-Light.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="1144" height="2568" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-Light.webp" class="slider-6687 slide-6690 msDefaultImage" alt="" rel="" title="Code Block Pro [Light Plus] (Light)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-Light.webp 1144w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-Light-114x256.webp 114w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-Light-228x512@2x.webp 456w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-Light-912x2048.webp 912w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-Light-228x512.webp 228w" sizes="auto, (max-width: 1144px) 100vw, 1144px" /><div class="caption-wrap"><div class="caption">Light mode</div></div></li>
                <li style="display: none; width: 100%;" class="slide-6691 ms-image " aria-roledescription="slide" data-date="2023-12-13 20:22:37" data-filename="Code-Block-Pro-Light-Plus-Dark.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="1144" height="2568" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-Dark.webp" class="slider-6687 slide-6691 msDefaultImage" alt="" rel="" title="Code Block Pro [Light Plus] (Dark)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-Dark.webp 1144w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-Dark-114x256.webp 114w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-Dark-228x512@2x.webp 456w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-Dark-912x2048.webp 912w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-Dark-228x512.webp 228w" sizes="auto, (max-width: 1144px) 100vw, 1144px" /><div class="caption-wrap"><div class="caption">Dark mode</div></div></li>
            </ul>
        </div>
        
    </div>
</div></div>



<p>This advertises itself as using the syntax highlighting engine from <a href="https://code.visualstudio.com" data-wpel-link="external" target="_blank" rel="external noopener">Visual Studio Code</a>, but that&#8217;s actually misleading &#8211; it uses <a href="https://github.com/shikijs/shiki" data-wpel-link="external" target="_blank" rel="external noopener">Shiki</a>, which is really its own engine albeit one that utilises the same TextMate-inspired grammar definitions and themes as does Visual Studio Code.</p>



<p>It&#8217;s <a href="https://github.com/KevinBatdorf/code-block-pro" data-wpel-link="external" target="_blank" rel="external noopener">open source</a> and free for the most part &#8211; for a token $12 you can support the author and obtain a couple of dozen extra themes, adding to the two dozen or so that it includes by default.</p>



<h3 class="wp-block-heading">Performance</h3>



<p>If you&#8217;re familiar with Visual Studio Code for Swift development, then you basically already know how it performs, as the results are (in my testing) identical.</p>



<p>That&#8217;s only <em>mostly</em> a compliment, though.  This plug-in, like Visual Studio Code, doesn&#8217;t <em>really</em> understand Swift, it merely does a relatively good job of faking it.</p>



<p>Unlike every other plug-in tested, where the grammar parsing is completely independent of the theming, the performance of this plug-in <em>does</em> vary between themes.  Thus, some themes might have colours you hate yet be the only ones that actually identify Swift keywords correctly, while others are the reverse.  This is demonstrated in the example shown here &#8211; the <em>Light Plus</em> theme &#8211; where the colours are the least ugly of the themes available but it doesn&#8217;t recognise some basic Swift syntax, like protocol conformances, which <em>is</em> recognised in other &#8211; albeit uglier &#8211; themes.</p>



<p>But, in <em>general</em>, it:</p>



<ul class="wp-block-list">
<li>Actually understands the difference between function parameter labels, parameter names, and parameter types.</li>



<li>Tends not to recognise custom type names, only the Swift stdlib &amp; Foundation ones (e.g. notice it doesn&#8217;t recognise <code>Floor</code> but does recognise <code>String</code>).  This is somewhat common behaviour amongst the plug-ins tested (and Xcode itself).</li>



<li>Doesn&#8217;t recognise some important keywords, such as <code>async</code> and <code>some</code>.<br><br>As it happens, this is because the Swift grammar file it uses is quite a few years old and seems like it might be largely abandoned (other than sporadic community updates such as <a href="https://forums.swift.org/t/updated-syntax-highlighting-in-github-vs-code/68972" data-wpel-link="external" target="_blank" rel="external noopener">this</a> which might or might not be incorporated by this plug-in).  This is the same grammar file that Visual Studio Code uses, making it doubly-surprising, but I guess it says a lot about the level of interest the Visual Studio Code community has in Swift.</li>



<li>Is not easily fooled by the use of ambiguous names, e.g. the <code>default</code> static property of <code>HomeItem</code> that&#8217;s often mistaken for the <code>default</code> keyword by other plug-ins.</li>
</ul>



<h3 class="wp-block-heading">Pros</h3>



<ul class="wp-block-list">
<li>Includes the ability to highlight an arbitrary set of lines by blurring out all the others (but readers can mouse over the code block to unblur everything, if they want to see the full context of what you&#8217;re highlighting).  This particular approach &#8211; blurring rather than just using a different background colour &#8211; is unique amongst all the plug-ins I found, and aesthetically far superior.  Most of the other plug-ins don&#8217;t even have a way to highlight or hide certain lines.</li>



<li>Uses server-side rendering with CSS inlined into the HTML, so code is highlighted right from page load without delays or visual glitches.<br><br>Some other plug-ins tested here do server-side syntax analysis too, but to actually effect styling they use class tagging of HTML <code>span</code>s with CSS, which can mean rendering glitches if the CSS takes a while to load and the browser renders the code without it in the interim.  Code Block Pro avoids that (and might also play better with other styling plug-ins or modifications, such as dark mode plug-ins).</li>



<li>Has a <a href="https://code-block-pro.com/themes?theme=andromeda&amp;lang=swift" data-wpel-link="external" target="_blank" rel="external noopener">live playground</a> so you can easily test it out (although that playground is hard-coded to use the Fira Code font, which is only one of a number of open-source font options it provides).</li>
</ul>



<h3 class="wp-block-heading">Cons</h3>



<ul class="wp-block-list">
<li>No global settings &#8211; if you decide to change <em>any</em> settings, such as the theme, at any point, you have to manually find and adjust every existing code snippet manually.<br><br>This might be considered a positive by some users, where they want existing content to remain as-is.  However, some plug-ins offer both a global setting <em>and</em> the ability to override that on a per-case basis, providing more flexibility.</li>



<li>The provided themes &#8211; even with the paid expansion pack &#8211; are predominately intended only for dark mode, and most of the light mode ones are pastel.  So if you want a clean light mode theme, as I do, you have only about three options with this plug-in.<br><br>Furthermore, the performance varies between themes, as &#8211; unlike every other plug-in tested here &#8211; the themes are in essence tied into the parsing.<br><br>None of the provided themes really do Swift justice compared to how well they work for other languages.  Especially within the limited selection of light-mode themes, there&#8217;s precious few that don&#8217;t make obvious mistakes (like conflating the <code>some</code> keyword with operators, or being confounded by generics syntax).</li>



<li>Theme customisation options are extremely limited, not just officially but even unofficially with custom CSS.  Although, <a href="https://github.com/KevinBatdorf/code-block-pro/issues/270#issuecomment-1820896240" data-wpel-link="external" target="_blank" rel="external noopener">the author seems receptive to theme suggestions</a> &#8211; to add to the <em>paid</em> expansion pack &#8211; if you find something you like in the <a href="https://marketplace.visualstudio.com/search?target=VSCode&amp;category=Themes&amp;sortBy=Installs" data-wpel-link="external" target="_blank" rel="external noopener">Visual Studio Code Marketplace</a>.
<ul class="wp-block-list">
<li>The only way it officially allows any custom theming is with an unusual mechanism documented only in <a href="https://github.com/KevinBatdorf/code-block-pro/discussions/168" data-wpel-link="external" target="_blank" rel="external noopener">a tangential GitHub discussion</a>: you select the theme called &#8220;Use CSS Variables&#8221;, which is a &#8216;theme&#8217; that merely specifies <code>var(--xyz)</code> values for the <code>color</code> CSS property.  You&#8217;re then expected to specify values for those CSS variables in some suitable stylesheet (which the plug-in does <em>not</em> facilitate).<br><br>This custom theming functionality is only available in the paid version.</li>



<li>It only officially supports adjusting the colours &#8211; you nominally don&#8217;t have the ability to adjust font families, sizes, weights, or styles.<br><br>It is <em>possible</em> to match each type of element, but it&#8217;s pretty clumsy and fragile, because…</li>



<li>As mentioned under <em>Pros</em>, it inlines the style information directly into the HTML <code>span</code> tags, as simple <code>color</code> style attributes.  While that&#8217;s good for avoiding rendering glitches, the downsides are that:
<ul class="wp-block-list">
<li>It produces more verbose HTML than if it just used a short class name on the <code>span</code>s (as all the other plug-ins do), which can hurt page load times.</li>



<li>It&#8217;s more difficult to customise the styling with CSS, since you have to match on the colours &#8211; using CSS attribute queries like <code>span[style*=#xxyyzz]</code> &#8211; which is not just awkward but can be impossible to do precisely for multiple distinct grammar elements depending on the base theme used.</li>



<li>It optimises the HTML by merging (server-side) <code>span</code> elements with the same style information.  That&#8217;s great for reducing page size and load times, but if the base theme doesn&#8217;t already <em>visually</em> distinguish between two distinct grammar elements, it&#8217;s impossible to distinguish them through custom CSS.</li>
</ul>
</li>
</ul>
</li>



<li>Custom themes don&#8217;t render in the post editor &#8211; you just get plain pre-formatted text.  (built-in themes work fine in the editor)</li>



<li>Uses a custom Gutenberg block type, rather than just extending the standard Code block.  So you can&#8217;t just upgrade your whole existing site &#8211; you have to manually go through and find every existing Code block, and manually migrate each one.<br><br>Inversely it&#8217;ll also be more difficult to migrate away from, if you choose to do that some day, as you&#8217;ll likely have to repeat that whole process no matter what replacement plug-in you choose.</li>



<li>If you enable the &#8216;Copy&#8217; button for the convenience of your readers, it includes a duplicate copy of the code in a hidden <code>span</code> (as do at least some of the other plug-ins tested, although I didn&#8217;t always call it out here).</li>
</ul>



<p>So in a nutshell, if you&#8217;re completely happy with its built-in theme options, then this is one of your better options.  But if you want theme customisation, it becomes <em>worse</em> than many of the other plug-ins, sadly.</p>



<h2 class="wp-block-heading"><a href="https://wordpress.org/plugins/codecolorer/" data-wpel-link="external" target="_blank" rel="external noopener">CodeColorer</a></h2>



<div class="alignnormal"><div id="metaslider-id-7047" style="max-width: 435px;" class="ml-slider-3-107-0 metaslider metaslider-flex metaslider-7047 ml-slider ms-theme-default nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden" role="region" aria-label="Syntax highlighting: CodeColorer [Slush &amp; Poppies]" data-height="300" data-width="435">
    <div id="metaslider_container_7047">
        <div id="metaslider_7047" class="flexslider">
            <ul class='slides'>
                <li style="display: block; width: 100%;" class="slide-7053 ms-image " aria-roledescription="slide" data-date="2023-12-29 10:32:25" data-filename="CodeColorer-Slush-Poppies-Light.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="870" height="600" src="https://wadetregaskis.com/wp-content/uploads/2023/12/CodeColorer-Slush-Poppies-Light.webp" class="slider-7047 slide-7053 msDefaultImage" alt="" rel="" title="CodeColorer [Slush &amp; Poppies] (Light)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/CodeColorer-Slush-Poppies-Light.webp 870w, https://wadetregaskis.com/wp-content/uploads/2023/12/CodeColorer-Slush-Poppies-Light-256x177.webp 256w, https://wadetregaskis.com/wp-content/uploads/2023/12/CodeColorer-Slush-Poppies-Light-512x353.webp 512w" sizes="auto, (max-width: 870px) 100vw, 870px" /><div class="caption-wrap"><div class="caption">Light mode</div></div></li>
                <li style="display: none; width: 100%;" class="slide-7052 ms-image " aria-roledescription="slide" data-date="2023-12-29 10:32:24" data-filename="CodeColorer-Slush-Poppies-Dark.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="870" height="600" src="https://wadetregaskis.com/wp-content/uploads/2023/12/CodeColorer-Slush-Poppies-Dark.webp" class="slider-7047 slide-7052 msDefaultImage" alt="" rel="" title="CodeColorer [Slush &amp; Poppies] (Dark)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/CodeColorer-Slush-Poppies-Dark.webp 870w, https://wadetregaskis.com/wp-content/uploads/2023/12/CodeColorer-Slush-Poppies-Dark-256x177.webp 256w, https://wadetregaskis.com/wp-content/uploads/2023/12/CodeColorer-Slush-Poppies-Dark-512x353.webp 512w" sizes="auto, (max-width: 870px) 100vw, 870px" /><div class="caption-wrap"><div class="caption">Dark mode</div></div></li>
            </ul>
        </div>
        
    </div>
</div></div>



<p>A <em>very</em> old &#8211; though nominally still maintained &#8211; plug-in uniquely based on GeSHi.</p>



<p>It&#8217;s <a href="https://github.com/kpumuk/codecolorer/" data-wpel-link="external" target="_blank" rel="external noopener">open source</a> and free (as is the <a href="https://github.com/GeSHi/geshi-1.0" data-wpel-link="external" target="_blank" rel="external noopener">GeSHi</a> engine underneath it).</p>



<p>Neither the plug-in itself nor the GeSHi engine have seen a lot of activity in recent years (and confusingly <a href="http://qbnz.com/highlighter/" data-wpel-link="external" target="_blank" rel="external noopener">the old GeSHi webpage</a> is still up as is <a href="https://sourceforge.net/projects/geshi/" data-wpel-link="external" target="_blank" rel="external noopener">the early GeSHi page on SourceForge</a>, creating an even worse first impression).  Both predate the [public] existence of Swift entirely.</p>



<p>To be honest I&#8217;m including it here only for completeness.  It basically doesn&#8217;t work &#8211; especially for Swift &#8211; and shouldn&#8217;t actually be considered.  It seems intended <em>solely</em> for use via shortcodes &#8211; even though it does take over all existing <code>&lt;code&gt;</code> blocks &#8211; which I didn&#8217;t test as the use of shortcodes in WordPress is archaic, and poorly supported in the modern (Gutenberg) editor.  <a href="https://wordpress.com/support/wordpress-editor/blocks/shortcode-block/" data-wpel-link="external" target="_blank" rel="external noopener">They <em>seem</em> to still be officially supported</a>, and not formally deprecated, but I think introducing any new reliance on them at this point is foolish.</p>



<h3 class="wp-block-heading">Performance</h3>



<p>So, yeah… no syntax highlighting at all.  It&#8217;s not apparent to me if this is a failure specific to Swift or if the plug-in in general just doesn&#8217;t work.  It does offer a [non-live] preview in its settings, which does work for its example snippet of JavaScript.</p>



<p>It also (by default) forces the code into a tiny box, although you can fix this through its settings.</p>



<p>There&#8217;s no per-use customisation since it just takes over any existing <code>&lt;code&gt;</code> blocks, and there&#8217;s very few global settings &#8211; including an absence of any setting for a default language.</p>



<p>I won&#8217;t bother trying to enumerate its specific pros and cons &#8211; it&#8217;s clearly not a viable contender.</p>



<h2 class="wp-block-heading" id="code-syntax-block"><a href="https://wordpress.org/plugins/code-syntax-block/" data-wpel-link="external" target="_blank" rel="external noopener">Code Syntax Block</a></h2>



<div class="alignnormal"><div id="metaslider-id-6738" style="max-width: 594px;" class="ml-slider-3-107-0 metaslider metaslider-flex metaslider-6738 ml-slider ms-theme-default nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden" role="region" aria-label="Syntax highlighting: Code Syntax Block [GitHub (Light)]" data-height="1158" data-width="594">
    <div id="metaslider_container_6738">
        <div id="metaslider_6738" class="flexslider">
            <ul class='slides'>
                <li style="display: block; width: 100%;" class="slide-6741 ms-image " aria-roledescription="slide" data-date="2023-12-15 21:44:10" data-filename="Code-Syntax-Block-GitHub-Light-Light.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="1188" height="2316" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Syntax-Block-GitHub-Light-Light.webp" class="slider-6738 slide-6741 msDefaultImage" alt="" rel="" title="Code Syntax Block [GitHub (Light)] (Light)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Syntax-Block-GitHub-Light-Light.webp 1188w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Syntax-Block-GitHub-Light-Light-131x256.webp 131w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Syntax-Block-GitHub-Light-Light-525x1024.webp 525w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Syntax-Block-GitHub-Light-Light-1051x2048.webp 1051w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Syntax-Block-GitHub-Light-Light-263x512.webp 263w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Syntax-Block-GitHub-Light-Light-131x256@2x.webp 262w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Syntax-Block-GitHub-Light-Light-525x1024@2x.webp 1050w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Syntax-Block-GitHub-Light-Light-263x512@2x.webp 526w" sizes="auto, (max-width: 1188px) 100vw, 1188px" /><div class="caption-wrap"><div class="caption">Light mode</div></div></li>
                <li style="display: none; width: 100%;" class="slide-6742 ms-image " aria-roledescription="slide" data-date="2023-12-15 21:44:10" data-filename="Code-Syntax-Block-GitHub-Light-Dark.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="1188" height="2316" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Syntax-Block-GitHub-Light-Dark.webp" class="slider-6738 slide-6742 msDefaultImage" alt="" rel="" title="Code Syntax Block [GitHub (Light)] (Dark)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Syntax-Block-GitHub-Light-Dark.webp 1188w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Syntax-Block-GitHub-Light-Dark-131x256.webp 131w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Syntax-Block-GitHub-Light-Dark-525x1024.webp 525w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Syntax-Block-GitHub-Light-Dark-1051x2048.webp 1051w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Syntax-Block-GitHub-Light-Dark-263x512.webp 263w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Syntax-Block-GitHub-Light-Dark-131x256@2x.webp 262w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Syntax-Block-GitHub-Light-Dark-525x1024@2x.webp 1050w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Syntax-Block-GitHub-Light-Dark-263x512@2x.webp 526w" sizes="auto, (max-width: 1188px) 100vw, 1188px" /><div class="caption-wrap"><div class="caption">Dark mode</div></div></li>
            </ul>
        </div>
        
    </div>
</div></div>



<p>A simple plug-in based on <a href="https://prismjs.com" data-wpel-link="external" target="_blank" rel="external noopener">Prism.js</a>, with very limited customisation options.</p>



<p>It&#8217;s <a href="https://github.com/mkaz/code-syntax-block" data-wpel-link="external" target="_blank" rel="external noopener">open source</a> and free (as is the <a href="https://github.com/PrismJS/prism" data-wpel-link="external" target="_blank" rel="external noopener">Prism.js</a> engine underneath it).</p>



<h3 class="wp-block-heading">Performance</h3>



<p>Prism.js prides itself on being [relatively] small.  Perhaps because of that goal of being &#8220;lightweight&#8221;, its performance is a bit mediocre.</p>



<p>The default theme makes it look even worse than it really is, because it bizarrely doesn&#8217;t provide any distinguishing styling for important things, like type names.</p>



<p>On the upside, it does get a few things right which other plug-ins often don&#8217;t &#8211; even others which also use Prism.js, curiously, like <a href="#highlighting-code-block">Highlighting Code Block</a>.  Things like it:</p>



<ul class="wp-block-list">
<li>Recognises @-attributes, such as macro and property wrapper invocations.</li>



<li>Recognises relatively new Swift keywords such as <code>async</code> &amp; <code>await</code>.</li>



<li>Understands multi-line and raw strings.</li>
</ul>



<p>On the downside it:</p>



<ul class="wp-block-list">
<li>Doesn&#8217;t recognise a <em>lot</em> of very basic Swift syntax &#8211; or, at least, doesn&#8217;t distinguish them with a <code>span</code> and therefore resigns them to the default, plain text styling of the overall <code>code</code> block &#8211; including but not limited to:
<ul class="wp-block-list">
<li>Variable names (neither their declaration nor references to them).</li>



<li>Function parameter labels &amp; names.</li>



<li>Property names.</li>



<li>Tuple field labels.</li>
</ul>
</li>



<li>Doesn&#8217;t recognise method calls consistently (e.g. <code>pack</code> &amp; <code>reduce</code> vs <code>map</code> in the example shown).</li>
</ul>



<p>Although you can&#8217;t tell with its default theme, it actually recognises custom type names (although doesn&#8217;t distinguish them from Swift standard library types, like Xcode &#8211; though it&#8217;s debatable whether that&#8217;s a feature).</p>



<p>It uses font weight, not just colour, which <em>would</em> go a long way towards giving it higher fidelity without making it look garish <em>if</em> it didn&#8217;t use it really weirdly.  Instead of bolding keywords, for example, it bolds function &amp; method names &#8211; sometimes, when it recognises them correctly.</p>



<p>At least it defaults to Menlo, which is actually a respectable choice and makes it one of the few plug-ins tested that have a decent default for Apple platforms.  In case you&#8217;re unfamiliar, <a href="https://en.wikipedia.org/wiki/Menlo_(typeface)" data-wpel-link="external" target="_blank" rel="external noopener">Menlo</a> was the default monospace font for Snow Leopard through Yosemite (before it was replaced by SF Mono).  You&#8217;d most likely have encountered it in Terminal or Xcode, if you used a Mac in that timeframe (2009 &#8211; 2015).  It&#8217;s still available on every Apple device (as of time of writing, December 2023).</p>



<h3 class="wp-block-heading">Pros</h3>



<ul class="wp-block-list">
<li>Extends the built-in, standard Code block.  This makes it comparatively trivial to adopt if you&#8217;ve already got Code blocks on your website (although you may still need to go through and customise some things, such as the language in case auto-detection doesn&#8217;t work correctly).<br><br>This also makes it easier to switch syntax-highlighting plug-ins, <em>provided</em> that the one you switch from or to also supports the standard Code block, which is sadly a minority of them.</li>
</ul>



<h3 class="wp-block-heading">Cons</h3>



<ul class="wp-block-list">
<li>Hasn&#8217;t been updated in a year &#8211; possibly abandoned.</li>



<li>Does everything client-side, so there&#8217;s a noticeable delay before syntax highlighting is actually applied (especially on first load, when the relevant JavaScript &amp; CSS isn&#8217;t cached in the browser).  It&#8217;s a bit visually jarring as the unstyled code is replaced with the styled.</li>



<li>Adds its Prism CSS &amp; JavaScript files to <em>every</em> page load, irrespective of whether the page actually needs them or not.  This is the core Prism.js library only &#8211; the grammar file for each language is only loaded when actually needed.<br><br>They are somewhat small files, at least &#8211; most of it is Prism.js at 30 KB alone, plus a few extra KBs for the chosen theme&#8217;s CSS.  With Brotli compression they&#8217;re ~13 KB.  Language grammar files tend to be only 3 KB or less.</li>



<li>Very few built-in themes &#8211; only four &#8211; and using a custom theme is technically possible but awkward.  <a href="https://github.com/mkaz/code-syntax-block" data-wpel-link="external" target="_blank" rel="external noopener">The official instructions</a> didn&#8217;t work for me, either &#8211; I had to use the <a href="https://wpcode.com" data-wpel-link="external" target="_blank" rel="external noopener">WPCode</a> plug-in to execute the relevant PHP:<br><br><code>add_filter('mkaz_prism_css_url', function() {</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp;return '/wp-content/themes/prism-xcode.css';<br>});</code></li>



<li>Theming is controlled globally with no ability to override it for specific uses.<br><br>This is (IMO) better than not having any global controls at all, as with some plug-ins, but it can be problematic if you use more than one language in these code blocks across your website, as you might prefer different themes for different languages.<br><br>You can technically work around this limitation using custom CSS, since the language is included as a class on the relevant <code>pre</code> and <code>code</code> HTML elements.</li>



<li>Doesn&#8217;t render the syntax highlighting in the Gutenberg editor, so you&#8217;re stuck with the generic <code>pre</code> appearance there.</li>
</ul>



<h2 class="wp-block-heading"><a href="https://wordpress.org/plugins/enlighter/" data-wpel-link="external" target="_blank" rel="external noopener">Enlighter</a></h2>



<div class="alignnormal"><div id="metaslider-id-6694" style="max-width: 473px;" class="ml-slider-3-107-0 metaslider metaslider-flex metaslider-6694 ml-slider ms-theme-default nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden" role="region" aria-label="Syntax highlighting: Enlighter [Default]" data-height="1023" data-width="473">
    <div id="metaslider_container_6694">
        <div id="metaslider_6694" class="flexslider">
            <ul class='slides'>
                <li style="display: block; width: 100%;" class="slide-6697 ms-image " aria-roledescription="slide" data-date="2023-12-13 21:31:57" data-filename="Enlighter-Default-theme-Light.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="946" height="2046" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Enlighter-Default-theme-Light.webp" class="slider-6694 slide-6697 msDefaultImage" alt="" rel="" title="Enlighter [Default theme] (Light)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Enlighter-Default-theme-Light-473x1024@2x.webp 946w, https://wadetregaskis.com/wp-content/uploads/2023/12/Enlighter-Default-theme-Light-473x1024.webp 473w, https://wadetregaskis.com/wp-content/uploads/2023/12/Enlighter-Default-theme-Light-118x256.webp 118w, https://wadetregaskis.com/wp-content/uploads/2023/12/Enlighter-Default-theme-Light-237x512.webp 237w, https://wadetregaskis.com/wp-content/uploads/2023/12/Enlighter-Default-theme-Light-118x256@2x.webp 236w, https://wadetregaskis.com/wp-content/uploads/2023/12/Enlighter-Default-theme-Light-237x512@2x.webp 474w" sizes="auto, (max-width: 946px) 100vw, 946px" /><div class="caption-wrap"><div class="caption">Light mode</div></div></li>
                <li style="display: none; width: 100%;" class="slide-6698 ms-image " aria-roledescription="slide" data-date="2023-12-13 21:31:58" data-filename="Enlighter-Default-theme-Dark.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="946" height="2046" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Enlighter-Default-theme-Dark.webp" class="slider-6694 slide-6698 msDefaultImage" alt="" rel="" title="Enlighter [Default theme] (Dark)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Enlighter-Default-theme-Dark-473x1024@2x.webp 946w, https://wadetregaskis.com/wp-content/uploads/2023/12/Enlighter-Default-theme-Dark-473x1024.webp 473w, https://wadetregaskis.com/wp-content/uploads/2023/12/Enlighter-Default-theme-Dark-118x256.webp 118w, https://wadetregaskis.com/wp-content/uploads/2023/12/Enlighter-Default-theme-Dark-237x512.webp 237w, https://wadetregaskis.com/wp-content/uploads/2023/12/Enlighter-Default-theme-Dark-118x256@2x.webp 236w, https://wadetregaskis.com/wp-content/uploads/2023/12/Enlighter-Default-theme-Dark-237x512@2x.webp 474w" sizes="auto, (max-width: 946px) 100vw, 946px" /><div class="caption-wrap"><div class="caption">Dark mode</div></div></li>
            </ul>
        </div>
        
    </div>
</div></div>



<p>The official WordPress plug-in for the <a href="https://enlighterjs.org/" data-wpel-link="external" target="_blank" rel="external noopener">EnlighterJS</a> engine.</p>



<p>It&#8217;s <a href="https://github.com/EnlighterJS/Plugin.WordPress" data-wpel-link="external" target="_blank" rel="external noopener">open source</a> and free (as is the <a href="https://github.com/EnlighterJS/EnlighterJS" data-wpel-link="external" target="_blank" rel="external noopener">EnlighterJS</a> engine underneath it).</p>



<h3 class="wp-block-heading">Performance</h3>



<p>Generally it does a poor job, with Swift code, and it&#8217;s not really a mystery why &#8211; <a href="https://github.com/EnlighterJS/EnlighterJS/blob/a0e3a9be4b6a09a5506567fc18f456a177eeed31/src/lang/swift.js" data-wpel-link="external" target="_blank" rel="external noopener">its grammar file for Swift</a> is <em>especially</em> spartan and hasn&#8217;t been updated since it was created over five years ago!  That&#8217;s the Swift 4.1 era at best.</p>



<p>It actually behaves very similarly to the <a href="#syntaxhighlighter-evolved" data-type="internal" data-id="#syntaxhighlighter-evolved">SyntaxHighlighter Evolved</a> plug-in, but with the significant difference that it leaves things it doesn&#8217;t understand as the plain text colour (e.g. black in Light mode), so it&#8217;s <em>much</em> more apparent even at a glance that it doesn&#8217;t really understand much.</p>



<p>For example, it:</p>



<ul class="wp-block-list">
<li>Doesn&#8217;t understand @-attributes, such as macro and property wrapper invocations.</li>



<li>Has no idea about the difference between function parameter labels and parameter arguments.</li>



<li>Doesn&#8217;t consistently recognise references to properties, such as when they&#8217;re part of KeyPaths.</li>



<li>Doesn&#8217;t understand some important keywords, like <code>async</code>, <code>await</code>, <code>Never</code>, etc.</li>



<li>Recognises <em>only</em> a limited selection of types &#8211; all from the Swift standard library &#8211; and has no idea about custom types.</li>



<li>Doesn&#8217;t recognise method calls consistently (e.g. <code>pack</code> &amp; <code>reduce</code> vs <code>map</code> in the example shown).</li>
</ul>



<p>In a nutshell, it&#8217;s doing little more than picking out a pre-defined list of keywords, identifying string &amp; numeric literals, and comments.</p>



<p>Though it does at least handle multi-line and raw strings correctly (albeit only in some themes &#8211; in a few it underlines strings and mistakes the indentation as part of the string, for multi-line strings).</p>



<p>The choice of Courier New as the default font is… brave.  It&#8217;s not actually its preferred default &#8211; it favours Source Code Pro foremost, with Liberation Mono as a second choice.  They&#8217;re both reasonable open-source monospace fonts, but neither are standard fonts on any Apple devices, and the plug-in doesn&#8217;t include them.</p>



<p>You can customise the font to a very limited degree &#8211; the plug-in provides only five options, none of which are standard Apple OS fonts so the choice is effectively pointless.  Thankfully you can override its font choices, like pretty much all its styling, with custom CSS.</p>



<h3 class="wp-block-heading">Pros</h3>



<ul class="wp-block-list">
<li>Supports both a global theme setting as well as use-specific overrides.</li>



<li>Supports both soft &amp; hard wrapping (the latter meaning it uses a horizontal scroller if necessary, rather than fitting the text to the viewport &#8211; generally not what I recommend since it&#8217;s pretty hostile to small screens but it&#8217;s a notable feature to make this behaviour configurable).</li>



<li>Includes a pretty extensive theme customiser, as an actual HTML forms-style interface in the plug-in settings pages.  That GUI is ultimately just a bespoke configurator for the CSS &#8211; which helpfully it also provides, in case you want to save or serve that elsewhere.<br><br>And if that proves insufficient &#8211; or you just prefer to do it manually &#8211; it uses a sensible system of spans with suitable classes, so it&#8217;s easy to write custom CSS for styling.</li>



<li>Provides its own Gutenberg block, but can also optionally be applied to the built-in WordPress Code block, as well as potentially blocks from other plug-ins (<a href="https://github.com/aramk/crayon-syntax-highlighter" data-wpel-link="external" target="_blank" rel="external noopener">Crayon Syntax Highlighter</a> &amp; <a href="https://wordpress.org/plugins/codecolorer/" data-wpel-link="external" target="_blank" rel="external noopener">CodeColorer</a> are explicitly supported &#8211; unclear if it also supports <a href="https://wordpress.org/plugins/urvanov-syntax-highlighter/" data-wpel-link="external" target="_blank" rel="external noopener">Urvanov Syntax Highlighter</a>, the &#8216;reincarnation&#8217; of the otherwise abandoned Crayon Syntax Highlighter).</li>
</ul>



<h3 class="wp-block-heading">Cons</h3>



<ul class="wp-block-list">
<li>Built-in themes are pretty limited and (IMO) pretty ugly, at least for the light-style ones (which is ten of the thirteen).  The one demonstrated here is the default &#8211; just called &#8220;Enlighter&#8221; &#8211; which is about the best it has to offer. 😕</li>



<li>Puts its settings item at the top level of the WordPress admin menu, rather than under Settings.</li>



<li>Adds its CSS &amp; JavaScript files to <em>every</em> page load, irrespective of whether the page actually uses the Enlighter block or not.  Along with some inline JavaScript in every page header.<br><br>And they&#8217;re not trivial files, either.  The CSS is 80 KB uncompressed &#8211; ~10 KB with Brotli compression, larger with GZip or Zip (Deflate).  That&#8217;s factoring in CSS minification, too.  The JavaScript is 63 KB uncompressed (~19 KB with Brotli).<br><br>It does offer an option to supposedly avoid this &#8211; &#8220;Dynamic Resource Invocation&#8221; &#8211; but it&#8217;s disabled by default, and still requires inclusion of a &#8220;small&#8221; 1 KB JavaScript file with every page load just to determine if the rest of the code &amp; CSS should be loaded.  So, kind of a hack to try to cover up a design flaw.  Alternatively, you can disable automatic inclusion of the CSS &amp; JavaScript files and handle that manually, but I can&#8217;t imagine anyone actually <em>wants</em> to have to deal with that.</li>



<li>Doesn&#8217;t render the syntax highlighting in the Gutenberg editor, so you&#8217;re stuck with the generic <code>pre</code> appearance there.</li>
</ul>



<p>So, overall a pretty poor option, both in terms of how well it understands Swift &#8211; i.e. <em>particularly</em> badly &#8211; and how it looks out of the box.  It does have a lot more options than most of the other plug-ins, and its GUI for theme editing <em>might</em> be a unique selling point for a &#8211; presumably rather limited &#8211; market of people that want to include Swift code on their website but aren&#8217;t comfortable writing CSS.  Even that withstanding for argument&#8217;s sake, I think it falls solidly towards the bottom of the pile.</p>



<h2 class="wp-block-heading" id="highlighting-code-block"><a href="https://wordpress.org/plugins/highlighting-code-block/" data-wpel-link="external" target="_blank" rel="external noopener">Highlighting Code Block</a></h2>



<div class="alignnormal"><div id="metaslider-id-6707" style="max-width: 564px;" class="ml-slider-3-107-0 metaslider metaslider-flex metaslider-6707 ml-slider ms-theme-default nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden" role="region" aria-label="Syntax highlighting: Highlighting Code Block [Light]" data-height="1347" data-width="564">
    <div id="metaslider_container_6707">
        <div id="metaslider_6707" class="flexslider">
            <ul class='slides'>
                <li style="display: block; width: 100%;" class="slide-6710 ms-image " aria-roledescription="slide" data-date="2023-12-14 10:51:28" data-filename="Highlighting-Code-Block-Light-Light.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="1128" height="2694" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Highlighting-Code-Block-Light-Light.webp" class="slider-6707 slide-6710 msDefaultImage" alt="" rel="" title="Highlighting Code Block [Light] (Light)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Highlighting-Code-Block-Light-Light.webp 1128w, https://wadetregaskis.com/wp-content/uploads/2023/12/Highlighting-Code-Block-Light-Light-107x256.webp 107w, https://wadetregaskis.com/wp-content/uploads/2023/12/Highlighting-Code-Block-Light-Light-429x1024.webp 429w, https://wadetregaskis.com/wp-content/uploads/2023/12/Highlighting-Code-Block-Light-Light-858x2048.webp 858w, https://wadetregaskis.com/wp-content/uploads/2023/12/Highlighting-Code-Block-Light-Light-214x512.webp 214w, https://wadetregaskis.com/wp-content/uploads/2023/12/Highlighting-Code-Block-Light-Light-214x512@2x.webp 428w" sizes="auto, (max-width: 1128px) 100vw, 1128px" /><div class="caption-wrap"><div class="caption">Light mode</div></div></li>
                <li style="display: none; width: 100%;" class="slide-6711 ms-image " aria-roledescription="slide" data-date="2023-12-14 10:51:29" data-filename="Highlighting-Code-Block-Light-Dark.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="1128" height="2694" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Highlighting-Code-Block-Light-Dark.webp" class="slider-6707 slide-6711 msDefaultImage" alt="" rel="" title="Highlighting Code Block [Light] (Dark)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Highlighting-Code-Block-Light-Dark.webp 1128w, https://wadetregaskis.com/wp-content/uploads/2023/12/Highlighting-Code-Block-Light-Dark-107x256.webp 107w, https://wadetregaskis.com/wp-content/uploads/2023/12/Highlighting-Code-Block-Light-Dark-429x1024.webp 429w, https://wadetregaskis.com/wp-content/uploads/2023/12/Highlighting-Code-Block-Light-Dark-858x2048.webp 858w, https://wadetregaskis.com/wp-content/uploads/2023/12/Highlighting-Code-Block-Light-Dark-214x512.webp 214w, https://wadetregaskis.com/wp-content/uploads/2023/12/Highlighting-Code-Block-Light-Dark-214x512@2x.webp 428w" sizes="auto, (max-width: 1128px) 100vw, 1128px" /><div class="caption-wrap"><div class="caption">Dark mode</div></div></li>
            </ul>
        </div>
        
    </div>
</div></div>



<p>A relatively simple plug-in based on <a href="https://prismjs.com" data-wpel-link="external" target="_blank" rel="external noopener">Prism.js</a>, with limited customisation options.</p>



<p>It&#8217;s <a href="https://github.com/ddryo/Highlighting-Code-Block" data-wpel-link="external" target="_blank" rel="external noopener">open source</a> and free (as is the <a href="https://github.com/PrismJS/prism" data-wpel-link="external" target="_blank" rel="external noopener">Prism.js</a> engine underneath it).</p>



<h3 class="wp-block-heading">Performance</h3>



<p>Prism.js prides itself on being [relatively] small.  Perhaps because of that goal of being &#8220;lightweight&#8221;, its performance is pretty poor &#8211; and pretty obviously so even at just a glance.</p>



<p>For example, it:</p>



<ul class="wp-block-list">
<li>Doesn&#8217;t understand @-attributes, such as macro and property wrapper invocations.</li>



<li>Has no idea about the difference between function parameter labels and parameter arguments.</li>



<li>Doesn&#8217;t consistently recognise references to properties, such as when they&#8217;re part of KeyPaths.</li>



<li>Doesn&#8217;t understand some important keywords, like <code>async</code> &amp; <code>await</code>.</li>



<li>Doesn&#8217;t recognise method calls consistently (e.g. <code>pack</code> &amp; <code>reduce</code> vs <code>map</code> in the example shown).</li>



<li>Doesn&#8217;t understand multi-line nor raw strings.</li>
</ul>



<p>On the positive side, it actually recognises custom type names (although doesn&#8217;t distinguish them from Swift standard library types, like Xcode &#8211; though it&#8217;s debatable whether that&#8217;s a feature).</p>



<p>It uses italics, not just colour, which goes a long way towards giving it higher fidelity without making it look garish.  Unfortunately, its use of italics is weirdly inconsistent &#8211; e.g. it italicises <em>some</em> keywords but not all (e.g. <code>final</code> vs <code><em>class</em></code>), and italicises <em>some</em> type names but not others (e.g. <code><em>VStack</em></code> vs <code>Image</code> &amp; <code>Text</code>).</p>



<p>It doesn&#8217;t take much effort to understand why &#8211; it&#8217;s using a <em>very</em> simplistic parser that knows virtually nothing about the language (other than a hard-coded list of keywords) and instead is just going off of capitalisation, mostly.  Which is somewhat clever, and gets it a long way for such a simple method, but ultimately results in poor performance.</p>



<p>At least it defaults to Menlo, which is actually a respectable choice and makes it one of the few plug-ins tested that have a decent default for Apple platforms.  In case you&#8217;re unfamiliar, <a href="https://en.wikipedia.org/wiki/Menlo_(typeface)" data-wpel-link="external" target="_blank" rel="external noopener">Menlo</a> was the default monospace font for Snow Leopard through Yosemite (before it was replaced by SF Mono).  You&#8217;d most likely have encountered it in Terminal or Xcode, if you used a Mac in that timeframe (2009 &#8211; 2015).  It&#8217;s still available on every Apple device (as of time of writing, December 2023).</p>



<p>It&#8217;s a bit weird that the performance is significantly different from some other Prism.js-based plug-ins, like <a href="#code-syntax-block">Code Syntax Block</a>.  It&#8217;d be explicable if one plug-in were strictly superior to the other &#8211; suggesting simply use of a newer version of Prism.js by one than the other &#8211; but it&#8217;s actually a weird mix of improvements and regressions.</p>



<h3 class="wp-block-heading">Pros</h3>



<ul class="wp-block-list">
<li>Good bang-for-your-buck configuration options, which is to say that it has relatively few but it includes the essentials and with maximum flexibility (e.g. font customisation is by entering the actual <code>font-family</code> CSS string, rather than being limited to do a predefined short list of options as with most other plug-ins).</li>
</ul>



<h3 class="wp-block-heading">Cons</h3>



<ul class="wp-block-list">
<li>Does everything client-side, so there&#8217;s a noticeable delay before syntax highlighting is actually applied (especially on first load, when the relevant JavaScript &amp; CSS isn&#8217;t cached in the browser).  It&#8217;s a bit visually jarring as the unstyled code is replaced with the styled.</li>



<li>Adds its CSS &amp; JavaScript files to <em>every</em> page load, plus some inline CSS &amp; JavaScript, irrespective of whether the page actually needs it or not.  This includes the entire Prism.js library with grammar parsers for every supported language, irrespective of which ones are actually used.<br><br>And they&#8217;re not entirely trivial files, either &#8211; mainly because of Prism.js at 35 KB alone.  Overall they&#8217;re 41 KB before compression (~18 KB with Brotli).</li>



<li>Limited theming control &#8211; it has an unnamed built-in default, which you can override by specifying a server-side path to a custom CSS file (although functionally this isn&#8217;t much different from just putting your custom CSS in your website&#8217;s general custom CSS file, because of the aforementioned flaw whereby this plug-in inserts its CSS into <em>every</em> page load).</li>



<li>Theming is controlled globally with no ability to override it for specific uses.<br><br>This is (IMO) better than not having any global controls at all, as with some plug-ins, but it can be problematic if you use more than one language in these code blocks across your website, as you might prefer different themes for different languages.<br><br>You can technically work around this limitation using custom CSS, since the language is included as a class on the relevant <code>pre</code> and <code>code</code> HTML elements.</li>



<li>Includes support for a relatively small number of languages (by default), although that does include Swift and Objective-C, among many other popular languages.  I list this as &#8216;con&#8217; only in a relative sense &#8211; for most users its built-in shortlist is likely quite sufficient.<br><br>You can provide a custom build of Prism.js if you need others, although it&#8217;s left as an exercise to the user to figure out how to do that (and to then maintain it).</li>



<li>Doesn&#8217;t render the syntax highlighting in the Gutenberg editor, so you&#8217;re stuck with the generic <code>pre</code> appearance there.</li>



<li>Uses a custom Gutenberg block type, rather than just extending the standard Code block.  So you can&#8217;t just upgrade your whole existing site &#8211; you have to manually go through and find every existing Code block, and manually migrate each one.<br><br>Inversely it&#8217;ll also be more difficult to migrate away from, if you choose to do that some day, as you&#8217;ll likely have to repeat that whole process no matter what replacement plug-in you choose.</li>
</ul>



<h2 class="wp-block-heading"><a href="https://wordpress.org/plugins/prismatic/" data-wpel-link="external" target="_blank" rel="external noopener">Prismatic</a></h2>



<p>A uniquely versatile plug-in that supports both the <a href="https://prismjs.com" data-wpel-link="external" target="_blank" rel="external noopener">Prism.js</a> and <a href="https://highlightjs.org" data-wpel-link="external" target="_blank" rel="external noopener">highlight.js</a> engines.</p>



<p>It&#8217;s <a href="https://plugins.svn.wordpress.org/prismatic/" data-wpel-link="external" target="_blank" rel="external noopener">open source</a> and free (as are the <a href="https://github.com/PrismJS/prism" data-wpel-link="external" target="_blank" rel="external noopener">Prism.js</a> and <a href="https://github.com/highlightjs/highlight.js" data-wpel-link="external" target="_blank" rel="external noopener">highlight.js</a> engines underneath it).</p>



<p>Unfortunately, it immediately disqualified itself by simply not working.  After installing &amp; activating it in WordPress, nothing happens.  The built-in Code block doesn&#8217;t change, there is no new Gutenberg block (contrary to its documentation which claims it adds a &#8220;Prismatic&#8221; block), and nothing appears anywhere in the WordPress Admin menu, such as a global settings page.</p>



<p>I checked the PHP logs and found no mention of the plug-in nor any relevant log messages.</p>



<p>It&#8217;s unusual &#8211; in my experience &#8211; for a WordPress plug-in to just silently fail like this.  While it might be possible to enable WordPress debug logging and ultimately figure out what&#8217;s going on, in my experience first impressions are indicative when it comes to WordPress plug-ins, so I&#8217;m not going to spend time trying to get a plug-in to work at all when it&#8217;s probable it&#8217;ll have numerous other problems anyway.</p>



<h2 class="wp-block-heading"><a href="https://wordpress.org/plugins/syntax-highlighting-code-block/" data-wpel-link="external" target="_blank" rel="external noopener">Syntax-highlighting Code Block (with Server-side Rendering)</a></h2>



<div class="alignnormal"><div id="metaslider-id-6719" style="max-width: 412px;" class="ml-slider-3-107-0 metaslider metaslider-flex metaslider-6719 ml-slider ms-theme-default nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden" role="region" aria-label="Syntax highlighting: Syntax-highlighting Code Block (with Server-side Rendering) [Default]" data-height="1155" data-width="412">
    <div id="metaslider_container_6719">
        <div id="metaslider_6719" class="flexslider">
            <ul class='slides'>
                <li style="display: block; width: 100%;" class="slide-6722 ms-image " aria-roledescription="slide" data-date="2023-12-14 21:22:33" data-filename="Syntax-highlighting-Code-Block-with-Server-side-Rendering-Default-Light.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="824" height="2310" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Syntax-highlighting-Code-Block-with-Server-side-Rendering-Default-Light.webp" class="slider-6719 slide-6722 msDefaultImage" alt="" rel="" title="Syntax-highlighting Code Block (with Server-side Rendering) [Default] (Light)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Syntax-highlighting-Code-Block-with-Server-side-Rendering-Default-Light.webp 824w, https://wadetregaskis.com/wp-content/uploads/2023/12/Syntax-highlighting-Code-Block-with-Server-side-Rendering-Default-Light-365x1024.webp 365w, https://wadetregaskis.com/wp-content/uploads/2023/12/Syntax-highlighting-Code-Block-with-Server-side-Rendering-Default-Light-731x2048.webp 731w, https://wadetregaskis.com/wp-content/uploads/2023/12/Syntax-highlighting-Code-Block-with-Server-side-Rendering-Default-Light-91x256.webp 91w, https://wadetregaskis.com/wp-content/uploads/2023/12/Syntax-highlighting-Code-Block-with-Server-side-Rendering-Default-Light-183x512.webp 183w, https://wadetregaskis.com/wp-content/uploads/2023/12/Syntax-highlighting-Code-Block-with-Server-side-Rendering-Default-Light-365x1024@2x.webp 730w, https://wadetregaskis.com/wp-content/uploads/2023/12/Syntax-highlighting-Code-Block-with-Server-side-Rendering-Default-Light-91x256@2x.webp 182w, https://wadetregaskis.com/wp-content/uploads/2023/12/Syntax-highlighting-Code-Block-with-Server-side-Rendering-Default-Light-183x512@2x.webp 366w" sizes="auto, (max-width: 824px) 100vw, 824px" /><div class="caption-wrap"><div class="caption">Light mode</div></div></li>
                <li style="display: none; width: 100%;" class="slide-6723 ms-image " aria-roledescription="slide" data-date="2023-12-14 21:22:34" data-filename="Syntax-highlighting-Code-Block-with-Server-side-Rendering-Default-Dark.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="824" height="2310" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Syntax-highlighting-Code-Block-with-Server-side-Rendering-Default-Dark.webp" class="slider-6719 slide-6723 msDefaultImage" alt="" rel="" title="Syntax-highlighting Code Block (with Server-side Rendering) [Default] (Dark)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Syntax-highlighting-Code-Block-with-Server-side-Rendering-Default-Dark.webp 824w, https://wadetregaskis.com/wp-content/uploads/2023/12/Syntax-highlighting-Code-Block-with-Server-side-Rendering-Default-Dark-365x1024.webp 365w, https://wadetregaskis.com/wp-content/uploads/2023/12/Syntax-highlighting-Code-Block-with-Server-side-Rendering-Default-Dark-731x2048.webp 731w, https://wadetregaskis.com/wp-content/uploads/2023/12/Syntax-highlighting-Code-Block-with-Server-side-Rendering-Default-Dark-91x256.webp 91w, https://wadetregaskis.com/wp-content/uploads/2023/12/Syntax-highlighting-Code-Block-with-Server-side-Rendering-Default-Dark-183x512.webp 183w, https://wadetregaskis.com/wp-content/uploads/2023/12/Syntax-highlighting-Code-Block-with-Server-side-Rendering-Default-Dark-365x1024@2x.webp 730w, https://wadetregaskis.com/wp-content/uploads/2023/12/Syntax-highlighting-Code-Block-with-Server-side-Rendering-Default-Dark-91x256@2x.webp 182w, https://wadetregaskis.com/wp-content/uploads/2023/12/Syntax-highlighting-Code-Block-with-Server-side-Rendering-Default-Dark-183x512@2x.webp 366w" sizes="auto, (max-width: 824px) 100vw, 824px" /><div class="caption-wrap"><div class="caption">Dark mode</div></div></li>
            </ul>
        </div>
        
    </div>
</div></div>



<p>Nominally a fork of <a href="#code-syntax-block">Code Syntax Block</a> that renders server-side instead of client-side, although it uses a different engine &#8211; <a href="https://github.com/scrivo/highlight.php" data-wpel-link="external" target="_blank" rel="external noopener">Highlight.php</a> instead of <a href="https://prismjs.com" data-wpel-link="external" target="_blank" rel="external noopener">Prism.js</a>.</p>



<p><a href="https://github.com/scrivo/highlight.php" data-wpel-link="external" target="_blank" rel="external noopener">highlight.php</a> is a PHP port of <a href="https://highlightjs.org" data-wpel-link="external" target="_blank" rel="external noopener">Highlight.js</a>.  It&#8217;s unclear to me how closely or promptly that tracks changes to the original JavaScript library.</p>



<p>It&#8217;s <a href="https://github.com/westonruter/syntax-highlighting-code-block" data-wpel-link="external" target="_blank" rel="external noopener">open source</a> and free (as is the highlight.php engine underneath it).</p>



<h3 class="wp-block-heading">Performance</h3>



<p>The default theme is particularly bland.  It&#8217;s actually hard to judge its understanding of Swift purely from its appearance since so much of it looks the same.</p>



<p>It&#8217;s noteworthy as a <em>particularly</em> hostile plug-in (with its default theme) for colourblind viewers, due to its use of <em>very</em> similar shades for almost everything, and in particular its use of red vs grey in a way which makes them virtually indistinguishable to a significant portion of the population.  It&#8217;s not the only plug-in to be thoughtless in this way, but it is the worst.</p>



<p>It does come with a lot of other themes &#8211; nearly ninety at time of writing &#8211; but you&#8217;d be forgiven for thinking it does not, as it puts the theme selection setting in a surprising location &#8211; the &#8216;Customize&#8217; section of WordPress&#8217;s Appearance settings.  While this actually makes tremendous sense, <em>no</em> other syntax-highlighting plug-ins put their settings there.  It&#8217;s hard to hold that against this plug-in, for being the <em>one</em> plug-in which (arguably) does the right thing, but I almost overlooked this critical functionality &#8211; I only discovered it by chance because I happened upon its <a href="https://github.com/westonruter/syntax-highlighting-code-block/wiki/Advanced-Usage" data-wpel-link="external" target="_blank" rel="external noopener">Advanced Usage</a> documentation.</p>



<p>That all said, one thing the bland default does have going for it is that the visual sameness helps to slightly obscure how poorly the plug-in understands Swift.</p>



<p>For example, it:</p>



<ul class="wp-block-list">
<li>Doesn&#8217;t understand @-attributes, such as macro and property wrapper invocations.</li>



<li>Has no idea about the difference between function parameter labels and parameter arguments.</li>



<li>Doesn&#8217;t consistently recognise references to properties, such as when they&#8217;re part of KeyPaths.</li>



<li>Doesn&#8217;t understand some important keywords, like <code>async</code> &amp; <code>await</code>.</li>



<li>Doesn&#8217;t recognise method calls consistently (e.g. <code>pack</code> vs <code>reduce</code> &amp; <code>map</code> in the example shown).</li>



<li>Doesn&#8217;t understand raw strings (though it does handle multi-line strings correctly).</li>



<li>Is fooled by the use of keyword-looking names in places where they aren&#8217;t keywords, e.g. the <code>default</code> static property of <code>HomeItem</code>.</li>
</ul>



<p>It&#8217;s pretty apparent, especially once you look at the HTML itself, that it&#8217;s doing only a rudimentary analysis mainly based on a hard-coded list of keywords and heuristics like whether words start with capital letters.  That&#8217;s why it confuses literals (strings &amp; numbers) with type names, function names with property names, and so forth.  It&#8217;s not the only plug-in to try to fake it with such a simplistic algorithm, but it does the worst job of pulling it off.</p>



<p>It renders keywords in bold (like Xcode), which greatly aids readability.</p>



<p>Since it uses the built-in WordPress Code block as its basis, and doesn&#8217;t muck with the fonts, it defaults to whatever the active WordPress theme uses.  As shown in this example, with <a href="https://generatepress.com" data-wpel-link="external" target="_blank" rel="external noopener">GeneratePress</a>, that&#8217;s not even necessarily a monospaced font!  Worst, the plug-in has no built-in configuration option for font (although you can use custom CSS to override it).</p>



<h3 class="wp-block-heading">Pros</h3>



<ul class="wp-block-list">
<li>Extends the built-in, standard Code block.  This makes it comparatively trivial to adopt if you&#8217;ve already got Code blocks on your website (although you may still need to go through and customise some things, such as the language in case auto-detection doesn&#8217;t work correctly).<br><br>This also makes it easier to switch syntax-highlighting plug-ins, <em>provided</em> that the one you switch from or to also supports the standard Code block, which is sadly a minority of them.</li>
</ul>



<h3 class="wp-block-heading">Cons</h3>



<ul class="wp-block-list">
<li>No official theming support.<br><br>You can use custom CSS to re-theme it, thanks to its use of sensible class names for its <code>span</code>s, but other than fixing its bland default colours you can&#8217;t really improve it much, since a <em>lot</em> of the code is emitted as runs of plain text because of the plug-in&#8217;s very poor understanding of Swift.</li>



<li>No global settings &#8211; if you decide to change <em>any</em> settings, at any point, you have to manually find and adjust every existing code snippet manually.<br><br>This might be considered a positive by some users, where they want existing content to remain as-is.  However, some plug-ins offer both a global setting <em>and</em> the ability to override that on a per-case basis, providing more flexibility.</li>



<li>Very limited settings &#8211; just the language (if you don&#8217;t want to rely on auto-detection), which line(s) to highlight, whether to soft wrap, and whether to show line numbers.</li>
</ul>



<h2 class="wp-block-heading" id="syntaxhighlighter-evolved"><a href="https://alex.blog/wordpress-plugins/syntaxhighlighter/" data-wpel-link="external" target="_blank" rel="external noopener">SyntaxHighlighter Evolved</a></h2>



<div class="alignnormal"><div id="metaslider-id-7132" style="max-width: 590px;" class="ml-slider-3-107-0 metaslider metaslider-flex metaslider-7132 ml-slider ms-theme-default nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden" role="region" aria-label="Syntax highlighting: SyntaxHighlighter Evolved [Default theme]" data-height="1030" data-width="590">
    <div id="metaslider_container_7132">
        <div id="metaslider_7132" class="flexslider">
            <ul class='slides'>
                <li style="display: block; width: 100%;" class="slide-7133 ms-image " aria-roledescription="slide" data-date="2023-12-29 18:25:40" data-filename="SyntaxHighlighter-Evolved-Default-theme-Light.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="1180" height="2060" src="https://wadetregaskis.com/wp-content/uploads/2023/12/SyntaxHighlighter-Evolved-Default-theme-Light.webp" class="slider-7132 slide-7133 msDefaultImage" alt="" rel="" title="SyntaxHighlighter Evolved [Default theme] (Light)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/SyntaxHighlighter-Evolved-Default-theme-Light.webp 1180w, https://wadetregaskis.com/wp-content/uploads/2023/12/SyntaxHighlighter-Evolved-Default-theme-Light-147x256.webp 147w, https://wadetregaskis.com/wp-content/uploads/2023/12/SyntaxHighlighter-Evolved-Default-theme-Light-587x1024.webp 587w, https://wadetregaskis.com/wp-content/uploads/2023/12/SyntaxHighlighter-Evolved-Default-theme-Light-1173x2048.webp 1173w, https://wadetregaskis.com/wp-content/uploads/2023/12/SyntaxHighlighter-Evolved-Default-theme-Light-293x512.webp 293w, https://wadetregaskis.com/wp-content/uploads/2023/12/SyntaxHighlighter-Evolved-Default-theme-Light-147x256@2x.webp 294w, https://wadetregaskis.com/wp-content/uploads/2023/12/SyntaxHighlighter-Evolved-Default-theme-Light-587x1024@2x.webp 1174w, https://wadetregaskis.com/wp-content/uploads/2023/12/SyntaxHighlighter-Evolved-Default-theme-Light-293x512@2x.webp 586w" sizes="auto, (max-width: 1180px) 100vw, 1180px" /><div class="caption-wrap"><div class="caption">Light mode</div></div></li>
                <li style="display: none; width: 100%;" class="slide-7134 ms-image " aria-roledescription="slide" data-date="2023-12-29 18:25:40" data-filename="SyntaxHighlighter-Evolved-Default-theme-Dark.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="1180" height="2060" src="https://wadetregaskis.com/wp-content/uploads/2023/12/SyntaxHighlighter-Evolved-Default-theme-Dark.webp" class="slider-7132 slide-7134 msDefaultImage" alt="" rel="" title="SyntaxHighlighter Evolved [Default theme] (Dark)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/SyntaxHighlighter-Evolved-Default-theme-Dark.webp 1180w, https://wadetregaskis.com/wp-content/uploads/2023/12/SyntaxHighlighter-Evolved-Default-theme-Dark-147x256.webp 147w, https://wadetregaskis.com/wp-content/uploads/2023/12/SyntaxHighlighter-Evolved-Default-theme-Dark-587x1024.webp 587w, https://wadetregaskis.com/wp-content/uploads/2023/12/SyntaxHighlighter-Evolved-Default-theme-Dark-1173x2048.webp 1173w, https://wadetregaskis.com/wp-content/uploads/2023/12/SyntaxHighlighter-Evolved-Default-theme-Dark-293x512.webp 293w, https://wadetregaskis.com/wp-content/uploads/2023/12/SyntaxHighlighter-Evolved-Default-theme-Dark-147x256@2x.webp 294w, https://wadetregaskis.com/wp-content/uploads/2023/12/SyntaxHighlighter-Evolved-Default-theme-Dark-587x1024@2x.webp 1174w, https://wadetregaskis.com/wp-content/uploads/2023/12/SyntaxHighlighter-Evolved-Default-theme-Dark-293x512@2x.webp 586w" sizes="auto, (max-width: 1180px) 100vw, 1180px" /><div class="caption-wrap"><div class="caption">Dark mode</div></div></li>
            </ul>
        </div>
        
    </div>
</div></div>



<p>This is what I was using for years.  It&#8217;s completely free and <a href="https://github.com/Automattic/syntaxhighlighter" data-wpel-link="external" target="_blank" rel="external noopener">open source</a>.  It uses a proprietary syntax parsing system based on regular expressions.</p>



<h3 class="wp-block-heading">Performance</h3>



<p>It&#8217;s an interesting one, because it actually understands so <em>little</em> Swift syntax that most of it is bucketed together as &#8216;plain&#8217; text.  However, because it renders &#8216;plain&#8217; text in a colour other than black, it gives the surprisingly convincing (at a glance) illusion that it understands much more than it really does.</p>



<p>Overall its rendering is close to Xcode&#8217;s, which is very surprising given its highly rudimentary grammar parser.</p>



<p>It is actually pretty good about identifying keywords &#8211; it actually gets <code>async</code> which many do not &#8211; but it doesn&#8217;t understand them with context, e.g. it mistakes the <code>default</code> static property of <code>HomeItem</code> with the <code>default</code> keyword.</p>



<p>It renders keywords in bold (like Xcode) which greatly aids readability, although note how (unlike Xcode) it messes up the letter spacing as a result (this is a result of the font used &#8211; Monaco &#8211; and thus can be fixed by overriding that with a better font, e.g. SF Mono).</p>



<p>While it covers up a lot of its ignorance with its clever colour choices, there&#8217;s still a few important things that it gets visibly wrong.  For example, it:</p>



<ul class="wp-block-list">
<li>Doesn&#8217;t understand @-attributes, such as macro and property wrapper invocations.</li>



<li>Has no idea about the difference between function parameter labels and parameter arguments.</li>



<li>Doesn&#8217;t understand raw strings.</li>
</ul>



<p>Its choice of Monaco as its font is… interesting, although modern versions of Monaco are thankfully a little smoother than their 1980s ancestor.  That&#8217;s easy to override, however, via custom CSS in a suitable WordPress-generic stylesheet (the plug-in doesn&#8217;t provide any direct way to manipulate styling, beyond choosing from a short list of built-in themes).</p>



<h3 class="wp-block-heading">Pros</h3>



<ul class="wp-block-list">
<li>Most of its settings are global.  So changing themes for a whole site is trivial.</li>



<li>Uses sensible HTML structure and class names, so it&#8217;s easy to unofficially re-theme (although it has a very limited vocabulary of grammar, so you can&#8217;t greatly improve what you see here).</li>



<li>Supports end-user editing of the code (with the syntax highlighting updating appropriately).  This is purely superficial text editing &#8211; there&#8217;s no support for interpreting, compiling, or executing the code.  So I&#8217;m not really sure what the point of this feature is, but I list it here since it is unique to this plug-in (amongst all those I tested).</li>
</ul>



<h3 class="wp-block-heading">Cons</h3>



<ul class="wp-block-list">
<li>Doesn&#8217;t formally support light/dark mode (as do <em>none</em> of the plug-ins tested).  Colours are fixed (to whatever theme you choose) irrespective of the end-user&#8217;s light/dark setting (again, same as all the other plug-ins).  However, one difference versus all the other plug-ins is that this one doesn&#8217;t work properly with <a href="https://wordpress.org/plugins/wp-dark-mode/" data-wpel-link="external" target="_blank" rel="external noopener">WP Dark Mode</a> &#8211; it remains in light mode even while the rest of the page renders correctly in dark mode.<br><br>I strongly suspect the fault lies in WP Dark Mode, not SyntaxHighlighter Evolved, but irrespective it is there and might be a deal-breaker if you&#8217;re particularly attached to WP Dark Mode.</li>



<li>Doesn&#8217;t render the syntax highlighting in the Gutenberg editor, so you&#8217;re stuck with the generic <code>pre</code> appearance there.</li>



<li>Uses a custom Gutenberg block type, rather than just extending the standard Code block.  So you can&#8217;t just upgrade your whole existing site &#8211; you have to manually go through and find every existing Code block, and manually migrate each one.</li>



<li>Doesn&#8217;t get updated super often, although it has been around for years and has generally kept up with new WordPress versions, eventually.</li>
</ul>



<h2 class="wp-block-heading"><a href="https://wordpress.org/plugins/urvanov-syntax-highlighter/" data-wpel-link="external" target="_blank" rel="external noopener">Urvanov Syntax Highlighter</a></h2>



<div class="alignnormal"><div id="metaslider-id-7034" style="max-width: 1140px;" class="ml-slider-3-107-0 metaslider metaslider-flex metaslider-7034 ml-slider ms-theme-default nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden" role="region" aria-label="Syntax highlighting: Urvanov Syntax Highlighter [Classic]" data-height="962" data-width="1140">
    <div id="metaslider_container_7034">
        <div id="metaslider_7034" class="flexslider">
            <ul class='slides'>
                <li style="display: block; width: 100%;" class="slide-7040 ms-image " aria-roledescription="slide" data-date="2023-12-29 09:36:07" data-filename="Urvanov-Syntax-Highlighter-Classic-Light.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="2280" height="1924" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Urvanov-Syntax-Highlighter-Classic-Light.webp" class="slider-7034 slide-7040 msDefaultImage" alt="" rel="" title="Urvanov Syntax Highlighter [Classic] (Light)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Urvanov-Syntax-Highlighter-Classic-Light.webp 2280w, https://wadetregaskis.com/wp-content/uploads/2023/12/Urvanov-Syntax-Highlighter-Classic-Light-256x216.webp 256w, https://wadetregaskis.com/wp-content/uploads/2023/12/Urvanov-Syntax-Highlighter-Classic-Light-512x432@2x.webp 1024w, https://wadetregaskis.com/wp-content/uploads/2023/12/Urvanov-Syntax-Highlighter-Classic-Light-2048x1728.webp 2048w, https://wadetregaskis.com/wp-content/uploads/2023/12/Urvanov-Syntax-Highlighter-Classic-Light-512x432.webp 512w" sizes="auto, (max-width: 2280px) 100vw, 2280px" /><div class="caption-wrap"><div class="caption">Light mode</div></div></li>
                <li style="display: none; width: 100%;" class="slide-7039 ms-image " aria-roledescription="slide" data-date="2023-12-29 09:36:06" data-filename="Urvanov-Syntax-Highlighter-Classic-Dark.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="2280" height="1924" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Urvanov-Syntax-Highlighter-Classic-Dark.webp" class="slider-7034 slide-7039 msDefaultImage" alt="" rel="" title="Urvanov Syntax Highlighter [Classic] (Dark)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Urvanov-Syntax-Highlighter-Classic-Dark.webp 2280w, https://wadetregaskis.com/wp-content/uploads/2023/12/Urvanov-Syntax-Highlighter-Classic-Dark-256x216.webp 256w, https://wadetregaskis.com/wp-content/uploads/2023/12/Urvanov-Syntax-Highlighter-Classic-Dark-512x432@2x.webp 1024w, https://wadetregaskis.com/wp-content/uploads/2023/12/Urvanov-Syntax-Highlighter-Classic-Dark-2048x1728.webp 2048w, https://wadetregaskis.com/wp-content/uploads/2023/12/Urvanov-Syntax-Highlighter-Classic-Dark-512x432.webp 512w" sizes="auto, (max-width: 2280px) 100vw, 2280px" /><div class="caption-wrap"><div class="caption">Dark mode</div></div></li>
            </ul>
        </div>
        
    </div>
</div></div>



<p>A fork of the abandoned <a href="https://wordpress.org/plugins/crayon-syntax-highlighter/" data-wpel-link="external" target="_blank" rel="external noopener">Crayon Syntax Highlighter</a> that uses its own syntax-highlighting engine.</p>



<p>It&#8217;s <a href="https://github.com/urvanov-ru/crayon-syntax-highlighter" data-wpel-link="external" target="_blank" rel="external noopener">open source</a> and free.</p>



<p>I almost didn&#8217;t include this because (a) it&#8217;s really very broken and (b) it doesn&#8217;t really support Swift at all.  I strongly recommend against using it, for numerous reasons.</p>



<h3 class="wp-block-heading">Performance</h3>



<p>Pretty terrible, in a nutshell.  I&#8217;m not going to go into full detail here because the plug-in is largely broken anyway (details shortly, in the Cons section).</p>



<p>Ironically it works better out of the box than if you actually configure it &#8220;correctly&#8221;; it doesn&#8217;t recognise this example as any specific language and falls back to some generic &#8220;Default&#8221; grammar parser.  If you explicitly set it to Swift, the syntax highlighting actually gets markedly worse, and it&#8217;s no surprise why &#8211; <a href="https://github.com/urvanov-ru/crayon-syntax-highlighter/tree/master/langs/swift" data-wpel-link="external" target="_blank" rel="external noopener">its Swift grammar definition</a> is nearly a decade old, dating back to Swift 1.0 in 2014!</p>



<p>One of its most egregious rendering problems is that it translates various special characters &#8211; <code>[</code>, <code>&lt;</code>, <code>&gt;</code>, etc &#8211; to their escaped HTML entities.  This can be &#8216;corrected&#8217; in its settings &#8211; it has a &#8220;Decode HTML entities in code&#8221; option &#8211; but that&#8217;s a hacky bandaid over the bug, that precludes you from <em>actually</em> using HTML entities in your code example (so you can&#8217;t use this plug-in for the HTML language itself).</p>



<p>Another rendering annoyance is that it makes the code block&#8217;s width 100%, irrespective of the actual width of the code.  Most of the plug-ins do that, actually, but it&#8217;s much more apparent with this one because of its use of a visual border and alternating line background colours.  You can configure a maximum width in its global settings, but (as with most of these plug-ins) there&#8217;s no (built-in) way to make it size to fit.</p>



<p>On syntax understanding itself, it basically has none.  It simply recognises some fairly general syntax patterns, such as strings, literals, and parenthesis-indicated function calls.  It doesn&#8217;t recognise most keywords, even.</p>



<h3 class="wp-block-heading">Pros</h3>



<ul class="wp-block-list">
<li>Very configurable &#8211; perhaps the <em>most</em> configurable plug-in tested.  Beyond just theming options &#8211; including the ability to easily change the font from its default of Monaco &#8211; it includes options rarely covered by other plug-ins such as margin customisations.</li>
</ul>



<h3 class="wp-block-heading">Cons</h3>



<ul class="wp-block-list">
<li>Nominally offers a Gutenberg block, but it doesn&#8217;t work &#8211; you cannot actually edit the textual contents, in the Gutenberg editor, and it doesn&#8217;t render at all on the actual published page.  Thus you can <em>only</em> use the plug-in by having it take over existing <code>&lt;code</code>&gt; and/or <code>&lt;pre&gt;</code> blocks…</li>



<li>Takes over all existing <code>&lt;code</code>&gt; and <code>&lt;pre&gt;</code> blocks by default, even those by other plug-ins, and those that don&#8217;t contain code at all (e.g. where you were simply presenting monospaced text such as Terminal output).  You can configure this in the settings, including turning it off, but given the Gutenberg block doesn&#8217;t work, this is the <em>only</em> way to actually use the plug-in.<br><br><img loading="lazy" decoding="async" width="391" height="225" class="wp-image-7042" style="width: 391px;" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Urvanov-Syntax-Highlighter-22Tag22-settings.webp" alt="Screenshot of the 'Tag' settings for the Urvanov Syntax Highlighter WordPress plug-in" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Urvanov-Syntax-Highlighter-22Tag22-settings.webp 782w, https://wadetregaskis.com/wp-content/uploads/2023/12/Urvanov-Syntax-Highlighter-22Tag22-settings-256x147.webp 256w, https://wadetregaskis.com/wp-content/uploads/2023/12/Urvanov-Syntax-Highlighter-22Tag22-settings-512x295.webp 512w" sizes="auto, (max-width: 391px) 100vw, 391px" /><br><br>I spent some time playing with different combinations of these settings, but many combinations are inexplicably unusable &#8211; they just result in broken rendering &#8211; and I couldn&#8217;t find anything that improved on the default behaviour.<br><br>As such, this is an especially all-or-nothing syntax highlighter.  It <em>really</em> doesn&#8217;t play well with others.</li>



<li>Since it just takes over existing <code>&lt;code</code>&gt; and/or <code>&lt;pre&gt;</code> blocks, there&#8217;s no per-use customisation possible &#8211; everything is exclusively controlled through global settings, including the code language.</li>



<li>By default adds its CSS &amp; JavaScript files to <em>every</em> page load, plus some inline CSS &amp; JavaScript, irrespective of whether the page actually needs it or not.  This can nominally be corrected in the settings, via the &#8220;Attempt to load Crayon&#8217;s CSS and JavaScript only when needed&#8221; option, but I didn&#8217;t test it (and it&#8217;s not encouraging that it&#8217;s both disabled by default and uses the word <em>attempt</em>, both suggesting this feature doesn&#8217;t work reliably).<br><br>And they&#8217;re not entirely trivial files, either, even though rendering is done server-side &#8211; its JavaScript is 65 KB alone!  Its CSS is another 28 KB.  With Brotli compression they&#8217;re ~18 KB.  They compress well in part for the same reason they&#8217;re so egregiously large &#8211; the use of &#8220;urvanov-syntax-highlighter&#8221; / &#8220;urvanov_syntax_highlighter&#8221; prefixes on so many of the names.  This bloats up the page source as well, with oversized HTML class names for every snippet of styled code.</li>



<li>Doesn&#8217;t render the syntax highlighting in the Gutenberg editor, so you&#8217;re stuck with the generic <code>pre</code> appearance there.</li>
</ul>



<h1 class="wp-block-heading">The winner</h1>



<p>…is hard to pick unilaterally.  Each plug-in has significant limitations or trade-offs.  Which is best may depend on your personal preferences and specific needs.</p>



<p>Most of the plug-ins do a pretty atrocious job at actually understanding Swift, and at best for them it&#8217;s a question of how well they can fake it through clever heuristics and styling choices.  <a href="#syntaxhighlighter-evolved">SyntaxHighlighter Evolved</a> warrants an honourable mention in this regard for doing a particularly impressive job despite its very limited brains.  There&#8217;s a reason I used it for years with relatively few complaints, and if it hadn&#8217;t had issues with WP Dark Mode &#8211; before I realised WP Dark Mode was buggy anyway and had to be replaced &#8211; I probably wouldn&#8217;t have bothered doing all this competitive research, and wouldn&#8217;t be switching away from it.</p>



<p>The most common engines used by syntax-highlighting plug-ins are <a href="https://prismjs.com" data-wpel-link="external" target="_blank" rel="external noopener">Prism.js</a> and <a href="https://highlightjs.org" data-wpel-link="external" target="_blank" rel="external noopener">Highlight.js</a> / <a href="https://github.com/scrivo/highlight.php" data-wpel-link="external" target="_blank" rel="external noopener">Highlight.php</a>, but frankly they&#8217;re bad at Swift &#8211; a situation that&#8217;s unlikely to change given Swift is such a niche language for them; they&#8217;re clearly focused on browser languages like JavaScript, HTML, and CSS.  Even that aside, they tend to use client-side rendering which is slower and buggier.</p>



<figure class="wp-block-pullquote"><blockquote><p>Ultimately, I tentatively believe that <a href="#code-block-pro">Code Block Pro</a> is the best option.</p></blockquote></figure>



<p>It <em>currently</em> does a somewhat average job in understanding Swift and rendering it pleasingly &#8211; just like all the plug-ins tested &#8211; but it seems to have the most promising foundation, being based on the same grammar &amp; theme files as are used by Visual Studio Code (and <a href="https://github.com/github-linguist/linguist/tree/master/vendor/grammars" data-wpel-link="external" target="_blank" rel="external noopener">GitHub</a>).  So it has the possibility of significant improvements in future; at the very least it would make sense for the Swift community to focus on it since the benefits will be applicable not just to WordPress websites but also Visual Studio Code and GitHub.</p>



<h4 class="wp-block-heading">Refinements to Code Block Pro</h4>



<div class="alignnormal"><div id="metaslider-id-7116" style="max-width: 570px;" class="ml-slider-3-107-0 metaslider metaslider-flex metaslider-7116 ml-slider ms-theme-default nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden nav-hidden" role="region" aria-label="Syntax highlighting: Code Block Pro [Light Plus w/ modifications]" data-height="1280" data-width="570">
    <div id="metaslider_container_7116">
        <div id="metaslider_7116" class="flexslider">
            <ul class='slides'>
                <li style="display: block; width: 100%;" class="slide-7117 ms-image " aria-roledescription="slide" data-date="2023-12-29 16:29:49" data-filename="Code-Block-Pro-Light-Plus-w-customisations-Light.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="1140" height="2560" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-w-customisations-Light.webp" class="slider-7116 slide-7117 msDefaultImage" alt="" rel="" title="Code Block Pro [Light Plus w: customisations] (Light)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-w-customisations-Light.webp 1140w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-w-customisations-Light-114x256.webp 114w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-w-customisations-Light-228x512@2x.webp 456w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-w-customisations-Light-912x2048.webp 912w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-w-customisations-Light-228x512.webp 228w" sizes="auto, (max-width: 1140px) 100vw, 1140px" /><div class="caption-wrap"><div class="caption">Light mode</div></div></li>
                <li style="display: none; width: 100%;" class="slide-7118 ms-image " aria-roledescription="slide" data-date="2023-12-29 16:29:49" data-filename="Code-Block-Pro-Light-Plus-w-customisations-Dark.webp" data-slide-type="image"><img loading="lazy" decoding="async" width="1140" height="2560" src="https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-w-customisations-Dark.webp" class="slider-7116 slide-7118 msDefaultImage" alt="" rel="" title="Code Block Pro [Light Plus w: customisations] (Dark)" srcset="https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-w-customisations-Dark.webp 1140w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-w-customisations-Dark-228x512@2x.webp 456w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-w-customisations-Dark-912x2048.webp 912w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-w-customisations-Dark-114x256.webp 114w, https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-w-customisations-Dark-228x512.webp 228w" sizes="auto, (max-width: 1140px) 100vw, 1140px" /><div class="caption-wrap"><div class="caption">Dark mode</div></div></li>
            </ul>
        </div>
        
    </div>
</div></div>



<p>Every light-style theme available with Code Block Pro &#8211; including the paid expansion pack &#8211; has significant rendering errors for Swift, but after spending an egregious amount of time exploring the themes and experimenting with fixes for them, I&#8217;ve concluded that Light Plus is the least bad option.  With some crude but simple CSS I&#8217;m able to adjust its appearance as shown here, which is loosely styled after Xcode&#8217;s default (light mode) theme.</p>



<p>I didn&#8217;t do much to accomodate Dark mode, limiting my modifications there to merely using SF Pro (&#8220;system-ui&#8221;) for comments.  I don&#8217;t use Dark mode myself, so I might not have a good eye for what looks good there, but the default colours (from the simple inversion by the Dracula Dark Mode plug-in) seem alright to me.  And pragmatically, I&#8217;d have to overwrite <em>every</em> colour used in the theme in order to ensure no rendering issues, and that&#8217;s a whole lot of CSS I don&#8217;t want to write nor bloat my page loads with.</p>



<p>I also turn on &#8220;Disable padding&#8221; in its &#8220;Extra Settings&#8221;, as by default it uses (a) hard-coded padding dimensions, in pixels and (b) padding, not margins.  A strange choice, but at least it has the option to disable it.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-disabled" data-code-block-pro-font-family="" style="font-size:.875rem;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><pre class="shiki light-plus" style="background-color: #FFFFFF" tabindex="0"><code><span class="line"><span style="color: #800000">div.wp-block-kevinbatdorf-code-block-pro</span><span style="color: #000000"> {</span></span>
<span class="line"><span style="color: #000000">	</span><span style="color: #E50000">font-family</span><span style="color: #000000">: </span><span style="color: #A31515">&quot;SF Mono&quot;</span><span style="color: #000000">, SFMono-Regular, </span><span style="color: #0451A5">ui-monospace</span><span style="color: #000000">, </span><span style="color: #0451A5">monospace</span><span style="color: #000000">;</span></span>
<span class="line"><span style="color: #000000">	</span><span style="color: #E50000">width</span><span style="color: #000000">: </span><span style="color: #0451A5">fit-content</span><span style="color: #000000">;</span></span>
<span class="line"><span style="color: #000000">	</span><span style="color: #E50000">margin</span><span style="color: #000000">: </span><span style="color: #098658">1em</span><span style="color: #000000">;</span></span>
<span class="line"><span style="color: #000000">	</span></span>
<span class="line"><span style="color: #000000">	&amp; </span><span style="color: #E50000">span</span><span style="color: #000000">[</span><span style="color: #E50000">style</span><span style="color: #000000">*=</span><span style="color: #EE0000">\#</span><span style="color: #000000">0000FF], </span><span style="color: #E50000">span</span><span style="color: #000000">[</span><span style="color: #E50000">style</span><span style="color: #000000">*=</span><span style="color: #EE0000">\#</span><span style="color: #000000">AF00DB] { </span><span style="color: #008000">/* Keywords */</span></span>
<span class="line"><span style="color: #000000">		</span><span style="color: #E50000">font-weight</span><span style="color: #000000">: </span><span style="color: #098658">675</span><span style="color: #000000">;</span></span>
<span class="line"><span style="color: #000000">		</span><span style="color: #E50000">color</span><span style="color: #000000">: </span><span style="color: #0451A5">#9B2393</span><span style="color: #000000"> </span><span style="color: #0000FF">!important</span><span style="color: #000000">;</span></span>
<span class="line"><span style="color: #000000">	}</span></span>
<span class="line"><span style="color: #000000">	</span></span>
<span class="line"><span style="color: #000000">	&amp; </span><span style="color: #800000">span</span><span style="color: #000000">[</span><span style="color: #E50000">style</span><span style="color: #000000">*=</span><span style="color: #EE0000">\#</span><span style="color: #A31515">008000</span><span style="color: #000000">], </span><span style="color: #800000">span</span><span style="color: #000000">[</span><span style="color: #E50000">style</span><span style="color: #000000">*=</span><span style="color: #EE0000">\#</span><span style="color: #A31515">81f179</span><span style="color: #000000">] { </span><span style="color: #008000">/* Comments */</span></span>
<span class="line"><span style="color: #000000">		</span><span style="color: #E50000">font-family</span><span style="color: #000000">: </span><span style="color: #0451A5">system-ui</span><span style="color: #000000"> </span><span style="color: #0000FF">!important</span><span style="color: #000000">;</span></span>
<span class="line"><span style="color: #000000">		</span><span style="color: #E50000">font-style</span><span style="color: #000000">: </span><span style="color: #0451A5">italic</span><span style="color: #000000">;</span></span>
<span class="line"><span style="color: #000000">	}</span></span>
<span class="line"><span style="color: #000000">	</span></span>
<span class="line"><span style="color: #000000">	&amp; </span><span style="color: #800000">span</span><span style="color: #000000">[</span><span style="color: #E50000">style</span><span style="color: #000000">*=</span><span style="color: #EE0000">\#</span><span style="color: #A31515">008000</span><span style="color: #000000">] { </span><span style="color: #008000">/* Comments */</span></span>
<span class="line"><span style="color: #000000">		</span><span style="color: #E50000">color</span><span style="color: #000000">: </span><span style="color: #0451A5">#5D6C79</span><span style="color: #000000"> </span><span style="color: #0000FF">!important</span><span style="color: #000000">;</span></span>
<span class="line"><span style="color: #000000">	}</span></span>
<span class="line"><span style="color: #000000">	</span></span>
<span class="line"><span style="color: #000000">	&amp; </span><span style="color: #800000">span</span><span style="color: #000000">[</span><span style="color: #E50000">style</span><span style="color: #000000">*=</span><span style="color: #EE0000">\#</span><span style="color: #A31515">001080</span><span style="color: #000000">] { </span><span style="color: #008000">/* Properties */</span></span>
<span class="line"><span style="color: #000000">		</span><span style="color: #E50000">color</span><span style="color: #000000">: </span><span style="color: #0451A5">#3E8087</span><span style="color: #000000"> </span><span style="color: #0000FF">!important</span><span style="color: #000000">;</span></span>
<span class="line"><span style="color: #000000">	}</span></span>
<span class="line"><span style="color: #000000">	</span></span>
<span class="line"><span style="color: #000000">	&amp; </span><span style="color: #800000">span</span><span style="color: #000000">[</span><span style="color: #E50000">style</span><span style="color: #000000">*=</span><span style="color: #EE0000">\#</span><span style="color: #A31515">795E26</span><span style="color: #000000">] { </span><span style="color: #008000">/* Function names and argument labels */</span></span>
<span class="line"><span style="color: #000000">		</span><span style="color: #E50000">color</span><span style="color: #000000">: </span><span style="color: #0451A5">#804FB8</span><span style="color: #000000"> </span><span style="color: #0000FF">!important</span><span style="color: #000000">;</span></span>
<span class="line"><span style="color: #000000">	}</span></span>
<span class="line"><span style="color: #000000">	</span></span>
<span class="line"><span style="color: #000000">	&amp; </span><span style="color: #800000">span</span><span style="color: #000000">[</span><span style="color: #E50000">style</span><span style="color: #000000">*=</span><span style="color: #EE0000">\#</span><span style="color: #A31515">267F99</span><span style="color: #000000">] { </span><span style="color: #008000">/* Type names */</span></span>
<span class="line"><span style="color: #000000">		</span><span style="color: #E50000">color</span><span style="color: #000000">: </span><span style="color: #0451A5">#4B22B0</span><span style="color: #000000"> </span><span style="color: #0000FF">!important</span><span style="color: #000000">;</span></span>
<span class="line"><span style="color: #000000">	}</span></span>
<span class="line"><span style="color: #000000">	</span></span>
<span class="line"><span style="color: #000000">	&amp; </span><span style="color: #800000">span</span><span style="color: #000000">[</span><span style="color: #E50000">style</span><span style="color: #000000">*=</span><span style="color: #EE0000">\#</span><span style="color: #A31515">A31515</span><span style="color: #000000">] { </span><span style="color: #008000">/* String literals */</span></span>
<span class="line"><span style="color: #000000">		</span><span style="color: #E50000">font-weight</span><span style="color: #000000">: </span><span style="color: #098658">500</span><span style="color: #000000">;</span></span>
<span class="line"><span style="color: #000000">		</span><span style="color: #E50000">color</span><span style="color: #000000">: </span><span style="color: #0451A5">#D12F1B</span><span style="color: #000000"> </span><span style="color: #0000FF">!important</span><span style="color: #000000">;</span></span>
<span class="line"><span style="color: #000000">	}</span></span>
<span class="line"><span style="color: #000000">	</span></span>
<span class="line"><span style="color: #000000">	&amp; </span><span style="color: #800000">span</span><span style="color: #000000">[</span><span style="color: #E50000">style</span><span style="color: #000000">*=</span><span style="color: #EE0000">\#</span><span style="color: #A31515">098658</span><span style="color: #000000">] { </span><span style="color: #008000">/* Numeric literals */</span></span>
<span class="line"><span style="color: #000000">		</span><span style="color: #E50000">font-weight</span><span style="color: #000000">: </span><span style="color: #098658">500</span><span style="color: #000000">;</span></span>
<span class="line"><span style="color: #000000">		</span><span style="color: #E50000">color</span><span style="color: #000000">: </span><span style="color: #0451A5">#272AD8</span><span style="color: #000000"> </span><span style="color: #0000FF">!important</span><span style="color: #000000">;</span></span>
<span class="line"><span style="color: #000000">	}</span></span>
<span class="line"><span style="color: #000000">}</span></span></code></pre></div>



<h1 class="wp-block-heading">What are other websites using?</h1>



<p>I figured it might be helpful to look at what other Swift-code-rendering websites use, to see if there&#8217;s any I missed (there wasn&#8217;t) and which the community seems to believe is best.</p>



<ul class="wp-block-list">
<li><a href="https://www.swiftbysundell.com" data-type="link" data-id="https://www.swiftbysundell.com" data-wpel-link="external" target="_blank" rel="external noopener">Swift by Sundell</a> is using <a href="https://github.com/johnsundell/publish" data-type="link" data-id="https://github.com/johnsundell/publish" data-wpel-link="external" target="_blank" rel="external noopener">Publish</a> and the <a href="https://github.com/johnsundell/splash" data-type="link" data-id="https://github.com/johnsundell/splash" data-wpel-link="external" target="_blank" rel="external noopener">Splash</a> plug-in.  Splash seems to do a pretty good job &#8211; clearly better than any JavaScript or PHP syntax highlighters.</li>



<li><a href="https://www.hackingwithswift.com" data-type="link" data-id="https://www.hackingwithswift.com" data-wpel-link="external" target="_blank" rel="external noopener">Hacking with Swift</a> is using <a href="https://wordpress.org" data-type="link" data-id="https://wordpress.org" data-wpel-link="external" target="_blank" rel="external noopener">WordPress</a> and ultimately <a href="https://prismjs.com" data-wpel-link="external" target="_blank" rel="external noopener">Prism.js</a>, although I&#8217;m not sure through which plug-in (possibly <a href="https://github.com/mkaz/code-syntax-block" data-type="link" data-id="https://github.com/mkaz/code-syntax-block" data-wpel-link="external" target="_blank" rel="external noopener">Code Syntax Block</a>).</li>



<li><a href="https://www.cocoawithlove.com" data-type="link" data-id="https://www.cocoawithlove.com" data-wpel-link="external" target="_blank" rel="external noopener">Cocoa with Love</a> might be using some Ruby-based platform or static generator, but it&#8217;s clear it&#8217;s using <a href="https://github.com/rouge-ruby/rouge" data-type="link" data-id="https://github.com/rouge-ruby/rouge" data-wpel-link="external" target="_blank" rel="external noopener">Rouge</a> for syntax highlighting.<br><br>Sidenote: Rouge seems to do a decent job of correctly identifying tokens and their types, although its underlying model looks pretty simplistic (it tends to default to the &#8220;n&#8221; class by default, meaning &#8220;name&#8221;, meaning it doesn&#8217;t really know if it&#8217;s a parameter label, parameter name, type name, etc).</li>



<li><a href="https://www.donnywals.com" data-type="link" data-id="https://www.donnywals.com" data-wpel-link="external" target="_blank" rel="external noopener">Donny Wals</a> is using <a href="https://wordpress.org" data-type="link" data-id="https://wordpress.org" data-wpel-link="external" target="_blank" rel="external noopener">WordPress</a> with the <a href="https://github.com/westonruter/syntax-highlighting-code-block" data-type="link" data-id="https://github.com/westonruter/syntax-highlighting-code-block" data-wpel-link="external" target="_blank" rel="external noopener">Syntax-highlighting Code Block</a> plug-in, which uses <a href="https://github.com/scrivo/highlight.php" data-type="link" data-id="https://github.com/scrivo/highlight.php" data-wpel-link="external" target="_blank" rel="external noopener">Highlight.php</a> (based on <a href="https://highlightjs.org" data-wpel-link="external" target="_blank" rel="external noopener">Highlight.js</a>).</li>



<li><a href="https://matteomanferdini.com" data-type="link" data-id="https://matteomanferdini.com" data-wpel-link="external" target="_blank" rel="external noopener">Matteo Manferdini</a> is using <a href="https://wordpress.org" data-type="link" data-id="https://wordpress.org" data-wpel-link="external" target="_blank" rel="external noopener">WordPress</a> with the <a href="https://generatepress.com" data-type="link" data-id="https://generatepress.com" data-wpel-link="external" target="_blank" rel="external noopener">GeneratePress</a> theme (same as this site, at time of writing) and ultimately <a href="https://prismjs.com" data-wpel-link="external" target="_blank" rel="external noopener">Prism.js</a>, likely through <a href="https://github.com/mkaz/code-syntax-block" data-type="link" data-id="https://github.com/mkaz/code-syntax-block" data-wpel-link="external" target="_blank" rel="external noopener">Code Syntax Block</a>.</li>



<li><a href="https://nshipster.com" data-type="link" data-id="https://nshipster.com" data-wpel-link="external" target="_blank" rel="external noopener">NSHipster</a> appears to be statically generated with <a href="https://github.com/NSHipster/nshipster.com" data-wpel-link="external" target="_blank" rel="external noopener">a bespoke tool written in Ruby</a> using <a href="https://github.com/NSHipster/rouge" data-type="link" data-id="https://github.com/NSHipster/rouge" data-wpel-link="external" target="_blank" rel="external noopener">a custom fork</a> of <a href="https://github.com/rouge-ruby/rouge" data-wpel-link="external" target="_blank" rel="external noopener">Rouge</a>.</li>



<li><a href="https://developer.apple.com/swift/blog/" data-wpel-link="external" target="_blank" rel="external noopener">The old Swift Blog</a> uses… I don&#8217;t know.  Possibly a proprietary system, for both the platform and the syntax highlighting.  I didn&#8217;t find any identification or indicators otherwise of any particular library.</li>



<li><a href="https://www.swift.org/blog/" type="link" id="https://www.swift.org/blog" data-wpel-link="external" target="_blank" rel="external noopener">The newer Swift Blog</a> uses… possibly the same mystery platform as the old one.  But it does clearly use <a href="https://github.com/rouge-ruby/rouge" data-type="link" data-id="https://github.com/rouge-ruby/rouge" data-wpel-link="external" target="_blank" rel="external noopener">Rouge</a> for syntax highlighting.</li>



<li><a href="https://swiftevolution.substack.com" data-wpel-link="external" target="_blank" rel="external noopener">Swift Evolution Monthly</a> is hosted on <a href="https://substack.com" data-type="link" data-id="https://substack.com" data-wpel-link="external" target="_blank" rel="external noopener">Substack</a> and doesn&#8217;t do any syntax highlighting at all!</li>



<li><a href="https://www.swiftwithvincent.com" data-type="link" data-id="https://www.swiftwithvincent.com" data-wpel-link="external" target="_blank" rel="external noopener">Swift with Vincent</a> is hosted on <a href="https://www.squarespace.com" data-wpel-link="external" target="_blank" rel="external noopener">Squarespace</a>, which ultimately uses <a href="https://prismjs.com" data-wpel-link="external" target="_blank" rel="external noopener">Prism.js</a>.</li>



<li><a href="https://swiftwithmajid.com" data-type="link" data-id="https://swiftwithmajid.com" data-wpel-link="external" target="_blank" rel="external noopener">Swift with Majid</a> is statically generated using <a href="https://jekyllrb.com" data-type="link" data-id="https://jekyllrb.com" data-wpel-link="external" target="_blank" rel="external noopener">Jekyll</a> and uses <a href="https://github.com/rouge-ruby/rouge" data-type="link" data-id="https://github.com/rouge-ruby/rouge" data-wpel-link="external" target="_blank" rel="external noopener">Rouge</a>.</li>



<li><a href="https://swiftinit.org" data-type="link" data-id="https://swiftinit.org" data-wpel-link="external" target="_blank" rel="external noopener">Swiftinit</a> (by Dianna a.k.a. &#8220;<a href="https://forums.swift.org/u/taylorswift" data-type="link" data-id="https://forums.swift.org/u/taylorswift" data-wpel-link="external" target="_blank" rel="external noopener">taylorswift</a>&#8221; / &#8220;<a href="https://github.com/tayloraswift?tab=repositories" data-type="link" data-id="https://github.com/tayloraswift?tab=repositories" data-wpel-link="external" target="_blank" rel="external noopener">tayloraswift</a>&#8220;) uses a proprietary platform (written in Swift).  The syntax highlighting is presumably also proprietary.<br><br>Sidenote:  there&#8217;s not a lot of syntax-highlighted code on Swiftinit (mostly it&#8217;s in some hidden blog posts from 2022), but what&#8217;s there looks pretty similar to what <a href="https://github.com/rouge-ruby/rouge" data-type="link" data-id="https://github.com/rouge-ruby/rouge" data-wpel-link="external" target="_blank" rel="external noopener">Rouge</a> generates.  It does a pretty good job of correctly interpreting the syntax, although there&#8217;s not a great deal of apparent fidelity &#8211; mostly it&#8217;s just dividing things into formal names (types, functions, etc), variables, keywords, and everything else.</li>



<li><a href="https://www.avanderlee.com" data-wpel-link="external" target="_blank" rel="external noopener">SwiftLee</a> is using <a href="https://wordpress.org" data-type="link" data-id="https://wordpress.org" data-wpel-link="external" target="_blank" rel="external noopener">WordPress</a> and the <a href="https://github.com/mkaz/code-syntax-block" data-type="link" data-id="https://github.com/mkaz/code-syntax-block" data-wpel-link="external" target="_blank" rel="external noopener">Code Syntax Block</a> plug-in, which is <a href="https://prismjs.com" data-wpel-link="external" target="_blank" rel="external noopener">Prism.js</a> underneath.</li>



<li><a href="https://swiftrocks.com" data-wpel-link="external" target="_blank" rel="external noopener">SwiftRocks</a> is using <a href="https://getbootstrap.com" data-type="link" data-id="https://getbootstrap.com" data-wpel-link="external" target="_blank" rel="external noopener">Bootstrap</a> and <a href="https://prismjs.com" data-type="link" data-id="https://prismjs.com" data-wpel-link="external" target="_blank" rel="external noopener">Prism.js</a>.</li>



<li><a href="https://swiftui-lab.com" data-wpel-link="external" target="_blank" rel="external noopener">SwiftUI Lab</a> is using <a href="https://wordpress.org" data-type="link" data-id="https://wordpress.org" data-wpel-link="external" target="_blank" rel="external noopener">WordPress</a> and the <a href="https://wordpress.org/plugins/prismatic/" data-wpel-link="external" target="_blank" rel="external noopener">Prismatic</a> plug-in, which is configurable to either <a href="https://prismjs.com" data-wpel-link="external" target="_blank" rel="external noopener">Prism.js</a> or <a href="https://highlightjs.org" data-type="link" data-id="https://highlightjs.org" data-wpel-link="external" target="_blank" rel="external noopener">Highlight.js</a> underneath; the site has elected to use Prism.js.</li>



<li><a href="https://troz.net" data-wpel-link="external" target="_blank" rel="external noopener">TrozWare</a> is using <a href="https://gohugo.io" data-type="link" data-id="https://gohugo.io" data-wpel-link="external" target="_blank" rel="external noopener">Hugo</a> and <a href="https://prismjs.com" data-type="link" data-id="https://prismjs.com" data-wpel-link="external" target="_blank" rel="external noopener">Prism.js</a>.</li>



<li><a href="https://www.vadimbulavin.com" data-wpel-link="external" target="_blank" rel="external noopener">Yet Another Swift Blog</a> is statically generated using <a href="https://jekyllrb.com" data-type="link" data-id="https://jekyllrb.com" data-wpel-link="external" target="_blank" rel="external noopener">Jekyll</a> and uses <a href="https://github.com/rouge-ruby/rouge" data-type="link" data-id="https://github.com/rouge-ruby/rouge" data-wpel-link="external" target="_blank" rel="external noopener">Rouge</a> (though oddly I also see fragments of <a href="https://prismjs.com" data-wpel-link="external" target="_blank" rel="external noopener">Prism.js</a> and <a href="https://highlightjs.org" data-type="link" data-id="https://highlightjs.org" data-wpel-link="external" target="_blank" rel="external noopener">Highlight.js</a> on the site, although I didn&#8217;t see any actual use of them to render code).</li>
</ul>



<p>If you&#8217;re keeping score, that&#8217;s (syntax-highlighter-wise):</p>



<ul class="narrow-line-spacing wp-block-list">
<li>Prism.js: 7</li>



<li>Rouge: 5</li>



<li>Unknown: 2</li>



<li>Highlight.js: 1</li>



<li>Splash: 1</li>
</ul>



<p>And platform-wise:</p>



<ul class="narrow-line-spacing wp-block-list">
<li>WordPress: 5</li>



<li>Unknown: 3</li>



<li>Jekyll: 2</li>



<li>Proprietary: 2</li>



<li>Bootstrap: 1</li>



<li>Hugo: 1</li>



<li>Substack: 1</li>



<li>Squarespace: 1</li>



<li>Publish: 1</li>
</ul>



<p>It&#8217;s notable that <em>not one</em> is using Code Block Pro nor the underlying Shiki engine, even though (with the serious caveats mentioned earlier) they do the best job of actually understanding Swift.</p>


<ol class="wp-block-footnotes"><li id="f5cd2d93-b8e5-4773-8838-26add7d33f48">Strictly-speaking not for any technical reason, as the plug-ins could run more advanced tooling on the server (as some bespoke CMS&#8217;s do), but I have not encountered any WordPress plug-in which does so. <a href="#f5cd2d93-b8e5-4773-8838-26add7d33f48-link" aria-label="Jump to footnote reference 1">↩︎</a></li><li id="395a26f7-0a74-4647-ae97-e770481a032a">Technically you can do it with just custom CSS, by overriding your theme&#8217;s defaults inside a <code>@media (prefers-color-scheme: dark)</code> block, but this is likely impractical for all but the most simplistic and static WordPress installations &#8211; you have to be <em>sure</em> you catch <em>every</em> GUI element and colour.  A good plug-in will dynamically rewrite the CSS client-side, ensuring everything is covered. <a href="#395a26f7-0a74-4647-ae97-e770481a032a-link" aria-label="Jump to footnote reference 2">↩︎</a></li></ol>]]></content:encoded>
					
					<wfw:commentRss>https://wadetregaskis.com/swift-code-syntax-highlighting-in-wordpress/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			<media:content url="https://wadetregaskis.com/wp-content/uploads/2023/12/Code-Block-Pro-Light-Plus-w-customisations-Light-feature-image.webp" medium="image" />
<post-id xmlns="com-wordpress:feed-additions:1">5561</post-id>	</item>
		<item>
		<title>Blog like it&#8217;s 2005</title>
		<link>https://wadetregaskis.com/blog-like-its-2005/</link>
					<comments>https://wadetregaskis.com/blog-like-its-2005/#respond</comments>
		
		<dc:creator><![CDATA[]]></dc:creator>
		<pubDate>Wed, 29 Nov 2023 03:19:58 +0000</pubDate>
				<category><![CDATA[Ancient History]]></category>
		<category><![CDATA[AUC]]></category>
		<category><![CDATA[Meta]]></category>
		<category><![CDATA[.mac]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Apple Backup]]></category>
		<category><![CDATA[Apple HomePage]]></category>
		<category><![CDATA[Dropbox]]></category>
		<category><![CDATA[Gmail]]></category>
		<category><![CDATA[Hotmail]]></category>
		<category><![CDATA[iCloud]]></category>
		<category><![CDATA[iCloud Drive]]></category>
		<category><![CDATA[iDisk]]></category>
		<category><![CDATA[iTools]]></category>
		<category><![CDATA[MobileMe]]></category>
		<guid isPermaLink="false">https://wadetregaskis.com/?p=5926</guid>

					<description><![CDATA[On a bit of a whim &#8211; a silly tangent off of migrating to a new web host &#8211; I resurrected the &#8216;frozen in time&#8217; copy of my iTools / .Mac / MobileMe HomePage website. You can find it here, for better or worse. My old website dates back to at the latest September 2005&#8230; <a class="read-more-link" href="https://wadetregaskis.com/blog-like-its-2005/" data-wpel-link="internal">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>On a bit of a whim &#8211; a silly tangent off of <a href="https://wadetregaskis.com/migrated-hosts-out-of-the-subdomain/" data-wpel-link="internal">migrating to a new web host</a> &#8211; I resurrected the &#8216;frozen in time&#8217; copy of my <a href="https://apple.fandom.com/wiki/HomePage" data-wpel-link="external" target="_blank" rel="external noopener">iTools / .Mac / MobileMe HomePage</a> website.  You can find it <a href="https://wadetregaskis.com/MobileMe/Sites/index.html" data-wpel-link="internal">here</a>, for better or worse.</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<details class="wp-block-details is-layout-flow wp-block-details-is-layout-flow"><summary>iTools</summary><div class="wp-block-image">
<figure class="alignright size-full is-resized"><img loading="lazy" decoding="async" width="700" height="677" src="https://wadetregaskis.com/wp-content/uploads/2023/11/Apple-iTools.avif" alt="" class="wp-image-5928" style="width:350px;height:auto" srcset="https://wadetregaskis.com/wp-content/uploads/2023/11/Apple-iTools.avif 700w, https://wadetregaskis.com/wp-content/uploads/2023/11/Apple-iTools-256x248.avif 256w, https://wadetregaskis.com/wp-content/uploads/2023/11/Apple-iTools-512x495.avif 512w" sizes="auto, (max-width: 700px) 100vw, 700px" /></figure>
</div>


<p>Long before iCloud, <a href="https://en.wikipedia.org/wiki/MobileMe#iTools" data-wpel-link="external" target="_blank" rel="external noopener">iTools</a> was was of Apple&#8217;s first forays into web services as we recognise them today.  The headlining features were the ability to create an email address (free!) under the @mac.com domain (which I still use to this day!) and an online file storage and sharing system called <a href="https://en.wikipedia.org/wiki/IDisk" data-wpel-link="external" target="_blank" rel="external noopener">iDisk</a>, which was the foundation for several other services &amp; tools within the bundle including HomePage and <a href="https://en.wikipedia.org/wiki/MobileMe#Backup" data-wpel-link="external" target="_blank" rel="external noopener">Backup</a>.</p>



<p>Backup wasn&#8217;t exclusively tied to iDisk, and I used it (in the later .Mac era) for a couple of years to backup my essential documents to iDisk and my entire computer to a external hard drives and CDs.  I think it was my first <em>real</em> backup system…?  And I still have all those backups!</p>


<div class="wp-block-image">
<figure class="alignleft size-full is-resized"><img loading="lazy" decoding="async" width="819" height="879" src="https://wadetregaskis.com/wp-content/uploads/2023/11/iTools.avif" alt="" class="wp-image-5930" style="width:410px" srcset="https://wadetregaskis.com/wp-content/uploads/2023/11/iTools.avif 819w, https://wadetregaskis.com/wp-content/uploads/2023/11/iTools-239x256.avif 239w, https://wadetregaskis.com/wp-content/uploads/2023/11/iTools-477x512.avif 477w, https://wadetregaskis.com/wp-content/uploads/2023/11/iTools-239x256@2x.avif 478w" sizes="auto, (max-width: 819px) 100vw, 819px" /></figure>
</div>


<p>I don&#8217;t recall that I used iTools, or at least not in any serious way.  I was still in high school when it came out (just), going into university, and I recall using my university email address during that time.</p>



<p>If I remember correctly, iTools was pretty well received by actual users but panned critically, with the press and technorati unimpressed by it in light of antecedents like <a href="https://en.wikipedia.org/wiki/Outlook.com" data-wpel-link="external" target="_blank" rel="external noopener">Hotmail</a> (launched three years earlier in 1997) and numerous existing &#8220;DIY&#8221; website builders and free webhosts (<a href="https://en.wikipedia.org/wiki/GeoCities" data-wpel-link="external" target="_blank" rel="external noopener">GeoCities</a>!).</p>



<p>There was also some resentment due to its Mac-only nature, although technically most of the services worked through a web browser on any platform, you just couldn&#8217;t create an account except on a Mac.</p>



<p>Remember, too, that Mac OS X didn&#8217;t exist when iTools launched.  It was Mac OS 9 &#8211; retroactively named &#8220;Classic Mac OS&#8221; re. <a href="https://en.wikipedia.org/wiki/Rosetta_(software)" data-wpel-link="external" target="_blank" rel="external noopener">Rosetta</a> etc &#8211; and for Mac users the world was a <em>very</em> different place.  Once Mac OS X did launch, iTools became even better with integration into the Finder (for iDisk).  This was over <em>six years</em> before <a href="https://en.wikipedia.org/wiki/Dropbox" data-wpel-link="external" target="_blank" rel="external noopener">Dropbox</a> even existed.</p>



<p>Hotmail and lesser known contemporaries pioneered free email, but with tight limits on usage (e.g. only 2 MB of email storage, enough for about two modern spam emails!).  .Mac offered 50 MB (upgradable to 2 GB for a fee).  This was three years before <a href="https://en.wikipedia.org/wiki/Gmail" data-wpel-link="external" target="_blank" rel="external noopener">Gmail</a> was launched, too (at which time the word &#8220;unlimited&#8221; started to get thrown around, although technically Gmail only offered 1 GB initially).</p>
</details>
</div></div>



<p>My old website dates back to <em>at the latest </em>September 2005 when I launched my blog, although I&#8217;m pretty sure I&#8217;d been using it for quite some time before that (though the <a href="https://web.archive.org" data-wpel-link="external" target="_blank" rel="external noopener">Wayback Machine</a> didn&#8217;t notice it for <em>three</em> more years, <a href="https://web.archive.org/web/20080920125519/http://homepage.mac.com/wadetregaskis/Menu14.html" data-wpel-link="external" target="_blank" rel="external noopener">until September 2008</a> 😂).</p>



<p>It took a little bit of effort to get it functioning again &#8211; it contained a lot of references to 3rd party resources (Google Adsense &amp; Analytics, Haloscan, etc) that are no longer valid / necessary, as well as to some more intrinsic .Mac HomePage functionality that&#8217;s long gone, like <a href="https://en.wikipedia.org/wiki/IDisk" data-wpel-link="external" target="_blank" rel="external noopener">iDisk</a> (the early file-sharing functionality a la Dropbox / iCloud Drive).  I pruned out most of that for the sake of removing long-dead, broken links &amp; images.</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<details class="wp-block-details is-layout-flow wp-block-details-is-layout-flow"><summary>.Mac</summary><div class="wp-block-image">
<figure class="alignleft size-full is-resized"><img loading="lazy" decoding="async" width="474" height="468" src="https://wadetregaskis.com/wp-content/uploads/2023/11/Mac-retail-box-1.avif" alt="" class="wp-image-5932" style="width:237px" srcset="https://wadetregaskis.com/wp-content/uploads/2023/11/Mac-retail-box-1.avif 474w, https://wadetregaskis.com/wp-content/uploads/2023/11/Mac-retail-box-1-256x253.avif 256w" sizes="auto, (max-width: 474px) 100vw, 474px" /></figure>
</div>

<div class="wp-block-image">
<figure class="alignright size-full is-resized"><img loading="lazy" decoding="async" width="240" height="332" src="https://wadetregaskis.com/wp-content/uploads/2023/11/Mac-logo.avif" alt="" class="wp-image-5929" style="width:120px" srcset="https://wadetregaskis.com/wp-content/uploads/2023/11/Mac-logo.avif 240w, https://wadetregaskis.com/wp-content/uploads/2023/11/Mac-logo-185x256.avif 185w" sizes="auto, (max-width: 240px) 100vw, 240px" /></figure>
</div>


<p>.Mac was <a href="https://www.apple.com/newsroom/2002/07/17Apple-Launches-Mac/" data-wpel-link="external" target="_blank" rel="external noopener">a relaunch</a> of iTools &#8211; a major version update in technical terms, but also a major departure in that it was no longer free for all Mac users.  You now had to buy it!  For actual money!  And <em>keep</em> paying for it, every year, like a caveman!  $100!</p>



<p>I still remember receiving an actual box for .Mac, and I suspect that was when I first really used the service.  I think I might have received it through <a href="https://en.wikipedia.org/wiki/Apple_University_Consortium" data-wpel-link="external" target="_blank" rel="external noopener">the AUC</a> as part of their scholarship program which effectively launched my career, lining me up to work at Apple, move to California, and all the rest.</p>



<p>As for .Mac, it was somewhat ill-received, and despite <a href="https://www.apple.com/newsroom/2002/09/17Apples-Mac-Subscribers-Top-100-000/" data-wpel-link="external" target="_blank" rel="external noopener">Apple bragging about receiving 100,000 sign-ups</a>, the general attitude was that it was too little for too much.  It didn&#8217;t help that it then went years without much improvement or attention from Apple.</p>



<p>The name was a bit weird, too &#8211; clearly playing on the .com TLD, but in an era long before the expansion of TLDs, back when there was basically just .com, .net, .org, and .edu<sup data-fn="31698b84-b059-478b-a95e-9d77210cd3ca" class="fn"><a href="#31698b84-b059-478b-a95e-9d77210cd3ca" id="31698b84-b059-478b-a95e-9d77210cd3ca-link">1</a></sup>.  It&#8217;s interesting that to this day there&#8217;s <em>still</em> no .mac TLD (although there is .apple, albeit for no apparent reason since <a href="https://www.apple.com/legal/intellectual-property/tld/" data-wpel-link="external" target="_blank" rel="external noopener">it&#8217;s retained by Apple for their exclusive use</a>, and they don&#8217;t use it).</p>



<p>Years later, in 2008, it was rebranded and &#8220;relaunched&#8221; yet again as MobileMe.  I for one don&#8217;t recall ever having significant issues with MobileMe, but it was widely lambasted for being unreliable.  I certainly don&#8217;t think it was any worse than iCloud (<em>especially</em> in light of macOS Sonoma&#8217;s catastrophic embuggering of iCloud Drive).</p>
</details>
</div></div>



<p>Incidentally, as part of this trip down memory lane, I also went through and fixed the broken images on my very earliest blog posts, that didn&#8217;t originally import into WordPress when <a href="https://wadetregaskis.com/converting-my-old-journal/" data-wpel-link="internal">I migrated off of MobileMe HomePage in 2012</a>, when the product was shut down by Apple (in favour of iCloud, which was mostly a PR move to distance themselves from perceived reliability problems with MobileMe &#8211; notably not an <em>actual</em> improvement in reliability, which to this day remains sorely needed).</p>


<ol class="wp-block-footnotes"><li id="31698b84-b059-478b-a95e-9d77210cd3ca">Well, plus .gov and .mil, but regular people never encountered those in everyday life. <a href="#31698b84-b059-478b-a95e-9d77210cd3ca-link" aria-label="Jump to footnote reference 1">↩︎</a></li></ol>]]></content:encoded>
					
					<wfw:commentRss>https://wadetregaskis.com/blog-like-its-2005/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			<media:content url="https://wadetregaskis.com/wp-content/uploads/2023/11/My-.Mac-website.webp" medium="image" />
<post-id xmlns="com-wordpress:feed-additions:1">5926</post-id>	</item>
		<item>
		<title>Migrated hosts &#038; out of the subdomain</title>
		<link>https://wadetregaskis.com/migrated-hosts-out-of-the-subdomain/</link>
					<comments>https://wadetregaskis.com/migrated-hosts-out-of-the-subdomain/#respond</comments>
		
		<dc:creator><![CDATA[]]></dc:creator>
		<pubDate>Tue, 28 Nov 2023 03:53:25 +0000</pubDate>
				<category><![CDATA[Meta]]></category>
		<category><![CDATA[Cyberduck]]></category>
		<category><![CDATA[DNS]]></category>
		<category><![CDATA[Gandi.net]]></category>
		<category><![CDATA[IONOS]]></category>
		<category><![CDATA[TLS]]></category>
		<category><![CDATA[Transmit]]></category>
		<category><![CDATA[UpdraftPlus]]></category>
		<category><![CDATA[VPS]]></category>
		<category><![CDATA[webhosting]]></category>
		<category><![CDATA[Wordpress]]></category>
		<guid isPermaLink="false">https://wadetregaskis.com/?p=5896</guid>

					<description><![CDATA[Mainly just a note for posterity &#8211; after many years of wanting to do it but procrastinating, I&#8217;ve finally migrated to a new web host. While I was doing that, I figured it was high time to drop the subdomain, so now it&#8217;s just https://wadetregaskis.com, instead of https://blog.wadetregaskis.com. Blogs are so last year. Previously I&#8230; <a class="read-more-link" href="https://wadetregaskis.com/migrated-hosts-out-of-the-subdomain/" data-wpel-link="internal">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>Mainly just a note for posterity &#8211; after many years of wanting to do it but procrastinating, I&#8217;ve finally migrated to a new web host.</p>



<p>While I was doing that, I figured it was high time to drop the subdomain, so now it&#8217;s just <a href="https://wadetregaskis.com" data-wpel-link="internal">https://wadetregaskis.com</a>, instead of <a href="https://blog.wadetregaskis.com" data-wpel-link="internal">https://blog.wadetregaskis.com</a>.  Blogs are <em>so</em> last year.</p>



<p>Previously I was using <a href="https://www.gandi.net" data-type="link" data-id="https://www.gandi.net" data-wpel-link="external" target="_blank" rel="external noopener">Gandi.net</a> (I recall choosing them because they were touted as a particularly privacy-centric host) <a href="https://www.gandi.net/en-AU/simple-hosting" data-wpel-link="external" target="_blank" rel="external noopener">shared webhosting</a>.  I&#8217;m now using an <a href="https://www.ionos.com/servers/vps" data-wpel-link="external" target="_blank" rel="external noopener">unmanaged VPS</a> from <a href="https://www.ionos.com" data-wpel-link="external" target="_blank" rel="external noopener">IONOS</a>.  This is far superior &#8211; site performance is much higher, I can finally use modern web technologies like TLS 1.3 and AVIF<sup data-fn="e357962a-2622-48d7-a0a8-7a1f62278e12" class="fn"><a href="#e357962a-2622-48d7-a0a8-7a1f62278e12" id="e357962a-2622-48d7-a0a8-7a1f62278e12-link">1</a></sup>, and frankly it&#8217;s just deeply satisfying to have a whole [virtual] machine at my disposal.  It might be a gateway to bigger things.</p>



<p>I chose IONOS because they offered the best apparent value amongst hosts that seemed well-reviewed.  I&#8217;m now paying just a <em>third</em> of what I was at Gandi.net (for what amounts to at least 2x the CPU performance and 4x the RAM!).  They also include a full copy of <a href="https://www.plesk.com" data-wpel-link="external" target="_blank" rel="external noopener">Plesk</a>, which has proven a net win in getting everything set up and configured &#8211; notwithstanding some serious initial issues with it, that ended up requiring me to reimage the whole VM and restart from scratch. 😒</p>



<p>The process took over two full days, partly because of the aforementioned Plesk issue which cost me nearly a full day by itself, and otherwise because of just a whole bunch of issues along the way.  e.g.:</p>



<ul class="wp-block-list">
<li>File transfers (via HTTPS or SFTP) to &amp; from Gandi are slow.  They always have been &#8211; it&#8217;s one of several things that always bothered me about Gandi.</li>



<li>TCP connections to Gandi tend to get killed if they hang around for any significant amount of time (such as for large file transfers over HTTPS or SFTP<sup data-fn="9a5ac91a-c7ce-450d-9d7e-d2f7434e5772" class="fn"><a href="#9a5ac91a-c7ce-450d-9d7e-d2f7434e5772" id="9a5ac91a-c7ce-450d-9d7e-d2f7434e5772-link">2</a></sup>).
<ul class="wp-block-list">
<li>This in turn exacerbated a few bugs in <a href="https://cyberduck.io" data-wpel-link="external" target="_blank" rel="external noopener">Cyberduck</a> whereby automatic retries don&#8217;t work <em>and</em> I had to manually relaunch Cyberduck completely between retries (otherwise it locked up).<br><br>I partly addressed this by using <a href="https://panic.com/transmit/" data-wpel-link="external" target="_blank" rel="external noopener">Transmit</a> instead, which isn&#8217;t <em>entirely</em> immune to Gandi&#8217;s bugginess but seemed to hit it <em>much</em> less often.  And is also a much more elegant application, in any case.</li>



<li>Combined with the general slowness, this meant it took most of an entire day to copy out the compressed copy of the old site &#8211; which was just a few gigabytes.</li>
</ul>
</li>



<li>I struggled to find a good way to migrate the site <em>before</em> committing to the actual domain name migration.  I had never migrated a WordPress site between hosts &#8211; never even restored in-place from an existing backup &#8211; so I had no real idea to what degree it would work.<br><br>This would have been easier without TLS.  I long-ago enabled HSTS for my site, and I technically could have worked around that in various ways, but no matter which approach I took I think it would have been challenging.<br><br>Ultimately I just got too frustrated and said &#8220;screw it, I&#8217;ll switch the domain name and <em>then</em> figure out how to move WordPress&#8221;.  Thankfully almost nobody visits this site, so breaking it for a day or so was inconsequential.
<ul class="wp-block-list">
<li>I made this slightly harder on myself by insisting on a &#8220;proper&#8221; TLS certificate for the new host &#8211; and therefore from IONOS since they include one free with each VPS &#8211; rather than using <a href="https://letsencrypt.org" data-wpel-link="external" target="_blank" rel="external noopener">Let&#8217;s Encrypt</a> (support for which is provided by a pre-installed <a href="https://www.plesk.com/extensions/letsencrypt/" data-wpel-link="external" target="_blank" rel="external noopener">extension</a> to Plesk).  IONOS&#8217;s control dashboard didn&#8217;t particularly want to issue the certificate while non-IONOS nameservers were used for the domain, although eventually I coaxed it into doing so.</li>
</ul>
</li>



<li>It took a while to figure out how DNS needed to be configured, between the old host (and registrar), the new host, and Cloudflare.  DNS isn&#8217;t <em>that</em> complicated in principle, I just wasn&#8217;t all that familiar with it.  I&#8217;ve added TXT records before and done a few other tweaks, but nothing of the complexity of multiple intertwined nameservers and non-trivial subdomain routing.<br><br>Although in retrospect having Cloudflare in front of everything perhaps made it easier since ultimately I just had to change settings there, as opposed to having to move nameservers.
<ul class="wp-block-list">
<li>DNS propagation delays were a significant irritation and cause of substantial delays.  After several key changes, I had no choice but to wait an indeterminate number of hours before I could see their effects and move on to subsequent steps.
<ul class="wp-block-list">
<li>macOS bugs whereby it ignores the last entry in <code>/etc/hosts</code><sup data-fn="bb84bf6a-f6e4-4802-98c5-84b06ed2ef00" class="fn"><a href="#bb84bf6a-f6e4-4802-98c5-84b06ed2ef00" id="bb84bf6a-f6e4-4802-98c5-84b06ed2ef00-link">3</a></sup> also didn&#8217;t help.</li>
</ul>
</li>
</ul>
</li>



<li><a href="https://updraftplus.com" data-wpel-link="external" target="_blank" rel="external noopener">UpdraftPlus</a> kept failing to restore the new site from a backup of the old (ultimately it turned out to be an OOM-killing problem, easily fixed by <a href="https://www.digitalocean.com/community/tutorials/how-to-add-swap-space-on-ubuntu-22-04" data-wpel-link="external" target="_blank" rel="external noopener">enabling some swap space</a>).</li>



<li>Many miscellaneous bugs in Plesk, half of which I&#8217;ve already successfully repressed, but as merely a few examples:
<ul class="wp-block-list">
<li>Plesk&#8217;s <a href="https://www.plesk.com/wp-toolkit/" data-wpel-link="external" target="_blank" rel="external noopener">WP Toolkit</a> extension <em>believes</em> it can set up a crontab entry to poke <code>wp-cron.php</code> periodically, but it can&#8217;t (because apparently you can&#8217;t invoke that directly via <code>php</code>, you have to actually go through Apache with a real HTTPS request &#8211; I never got to the bottom of why).</li>



<li>Sendmail / postfix don&#8217;t work out of the box with Plesk; WordPress &amp; Plesk just silently fail to send emails.  I never found any way to get them to log their failures, but I did ultimately get it working through trial-and-error (and I can&#8217;t even say what specific configuration change(s) actually fixed it).
<ul class="wp-block-list">
<li>It also took a while to figure out how to properly set up DKIM, SPF, and DMARC, although that was relatively straightforward once I found <a href="https://docs.plesk.com/en-US/obsidian/administrator-guide/mail/antispam-tools/dkim-spf-and-dmarc-protection.59433" data-wpel-link="external" target="_blank" rel="external noopener">this documentation</a>.</li>
</ul>
</li>



<li>After using Plesk and staying logging in just fine for over a day, on multiple computers, it suddenly decided it would log me out instantly almost every time.  This is <a href="https://duckduckgo.com/?q=plesk+logs+me+out+immediately" data-wpel-link="external" target="_blank" rel="external noopener">apparently a common issue</a>, and through sheer stubbornness of countless login cycles I was able to get to the &#8220;Allow IP address changes during a single session&#8221; checkbox, which fixed it for me.</li>
</ul>
</li>
</ul>



<p>I&#8217;m glad it&#8217;s done, and there is a solid sense of satisfaction with having conquered the litany of bugs, design flaws, and limitations throughout the whole process.</p>



<p>But I really hope I don&#8217;t have to move hosts again anytime soon.</p>


<ol class="wp-block-footnotes"><li id="e357962a-2622-48d7-a0a8-7a1f62278e12">…because I can install modern versions of basic tools &amp; libraries, like curl and ImageMagick, that support things like TLS 1.3 and AVIF. <a href="#e357962a-2622-48d7-a0a8-7a1f62278e12-link" aria-label="Jump to footnote reference 1">↩︎</a></li><li id="9a5ac91a-c7ce-450d-9d7e-d2f7434e5772">Made worse by Gandi&#8217;s weird SSH server being incompatible with rsync, thus forcing the use of all-or-nothing transfers over SFTP. <a href="#9a5ac91a-c7ce-450d-9d7e-d2f7434e5772-link" aria-label="Jump to footnote reference 2">↩︎</a></li><li id="bb84bf6a-f6e4-4802-98c5-84b06ed2ef00">It always ignores the last line of the file, so you have to explicitly add a trailing line return.  This is actually not uncommon with Unix tools of a certain pedigree, from before good design, robustness, and user-friendliness were values. <a href="#bb84bf6a-f6e4-4802-98c5-84b06ed2ef00-link" aria-label="Jump to footnote reference 3">↩︎</a></li></ol>]]></content:encoded>
					
					<wfw:commentRss>https://wadetregaskis.com/migrated-hosts-out-of-the-subdomain/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">5896</post-id>	</item>
		<item>
		<title>Now available in Fedivision®</title>
		<link>https://wadetregaskis.com/now-available-in-fedivision/</link>
					<comments>https://wadetregaskis.com/now-available-in-fedivision/#respond</comments>
		
		<dc:creator><![CDATA[]]></dc:creator>
		<pubDate>Sun, 17 Sep 2023 17:04:16 +0000</pubDate>
				<category><![CDATA[Meta]]></category>
		<category><![CDATA[ActivityPub]]></category>
		<category><![CDATA[Fediverse]]></category>
		<category><![CDATA[Mastodon]]></category>
		<category><![CDATA[Mona]]></category>
		<guid isPermaLink="false">https://blog.wadetregaskis.com/?p=5262</guid>

					<description><![CDATA[With the release today of the ActivityPub plug-in version 1, I&#8217;ve configured my wee blog here to publish to the &#8220;Fediverse&#8221; (basically, Mastodon). You can find it at @everything@blog.wadetregaskis.com. Bafflingly there&#8217;s apparently no way to deep-link into Mona (or &#8216;Mastodon&#8217; generally), so apparently you&#8217;ll have to copy-paste that user ID into your client of choice&#8217;s&#8230; <a class="read-more-link" href="https://wadetregaskis.com/now-available-in-fedivision/" data-wpel-link="internal">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>With the release today of the ActivityPub plug-in version 1, I&#8217;ve configured my wee blog here to publish to the &#8220;Fediverse&#8221; (basically, Mastodon).  You can find it at <em>@everything@blog.wadetregaskis.com</em>.</p>



<p>Bafflingly there&#8217;s apparently no way to deep-link into <a href="https://apps.apple.com/us/app/mona-for-mastodon/id1659154653" data-wpel-link="external" target="_blank" rel="external noopener">Mona</a> (or &#8216;Mastodon&#8217; generally), so apparently you&#8217;ll have to copy-paste that user ID into your client of choice&#8217;s user search.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wadetregaskis.com/now-available-in-fedivision/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">5262</post-id>	</item>
		<item>
		<title>Welcome to the Internet</title>
		<link>https://wadetregaskis.com/welcome-to-the-internet/</link>
					<comments>https://wadetregaskis.com/welcome-to-the-internet/#comments</comments>
		
		<dc:creator><![CDATA[]]></dc:creator>
		<pubDate>Sun, 13 Mar 2022 20:29:32 +0000</pubDate>
				<category><![CDATA[Meta]]></category>
		<category><![CDATA[Photography]]></category>
		<category><![CDATA[comments]]></category>
		<category><![CDATA[feedback]]></category>
		<category><![CDATA[Nikon]]></category>
		<category><![CDATA[Nikon Rumors]]></category>
		<category><![CDATA[trolls]]></category>
		<category><![CDATA[Z9]]></category>
		<guid isPermaLink="false">https://blog.wadetregaskis.com/?p=5083</guid>

					<description><![CDATA[Nikon Rumors recently ran my Nikon Z9 second impressions as a guest post on their site. That was very flattering. It was also a novel experience for me &#8211; generally nobody reads what I post here on my blog, and it&#8217;s as much for my own benefit as anything else (e.g. a form of &#8220;rubber&#8230; <a class="read-more-link" href="https://wadetregaskis.com/welcome-to-the-internet/" data-wpel-link="internal">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>Nikon Rumors recently ran my <a href="https://wadetregaskis.com/z9-second-impressions/" data-wpel-link="internal">Nikon Z9 second impressions</a> as <a rel="noreferrer noopener external" href="https://nikonrumors.com/2022/03/12/nikon-z9-camera-first-impressions.aspx/" data-type="URL" data-id="https://nikonrumors.com/2022/03/12/nikon-z9-camera-first-impressions.aspx/" target="_blank" data-wpel-link="external">a guest post on their site</a>.  That was very flattering.  It was also a novel experience for me &#8211; generally nobody reads what I post here on my blog, and it&#8217;s as much for my own benefit as anything else (e.g. a form of &#8220;rubber ducking&#8221; when I&#8217;m trying to figure something out, or simply a record of my thoughts for me to laugh at in years to come).</p>



<p>I was surprised how much traffic it brought to my site &#8211; my vague intuition was that with the content repeated wholesale there&#8217;d be no motivation for folks to visit the original.</p>



<p>I was also slightly surprised by the comments section (on Nikon Rumors), though upon reflection I probably shouldn&#8217;t have been.  As Peter (Nikon Rumors admin) quipped to me, &#8220;Welcome to the Internet :)&#8221;.</p>



<p>Roughly-speaking, it seems to break down into:</p>



<h3 class="wp-block-heading">Constructive</h3>



<p>A very small portion of the feedback was constructive (and sometimes intentionally so, even), e.g. typos, my embarrassing mislabelling of a jaguar as a leopard, etc.  Some was interesting in revealing unintended ambiguity in my phrasing &#8211; I always find it intriguing to find valid, <em>different</em> interpretations of things I wrote.  It&#8217;s a worthy challenge to try to write without ambiguity.</p>



<p>I really appreciate when people provide useful feedback &#8211; even if it&#8217;s not well-motivated.  It&#8217;s so rare in life to receive useful feedback.</p>



<h3 class="wp-block-heading">Missing context</h3>



<p>A lot of the feedback was because of missing context &#8211; many folks assumed it was a <em>review</em>, not merely a random collection of observations, and therefore meant to be balanced &amp; comprehensive.  Or that I&#8217;d only use the Sigma 150-600 C with the Z9 (I did mention use of other lenses, but apparently too briefly or obliquely for many to register).</p>



<p>That&#8217;s useful to know because it revealed I was unwittingly assuming folks would read the first impressions first, which provided a bit more context, and also assuming a lot about the reader&#8217;s mindset coming in &#8211; i.e. that they&#8217;d implicitly understand that a lot was tongue-in-cheek.</p>



<h3 class="wp-block-heading">Missed sarcasm / irony / frivolity</h3>



<p>It seems apparent from some comments that my sense of humour / writing style just didn&#8217;t sit well with many folks.  I&#8217;m used to that &#8211; I hate irony and never use it all the time.</p>



<p>The Nikon Z9&#8217;s acrobatic abilities seemed to particularly rub many folks the wrong way, which even in retrospect I still find odd because it seems so obviously (a) a very minor concern in any case and (b) just funny, really.  Many folks did wonder aloud why I had my camera loose in a car anyway, which is a totally valid question and one I didn&#8217;t think for a minute to address when I wrote the article.</p>



<p>(for the record, it&#8217;s mainly because I&#8217;d never really needed to before, and I like having the camera readily available &#8211; plus I&#8217;ve since figured out that I can kind of wedge the Z9 under the seats, in the rear footwells, so problem solved!)</p>



<h3 class="wp-block-heading">Mean</h3>



<p>Sadly, most feedback was acerbic and ill-intentioned.  Thankfully the novelty of the occasion neutered the mean-spirited comments, and they&#8217;re easy to skim over because they tend to be repetitive, pithy, and thus easy to identify.  I&#8217;m a bit mystified as to why those folks spend their time that way, though.  Some kind of game?  Catharsis?</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wadetregaskis.com/welcome-to-the-internet/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">5083</post-id>	</item>
		<item>
		<title>Yay!  An actual outage!  I&#8217;m a real blog now!</title>
		<link>https://wadetregaskis.com/yay-an-actual-outage-im-a-real-blog-now/</link>
					<comments>https://wadetregaskis.com/yay-an-actual-outage-im-a-real-blog-now/#respond</comments>
		
		<dc:creator><![CDATA[]]></dc:creator>
		<pubDate>Thu, 31 Mar 2016 17:08:31 +0000</pubDate>
				<category><![CDATA[Meta]]></category>
		<category><![CDATA[Bugs!]]></category>
		<category><![CDATA[crashtastic]]></category>
		<category><![CDATA[lies]]></category>
		<category><![CDATA[Site down!]]></category>
		<category><![CDATA[Wordpress]]></category>
		<guid isPermaLink="false">https://blog.wadetregaskis.com/?p=3614</guid>

					<description><![CDATA[I woke up this morning to find that my website &#8211; this one &#8211; had gone down only a few minutes earlier.  The host&#8217;s website, Gandi.net, was acting flaky and not letting me log in either, so I figured it was a widespread issue on their end. A few hours later, Gandi.net was working again,&#8230; <a class="read-more-link" href="https://wadetregaskis.com/yay-an-actual-outage-im-a-real-blog-now/" data-wpel-link="internal">Read more</a>]]></description>
										<content:encoded><![CDATA[<p>I woke up this morning to find that my website &#8211; this one &#8211; had gone down only a few minutes earlier.  The host&#8217;s website, Gandi.net, was acting flaky and not letting me log in either, so I figured it was a widespread issue on their end.</p>
<p>A few hours later, Gandi.net was working again, but my site wasn&#8217;t.  Sad panda.</p>
<p>Long story short, I used up all the disk space &#8211; and by &#8220;I&#8221;, I mean <em>something</em> &#8211; still haven&#8217;t figured out what, yet.  Apparently when you use up all the space, that simply kills the VM without any notification (their dashboard for my VM still claimed it was running just fine, no problems detected, which was obvious crap).</p>
<p>That said, their tech support identified the problem quickly and were ultimately able to rectify things for me (after first suggesting I delete some stuff myself, which I tried only to find that when your Gandi VM is wedged in this state, you can&#8217;t log in via SSH nor delete anything via SFTP, and those are your only two means for deleting any files…).</p>
<p>As far as I can recall, this is the first time my site&#8217;s actually been down in the ~four years I&#8217;ve hosted with them (other than a few errors on my part when messing with WordPress etc).</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wadetregaskis.com/yay-an-actual-outage-im-a-real-blog-now/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3614</post-id>	</item>
		<item>
		<title>Four years &#038; time for a new theme</title>
		<link>https://wadetregaskis.com/four-years-time-for-a-new-theme/</link>
					<comments>https://wadetregaskis.com/four-years-time-for-a-new-theme/#respond</comments>
		
		<dc:creator><![CDATA[]]></dc:creator>
		<pubDate>Wed, 30 Mar 2016 02:31:25 +0000</pubDate>
				<category><![CDATA[Meta]]></category>
		<category><![CDATA[Bugs!]]></category>
		<category><![CDATA[Sad]]></category>
		<category><![CDATA[Wordpress]]></category>
		<guid isPermaLink="false">https://blog.wadetregaskis.com/?p=3553</guid>

					<description><![CDATA[It&#8217;s been a bit over four years since I moved this blog off of the old statically-built site, by iBlog 2, to WordPress.  Apparently it&#8217;s time for an updated theme. Actually, Suffusion was pissing me off as per usual, and I accidentally applied a new theme when intending only to install it (apparently &#8216;Activating&#8217; a&#8230; <a class="read-more-link" href="https://wadetregaskis.com/four-years-time-for-a-new-theme/" data-wpel-link="internal">Read more</a>]]></description>
										<content:encoded><![CDATA[<p>It&#8217;s been a bit over four years since I moved this blog off of the old statically-built site, by iBlog 2, to WordPress.  Apparently it&#8217;s time for an updated theme.</p>
<p>Actually, Suffusion was pissing me off as per usual, and I accidentally applied a new theme when intending only to install it (apparently &#8216;Activating&#8217; a theme applies it, which is sensible in hindsight but not as clear as it should be given how plug-ins work).  Turns out, you can&#8217;t easily go back &#8211; changing themes permanently wipes out a bunch of settings.  #%@!</p>
<p>And as per usual the backups plug-in I have installed had silently wedged itself and failed to back anything up for a couple of months.  Sigh.</p>
<p>WordPress is kinda shit.  It&#8217;s a mess.  A complicated, slow, buggy mess.  If I actually cared to spend any more time on this site, I&#8217;d start by looking for another platform.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wadetregaskis.com/four-years-time-for-a-new-theme/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3553</post-id>	</item>
		<item>
		<title>Best viewed on an iPad 3</title>
		<link>https://wadetregaskis.com/best-viewed-on-an-ipad-3/</link>
					<comments>https://wadetregaskis.com/best-viewed-on-an-ipad-3/#comments</comments>
		
		<dc:creator><![CDATA[]]></dc:creator>
		<pubDate>Tue, 20 Mar 2012 07:10:12 +0000</pubDate>
				<category><![CDATA[Meta]]></category>
		<category><![CDATA[iPad]]></category>
		<guid isPermaLink="false">http://blog.wadetregaskis.com/?p=2381</guid>

					<description><![CDATA[I really like the text rendering on my iPad 3.  Yes, it&#8217;s ostensibly much the same as the iPhone 4 I&#8217;ve had for a while.  But it&#8217;s not.  The relatively huge screen makes a world of difference. So I&#8217;ve changed the font of this &#8216;ere website to something that looks nicer on the iPad 3.  It&#8230; <a class="read-more-link" href="https://wadetregaskis.com/best-viewed-on-an-ipad-3/" data-wpel-link="internal">Read more</a>]]></description>
										<content:encoded><![CDATA[<p>I <em>really</em> like the text rendering on my iPad 3.  Yes, it&#8217;s ostensibly much the same as the iPhone 4 I&#8217;ve had for a while.  But it&#8217;s not.  The relatively huge screen makes a world of difference.</p>
<p>So I&#8217;ve changed the font of this &#8216;ere website to something that looks nicer on the iPad 3.  It looks less impressive on pretty much any other device.  So get an iPad 3.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wadetregaskis.com/best-viewed-on-an-ipad-3/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2381</post-id>	</item>
		<item>
		<title>Python</title>
		<link>https://wadetregaskis.com/python/</link>
					<comments>https://wadetregaskis.com/python/#respond</comments>
		
		<dc:creator><![CDATA[]]></dc:creator>
		<pubDate>Fri, 24 Feb 2012 07:59:59 +0000</pubDate>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Meta]]></category>
		<guid isPermaLink="false">http://blog.wadetregaskis.com/?p=2307</guid>

					<description><![CDATA[One good thing about working at Google has been that I&#8217;ve finally learnt Python. Properly. Which means I can whip up, in just a couple of minutes, a tested &#38; documented script to, say, replace ~2,500 HTML files with redirects. So now anyone using an old link to any HTML page under https://homepage.mac.com/wadetregaskis will get&#8230; <a class="read-more-link" href="https://wadetregaskis.com/python/" data-wpel-link="internal">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>One good thing about working at Google has been that I&#8217;ve finally learnt Python. Properly. Which means I can whip up, in just a couple of minutes, a tested &amp; documented script to, say, replace ~2,500 <acronym title="HyperText Markup Language">HTML</acronym> files with redirects. So now anyone using an old link to any <acronym title="HyperText Markup Language">HTML</acronym> page under <a href="https://web.archive.org/web/20080920125519/http://homepage.mac.com/wadetregaskis/Menu14.html" data-wpel-link="external" target="_blank" rel="external noopener">https://homepage.mac.com/wadetregaskis</a> will get automagically redirected to the page&#8217;s new location, here on <a href="https://wadetregaskis.com" data-wpel-link="internal">https://wadetregaskis.com</a> (shoved aside under /MobileMe/Sites/, &#8217;cause in theory I&#8217;ll be doing a real website from scratch).</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="" style="font-size:.875rem;line-height:1.25rem;--cbp-tab-width:4;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="#!/usr/bin/python

import errno
import os
import sys
import urllib


if 3 != len(sys.argv) or '-h' in sys.argv or '--help' in sys.argv or 'help' in sys.argv:
    print &gt;&gt; sys.stderr, '''Usage: {0} SITE_FOLDER NEW_BASE_URL

SITE_FOLDER is the path to the local folder containing the site to be redirected.
NEW_BASE_URL is the base URL of the new site, to which the redirects will point.  It is up to you to ensure proper URL escaping is performed; it will not be done by this script (except for the paths this script generates, to then append to this base URL).

For example, if the local path /www/mysite/ is used for SITE_FOLDER, and NEW_BASE_URL is given as &quot;http://foo.com/&quot;, then for a file /www/mysite/index.html a redirect will be created to &quot;http://foo.com/index.html&quot;.'''.format(sys.argv[0])
    exit(errno.EINVAL)

(_, siteFolder, newBaseURL) = sys.argv

if not newBaseURL.endswith('/'):
    newBaseURL = newBaseURL + '/'

siteFolderPathLength = len(siteFolder)

if not siteFolder.endswith('/'):
    siteFolderPathLength += 1

for (folder, subFolders, files) in os.walk(siteFolder):
    relativePath = folder[siteFolderPathLength:]
    
    if relativePath:
        relativePath = relativePath + '/'
    
    relativePath = urllib.quote(relativePath)
    
    for file in files:
        (_, fileExtension) = os.path.splitext(file)
        
        if fileExtension in (&quot;.htm&quot;, &quot;.html&quot;, &quot;.xhtml&quot;):
            replacementContents = '''&lt;html&gt;
    &lt;head&gt;
        &lt;meta http-equiv=&quot;refresh&quot; content=&quot;0;url={0}{1}{2}&quot;&gt;
        &lt;script src=&quot;http://www.google-analytics.com/urchin.js&quot; type=&quot;text/javascript&quot; /&gt;
        &lt;script type=&quot;text/javascript&quot;&gt;
            _uacct = &quot;UA-103051-1&quot;;
            urchinTracker();
        &lt;/script&gt;
    &lt;/head&gt;
    &lt;body&gt;&lt;/body&gt;
&lt;/html&gt;'''.format(newBaseURL, relativePath, urllib.quote(file))

            #print &quot;Would replace {0}/{1} with:\n\n{2}\n\n&quot;.format(folder, file, replacementContents)

            with open(os.path.join(folder, file), &quot;w&quot;) as f:
                f.write(replacementContents)" style="color:#24292eff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki min-light" style="background-color: #ffffff" tabindex="0"><code><span class="line"><span style="color: #C2C3C5">#!/usr/bin/python</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D32F2F">import</span><span style="color: #24292EFF"> errno</span></span>
<span class="line"><span style="color: #D32F2F">import</span><span style="color: #24292EFF"> os</span></span>
<span class="line"><span style="color: #D32F2F">import</span><span style="color: #24292EFF"> sys</span></span>
<span class="line"><span style="color: #D32F2F">import</span><span style="color: #24292EFF"> urllib</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #D32F2F">if</span><span style="color: #24292EFF"> </span><span style="color: #1976D2">3</span><span style="color: #24292EFF"> </span><span style="color: #D32F2F">!=</span><span style="color: #24292EFF"> </span><span style="color: #6F42C1">len</span><span style="color: #212121">(sys.argv)</span><span style="color: #24292EFF"> </span><span style="color: #D32F2F">or</span><span style="color: #24292EFF"> </span><span style="color: #22863A">&#39;-h&#39;</span><span style="color: #24292EFF"> </span><span style="color: #D32F2F">in</span><span style="color: #24292EFF"> sys</span><span style="color: #212121">.</span><span style="color: #24292EFF">argv </span><span style="color: #D32F2F">or</span><span style="color: #24292EFF"> </span><span style="color: #22863A">&#39;--help&#39;</span><span style="color: #24292EFF"> </span><span style="color: #D32F2F">in</span><span style="color: #24292EFF"> sys</span><span style="color: #212121">.</span><span style="color: #24292EFF">argv </span><span style="color: #D32F2F">or</span><span style="color: #24292EFF"> </span><span style="color: #22863A">&#39;help&#39;</span><span style="color: #24292EFF"> </span><span style="color: #D32F2F">in</span><span style="color: #24292EFF"> sys</span><span style="color: #212121">.</span><span style="color: #24292EFF">argv</span><span style="color: #212121">:</span></span>
<span class="line"><span style="color: #24292EFF">    </span><span style="color: #6F42C1">print</span><span style="color: #24292EFF"> </span><span style="color: #D32F2F">&gt;&gt;</span><span style="color: #24292EFF"> sys</span><span style="color: #212121">.</span><span style="color: #24292EFF">stderr</span><span style="color: #212121">,</span><span style="color: #24292EFF"> </span><span style="color: #22863A">&#39;&#39;&#39;Usage: </span><span style="color: #1976D2">{0}</span><span style="color: #22863A"> SITE_FOLDER NEW_BASE_URL</span></span>
<span class="line"></span>
<span class="line"><span style="color: #22863A">SITE_FOLDER is the path to the local folder containing the site to be redirected.</span></span>
<span class="line"><span style="color: #22863A">NEW_BASE_URL is the base URL of the new site, to which the redirects will point.  It is up to you to ensure proper URL escaping is performed; it will not be done by this script (except for the paths this script generates, to then append to this base URL).</span></span>
<span class="line"></span>
<span class="line"><span style="color: #22863A">For example, if the local path /www/mysite/ is used for SITE_FOLDER, and NEW_BASE_URL is given as &quot;http://foo.com/&quot;, then for a file /www/mysite/index.html a redirect will be created to &quot;http://foo.com/index.html&quot;.&#39;&#39;&#39;</span><span style="color: #212121">.</span><span style="color: #6F42C1">format</span><span style="color: #212121">(sys.argv[</span><span style="color: #1976D2">0</span><span style="color: #212121">])</span></span>
<span class="line"><span style="color: #24292EFF">    </span><span style="color: #6F42C1">exit</span><span style="color: #212121">(errno.EINVAL)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #24292EFF">(_</span><span style="color: #212121">,</span><span style="color: #24292EFF"> siteFolder</span><span style="color: #212121">,</span><span style="color: #24292EFF"> newBaseURL) </span><span style="color: #D32F2F">=</span><span style="color: #24292EFF"> sys</span><span style="color: #212121">.</span><span style="color: #24292EFF">argv</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D32F2F">if</span><span style="color: #24292EFF"> </span><span style="color: #D32F2F">not</span><span style="color: #24292EFF"> newBaseURL</span><span style="color: #212121">.</span><span style="color: #6F42C1">endswith</span><span style="color: #212121">(</span><span style="color: #22863A">&#39;/&#39;</span><span style="color: #212121">):</span></span>
<span class="line"><span style="color: #24292EFF">    newBaseURL </span><span style="color: #D32F2F">=</span><span style="color: #24292EFF"> newBaseURL </span><span style="color: #D32F2F">+</span><span style="color: #24292EFF"> </span><span style="color: #22863A">&#39;/&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #24292EFF">siteFolderPathLength </span><span style="color: #D32F2F">=</span><span style="color: #24292EFF"> </span><span style="color: #6F42C1">len</span><span style="color: #212121">(siteFolder)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D32F2F">if</span><span style="color: #24292EFF"> </span><span style="color: #D32F2F">not</span><span style="color: #24292EFF"> siteFolder</span><span style="color: #212121">.</span><span style="color: #6F42C1">endswith</span><span style="color: #212121">(</span><span style="color: #22863A">&#39;/&#39;</span><span style="color: #212121">):</span></span>
<span class="line"><span style="color: #24292EFF">    siteFolderPathLength </span><span style="color: #D32F2F">+=</span><span style="color: #24292EFF"> </span><span style="color: #1976D2">1</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D32F2F">for</span><span style="color: #24292EFF"> (folder</span><span style="color: #212121">,</span><span style="color: #24292EFF"> subFolders</span><span style="color: #212121">,</span><span style="color: #24292EFF"> files) </span><span style="color: #D32F2F">in</span><span style="color: #24292EFF"> os</span><span style="color: #212121">.</span><span style="color: #6F42C1">walk</span><span style="color: #212121">(siteFolder):</span></span>
<span class="line"><span style="color: #24292EFF">    relativePath </span><span style="color: #D32F2F">=</span><span style="color: #24292EFF"> folder</span><span style="color: #212121">[</span><span style="color: #24292EFF">siteFolderPathLength</span><span style="color: #212121">:]</span></span>
<span class="line"><span style="color: #24292EFF">    </span></span>
<span class="line"><span style="color: #24292EFF">    </span><span style="color: #D32F2F">if</span><span style="color: #24292EFF"> relativePath</span><span style="color: #212121">:</span></span>
<span class="line"><span style="color: #24292EFF">        relativePath </span><span style="color: #D32F2F">=</span><span style="color: #24292EFF"> relativePath </span><span style="color: #D32F2F">+</span><span style="color: #24292EFF"> </span><span style="color: #22863A">&#39;/&#39;</span></span>
<span class="line"><span style="color: #24292EFF">    </span></span>
<span class="line"><span style="color: #24292EFF">    relativePath </span><span style="color: #D32F2F">=</span><span style="color: #24292EFF"> urllib</span><span style="color: #212121">.</span><span style="color: #6F42C1">quote</span><span style="color: #212121">(relativePath)</span></span>
<span class="line"><span style="color: #24292EFF">    </span></span>
<span class="line"><span style="color: #24292EFF">    </span><span style="color: #D32F2F">for</span><span style="color: #24292EFF"> file </span><span style="color: #D32F2F">in</span><span style="color: #24292EFF"> files</span><span style="color: #212121">:</span></span>
<span class="line"><span style="color: #24292EFF">        (_</span><span style="color: #212121">,</span><span style="color: #24292EFF"> fileExtension) </span><span style="color: #D32F2F">=</span><span style="color: #24292EFF"> os</span><span style="color: #212121">.</span><span style="color: #24292EFF">path</span><span style="color: #212121">.</span><span style="color: #6F42C1">splitext</span><span style="color: #212121">(file)</span></span>
<span class="line"><span style="color: #24292EFF">        </span></span>
<span class="line"><span style="color: #24292EFF">        </span><span style="color: #D32F2F">if</span><span style="color: #24292EFF"> fileExtension </span><span style="color: #D32F2F">in</span><span style="color: #24292EFF"> (</span><span style="color: #22863A">&quot;.htm&quot;</span><span style="color: #212121">,</span><span style="color: #24292EFF"> </span><span style="color: #22863A">&quot;.html&quot;</span><span style="color: #212121">,</span><span style="color: #24292EFF"> </span><span style="color: #22863A">&quot;.xhtml&quot;</span><span style="color: #24292EFF">)</span><span style="color: #212121">:</span></span>
<span class="line"><span style="color: #24292EFF">            replacementContents </span><span style="color: #D32F2F">=</span><span style="color: #24292EFF"> </span><span style="color: #22863A">&#39;&#39;&#39;&lt;html&gt;</span></span>
<span class="line"><span style="color: #22863A">    &lt;head&gt;</span></span>
<span class="line"><span style="color: #22863A">        &lt;meta http-equiv=&quot;refresh&quot; content=&quot;0;url=</span><span style="color: #1976D2">{0}{1}{2}</span><span style="color: #22863A">&quot;&gt;</span></span>
<span class="line"><span style="color: #22863A">        &lt;script src=&quot;http://www.google-analytics.com/urchin.js&quot; type=&quot;text/javascript&quot; /&gt;</span></span>
<span class="line"><span style="color: #22863A">        &lt;script type=&quot;text/javascript&quot;&gt;</span></span>
<span class="line"><span style="color: #22863A">            _uacct = &quot;UA-103051-1&quot;;</span></span>
<span class="line"><span style="color: #22863A">            urchinTracker();</span></span>
<span class="line"><span style="color: #22863A">        &lt;/script&gt;</span></span>
<span class="line"><span style="color: #22863A">    &lt;/head&gt;</span></span>
<span class="line"><span style="color: #22863A">    &lt;body&gt;&lt;/body&gt;</span></span>
<span class="line"><span style="color: #22863A">&lt;/html&gt;&#39;&#39;&#39;</span><span style="color: #212121">.</span><span style="color: #6F42C1">format</span><span style="color: #212121">(newBaseURL, relativePath, urllib.</span><span style="color: #6F42C1">quote</span><span style="color: #212121">(file))</span></span>
<span class="line"></span>
<span class="line"><span style="color: #24292EFF">            </span><span style="color: #C2C3C5">#print &quot;Would replace {0}/{1} with:\n\n{2}\n\n&quot;.format(folder, file, replacementContents)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #24292EFF">            </span><span style="color: #D32F2F">with</span><span style="color: #24292EFF"> </span><span style="color: #6F42C1">open</span><span style="color: #212121">(os.path.</span><span style="color: #6F42C1">join</span><span style="color: #212121">(folder, file), </span><span style="color: #22863A">&quot;w&quot;</span><span style="color: #212121">)</span><span style="color: #24292EFF"> </span><span style="color: #D32F2F">as</span><span style="color: #24292EFF"> f</span><span style="color: #212121">:</span></span>
<span class="line"><span style="color: #24292EFF">                f</span><span style="color: #212121">.</span><span style="color: #6F42C1">write</span><span style="color: #212121">(replacementContents)</span></span></code></pre></div>



<p>What&#8217;s more difficult, however, is updating all the absolute paths and other references to homepage.mac.com within the <acronym title="HyperText Markup Language">HTML</acronym> files, now that they&#8217;re hosted on wadetregaskis.com. I did a bunch by hand, then realised there&#8217;s over a thousand <acronym title="HyperText Markup Language">HTML</acronym> files in the Photos subfolder that each contain many homepage.mac.com links. Sod.</p>



<p>I had a quick look for a utility to perform this, but found only a handful, and none that support Macs. I&#8217;m sure there&#8217;s tools out there, probably Perl or Python or Ruby scripts, that would ultimately work, but finding them is probably more trouble than just reproducing them myself.</p>



<p>I also tried BBEdit, knowing it had <acronym title="File Transfer Protocol">FTP</acronym> support (but no <acronym title="File Transfer Protocol with SSL/TLS">FTPS</acronym>, dangerously), but it doesn&#8217;t appear willing to perform a search &amp; replace via it. Bollocks.</p>



<p>Maybe I can write another script, but I&#8217;ve never done <acronym title="File Transfer Protocol with SSL/TLS">FTPS</acronym> in Python before. Hmm&#8230;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wadetregaskis.com/python/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2307</post-id>	</item>
		<item>
		<title>WordPress doesn&#8217;t get time zones</title>
		<link>https://wadetregaskis.com/wordpress-doesnt-get-time-zones/</link>
					<comments>https://wadetregaskis.com/wordpress-doesnt-get-time-zones/#respond</comments>
		
		<dc:creator><![CDATA[]]></dc:creator>
		<pubDate>Wed, 22 Feb 2012 00:01:14 +0000</pubDate>
				<category><![CDATA[Meta]]></category>
		<category><![CDATA[Snafu]]></category>
		<guid isPermaLink="false">http://blog.wadetregaskis.com/?p=2185</guid>

					<description><![CDATA[WordPress apparently has no understanding of time zones, at least in the sense that makes sense &#8211; it displays all times in the local time of the viewer (at least, I hope it does&#8230; the alternative is that it displays all times as PST, which would be highly suspect). So all my old, imported posts,&#8230; <a class="read-more-link" href="https://wadetregaskis.com/wordpress-doesnt-get-time-zones/" data-wpel-link="internal">Read more</a>]]></description>
										<content:encoded><![CDATA[<p>WordPress apparently has no understanding of time zones, at least in the sense that makes sense &#8211; it displays all times in the local time of the viewer (at least, I hope it does&#8230; the alternative is that it displays all times as PST, which would be highly suspect).  So all my old, imported posts, written way back when I lived in Australia, show up as having been posted about 17 hours ahead of reality.</p>
<p>So no, I didn&#8217;t write all my journal entries between midnight and eight in the morning.  Just ignore WordPress &#8211; try not to make eye contact as you back away, slowly&#8230;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wadetregaskis.com/wordpress-doesnt-get-time-zones/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2185</post-id>	</item>
		<item>
		<title>Converting my old journal</title>
		<link>https://wadetregaskis.com/converting-my-old-journal/</link>
					<comments>https://wadetregaskis.com/converting-my-old-journal/#respond</comments>
		
		<dc:creator><![CDATA[]]></dc:creator>
		<pubDate>Tue, 21 Feb 2012 04:11:41 +0000</pubDate>
				<category><![CDATA[Meta]]></category>
		<guid isPermaLink="false">http://blog.wadetregaskis.com/?p=31</guid>

					<description><![CDATA[It appears there&#8217;s simply no way to directly convert from iBlog to WordPress.  Awkward.  iBlog ostensibly has some ability to export the blog, but the relevant menu items are permanently greyed out.  Likewise WordPress ostensibly has many plugins for performing HTML import, but they really suck (and also just ignore categories, tags and other metadata,&#8230; <a class="read-more-link" href="https://wadetregaskis.com/converting-my-old-journal/" data-wpel-link="internal">Read more</a>]]></description>
										<content:encoded><![CDATA[<p>It appears there&#8217;s simply no way to directly convert from iBlog to WordPress.  Awkward.  iBlog ostensibly has some ability to export the blog, but the relevant menu items are permanently greyed out.  Likewise WordPress ostensibly has many plugins for performing HTML import, but they really suck (and also just ignore categories, tags and other metadata, as far as I can tell).</p>
<p>So I had no choice &#8211; I had to write my own converter.  A quick and very nasty hack in Python; 175 lines and a few hours later, with one false start (WordPress interprets line returns in its XML as essentially &lt;br&gt;s, which is awkward since iBlog hard wraps everything at ~80 columns).  But it&#8217;s done.  Well, mostly&#8230; I only pulled in the text, not the multimedia &#8211; pictures, mainly.  I guess I&#8217;ll have to think about how I can fix all those up&#8230; thankfully most of my old posts didn&#8217;t make use of any additional &#8220;attachments&#8221;, so it might even be feasible to fix things manually.</p>
<p>I contemplated generating replacement HTML files for all the existing content on MobileMe, with redirects to the new equivalents here&#8230; but then I thought, holy crap, that&#8217;d be a lot of work.  And for something which is going irreversibly dark in four or five months anyway. So to those who have bookmarks, we salute you..</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wadetregaskis.com/converting-my-old-journal/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">31</post-id>	</item>
		<item>
		<title>Urgh, WordPress theming</title>
		<link>https://wadetregaskis.com/urgh-wordpress-theming/</link>
					<comments>https://wadetregaskis.com/urgh-wordpress-theming/#respond</comments>
		
		<dc:creator><![CDATA[]]></dc:creator>
		<pubDate>Mon, 20 Feb 2012 19:08:57 +0000</pubDate>
				<category><![CDATA[Meta]]></category>
		<category><![CDATA[Snafu]]></category>
		<guid isPermaLink="false">http://blog.wadetregaskis.com/?p=19</guid>

					<description><![CDATA[Thus far this [long] weekend I&#8217;ve spent an unhealthy amount of time just trying to make this look good.  Installing WordPress itself is trivial, but then finding a half-decent theme, and then getting that theme to look exactly the way you want, is immensely time consuming and frustrating. For example, I want icons for each&#8230; <a class="read-more-link" href="https://wadetregaskis.com/urgh-wordpress-theming/" data-wpel-link="internal">Read more</a>]]></description>
										<content:encoded><![CDATA[<p>Thus far this [long] weekend I&#8217;ve spent an unhealthy amount of time just trying to make this look good.  Installing WordPress itself is trivial, but then finding a half-decent theme, and then getting that theme to look exactly the way you want, is immensely time consuming and frustrating.</p>
<p>For example, I want icons for each category.  It&#8217;s not an original idea &#8211; I did as much with my original journal years ago &#8211; and you&#8217;d think it would be brain-dead simple.  Indeed, this &#8220;Suffusion&#8221; theme even shows what you&#8217;d think are generic, placeholder icons for categories.  All ready to be replaced with the real ones.</p>
<p>Only, not really.  Apparently it just really likes showing these bland default icons repeatedly, redundantly, and in fact without any way to even turn them off (in the sidebar).  WTF.</p>
<p>I&#8217;m very quickly getting the feeling that when it comes to WordPress, you either find a theme that is exactly right to begin with, or you just concede defeat.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wadetregaskis.com/urgh-wordpress-theming/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">19</post-id>	</item>
		<item>
		<title>The Return of the Whim</title>
		<link>https://wadetregaskis.com/the-return-of-the-whim/</link>
					<comments>https://wadetregaskis.com/the-return-of-the-whim/#comments</comments>
		
		<dc:creator><![CDATA[]]></dc:creator>
		<pubDate>Mon, 20 Feb 2012 08:51:24 +0000</pubDate>
				<category><![CDATA[Meta]]></category>
		<guid isPermaLink="false">http://blog.wadetregaskis.com/?p=9</guid>

					<description><![CDATA[I&#8217;ve decided to finally get my website in order.  Partly because of MobileMe&#8217;s impending closure, but also because I&#8217;ve wanted to resume blogging for a long time now, and especially so most recently because of my renewed interest in coding for pleasure. I&#8217;ll be moving the old site and most of its content over here&#8230; <a class="read-more-link" href="https://wadetregaskis.com/the-return-of-the-whim/" data-wpel-link="internal">Read more</a>]]></description>
										<content:encoded><![CDATA[<p>I&#8217;ve decided to finally get my website in order.  Partly because of MobileMe&#8217;s impending closure, but also because I&#8217;ve wanted to resume blogging for a long time now, and especially so most recently because of my renewed interest in coding for pleasure.</p>
<p>I&#8217;ll be moving the old site and most of its content over here &#8211; I may even go to the effort of importing my old journal into this new, shiny, WordPress-powered version.  Or not.  We&#8217;ll see how easy that is.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wadetregaskis.com/the-return-of-the-whim/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">9</post-id>	</item>
	</channel>
</rss>
