Copy an Org Mode region as Markdown
2026-04-14
437 words, ~3 min reading time
Without doubt, Markdown is the standard for many plain-text input fields on the web. And even though I'd prefer it would be Org Mode (or Orgdown), I cannot escape this reality.
Well, at least not entirely. Like perhaps many others who are trapped inside Emacs, I write (especially longer) texts in Org Mode and export them to Markdown afterwards. This works more or less well. There are (to my knowledge) two org-export integrations for converting text to Markdown: ox-md is part of Org Mode itself, and additionally ox-pandoc, which allows exporting to various Markdown specifications like Common Mark and GitHub Flavoured Markdown. For longer texts or files, I've been using ox-pandoc for a long time, and I'm satisfied with the output. However, I don't like that it hard breaks lines at about 72 chars, and I haven't found a way to turn that off. ox-md on the other hand works well for some cases, but for exporting code it's not as ideal since it exports code blocks indented instead of surrounded by code fences, thereby losing the code language.
However, for a few months, I often need to export a subtree or region of a larger Org document for inserting it into some website. Always calling org-export, opening the file, selecting the text and then copying it gets tedious quite fast. So, I wanted to have an interactive function for directly copying a selected region as Markdown to my clipboard. I read and tried to understand the ox-pandoc package to learn how I can use it for this purpose, but I haven't found any solution. Searching online, I found a post by Marcin Borkowski with a nice little function that does exactly what I want, but using ox-md. Which in turn meant that I manually needed to fix the code blocks. Additionally, ox-md is just Markdown without support for tables, which I use extensively.
So today, I wrote my own function for copying an Org region as GitHub Flavoured Markdown to the clipboard. My requirements are relatively easy:
- Export using Pandoc to
gfm(which includes support for tables and checkboxes) - Export JSON code blocks (starting with
#+begin_src jsonin Org Mode) to``` json - Automatically promote the headlines so that the top-most level is an H2 (the source is quite nested, and the headings I export often are at level 4 or 5)
After many tries, I finally ended with the following function.
(defun mmk2410/copy-org-region-as-gfm ()
"Copy Org region as GitHub Flavoured Markdown using Pandoc.
Headings are shift automatically to level 2 and below.
JSON code blocks are marked as json instead of js-json."
(interactive)
(if (use-region-p)
(let* (;; Get currently selected region
(region (buffer-substring-no-properties
(region-beginning)
(region-end)))
(text (with-temp-buffer
(org-mode)
;; Accept headline up to level 9 to make sure Pandoc does not treat them as list items.
(insert "#+OPTIONS: H:9\n")
(insert region)
(goto-char (point-min))
;; Replace js-json with json for wide compatiblity of JSON code blocks.
(while (re-search-forward "#\\+begin_src js-json" nil t)
(replace-match "#+begin_src json" nil nil))
(goto-char (point-min))
;; Determine the level of the first Org heading for adjusting the heading shift.
(if (not (org-at-heading-p))
(org-next-visible-heading 1))
(list
(buffer-string)
(let ((level (org-current-level)))
(cond ((not level) 0)
((> level 2) (* (- (org-current-level) 2) -1))
((= level 1) 1)
(t 0))))))
(org-file (make-temp-file "oxcm-" nil ".org" (car text)))
(markdown (with-temp-buffer
(call-process
"pandoc"
nil t nil
(concat "--shift-heading-level-by=" (number-to-string (car (cdr text))))
"--wrap=none" "-f" "org" "-t" "gfm" "-o" "-" org-file)
(buffer-string))))
(gui-set-selection 'CLIPBOARD markdown)
(delete-file org-file))))
Although I've written some Emacs Lisp code during the last few years for automating some stuff, I'm by no means an Elisp hacker. Therefore, I'm quite sure there are better or cleaner solutions. But so far it seems to work, and it sure makes the process much easier. Additionally, I learned a bit more about how to extend my operating system and improve my workflow.
If this will be helpful to you or if you have any suggestions regarding the code, I'd be happy to hear from you.
I would like to hear what you think about this post. Feel free to write me a mail!
Reply by mail