BBEdit has a cool feature called Text Factories for automating repetitive text transformations. When Younghart mentioned it on the forum, it got me thinking.

While I can’t replicate the full power of Text Factories (which can chain multiple transformations, with all of BBEdit’s power), I could at least add a flexible regex search-and-replace system to md-fixup.

So that’s what I built: a YAML-driven regex replacement engine that lets you define custom patterns that run as part of an md-fixup pass. It’s not a replacement for Text Factories — it only does regex search and replace — but it offers a way to extend md-fixup with your own transformations.

How It Works

Replacements are defined in a YAML file and can be scoped to run before or after Markdown Fixup’s built-in rules. Each replacement can optionally run inside code blocks or YAML frontmatter, giving you fine-grained control over where transformations happen.

The replacement file lives in one of these locations (checked in order):

  • .md-fixup-replacements in your current directory
  • The path specified in your config file’s replacements_file: key

  • ~/.config/md-fixup/replacements.yml (or $XDG_CONFIG_HOME/md-fixup/replacements.yml)

Setting Up Replacements

Here’s a simple example that fixes double spaces and normalizes HTTP links:

replacements:
  - name: "fix-double-spaces"
    pattern: "  +"
    replacement: " "
    timing: after
    in_code_blocks: false
    in_frontmatter: false

  - name: "normalize-http"
    pattern: "http://"
    replacement: "https://"
    timing: after

Each replacement has a few key properties:

  • name: A human-readable identifier (useful for debugging)

  • pattern: A Rust regex pattern (supports capture groups)

  • replacement: The replacement string (use $1, $2, etc. for capture groups)

  • timing: When to run—before or after the built-in rules

  • in_code_blocks: If true, the pattern runs inside fenced code blocks

  • in_frontmatter: If true, the pattern runs inside YAML frontmatter

A More Complex Example

Here’s one that swaps version numbers using capture groups:

replacements:
  - name: "swap-version"
    pattern: "(\\d+)\\.(\\d+)"
    replacement: "$2.$1"
    timing: before

This would turn “Version 1.2 is released” into “Version 2.1 is released”. The pattern captures two groups of digits separated by a dot, then swaps them in the replacement. Stupid example, of course (why would you ever do that?), but hopefully you get the idea.

Controlling Replacements

You can enable or disable replacements via your config file:

width: 80
replacements: true
replacements_file: ~/my-replacements.yml
rules:
  skip:
    - wrap

Or use command-line flags:

# Force enable
md-fixup --replacements file.md

# Force disable
md-fixup --no-replacements file.md

# Use a specific file
md-fixup --replacement-file ./custom.yml file.md

This regex replacement system is intentionally limited, and as mentioned, is no replacement for Text Factories. It only does regex search and replace, but it runs automatically as part of md-fixup’s fixup pass, which means you can integrate custom transformations into your existing workflow without switching tools.

If you need the full power of Text Factories, by all means use BBEdit. It’s an amazing text editor. But if you just need a few regex replacements to run alongside Markdown Fixup’s built-in rules, this might be exactly what you’re looking for.

Check out the latest version of Markdown Fixup on GitHub. Find installation and usage instructions there!