branch: externals/org
commit 03148c5d1fcbbc47d57d7301ab2b8d0925e2e235
Author: Ihor Radchenko <[email protected]>
Commit: Ihor Radchenko <[email protected]>

    ox-org: Fix handling export snippets
    
    * lisp/org-element.el (org-element-interpret-data): Fix interpreting
    anonymous nodes.
    * lisp/ox-org.el (org-org-identity): Do not reproduce secondary
    strings verbatim.  Pass them through export.
    (org-org-headline): Pass headline title through export.
    (org-org-export-snippet): New transcoder.
    * testing/lisp/test-ox-org.el: New test file.
---
 lisp/org-element.el         |  2 +-
 lisp/ox-org.el              | 31 ++++++++++++++++++++++++-------
 testing/lisp/test-ox-org.el | 44 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 69 insertions(+), 8 deletions(-)

diff --git a/lisp/org-element.el b/lisp/org-element.el
index 5f64cc1c1d..7078ce1f89 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -5540,7 +5540,7 @@ DATA is a parse tree, an element, an object or a 
secondary string
 to interpret.  Return Org syntax as a string."
   (letrec ((fun
            (lambda (data parent)
-             (let* ((type (org-element-type data))
+             (let* ((type (org-element-type data 'allow-anonymous))
                     ;; Find interpreter for current object or
                     ;; element.  If it doesn't exist (e.g. this is
                     ;; a pseudo object or element), return contents,
diff --git a/lisp/ox-org.el b/lisp/ox-org.el
index e2c434fd6c..34a73f8f51 100644
--- a/lisp/ox-org.el
+++ b/lisp/ox-org.el
@@ -79,6 +79,7 @@ described in the Info node `(org)Advanced features'."
     (entity . org-org-identity)
     (example-block . org-org-identity)
     (export-block . org-org-export-block)
+    (export-snippet . org-org-export-snippet)
     (fixed-width . org-org-identity)
     (footnote-definition . ignore)
     (footnote-reference . org-org-identity)
@@ -158,13 +159,23 @@ CONTENTS and INFO are ignored."
   (and (equal (org-element-property :type export-block) "ORG")
        (org-element-property :value export-block)))
 
-(defun org-org-identity (blob contents _info)
+(defun org-org-identity (blob contents info)
   "Transcode BLOB element or object back into Org syntax.
-CONTENTS is its contents, as a string or nil.  INFO is ignored."
-  (let ((case-fold-search t))
-    (replace-regexp-in-string
-     "^[ \t]*#\\+attr_[-_a-z0-9]+:\\(?: .*\\)?\n" ""
-     (org-export-expand blob contents t))))
+CONTENTS is its contents, as a string or nil.  INFO is the information plist."
+  (let ((new-blob (org-element-copy blob)))
+    ;; Recursively export secondary objects.
+    (org-element-map new-blob t
+      (lambda (data)
+        (unless (eq data new-blob)
+          (let ((exported-data (copy-sequence (org-export-data data info))))
+            (unless (string-empty-p exported-data)
+              (org-element-insert-before exported-data data))
+            (org-element-extract-element data))))
+      info nil nil 'with-affiliated)
+    (let ((case-fold-search t))
+      (replace-regexp-in-string
+       "^[ \t]*#\\+attr_[-_a-z0-9]+:\\(?: .*\\)?\n" ""
+       (org-export-expand new-blob contents t)))))
 
 (defun org-org-headline (headline contents info)
   "Transcode HEADLINE element back into Org syntax.
@@ -178,7 +189,7 @@ CONTENTS is its contents, as a string or nil.  INFO is 
ignored."
       (org-element-put-property headline :priority nil))
     (org-element-put-property headline :level
                              (org-export-get-relative-level headline info))
-    (org-element-headline-interpreter headline contents)))
+    (org-org-identity headline contents info)))
 
 (defun org-org-keyword (keyword _contents _info)
   "Transcode KEYWORD element back into Org syntax.
@@ -195,6 +206,12 @@ INFO is a plist containing current export state."
   (or (org-export-custom-protocol-maybe link contents 'org info)
       (org-element-link-interpreter link contents)))
 
+(defun org-org-export-snippet (export-snippet _contents _info)
+  "Transcode a EXPORT-SNIPPET object from Org to Org.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  (when (eq (org-export-snippet-backend export-snippet) 'org)
+    (org-element-property :value export-snippet)))
+
 (defun org-org-template (contents info)
   "Return Org document template with document keywords.
 CONTENTS is the transcoded contents string.  INFO is a plist used
diff --git a/testing/lisp/test-ox-org.el b/testing/lisp/test-ox-org.el
new file mode 100644
index 0000000000..a56a1a2afb
--- /dev/null
+++ b/testing/lisp/test-ox-org.el
@@ -0,0 +1,44 @@
+;;; test-ox-md.el --- Tests for ox-org.el            -*- lexical-binding: t; 
-*-
+
+;; Copyright (C) 2026  Ihor Radchenko
+
+;; Author: Ihor Radchenko <[email protected]>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ox-org)
+
+(ert-deftest ox-org/honor-export-snippets ()
+  "Test exporting export snippets."
+  (org-test-with-temp-text "
+** @@comment:nope@@ title
+#+caption: @@comment:nope@@ Caption
+- @@comment:nope@@ tag ::
+- @@org:yes@@ tag ::
+"
+    (let ((export-buffer "*Test Org Export*")
+          (org-export-show-temporary-export-buffer nil))
+      (org-export-to-buffer 'org export-buffer)
+      (with-current-buffer export-buffer
+        (goto-char (point-min))
+        (should (search-forward "* title"))
+        (should (search-forward "#+caption: Caption"))
+        (should (search-forward "- tag :: "))
+        (should (search-forward "- yes tag :: "))))))
+
+(provide 'test-ox-org)
+
+;; test-ox-org.el ends here

Reply via email to