I kept it simple.

Related-to: https://list.orgmode.org/orgmode/[email protected]/
From a40a57ea3bcc19a8ab53d6b505b24f2d0d1be4f0 Mon Sep 17 00:00:00 2001
From: ApollonDeParnasse <[email protected]>
Date: Fri, 5 Jun 2026 21:03:35 -0500
Subject: [PATCH] lisp/ox.el: Added option to export file links verbatim

* lisp/ox.el (org-export-file-links-verbatim): New custom option.
When non-nil, `file:' will not be appended to file links that
start with `\' before they are exported.
(org-export-options-alist): Recognize `org-export-options-alist'.
(org-export-file-uri): Will not prepend `file:' to file links
if they start `\' and `org-export-file-links-verbatim'
is non-nil.

* testing/lisp/test-ox.el (test-org-export/file-uri/with-verbatim-file-links):
New test for `org-export-file-uri'.
---
 etc/ORG-NEWS            | 11 +++++++++++
 lisp/ox.el              |  9 +++++++++
 testing/lisp/test-ox.el | 21 +++++++++++++++++++++
 3 files changed, 41 insertions(+)

diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 5a72b69ea..3f44032c8 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -208,6 +208,17 @@ environment for descriptive lists when exporting to LaTeX.
 Use it when the default ~description~ environment does not fit your
 needs. The recommended alternative value is ~itemize~.
 
+*** New custom variable ~org-export-file-links-verbatim~
+
+~org-export-file-links-verbatim~ controls whether Org
+mode exports file links that start with "/" verbatim.
+Set it to t to export said links without first appending
+~file:~ to them.
+
+This variable has no effect on links that are already prefixed with
+=file:= or links that start with a =~=.
+
+
 ** New functions and changes in function arguments
 
 # This also includes changes in function behavior from Elisp perspective.
diff --git a/lisp/ox.el b/lisp/ox.el
index e0782c1e6..f7a5d6504 100644
--- a/lisp/ox.el
+++ b/lisp/ox.el
@@ -123,6 +123,7 @@
     (:with-author nil "author" org-export-with-author)
     (:expand-links nil "expand-links" org-export-expand-links)
     (:with-broken-links nil "broken-links" org-export-with-broken-links)
+    (:verbatim-file-links nil "verbatim-file-links" org-export-file-links-verbatim)
     (:with-clocks nil "c" org-export-with-clocks)
     (:with-creator nil "creator" org-export-with-creator)
     (:with-date nil "date" org-export-with-date)
@@ -880,6 +881,13 @@ This option can also be set with the OPTIONS keyword, e.g.,
   :package-version '(Org . "9.7")
   :type 'boolean)
 
+(defcustom org-export-file-links-verbatim nil
+  "Non-nil means export file links that start with `/' verbatim.
+`file:' will not be prepended to the path of these links."
+  :group 'org-export-general
+  :package-version '(Org . "9.8")
+  :type 'boolean)
+
 (defcustom org-export-replace-macros t
   "When non-nil, replace macros before export.
 This variable does not affect {{{results}}} macros when processing
@@ -4689,6 +4697,7 @@ Return value can be an object or an element:
   (cond ((string-prefix-p "//" filename) (concat "file:" filename))
 	((not (file-name-absolute-p filename)) filename)
 	((file-remote-p filename) (concat "file:/" filename))
+        ((and org-export-file-links-verbatim (not (string-prefix-p "~" filename))) filename)
 	(t
 	 (let ((fullname (expand-file-name filename)))
 	   (concat (if (string-prefix-p "/" fullname) "file://" "file:///")
diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el
index 79365ad29..3660073d5 100644
--- a/testing/lisp/test-ox.el
+++ b/testing/lisp/test-ox.el
@@ -3969,6 +3969,27 @@ Another text. (ref:text)
   (should (equal (org-export-file-uri "~/file.org")
 		 (concat (if (memq system-type '(windows-nt cygwin)) "file:///" "file://") (expand-file-name "~/file.org")))))
 
+(ert-deftest test-org-export/file-uri/with-verbatim-file-links ()
+  "Test `org-export-file-uri' with `org-export-file-links-verbatim' enabled."
+  (let ((org-export-file-links-verbatim t))
+    (should (equal
+             "/en/install-emacs-on-android"
+             (org-export-file-uri "/en/install-emacs-on-android")))
+    (should (equal
+            "/dominik/images/jupiter.jpg"
+            (org-export-file-uri "/dominik/images/jupiter.jpg")))
+    ;;Doesn't effect Local files start with "file://"
+    (should (equal "file:/local.org"
+	    (org-export-file-uri "file:/local.org")))
+
+    ;;Doesn't effect remote files with "file://"
+    (should (equal "file://ssh:[email protected]:papers/last.pdf"
+		   (org-export-file-uri "/ssh:[email protected]:papers/last.pdf")))
+
+    ;; Doesn't effect filenames that start with "~".
+    (should (equal (org-export-file-uri "~/file.org")
+		   (concat (if (memq system-type '(windows-nt cygwin)) "file:///" "file://") (expand-file-name "~/file.org"))))))
+
 (ert-deftest test-org-export/get-reference ()
   "Test `org-export-get-reference' specifications."
   (should
-- 
2.54.0

Reply via email to