I’ve made a couple of improvements to md-fixup, the opinionated Markdown formatting and linting tool I shared this week. The main additions are better emphasis handling and link conversion options.
Emphasis Handling
By default, md-fixup normalizes bold markers to __ (double underscore) and italic markers to * (single asterisk). So **bold** becomes __bold__ and _italic_ becomes *italic*. This keeps everything consistent in your Markdown files.
But what if you prefer the other style? You can use the --reverse-emphasis flag to swap them:
md-fixup --reverse-emphasis file.md
This will convert __bold__ to **bold** and *italic* to _italic_. Handy if you’re working with a different Markdown flavor or just have a preference.
And if you want to skip emphasis normalization entirely, just skip rule 25:
md-fixup --skip bold-italic file.md
# or
md-fixup --skip 25 file.md
Link Conversion
The new link conversion feature is one I should have had originally but kind of forgot. By default, md-fixup now converts all your links to numeric reference-style links, keeping your document body clean and all the URLs organized at the bottom.
Here’s what happens:
Before:
This is a [link](https://example.com) in the text.
Another [link](https://example.com) with the same URL.
After:
This is a [link][1] in the text.
Another [link][1] with the same URL.
[1]: https://example.com
Notice how the second link reuses the same reference number since it’s the same URL. It de-duplicates for you automatically.
Reference Links (Default)
Reference links are the default behavior (rule 28). Links get converted to [text][number] format, and all definitions are placed at the end of the document (rule 29, also default).
You can also put the link definitions at the beginning of the document instead. Just skip rule 29:
md-fixup --skip links-at-end file.md
# or
md-fixup --skip 29 file.md
This is useful if you prefer your reference definitions up top, or if you’re using a tool that reads links from the beginning.
Inline Links
If you prefer inline links instead, you can enable rule 30. This converts everything to [text](url) format and automatically disables the reference link behavior. Since inline links are disabled by default, the cleanest way to enable them is through a config file. Create ~/.config/md-fixup/config.yml:
rules:
skip: all
include:
- inline-links
Or if you’re using the skip/include pattern already, just add inline-links to your include list. Inline links will override reference links when enabled.
Configuration Examples
Here are some practical configuration setups:
Default (reference links at end):
width: 60
overwrite: false
# No rules section needed - reference links are default
Reference links at beginning:
rules:
skip:
- links-at-end # This puts links at the beginning
Inline links:
rules:
skip: all
include:
- inline-links
# Other rules to include
Skip emphasis conversion:
rules:
skip:
- bold-italic
Reverse emphasis markers:
md-fixup --reverse-emphasis file.md
This can’t be set in the config file yet—it’s command-line only for now.
What Gets Converted
The link converter handles:
- Inline links:
[text](url) → [text][1]
- Reference links:
[text][ref] → [text][1] (renumbered)
- Implicit reference links:
[text] → [text][1] (if definition exists)
- Links with titles:
[text](url "title") → [text][1] with [1]: url "title"
It also smartly ignores links inside code blocks and code spans, so your examples don’t get mangled.
I plan to continue modifying the link handling to maintain “implicit links” (links where there’s just text surrounded by square brackets and the exact text is used in a link definition); I do actually use those frequently and I think they’re great for readability. Stay tuned, I’m sure I’ll have another morning soon where I feel like hacking on that.
The emphasis normalizer handles nested cases too, like ***bold italic*** becoming __*bold italic*__ (or _**bold italic**_ in reverse mode). It’s aware of context and won’t mess with code blocks or other protected regions.
And Apex
Speaking of Markdown stuff, I also pushed v0.1.51 of Apex today. It adds support for : Caption syntax before tables (previously only after), with or without IAL attributes, and handles blank lines between captions and tables.
It fixes table and other parsing when files don’t end with a newline or use CR line endings. cmark-gfm already had great CRLF handling, but I broke some of it when building out the Apex extensions. Should be better now, and I’ve added regression tests to ensure it stays that way.