<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Get Info: #markdown</title>
    <description>Posts tagged “markdown” — Blog of independent game and app developer Matt Sephton. Featuring vintage Macintosh, game development, digital artwork, Japanese esoterica, video game reviews, hacks and tips, and much more.</description>
    <link>https://blog.gingerbeardman.com/tag/markdown/</link>
    <atom:link href="https://blog.gingerbeardman.com/tag/markdown/index.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Wed, 01 Jul 2026 16:09:47 +0000</pubDate>
    <lastBuildDate>Wed, 01 Jul 2026 16:09:47 +0000</lastBuildDate>
    <generator>Jekyll v4.4.1</generator>

    
      
        <item>
          <title>Automating the most annoying aspects of blogging</title>
          <description>&lt;p&gt;Back in 2021 I had a look around and decided to base this incarnation of my blog on an open-source &lt;a href=&quot;https://jekyllrb.com&quot;&gt;Jekyll&lt;/a&gt; theme called “&lt;a href=&quot;https://github.com/ahmadajmi/type&quot;&gt;Type&lt;/a&gt;”, though I’ve changed and added so much it’s quite some distance from the original as it stands today. As I added blog posts the performance became much worse. Initially I blamed Jekyll for this, until I took a closer look. What I learned was that the blog theme did some things in sub-optimal ways, so over the course of 2024 I have corrected as many of them as I can. Build time dropped from ~12 seconds to ~1 second.&lt;/p&gt;

&lt;p&gt;My fixes and optimisations included:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Optimised SASS to compile once in plugin rather than header of every page (23 Feb)&lt;/li&gt;
  &lt;li&gt;Optimised all includes and templates to reduce build time (19 Aug)&lt;/li&gt;
  &lt;li&gt;Improved “noun” replacement, which are automatically-emphasised words (3 Sep)&lt;/li&gt;
  &lt;li&gt;Better YouTube embeds using lite-yt-embed (11 Sep)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And my additions along the way:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Multi-carousel support (14 Jul)&lt;/li&gt;
  &lt;li&gt;Automatic transformation of local images urls to CDN urls (19 Aug)&lt;/li&gt;
  &lt;li&gt;Automatic smart quotes in post titles (19 Aug)&lt;/li&gt;
  &lt;li&gt;Added OpenSearch to allow searching blog from address bar (15 Sep)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You might ask… what’s left to do? Not much I reckon. So I took a closer look at what is involved in me creating a blog post and made a list of the most repetitive, awkward or error prone tasks:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Entering links, partcularly links to other blog posts&lt;/li&gt;
  &lt;li&gt;Entering tags, going from memory or using search across project&lt;/li&gt;
  &lt;li&gt;Getting images onto my CDN server, currently copy by SFTP&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s solve all these annoyances!&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;entering-links-and-tags&quot;&gt;Entering links and tags&lt;/h2&gt;

&lt;p&gt;You can read about these two in previous blog posts:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Created &lt;a href=&quot;/2024/10/08/markdown-file-linker/&quot;&gt;Markdown File Linker&lt;/a&gt; to make linking easier (8 Oct)&lt;/li&gt;
  &lt;li&gt;Created &lt;a href=&quot;/2024/10/08/yaml-tag-picker/&quot;&gt;YAML Tag Picker&lt;/a&gt; to make tagging easier (8 Oct)&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;getting-images-onto-my-cdn-server&quot;&gt;Getting images onto my CDN server&lt;/h2&gt;

&lt;p&gt;I was still having to copy my images to my CDN server manually, which was a pain. But the software stack on the server was intimidating. I kept putting it off for a rainy day, but I knew I would eventually get around to automating it.&lt;/p&gt;

&lt;p&gt;The idea was to not upload the images at all, but rather download them to the server directly. I’d use a GitHub Webhook to trigger a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pull&lt;/code&gt; of the latest files onto my server. It took a few hours and a few attempts, but I finally arrived at a fairly elegant system I’m happy with:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;GitHub Webhook that runs on push event&lt;/li&gt;
  &lt;li&gt;PHP script in web server docker container receives, validates, and creates a trigger file&lt;/li&gt;
  &lt;li&gt;Service on server outside of docker looks for trigger file and does &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pull&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note: in January 2025, since this post was originally written, I have simplified the following files after migrating away from web servers in Docker containers to &lt;a href=&quot;https://caddyserver.com&quot;&gt;Caddy server&lt;/a&gt;. Highly recommended!&lt;/p&gt;

