This morning I woke up wondering “what if I could do my lmno blogging from org-mode instead of Markdown?”

Partly “why not” and partly “you get real org-capture and it becomes easier to shuttle text around.”

That led to this:

(defun lmno/org-export-blog ()
  "Export ~/notes/blog.org → ~/notes/lmno.md."
  (interactive)
  (let* ((input-file  (expand-file-name "~/notes/lmno.org"))
         (output-file (expand-file-name "~/notes/lmno.md")))
    (with-temp-buffer
      (insert-file-contents input-file)
      (org-mode)
      ;; turn off all the bells that inject TOC, numbers, dates, etc.
      (let ((org-export-with-toc            nil)
            (org-export-with-section-numbers nil)
            (org-export-with-author         nil)
            (org-export-with-creator        nil)
            (org-export-with-date           nil)
            (org-export-with-priorities     nil)
            (org-export-with-timestamps     nil)
            (org-export-with-smart-quotes   nil)
            (org-export-with-broken-links   'mark))
      (org-export-to-buffer 'md "*lmno-export*" nil nil nil nil))
      (with-current-buffer "*lmno-export*"
        ;; strip the anchors org's export insists on inserting
        (goto-char (point-min))
        (while (re-search-forward "<a id=\"[^\"]+\"></a>" nil t)
          (replace-match ""))
        ;; strip the overhelpful datestamp spans
        (goto-char (point-min))
        (while (re-search-forward "</?span[^>]*>" nil t)
          (replace-match "")))
      ;; write out the clean Markdown
      (with-current-buffer "*lmno-export*"
        (write-region (point-min) (point-max) output-file)))
    (message "Clean export complete → %s" output-file)))

It has to do two things I wish it didn’t:

  • Find and replace a bunch of anchor links org’s HTML export drops onto headings
  • Find and replace a bunch of spans org’s HTML export wraps around what it considers datestamps

But then it just plops the whole monolith into the Markdown file I can drag into lmno’s uploader.

… then I noticed “the images have no alt tags,” so I found someone wrote this custom org link type:

(org-add-link-type
 "img" nil
 (lambda (path desc backend)
   (when (org-export-derived-backend-p backend 'md)
     (format "![%s](%s)" desc path))))

It just registers a custom org-mode img link, and exports to Markdown with an alt tag, so this in org-mode:

[[img:https://photos.smugmug.com/photos/i-rnGMdNb/0/K3vtM5mZMTn4s9zVwkhdGBXdcBgNPzD74g957cG6J/XL/i-rnGMdNb-XL.jpg][Some alt text]]

becomes this when exported to Markdown:

![Some alt text](https://photos.smugmug.com/photos/i-rnGMdNb/0/K3vtM5mZMTn4s9zVwkhdGBXdcBgNPzD74g957cG6J/XL/i-rnGMdNb-XL.jpg)

… so then I thought, what if imgup could provide not just Markdown and HTML snippets, but also org-mode img link snippets?

An imgup window showing snippets for Markdown, org, and HTML

(It’ll do that from the command line version, too.)

Fifteen years later, still true.