diff --git a/lisp/org-element.el b/lisp/org-element.el index 1aa7fad50..b69e9d1ec 100644 --- a/lisp/org-element.el +++ b/lisp/org-element.el @@ -194,8 +194,8 @@ is not sufficient to know if point is at a paragraph ending. See "Complete list of object types.") (defconst org-element-recursive-objects - '(bold italic link subscript radio-target strike-through superscript - table-cell underline) + '(bold footnote-reference italic link subscript radio-target strike-through + superscript table-cell underline) "List of recursive object types.") (defvar org-element-block-name-alist @@ -341,8 +341,7 @@ still has an entry since one of its properties (`:title') does.") (defconst org-element-secondary-value-alist '((headline . :title) (inlinetask . :title) - (item . :tag) - (footnote-reference . :inline-definition)) + (item . :tag)) "Alist between element types and location of secondary value.") (defconst org-element-object-variables '(org-link-abbrev-alist-local) @@ -2755,16 +2754,17 @@ CONTENTS is nil." When at a footnote reference, return a list whose car is `footnote-reference' and cdr a plist with `:label', `:type', -`:inline-definition', `:begin', `:end' and `:post-blank' as -keywords. Otherwise, return nil." +`:begin', `:end', `:content-begin', `:contents-end' and +`:post-blank' as keywords. Otherwise, return nil." (catch 'no-object (when (looking-at org-footnote-re) (save-excursion (let* ((begin (point)) - (label (or (org-match-string-no-properties 2) - (org-match-string-no-properties 3) - (and (match-string 1) - (concat "fn:" (org-match-string-no-properties 1))))) + (label + (or (org-match-string-no-properties 2) + (org-match-string-no-properties 3) + (and (match-string 1) + (concat "fn:" (org-match-string-no-properties 1))))) (type (if (or (not label) (match-string 1)) 'inline 'standard)) (inner-begin (match-end 0)) (inner-end @@ -2776,32 +2776,22 @@ keywords. Otherwise, return nil." (1- (point)))) (post-blank (progn (goto-char (1+ inner-end)) (skip-chars-forward " \t"))) - (end (point)) - (footnote-reference - (list 'footnote-reference - (list :label label - :type type - :begin begin - :end end - :post-blank post-blank)))) - (org-element-put-property - footnote-reference :inline-definition - (and (eq type 'inline) - (org-element-parse-secondary-string - (buffer-substring inner-begin inner-end) - (org-element-restriction 'footnote-reference) - footnote-reference)))))))) + (end (point))) + (list 'footnote-reference + (list :label label + :type type + :begin begin + :end end + :contents-begin (and (eq type 'inline) inner-begin) + :contents-end (and (eq type 'inline) inner-end) + :post-blank post-blank))))))) (defun org-element-footnote-reference-interpreter (footnote-reference contents) "Interpret FOOTNOTE-REFERENCE object as Org syntax. CONTENTS is nil." - (let ((label (or (org-element-property :label footnote-reference) "fn:")) - (def - (let ((inline-def - (org-element-property :inline-definition footnote-reference))) - (if (not inline-def) "" - (concat ":" (org-element-interpret-data inline-def)))))) - (format "[%s]" (concat label def)))) + (format "[%s]" + (concat (or (org-element-property :label footnote-reference) "fn:") + (and contents (concat ":" contents))))) ;;;; Inline Babel Call diff --git a/lisp/ox.el b/lisp/ox.el index 4a538aed5..7fbbed1bf 100644 --- a/lisp/ox.el +++ b/lisp/ox.el @@ -1579,17 +1579,31 @@ inferior to file-local settings." (let (alist) (org-with-wide-buffer (goto-char (point-min)) - (while (re-search-forward org-footnote-definition-re nil t) - (let ((def (save-match-data (org-element-at-point)))) - (when (eq (org-element-type def) 'footnote-definition) - (push - (cons (org-element-property :label def) - (let ((cbeg (org-element-property :contents-begin def))) - (when cbeg - (org-element--parse-elements - cbeg (org-element-property :contents-end def) - nil nil nil nil (list 'org-data nil))))) - alist)))) + (while (re-search-forward org-footnote-re nil t) + (backward-char) + (let ((fn (save-match-data (org-element-context)))) + (case (org-element-type fn) + (footnote-definition + (push + (cons (org-element-property :label fn) + (let ((cbeg (org-element-property :contents-begin fn))) + (when cbeg + (org-element--parse-elements + cbeg (org-element-property :contents-end fn) + nil nil nil nil (list 'org-data nil))))) + alist)) + (footnote-reference + (let ((label (org-element-property :label fn)) + (cbeg (org-element-property :contents-begin fn))) + (when (and label cbeg + (eq (org-element-property :type fn) 'inline)) + (push + (cons label + (org-element-parse-secondary-string + (buffer-substring + cbeg (org-element-property :contents-end fn)) + (org-element-restriction 'footnote-reference))) + alist))))))) alist)) :id-alist ;; Collect id references. @@ -3689,11 +3703,11 @@ INFO is the plist used as a communication channel." (defun org-export-get-footnote-definition (footnote-reference info) "Return definition of FOOTNOTE-REFERENCE as parsed data. INFO is the plist used as a communication channel. If no such -definition can be found, return the \"DEFINITION NOT FOUND\" -string." +definition can be found, return \"DEFINITION NOT FOUND\"." (let ((label (org-element-property :label footnote-reference))) - (or (org-element-property :inline-definition footnote-reference) - (cdr (assoc label (plist-get info :footnote-definition-alist))) + (or (if label + (cdr (assoc label (plist-get info :footnote-definition-alist))) + (org-element-contents footnote-reference)) "DEFINITION NOT FOUND."))) (defun org-export-get-footnote-number (footnote info) diff --git a/testing/lisp/test-org-element.el b/testing/lisp/test-org-element.el index 42a19bf44..b2b0c5235 100644 --- a/testing/lisp/test-org-element.el +++ b/testing/lisp/test-org-element.el @@ -891,45 +891,45 @@ Some other text (ert-deftest test-org-element/footnote-reference-parser () "Test `footnote-reference' parser." - ;; 1. Parse a standard reference. - (org-test-with-temp-text "Text[fn:label]" - (should + ;; Parse a standard reference. + (should + (org-test-with-temp-text "Text[fn:label]" (org-element-map - (org-element-parse-buffer) 'footnote-reference 'identity))) - ;; 2. Parse a normalized reference. - (org-test-with-temp-text "Text[1]" - (should + (org-element-parse-buffer) 'footnote-reference 'identity))) + ;; Parse a normalized reference. + (should + (org-test-with-temp-text "Text[1]" (org-element-map - (org-element-parse-buffer) 'footnote-reference 'identity))) - ;; 3. Parse an inline reference. - (org-test-with-temp-text "Text[fn:test:def]" - (should + (org-element-parse-buffer) 'footnote-reference 'identity))) + ;; Parse an inline reference. + (should + (org-test-with-temp-text "Text[fn:test:def]" (org-element-map - (org-element-parse-buffer) 'footnote-reference 'identity))) - ;; 4. Parse an anonymous reference. - (org-test-with-temp-text "Text[fn::def]" - (should + (org-element-parse-buffer) 'footnote-reference 'identity))) + ;; Parse an anonymous reference. + (should + (org-test-with-temp-text "Text[fn::def]" (org-element-map - (org-element-parse-buffer) 'footnote-reference 'identity))) - ;; 5. Parse nested footnotes. - (org-test-with-temp-text "Text[fn::def [fn:label]]" - (should + (org-element-parse-buffer) 'footnote-reference 'identity))) + ;; Parse nested footnotes. + (should + (= 2 + (length + (org-test-with-temp-text "Text[fn::def [fn:label]]" + (org-element-map + (org-element-parse-buffer) 'footnote-reference 'identity))))) + ;; Parse adjacent footnotes. + (should + (org-test-with-temp-text "Text[fn:label1][fn:label2]" (= 2 (length (org-element-map - (org-element-parse-buffer) 'footnote-reference 'identity))))) - ;; 6. Parse adjacent footnotes. - (org-test-with-temp-text "Text[fn:label1][fn:label2]" - (should - (= 2 - (length - (org-element-map - (org-element-parse-buffer) 'footnote-reference 'identity))))) - ;; 7. Only properly closed footnotes are recognized as such. - (org-test-with-temp-text "Text[fn:label" - (should-not + (org-element-parse-buffer) 'footnote-reference 'identity))))) + ;; Only properly closed footnotes are recognized as such. + (should-not + (org-test-with-temp-text "Text[fn:label" (org-element-map - (org-element-parse-buffer) 'footnote-reference 'identity)))) + (org-element-parse-buffer) 'footnote-reference 'identity)))) ;;;; Headline @@ -3136,6 +3136,11 @@ Paragraph \\alpha." (eq 'table-cell (org-test-with-temp-text "|a|b|c" (goto-char (point-max)) + (org-element-type (org-element-context))))) + ;; Special case: objects in inline footnotes. + (should + (eq 'link + (org-test-with-temp-text "[fn::[[http://orgmode.org]]]" (org-element-type (org-element-context))))))