&lt;h3 id=&quot;github-webhook&quot;&gt;GitHub Webhook&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Payload URL: https://www.example.com/webhook.php&lt;/li&gt;
  &lt;li&gt;Content type: application/json&lt;/li&gt;
  &lt;li&gt;SSL verification: enabled&lt;/li&gt;
  &lt;li&gt;Which events would you like to trigger this webhook: Just the push event&lt;/li&gt;
  &lt;li&gt;Active: on&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;webhook-receiver-php-script&quot;&gt;Webhook receiver (PHP script)&lt;/h3&gt;

&lt;noscript&gt;&lt;p&gt;&lt;a href=&quot;https://gist.github.com/gingerbeardman/63e4dc0bce459ad6609c2701963eb61f&quot;&gt;View the source code as a Gist&lt;/a&gt;&lt;/p&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/gingerbeardman/63e4dc0bce459ad6609c2701963eb61f.js&quot;&gt;&lt;/script&gt;

&lt;h3 id=&quot;webhook-git-pull-watcher-shell-script&quot;&gt;Webhook git pull watcher (Shell script)&lt;/h3&gt;

&lt;noscript&gt;&lt;p&gt;&lt;a href=&quot;https://gist.github.com/gingerbeardman/e1c513c69b9e9d41aa91155893ae7334&quot;&gt;View the source code as a Gist&lt;/a&gt;&lt;/p&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/gingerbeardman/e1c513c69b9e9d41aa91155893ae7334.js&quot;&gt;&lt;/script&gt;

&lt;h3 id=&quot;trigger-system-service&quot;&gt;Trigger (System service)&lt;/h3&gt;

&lt;noscript&gt;&lt;p&gt;&lt;a href=&quot;https://gist.github.com/gingerbeardman/1ff95ce64a6a255919b8262dd4a21bc7&quot;&gt;View the source code as a Gist&lt;/a&gt;&lt;/p&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/gingerbeardman/1ff95ce64a6a255919b8262dd4a21bc7.js&quot;&gt;&lt;/script&gt;

&lt;h3 id=&quot;access-control&quot;&gt;Access control&lt;/h3&gt;

&lt;noscript&gt;&lt;p&gt;&lt;a href=&quot;https://gist.github.com/gingerbeardman/23e0da9949a8d41ebd190d60b0bd033b&quot;&gt;View the source code as a Gist&lt;/a&gt;&lt;/p&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/gingerbeardman/23e0da9949a8d41ebd190d60b0bd033b.js&quot;&gt;&lt;/script&gt;

&lt;h3 id=&quot;setup&quot;&gt;Setup&lt;/h3&gt;

