2 minute read

I want to be able to use link abbreviations in Minimal Mistakes, for example, use foo:<filename> in place of the full link for images and images in a gallery like the following:

---
link_abbrs:
  - link_abbr: foo http://127.0.0.1:8123/archive/image/foo/
gallery:
  - url: foo:20260218184820.png
    image_path: foo:20260218184820.png
  - url: foo:20260218184820.png
    image_path: foo:20260218184820.png
  - url: foo:20260218184820.png
    image_path: foo:20260218184820.png
---

![](foo:20260218184820.png)

{% include gallery caption="Link abbreviations" %}

The links can then be translated to their full forms in the built result such as:

http://127.0.0.1:8123/archive/image/foo/20260218184820.png

Create a new Ruby plugin file

We can create a plugin under _plugins/link_abbr.rb which handles the link abbreviations:

require 'addressable/uri'

Jekyll::Hooks.register [:pages, :documents], :pre_render do |doc|
  next unless doc.data['link_abbrs'].is_a?(Array)

  doc.data['link_abbrs'].each do |item|
    next unless item.is_a?(Hash) && item['link_abbr']

    key, base_url = item['link_abbr'].split(' ', 2)
    next unless key && base_url

    # 1. Replaces "](key:filename)" inside the Markdown body content
    doc.content = doc.content.gsub(/\]\(#{Regexp.escape(key)}:([^\)]+)\)/) do
      escaped_path = Addressable::URI.escape(base_url + $1)
      prefix = base_url.start_with?('/assets') ? "https://josephtesfaye.com/josephs-blog" : ""
      "](#{prefix}#{escaped_path})"
    end

    # 2. Replace image_path in figures
    doc.content = doc.content.gsub(/image_path="#{Regexp.escape(key)}:([^"]+)"/) { "image_path=\"#{Addressable::URI.escape(base_url + $1)}\"" }

    # 3. Replace inside ANY front matter array (gallery, gallery1, gallery2, etc.)
    doc.data.each do |_, value|
      if value.is_a?(Array)
        value.each do |list_item|
          next unless list_item.is_a?(Hash)

          ['url', 'image_path'].each do |attr|
            if list_item[attr] && list_item[attr].to_s.start_with?("#{key}:")
              # Replace the exact abbreviation prefix with the base URL
              full_path = list_item[attr].to_s.sub(/^#{Regexp.escape(key)}:/, base_url)
              list_item[attr] = Addressable::URI.escape(full_path)
            end
          end

          if list_item['title']
            list_item['title'] = list_item['title'].to_s.gsub(/\]\(#{Regexp.escape(key)}:([^\)]+)\)/) do
              escaped_path = Addressable::URI.escape(base_url + $1)
              prefix = base_url.start_with?('/assets') ? "https://josephtesfaye.com/josephs-blog" : ""
              "](#{prefix}#{escaped_path})"
            end
          end
        end
      end
    end
  end
end

The github-pages gem enforces strict safe mode and completely disables the _plugins directory to mimic GitHub’s legacy deployment environment, overriding any safe: false settings in your configuration.

To allow custom plugins to run locally, you need to replace it with the standard Jekyll gem. Since you already have all your plugins explicitly listed in your Gemfile, this is a safe swap.

Gemfile:

-gem "github-pages", group: :jekyll_plugins
+gem "jekyll"
+gem "kramdown-parser-gfm"
+gem "faraday-retry"

_config.yml:

-remote_theme: mmistakes/minimal-mistakes@4.20.2
+theme: minimal-mistakes-jekyll

Terminal:

bundle install
bundle exec jekyll serve

Use GitHub Actions to build your GitHub Pages site

This affects the default GitHub Pages build. The classic GitHub Pages build environment strictly enforces safe mode and ignores all files in the _plugins directory. If you push the site using the default settings, it will still host successfully, but your custom plugin will not run and the link abbreviations will remain unparsed.

To use custom plugins while hosting on GitHub Pages, you must switch your deployment method to GitHub Actions. This modern approach uses your exact Gemfile, executes your Ruby scripts, and then hosts the final output on GitHub Pages.

  1. Go to your repository on GitHub.
  2. Click on Settings, then select Pages from the left sidebar.
  3. Under Build and deployment, change the Source from “Deploy from a branch” to “GitHub Actions”.
  4. GitHub will suggest a default Jekyll workflow. Click Configure.
  5. Commit the provided .github/workflows/jekyll.yml file to your repository.

With this workflow active, GitHub will read your updated Gemfile, run the link_abbr.rb plugin during the build step, and deploy the fully rendered HTML to your live site.

Comments