Hello, org exports to markdown automatically rename links to org files as links to md files. It's not possible to link to an org file and have it remain an org file in the exported markdown.
org exports to html do the same thing but have an option to disable this mapping so links to org file can remain links to org file. this patch brings this same option to markdown exporter. Thanks, Ian
From b33e34e7872162705efaa68036363a4766f13987 Mon Sep 17 00:00:00 2001 From: Ian Martins <ia...@jhu.edu> Date: Fri, 4 Apr 2025 21:28:58 -0400 Subject: [PATCH] ox-md.el: New option `org-md-link-org-files-as-md' * lisp/org-md.el: Define `org-md-link-org-files-as-md' and add an entry to `:options-alist'. (org-md-link): Disable mapping of linked org files to md during export to Markdown. * testing/lisp/text-ox-md.el: Add tests. --- etc/ORG-NEWS | 6 ++++++ lisp/ox-md.el | 28 +++++++++++++++++++++++----- testing/lisp/test-ox-md.el | 29 +++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 5 deletions(-) diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS index 982bac4e9..5bc05b8ae 100644 --- a/etc/ORG-NEWS +++ b/etc/ORG-NEWS @@ -335,6 +335,12 @@ This option makes ~org-cite~'s ~basic~ insert processor use It can also be set to dynamically compute ~crm-separator~ so that the separator does not appear in completion candidates. +*** New Option ~org-md-link-org-files-as-md~ + +This option makes it possible to disable mapping of linked org files +to markdown during export to Markdown. This is analogous to how +~org-html-link-org-files-as-html~ works in export to HTML. + ** New functions and changes in function arguments # This also includes changes in function behavior from Elisp perspective. diff --git a/lisp/ox-md.el b/lisp/ox-md.el index 0aa097033..0f621851d 100644 --- a/lisp/ox-md.el +++ b/lisp/ox-md.el @@ -93,6 +93,21 @@ headings for its own use." ;; Avoid `natnum' because that's not available until Emacs 28.1. :type 'integer) +(defcustom org-md-link-org-files-as-md t + "Non-nil means make file links to \"file.org\" point to \"file.md\". + +When Org mode is exporting an Org file to markdown, links to +non-markdown files are directly put into a \"href\" tag in +markdown. However, links to other Org files \(recognized by the +extension \".org\") should become links to the corresponding +markdown file, assuming that the linked Org file will also be +converted to markdown. + +When nil, the links still point to the plain \".org\" file." + :group 'org-export-md + :package-version '(Org . "9.8") + :type 'boolean) + ;;; Define Backend @@ -144,7 +159,8 @@ headings for its own use." '((:md-footnote-format nil nil org-md-footnote-format) (:md-footnotes-section nil nil org-md-footnotes-section) (:md-headline-style nil nil org-md-headline-style) - (:md-toplevel-hlevel nil nil org-md-toplevel-hlevel))) + (:md-toplevel-hlevel nil nil org-md-toplevel-hlevel) + (:md-link-org-files-as-md nil nil org-md-link-org-files-as-md))) ;;; Filters @@ -540,17 +556,19 @@ channel." DESC is the description part of the link, or the empty string. INFO is a plist holding contextual information. See `org-export-data'." - (let* ((link-org-files-as-md + (let* ((link-org-files-as-md-maybe (lambda (raw-path) ;; Treat links to `file.org' as links to `file.md'. - (if (string= ".org" (downcase (file-name-extension raw-path "."))) + (if (and + (plist-get info :md-link-org-files-as-md) + (string= ".org" (downcase (file-name-extension raw-path ".")))) (concat (file-name-sans-extension raw-path) ".md") raw-path))) (type (org-element-property :type link)) (raw-path (org-element-property :path link)) (path (cond ((string-equal type "file") - (org-export-file-uri (funcall link-org-files-as-md raw-path))) + (org-export-file-uri (funcall link-org-files-as-md-maybe raw-path))) (t (concat type ":" raw-path))))) (cond ;; Link type is handled by a special function. @@ -561,7 +579,7 @@ INFO is a plist holding contextual information. See (org-export-resolve-id-link link info)))) (pcase (org-element-type destination) (`plain-text ; External file. - (let ((path (funcall link-org-files-as-md destination))) + (let ((path (funcall link-org-files-as-md-maybe destination))) (if (not desc) (format "<%s>" path) (format "[%s](%s)" desc path)))) (`headline diff --git a/testing/lisp/test-ox-md.el b/testing/lisp/test-ox-md.el index dd2128a09..8f5b473d1 100644 --- a/testing/lisp/test-ox-md.el +++ b/testing/lisp/test-ox-md.el @@ -101,5 +101,34 @@ (should (search-forward "10. item")) (should (search-forward "101. item")))))) +(ert-deftest ox-md/link-org-mapping-enabled () + "Test `org-md-link' with org to md link mapping enabled." +(org-test-with-temp-text " +[[file:examples/babel.org][babel org file]] +[[file:examples/babel.el][babel script]] +" + (let ((export-buffer "*Test MD Export*") + (org-export-show-temporary-export-buffer nil)) + (org-export-to-buffer 'md export-buffer) + (with-current-buffer export-buffer + (goto-char (point-min)) + (should (search-forward "[babel org file](examples/babel.md)")) + (should (search-forward "[babel script](examples/babel.el)")))))) + +(ert-deftest ox-md/link-org-mapping-disabled () + "Test `org-md-link' with org link to md link mapping disabled." +(org-test-with-temp-text " +[[file:examples/babel.org][babel org file]] +[[file:examples/babel.el][babel script]] +" + (let ((export-buffer "*Test MD Export*") + (org-export-show-temporary-export-buffer nil) + (org-md-link-org-files-as-md nil)) + (org-export-to-buffer 'md export-buffer) + (with-current-buffer export-buffer + (goto-char (point-min)) + (should (search-forward "[babel org file](examples/babel.org)")) + (should (search-forward "[babel script](examples/babel.el)")))))) + (provide 'test-ox-md) ;;; test-ox-md.el ends here -- 2.43.0