&lt;p&gt;You can set up the service using:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo systemctl daemon-reload&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo systemctl start git-pull-watcher&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo systemctl enable git-pull-watcher&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Other commands&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo systemctl restart git-pull-watcher&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo systemctl status git-pull-watcher&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
          <author>by Matt Sephton</author>
          <pubDate>Fri, 11 Oct 2024 16:42:00 +0000</pubDate>
          <link>https://blog.gingerbeardman.com/2024/10/11/automating-the-most-annoying-aspects-of-blogging/</link>
          <guid isPermaLink="true">https://blog.gingerbeardman.com/2024/10/11/automating-the-most-annoying-aspects-of-blogging/</guid>
        </item>
      
    
      
        <item>
          <title>Turning a Twitter Thread into a Blog Post</title>
          <description>&lt;p&gt;Sometimes after posting to Twitter I’ll decide that I should really archive the information as a blog post. For single tweets that’s as easy (or difficult) as copying the text and images and publishing. For Twitter threads, it could be a lot more complicated. With a bit of lateral thinking I’ve found an easy way to do it.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Get the URL to a post in the thread&lt;/li&gt;
  &lt;li&gt;Unroll the thread using &lt;a href=&quot;https://threadreaderapp.com&quot;&gt;threadreaderapp.com&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Open the web inspector&lt;/li&gt;
  &lt;li&gt;Highlight the element that contains the content (the one with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data-controller=&quot;mentions&quot;&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Right click, and choose Copy &amp;gt; HTML&lt;/li&gt;
  &lt;li&gt;Paste the HTML into this &lt;a href=&quot;https://codebeautify.org/html-to-markdown&quot;&gt;Markdown converter&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Copy the Markdown&lt;/li&gt;
  &lt;li&gt;Paste into your blogging system&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The conversion from HTML to Markdown cleans or sanitises the content making for a straightforward paste into most blogging software.&lt;/p&gt;

&lt;h2 id=&quot;optional-post-processing&quot;&gt;Optional post-processing&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;You might want to repoint all embedded images from Twitter to locally-hosted copies&lt;/li&gt;
  &lt;li&gt;Some images in long threads might be lazy loaded, so you’ll need to fix those&lt;/li&gt;
  &lt;li&gt;Check and reinstate any embedded video iframes&lt;/li&gt;
&lt;/ul&gt;
</description>
          <author>by Matt Sephton</author>
          <pubDate>Mon, 09 Jan 2023 00:00:00 +0000</pubDate>
          <link>https://blog.gingerbeardman.com/2023/01/09/turning-a-twitter-thread-into-a-blog-post/</link>
          <guid isPermaLink="true">https://blog.gingerbeardman.com/2023/01/09/turning-a-twitter-thread-into-a-blog-post/</guid>
        </item>
      
    
      
        <item>
          <title>Adding Markdown Support to Safari</title>
          <description>&lt;p&gt;I recently created a Safari Extension that renders plain text Markdown files as good looking HTML right in your browser. I also added a context menu item so you can swap between the rendered HTML and the original Markdown text.&lt;/p&gt;

&lt;h2 id=&quot;download&quot;&gt;Download&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://www.gingerbeardman.com/safari/Doctor.safariextz&quot;&gt;gingerbeardman.com/safari/Doctor.safariextz&lt;/a&gt; (25Kb)&lt;/p&gt;

&lt;p&gt;To install: double click the file after it has downloaded.&lt;/p&gt;

&lt;h2 id=&quot;why&quot;&gt;Why?&lt;/h2&gt;

&lt;p&gt;Recently my buddy and fellow Former Apple Technology Evangelist @&lt;a href=&quot;https://medium.com/u/35a6b2e3855b?source=post_page-----c19f3d74f728--------------------------------&quot;&gt;TDRBY&lt;/a&gt; asked if there was an extension available for rendering Markdown files in Safari. I had a quick look—there wasn’t—and that got me thinking.&lt;/p&gt;

&lt;p&gt;On macOS you can use Quick Look plugins to add support for new file types to Finder’s Quick Look preview popup. These plugins are great, I use a bunch of them, but they only apply in Finder and not in Safari. Maybe I could do something similar?&lt;/p&gt;

&lt;p&gt;So, knowing that Safari renders plain text files by wrapping them in simple &lt;em&gt;HTML&lt;/em&gt; &amp;gt; &lt;em&gt;BODY&lt;/em&gt; &amp;gt; &lt;em&gt;PRE&lt;/em&gt; markup, I thought that an extension should be able to modify such files. That was enough to pique my interest—so I got to work!&lt;/p&gt;

&lt;h2 id=&quot;how&quot;&gt;How?&lt;/h2&gt;

&lt;p&gt;The extension took less than an hour to put together. This blog post took me a lot more time to write! Anyway, here’s how I did it:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Create new extension using &lt;em&gt;Safari&lt;/em&gt; &amp;gt; &lt;em&gt;Develop&lt;/em&gt; &amp;gt; &lt;em&gt;Extension Builder&lt;/em&gt; &amp;gt; &lt;em&gt;+ button&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Set website access level to &lt;em&gt;All&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Confirm extensions run on plain text files in Safari by adding a CSS file containing only &lt;em&gt;body { background-color: red !important; }&lt;/em&gt;—success, they do!&lt;/li&gt;
  &lt;li&gt;Find a suitable JavaScript Markdown to HTML converter &lt;a href=&quot;https://github.com/showdownjs/showdown&quot;&gt;showdown.js&lt;/a&gt;—this ticks two important boxes: it is easy to use, and is still being actively developed&lt;/li&gt;
  &lt;li&gt;Write a few lines of JavaScript to run &lt;em&gt;showdown.js&lt;/em&gt; on the page text and replace it with the generated HTML&lt;/li&gt;
  &lt;li&gt;Add &lt;a href=&quot;https://github.com/sindresorhus/github-markdown-css&quot;&gt;github-markdown.css&lt;/a&gt; and apply the &lt;em&gt;markdown-body&lt;/em&gt; class to make things look better&lt;/li&gt;
  &lt;li&gt;Configure the extension to run only on URLs ending in &lt;a href=&quot;http://superuser.com/a/285878&quot;&gt;common Markdown file extensions&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Manually add &lt;em&gt;https://&lt;/em&gt; variations of the Markdown file extensions to the &lt;em&gt;Info.plist&lt;/em&gt; (far quicker than using the Extension Builder user interface)&lt;/li&gt;
  &lt;li&gt;Edit the .map file reference out of the minimised &lt;em&gt;showdown.js&lt;/em&gt; to avoid a runtime access warning&lt;/li&gt;
  &lt;li&gt;Build the release package&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At this point I’d like to mention a couple of great open-source projects that made this task so much easier: &lt;a href=&quot;https://github.com/sindresorhus/github-markdown-css&quot;&gt;github-markdown.css&lt;/a&gt; by &lt;em&gt;Sindre Sorhus&lt;/em&gt;, and &lt;a href=&quot;https://github.com/showdownjs/showdown&quot;&gt;showdown.js&lt;/a&gt; by &lt;em&gt;Estevão Soares dos Santos&lt;/em&gt;—nice work guys!&lt;/p&gt;

&lt;h2 id=&quot;testing&quot;&gt;Testing&lt;/h2&gt;

&lt;p&gt;There are Markdown files all over the internet, but two notable source stand out.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Almost every GitHub project has a README.md file. View the RAW version to have the extension render it as HTML. Here’s &lt;a href=&quot;https://raw.githubusercontent.com/primer/primer-markdown/master/README.md&quot;&gt;the one I used&lt;/a&gt; for testing.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://medium.com/u/182e1a455da3?source=post_page-----c19f3d74f728--------------------------------&quot;&gt;John Gruber&lt;/a&gt;’s excellent &lt;a href=&quot;http://daringfireball.net&quot;&gt;daringfireball.net&lt;/a&gt; blog is written using Markdown, and the source of each post can be seen by appending .text to the URL. Here are &lt;a href=&quot;http://daringfireball.net/linked/2016/11/15/designed-by-apple-in-california.text&quot;&gt;two&lt;/a&gt; &lt;a href=&quot;http://daringfireball.net/2016/11/new_touch_bar_equipped_macbook_pros.text&quot;&gt;posts&lt;/a&gt; that I used to test. Of course, John is also the creator of Markdown. Thanks, John! 👍&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;postmortem&quot;&gt;Postmortem&lt;/h2&gt;

&lt;p&gt;After the initial build, a period of testing revealed some issues:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Strikethrough, and some other non-standard but frequently used Markdown, was not being rendered. This was fixed by enabling some options in the &lt;em&gt;showdown.js&lt;/em&gt; file.&lt;/li&gt;
  &lt;li&gt;Rendering quirks due to using &lt;em&gt;github-markdown.css&lt;/em&gt; outside of the GitHub page structure required few manual CSS tweaks. Mainly this was to make tables look better.&lt;/li&gt;
  &lt;li&gt;Markdown on GitHub that was already rendered as HTML was being processed a second time, resulting in corrupted pages. This was fixed by blacklisting the &lt;em&gt;github.com&lt;/em&gt; domain.&lt;/li&gt;
  &lt;li&gt;Sometimes I wanted to see the plain text Markdown. I fixed this by spending an inordinate amount of time adding a context menu item that allows you to &lt;em&gt;Show&lt;/em&gt; or &lt;em&gt;Render Markdown&lt;/em&gt;. I hope it was worth it! 😬&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;safari-wish-list&quot;&gt;Safari Wish List&lt;/h2&gt;

&lt;p&gt;Despite the brief development, I noticed a few quirks to do with Safari that I did not expect to encounter:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;You can’t open the Web Inspector whilst viewing a plain text file. But if you open the inspector on a blank tab, or an existing HTML page, you can then navigate to the plain text file and the inspector will remain open. Phew!&lt;/li&gt;
  &lt;li&gt;Due to the way Safari Extension access permissions work, I have had to enable the extension for all pages and then reduce its power by whitelisting a range of Markdown file extensions. This feels like cracking a nut with a sledgehammer.&lt;/li&gt;
  &lt;li&gt;Extensions do not run on local &lt;em&gt;file:///&lt;/em&gt; documents. 😩&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please join me in &lt;a href=&quot;http://bugreport.apple.com&quot;&gt;filing enhancement requests with Apple&lt;/a&gt; if you’d like to add your support to any of the above points.&lt;/p&gt;

&lt;h2 id=&quot;thanks-for-reading&quot;&gt;Thanks for reading!&lt;/h2&gt;

&lt;p&gt;If you have any questions feel free to get in touch using &lt;a href=&quot;http://twitter.com/gingerbeardman&quot;&gt;twitter&lt;/a&gt; or &lt;a href=&quot;http://www.gingerbeardman.com&quot;&gt;my website&lt;/a&gt;. I’m interested to see more extensions that add support for other file formats in Safari. And I’m available to help you make better products!&lt;/p&gt;
</description>
          <author>by Matt Sephton</author>
          <pubDate>Fri, 25 Nov 2016 00:00:00 +0000</pubDate>
          <link>https://blog.gingerbeardman.com/2016/11/25/adding-markdown-support-to-safari/</link>
          <guid isPermaLink="true">https://blog.gingerbeardman.com/2016/11/25/adding-markdown-support-to-safari/</guid>
        </item>
      
    

  </channel>
</rss>
