forked from mirrors/org-mode
ox: Make footnotes file specific when including Org files
* lisp/ox.el (org-export-expand-include-keyword, org-export--prepare-file-contents): Make footnotes file specific when including Org files. * doc/org.texi (Include files): Add documentation. * testing/lisp/test-ox.el (test-org-export/expand-include): Add tests. http://permalink.gmane.org/gmane.emacs.orgmode/83606
This commit is contained in:
parent
e84c1d8442
commit
b8781c4c85
|
@ -9953,9 +9953,11 @@ include your @file{.emacs} file, you could use:
|
|||
@noindent
|
||||
The optional second and third parameter are the markup (e.g., @samp{quote},
|
||||
@samp{example}, or @samp{src}), and, if the markup is @samp{src}, the
|
||||
language for formatting the contents. The markup is optional; if it is not
|
||||
given, the text will be assumed to be in Org mode format and will be
|
||||
processed normally.
|
||||
language for formatting the contents.
|
||||
|
||||
If no markup is given, the text will be assumed to be in Org mode format and
|
||||
will be processed normally. However, footnote labels (@pxref{Footnotes}) in
|
||||
the file will be made local to that file.
|
||||
|
||||
Contents of the included file will belong to the same structure (headline,
|
||||
item) containing the @code{INCLUDE} keyword. In particular, headlines within
|
||||
|
|
33
lisp/ox.el
33
lisp/ox.el
|
@ -3279,7 +3279,9 @@ with their line restriction, when appropriate. It is used to
|
|||
avoid infinite recursion. Optional argument DIR is the current
|
||||
working directory. It is used to properly resolve relative
|
||||
paths."
|
||||
(let ((case-fold-search t))
|
||||
(let ((case-fold-search t)
|
||||
(file-prefix (make-hash-table :test #'equal))
|
||||
(current-prefix 0))
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "^[ \t]*#\\+INCLUDE:" nil t)
|
||||
(let ((element (save-match-data (org-element-at-point))))
|
||||
|
@ -3349,13 +3351,16 @@ paths."
|
|||
(with-temp-buffer
|
||||
(let ((org-inhibit-startup t)) (org-mode))
|
||||
(insert
|
||||
(org-export--prepare-file-contents file lines ind minlevel))
|
||||
(org-export--prepare-file-contents
|
||||
file lines ind minlevel
|
||||
(or (gethash file file-prefix)
|
||||
(puthash file (incf current-prefix) file-prefix))))
|
||||
(org-export-expand-include-keyword
|
||||
(cons (list file lines) included)
|
||||
(file-name-directory file))
|
||||
(buffer-string)))))))))))))
|
||||
|
||||
(defun org-export--prepare-file-contents (file &optional lines ind minlevel)
|
||||
(defun org-export--prepare-file-contents (file &optional lines ind minlevel id)
|
||||
"Prepare the contents of FILE for inclusion and return them as a string.
|
||||
|
||||
When optional argument LINES is a string specifying a range of
|
||||
|
@ -3369,7 +3374,12 @@ headline encountered.
|
|||
|
||||
Optional argument MINLEVEL, when non-nil, is an integer
|
||||
specifying the level that any top-level headline in the included
|
||||
file should have."
|
||||
file should have.
|
||||
|
||||
Optional argument ID is an integer that will be inserted before
|
||||
each footnote definition and reference if FILE is an Org file.
|
||||
This is useful to avoid conflicts when more than one Org file
|
||||
with footnotes is included in a document."
|
||||
(with-temp-buffer
|
||||
(insert-file-contents file)
|
||||
(when lines
|
||||
|
@ -3428,6 +3438,21 @@ file should have."
|
|||
(org-map-entries
|
||||
(lambda () (if (< offset 0) (delete-char (abs offset))
|
||||
(insert (make-string offset ?*)))))))))))
|
||||
;; Append ID to all footnote references and definitions, so they
|
||||
;; become file specific and cannot collide with footnotes in other
|
||||
;; included files.
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward org-footnote-re nil t)
|
||||
(let ((reference (org-element-context)))
|
||||
(when (memq (org-element-type reference)
|
||||
'(footnote-reference footnote-definition))
|
||||
(goto-char (org-element-property :begin reference))
|
||||
(forward-char)
|
||||
(let ((label (org-element-property :label reference)))
|
||||
(cond ((not label))
|
||||
((org-string-match-p "\\`[0-9]+\\'" label)
|
||||
(insert (format "fn:%d-" id)))
|
||||
(t (forward-char 3) (insert (format "%d-" id))))))))
|
||||
(org-element-normalize-string (buffer-string))))
|
||||
|
||||
(defun org-export-execute-babel-code ()
|
||||
|
|
|
@ -850,7 +850,48 @@ body\n")))
|
|||
org-test-dir)
|
||||
(org-export-expand-include-keyword)
|
||||
(should (equal (buffer-string)
|
||||
"#+BEGIN_SRC emacs-lisp\n(+ 2 1)\n#+END_SRC\n"))))
|
||||
"#+BEGIN_SRC emacs-lisp\n(+ 2 1)\n#+END_SRC\n")))
|
||||
;; Footnotes labels are local to each included file.
|
||||
(should
|
||||
(= 6
|
||||
(length
|
||||
(delete-dups
|
||||
(let ((contents "
|
||||
Footnotes[fn:1], [fn:test] and [fn:inline:anonymous footnote].
|
||||
\[fn:1] Footnote 1
|
||||
\[fn:test] Footnote \"test\""))
|
||||
(org-test-with-temp-text-in-file contents
|
||||
(let ((file1 (buffer-file-name)))
|
||||
(org-test-with-temp-text-in-file contents
|
||||
(let ((file2 (buffer-file-name)))
|
||||
(org-test-with-temp-text
|
||||
(format "#+INCLUDE: \"%s\"\n#+INCLUDE: \"%s\""
|
||||
file1 file2)
|
||||
(org-export-expand-include-keyword)
|
||||
(let (unique-labels)
|
||||
(org-element-map (org-element-parse-buffer)
|
||||
'footnote-reference
|
||||
(lambda (ref)
|
||||
(org-element-property :label ref))))))))))))))
|
||||
;; Footnotes labels are not local to each include keyword.
|
||||
(should
|
||||
(= 3
|
||||
(length
|
||||
(delete-dups
|
||||
(let ((contents "
|
||||
Footnotes[fn:1], [fn:test] and [fn:inline:anonymous footnote].
|
||||
\[fn:1] Footnote 1
|
||||
\[fn:test] Footnote \"test\""))
|
||||
(org-test-with-temp-text-in-file contents
|
||||
(let ((file (buffer-file-name)))
|
||||
(org-test-with-temp-text
|
||||
(format "#+INCLUDE: \"%s\"\n#+INCLUDE: \"%s\"" file file)
|
||||
(org-export-expand-include-keyword)
|
||||
(let (unique-labels)
|
||||
(org-element-map (org-element-parse-buffer)
|
||||
'footnote-reference
|
||||
(lambda (ref)
|
||||
(org-element-property :label ref)))))))))))))
|
||||
|
||||
(ert-deftest test-org-export/expand-macro ()
|
||||
"Test macro expansion in an Org buffer."
|
||||
|
|
Loading…
Reference in New Issue