diff --git a/lisp/ox.el b/lisp/ox.el index 9b0faa6a5..3071e559f 100644 --- a/lisp/ox.el +++ b/lisp/ox.el @@ -2588,25 +2588,45 @@ The function assumes BUFFER's major mode is `org-mode'." "Delete commented areas in the buffer. Commented areas are comments, comment blocks, commented trees and inlinetasks. Trailing blank lines after a comment or a comment -block are preserved. Narrowing, if any, is ignored." +block are removed, as long as it doesn't alter the structure of +the document. Narrowing, if any, is ignored." (org-with-wide-buffer (goto-char (point-min)) - (let ((regexp (concat org-outline-regexp-bol ".*" org-comment-string - "\\|" - "^[ \t]*#\\(?: \\|$\\|\\+begin_comment\\)")) - (case-fold-search t)) + (let* ((case-fold-search t) + (comment-re "^[ \t]*#\\(?: \\|$\\|\\+end_comment\\)") + (regexp (concat org-outline-regexp-bol ".*" org-comment-string "\\|" + comment-re))) (while (re-search-forward regexp nil t) - (let ((e (org-element-at-point))) - (case (org-element-type e) - ((comment comment-block) - (delete-region (org-element-property :begin e) - (progn (goto-char (org-element-property :end e)) - (skip-chars-backward " \r\t\n") - (line-beginning-position 2)))) + (let ((element (org-element-at-point))) + (case (org-element-type element) ((headline inlinetask) - (when (org-element-property :commentedp e) - (delete-region (org-element-property :begin e) - (org-element-property :end e)))))))))) + (when (org-element-property :commentedp element) + (delete-region (org-element-property :begin element) + (org-element-property :end element)))) + ((comment comment-block) + (let* ((parent (org-element-property :parent element)) + (start (org-element-property :begin element)) + (end (org-element-property :end element)) + ;; We remove trailing blank lines. Doing so could + ;; modify the structure of the document. Therefore + ;; we ensure that any comment between elements is + ;; replaced with one empty line, so as to keep them + ;; separated. + (add-blank? + (save-excursion + (goto-char start) + (not (or (bobp) + (eq (org-element-property :contents-begin parent) + start) + (eq (org-element-property :contents-end parent) + end) + (progn + (forward-line -1) + (or (org-looking-at-p "^[ \t]*$") + (org-with-limited-levels + (org-at-heading-p))))))))) + (delete-region start end) + (when add-blank? (insert "\n")))))))))) (defun org-export--prune-tree (data info) "Prune non exportable elements from DATA. diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el index 5dee88732..31de8f454 100644 --- a/testing/lisp/test-ox.el +++ b/testing/lisp/test-ox.el @@ -1621,6 +1621,68 @@ Footnotes[fn:2], foot[fn:test], digit only[3], and [fn:inline:anonymous footnote '(:with-emphasize t))))) + +;;; Comments + +(ert-deftest test-org-export/comments () + "Test comments handling during export. +In particular, structure of the document mustn't be altered after +comments removal." + (should + (equal (org-test-with-temp-text " +Para1 +# Comment + +# Comment +Para2" + (org-export-as (org-test-default-backend))) + "Para1\n\nPara2\n")) + (should + (equal (org-test-with-temp-text " +Para1 +# Comment +Para2" + (org-export-as (org-test-default-backend))) + "Para1\n\nPara2\n")) + (should + (equal (org-test-with-temp-text " +\[fn:1] Para1 +# Inside definition + + +# Outside definition +Para2" + (org-export-as (org-test-default-backend))) + "[fn:1] Para1\n\n\nPara2\n")) + (should + (equal (org-test-with-temp-text " +\[fn:1] Para1 + +# Inside definition + +# Inside definition + +Para2" + (org-export-as (org-test-default-backend))) + "[fn:1] Para1\n\nPara2\n")) + (should + (equal (org-test-with-temp-text " +\[fn:1] Para1 +# Inside definition + +Para2" + (org-export-as (org-test-default-backend))) + "[fn:1] Para1\n\nPara2\n")) + (should + (equal (org-test-with-temp-text " +\[fn:1] Para1 + +# Inside definition +Para2" + (org-export-as (org-test-default-backend))) + "[fn:1] Para1\n\nPara2\n"))) + + ;;; Export Snippets