forked from mirrors/org-mode
ox: Fix duplicate internal references for same title headings
* lisp/ox.el (org-export-get-reference): Ensure different elements or objects generating the same search cell do not get the same internal reference. * testing/lisp/test-ox.el (test-org-export/get-reference): Add test. Reported-by: mstrey@strey.biz <http://permalink.gmane.org/gmane.emacs.orgmode/110211>
This commit is contained in:
parent
a3c366eb98
commit
27b10fb265
30
lisp/ox.el
30
lisp/ox.el
|
@ -4385,19 +4385,35 @@ reference consists of alphanumeric characters only."
|
||||||
(or (car (rassq datum cache))
|
(or (car (rassq datum cache))
|
||||||
(let* ((crossrefs (plist-get info :crossrefs))
|
(let* ((crossrefs (plist-get info :crossrefs))
|
||||||
(cells (org-export-search-cells datum))
|
(cells (org-export-search-cells datum))
|
||||||
;; If any other published document relies on an
|
;; Preserve any pre-existing association between
|
||||||
;; association between a search cell and a reference,
|
;; a search cell and a reference, i.e., when some
|
||||||
;; make sure to preserve it. See
|
;; previously published document referenced a location
|
||||||
;; `org-publish-resolve-external-link' for details.
|
;; within current file (see
|
||||||
(new (or (cdr (cl-some (lambda (c) (assoc c crossrefs)) cells))
|
;; `org-publish-resolve-external-link').
|
||||||
|
;;
|
||||||
|
;; However, there is no guarantee that search cells are
|
||||||
|
;; unique, e.g., there might be duplicate custom ID or
|
||||||
|
;; two headings with the same title in the file.
|
||||||
|
;;
|
||||||
|
;; As a consequence, before re-using any reference to
|
||||||
|
;; an element or object, we check that it doesn't refer
|
||||||
|
;; to a previous element or object.
|
||||||
|
(new (or (cl-some
|
||||||
|
(lambda (cell)
|
||||||
|
(let ((stored (cdr (assoc cell crossrefs))))
|
||||||
|
(when stored
|
||||||
|
(let ((old (org-export-format-reference stored)))
|
||||||
|
(and (not (assoc old cache)) stored)))))
|
||||||
|
cells)
|
||||||
(org-export-new-reference cache)))
|
(org-export-new-reference cache)))
|
||||||
(reference-string (org-export-format-reference new)))
|
(reference-string (org-export-format-reference new)))
|
||||||
;; Cache contains both data already associated to
|
;; Cache contains both data already associated to
|
||||||
;; a reference and in-use internal references, so as to make
|
;; a reference and in-use internal references, so as to make
|
||||||
;; unique references.
|
;; unique references.
|
||||||
(dolist (cell cells) (push (cons cell new) cache))
|
(dolist (cell cells) (push (cons cell new) cache))
|
||||||
;; Keep an associated related to DATUM as not every object
|
;; Retain a direct association between reference string and
|
||||||
;; and element can be associated to a search cell.
|
;; DATUM since (1) not every object or element can be given
|
||||||
|
;; a search cell (2) it permits quick lookup.
|
||||||
(push (cons reference-string datum) cache)
|
(push (cons reference-string datum) cache)
|
||||||
(plist-put info :internal-references cache)
|
(plist-put info :internal-references cache)
|
||||||
reference-string))))
|
reference-string))))
|
||||||
|
|
|
@ -3185,7 +3185,8 @@ Another text. (ref:text)
|
||||||
(let ((headline (org-element-map tree 'headline #'identity nil t)))
|
(let ((headline (org-element-map tree 'headline #'identity nil t)))
|
||||||
(equal (org-export-get-reference headline info)
|
(equal (org-export-get-reference headline info)
|
||||||
(org-export-get-reference headline info)))))
|
(org-export-get-reference headline info)))))
|
||||||
;; Use search cells defined in `:crossrefs'.
|
;; Use search cells defined in `:crossrefs'. However, handle
|
||||||
|
;; duplicate search cells.
|
||||||
(should
|
(should
|
||||||
(equal "org0000001"
|
(equal "org0000001"
|
||||||
(org-test-with-parsed-data "* Headline"
|
(org-test-with-parsed-data "* Headline"
|
||||||
|
@ -3193,7 +3194,16 @@ Another text. (ref:text)
|
||||||
(search-cell (car (org-export-search-cells headline))))
|
(search-cell (car (org-export-search-cells headline))))
|
||||||
(setq info
|
(setq info
|
||||||
(plist-put info :crossrefs (list (cons search-cell 1))))
|
(plist-put info :crossrefs (list (cons search-cell 1))))
|
||||||
(org-export-get-reference headline info))))))
|
(org-export-get-reference headline info)))))
|
||||||
|
(should-not
|
||||||
|
(equal '("org0000001" "org0000001")
|
||||||
|
(org-test-with-parsed-data "* H\n** H"
|
||||||
|
(org-element-map tree 'headline
|
||||||
|
(lambda (h)
|
||||||
|
(let* ((search-cell (car (org-export-search-cells h)))
|
||||||
|
(info (plist-put info :crossrefs
|
||||||
|
(list (cons search-cell 1)))))
|
||||||
|
(org-export-get-reference h info))))))))
|
||||||
|
|
||||||
|
|
||||||
;;; Pseudo objects and pseudo elements
|
;;; Pseudo objects and pseudo elements
|
||||||
|
|
Loading…
Reference in New Issue