Transforming Markdown links into HTML while editing
I write a lot of Markdown by hand. Links in Markdown look like this:
[This is a link to Zombo com](https://zombo.com/)
When a Markdown processor sees the above, it transforms it into an <a>
element like so:
<a href=https://zombo.com/>This is a link to Zombo com</a>
Most of the time this is all you need. But the <a>
element takes many attributes. When I want to add one—rel=nofollow
, say, or download=filename.ext
—I have to rewrite the link into HTML myself, because Markdown doesn’t have a syntax for attributes like these.
Transforming Markdown links to HTML is laborious to do by hand, so I wrote a bit of elisp to do it for me:
transform-link-at-point
commandLoad dependencies
(defun transform-link-at-point (point)
"Turn a Markdown link or image at `point' to an HTML element."
(interactive "d")
(goto-char point)
Only proceed if we're in the middle of a Markdown link
(let (Use intuitive names for the components of a Markdown link)
Remove the Markdown link
Insert the HTML equivalent
Reposition cursor before the >
))
transform-link-at-point
is a command that operates at the current point. Iff point is inside a Markdown link, we remove the old Markdown syntax, insert the HTML equivalent, and reposition the cursor to be right before the >
character of the open tag. (After all, the whole point of this hack is to make it more efficient to add attributes to links.)
Deleting the Markdown link is very easy:
(delete-region start end)
Creating an <a>
element is pretty easy too:
<a>
element(format "<a href=%s%s>%s</a>" url title-attr text)
We should also handle images; it’s not much more work. Markdown’s image syntax is basically the same at its link syntax, just with a !
character at the start:

Fortunately creating an <img>
element is just as easy as creating a link:
<img>
element(format "<img src=%s alt=\"%s\"%s>" url text title-attr)
So we figure out which element to use & then insert it:
(insert
(if is-image
Create an <img>
element
Create an <a>
element))
Of course, we shouldn’t attempt to do this unless we’re actually inside a Markdown link:
(unless (thing-at-point-looking-at markdown-regex-link-inline)
(error "Not in a Markdown link."))
thing-at-point-looking-at
is a predicate that returns t
if the cursor is currently inside the kind of thing you’re interested in, and markdown-regex-link-inline
is a regexp that matches Markdown links and images. They’re defined in thingatpt.el
(included in Emacs) and markdown-mode.el
, respectively:
(require 'thingatpt)
(require 'markdown-mode)
When thing-at-point-looking-at
succeeds, Emacs’ match data contains all of the various components of the Markdown link we’re in the middle of. Let’s give those components humane names so the rest of the code makes sense:
(start (match-beginning 0))
(end (match-end 0))
(is-image (match-string 1))
(text (match-string 3))
(url (match-string 6))
(title-attr (if (match-string 7)
(format " title=%s" (match-string 7))
""))
The last thing we do is position the cursor so I can quickly add more attributes to the element.
>
(goto-char start)
(search-forward ">" nil t)
(backward-char 1)