forked from mirrors/org-mode
contrib/lisp/org-export: Improve footnote API
* contrib/lisp/org-export.el (org-export-initial-options): Rename `:footnotes-labels-alist' property into `:footnote-definition-alist' for consistency. Add comments to code. (org-export-persistent-properties-list): Apply previous renaming. (org-export-update-info): Rename `:seen-footnote-labels' into `footnote-seen-labels'. (org-export-collect-footnote-definitions, org-export-footnote-first-reference-p, org-export-get-footnote-definition, org-export-get-footnote-number): New functions.
This commit is contained in:
parent
314e2647d7
commit
27480a2ee7
|
@ -579,12 +579,25 @@ while every other back-end will ignore it."
|
|||
;; - category :: option
|
||||
;; - type :: list of strings
|
||||
|
||||
;; + `footnotes-labels-alist' :: Alist between footnote labels and
|
||||
;; their definition, as parsed data. Once retrieved, the
|
||||
;; definition should be exported with `org-export-data'.
|
||||
;; + `footnote-definition-alist' :: Alist between footnote labels and
|
||||
;; their definition, as parsed data. Only non-inlined footnotes
|
||||
;; are represented in this alist. Also, every definition isn't
|
||||
;; guaranteed to be referenced in the parse tree. The purpose of
|
||||
;; this property is to preserve definitions from oblivion
|
||||
;; (i.e. when the parse tree comes from a part of the original
|
||||
;; buffer), it isn't meant for direct use in a back-end. To
|
||||
;; retrieve a definition relative to a reference, use
|
||||
;; `org-export-get-footnote-definition' instead.
|
||||
;; - category :: option
|
||||
;; - type :: alist (STRING . LIST)
|
||||
|
||||
;; + `footnote-seen-labels' :: List of already transcoded footnote
|
||||
;; labels. It is used to know when a reference appears for the
|
||||
;; first time. (cf. `org-export-footnote-first-reference-p').
|
||||
;; - category :: persistent
|
||||
;; - type :: list of strings
|
||||
;; - update :: `org-export-update-info'
|
||||
|
||||
;; + `genealogy' :: List of current element's parents types.
|
||||
;; - category :: local
|
||||
;; - type :: list of symbols
|
||||
|
@ -673,12 +686,6 @@ while every other back-end will ignore it."
|
|||
;; - category :: option
|
||||
;; - type :: symbol (nil, t)
|
||||
|
||||
;; + `seen-footnote-labels' :: List of already transcoded footnote
|
||||
;; labels.
|
||||
;; - category :: persistent
|
||||
;; - type :: list of strings
|
||||
;; - update :: `org-export-update-info'
|
||||
|
||||
;; + `select-tags' :: List of tags enforcing inclusion of sub-trees in
|
||||
;; transcoding. When such a tag is present,
|
||||
;; subtrees without it are de facto excluded from
|
||||
|
@ -1030,6 +1037,10 @@ BACKEND is a symbol specifying which back-end should be used."
|
|||
"Return a plist with non-optional properties.
|
||||
OPTIONS is the export options plist computed so far."
|
||||
(list
|
||||
;; `:macro-date', `:macro-time' and `:macro-property' could as well
|
||||
;; be initialized as persistent properties, since they don't depend
|
||||
;; on initial environment. Though, it may be more logical to keep
|
||||
;; them close to other ":macro-" properties.
|
||||
:macro-date "(eval (format-time-string \"$1\"))"
|
||||
:macro-time "(eval (format-time-string \"$1\"))"
|
||||
:macro-property "(eval (org-entry-get nil \"$1\" 'selective))"
|
||||
|
@ -1041,18 +1052,22 @@ OPTIONS is the export options plist computed so far."
|
|||
"))"))
|
||||
:macro-input-file (and (buffer-file-name)
|
||||
(file-name-nondirectory (buffer-file-name)))
|
||||
:footnotes-labels-alist
|
||||
;; Footnotes definitions must be collected in the original buffer,
|
||||
;; as there's no insurance that they will still be in the parse
|
||||
;; tree, due to some narrowing.
|
||||
:footnote-definition-alist
|
||||
(let (alist)
|
||||
(org-with-wide-buffer
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward org-footnote-definition-re nil t)
|
||||
(let ((def (org-footnote-at-definition-p)))
|
||||
(org-skip-whitespace)
|
||||
(push (cons (car def)
|
||||
(save-restriction
|
||||
(narrow-to-region (point) (nth 2 def))
|
||||
(org-element-parse-buffer)))
|
||||
alist)))
|
||||
(when def
|
||||
(org-skip-whitespace)
|
||||
(push (cons (car def)
|
||||
(save-restriction
|
||||
(narrow-to-region (point) (nth 2 def))
|
||||
(org-element-parse-buffer)))
|
||||
alist))))
|
||||
alist))))
|
||||
|
||||
(defvar org-export-allow-BIND-local nil)
|
||||
|
@ -1102,7 +1117,7 @@ retrieved."
|
|||
|
||||
(defconst org-export-persistent-properties-list
|
||||
'(:back-end :code-refs :headline-alist :headline-numbering :headline-offset
|
||||
:parse-tree :point-max :seen-footnote-labels :target-list
|
||||
:parse-tree :point-max :footnote-seen-labels :target-list
|
||||
:total-loc :use-select-tags)
|
||||
"List of persistent properties.")
|
||||
|
||||
|
@ -1278,6 +1293,8 @@ When RECURSEP is non-nil, assume the following element or object
|
|||
will be inside the current one.
|
||||
|
||||
The following properties are updated:
|
||||
`footnote-seen-labels' List of already parsed footnote
|
||||
labels (string list)
|
||||
`genealogy' List of current element's parents
|
||||
(symbol list).
|
||||
`inherited-properties' List of inherited properties from
|
||||
|
@ -1286,8 +1303,6 @@ The following properties are updated:
|
|||
(plist).
|
||||
`previous-element' Previous element's type (symbol).
|
||||
`previous-object' Previous object's type (symbol).
|
||||
`seen-footnote-labels' List of already parsed footnote
|
||||
labels (string list)
|
||||
|
||||
Return the property list."
|
||||
(let* ((type (and (not (stringp blob)) (car blob))))
|
||||
|
@ -1317,12 +1332,12 @@ Return the property list."
|
|||
(when (eq type 'footnote-reference)
|
||||
(let ((label (org-element-get-property :label blob))
|
||||
(seen-labels (plist-get org-export-persistent-properties
|
||||
:seen-footnote-labels)))
|
||||
:footnote-seen-labels)))
|
||||
;; Store anonymous footnotes (nil label) without checking if
|
||||
;; another anonymous footnote was seen before.
|
||||
(unless (and label (member label seen-labels))
|
||||
(setq info (org-export-set-property
|
||||
info :seen-footnote-labels (push label seen-labels))))))
|
||||
info :footnote-seen-labels (push label seen-labels))))))
|
||||
;; Set `:previous-element' or `:previous-object' according to
|
||||
;; BLOB.
|
||||
(setq info (cond ((not type)
|
||||
|
@ -2074,9 +2089,80 @@ Point is at buffer's beginning when BODY is applied."
|
|||
;; function general enough to have its use across many back-ends
|
||||
;; should be added here.
|
||||
|
||||
;; As of now, functions operating on headlines, include keywords,
|
||||
;; links, macros, references, src-blocks, tables and tables of
|
||||
;; contents are implemented.
|
||||
;; As of now, functions operating on footnotes, headlines, include
|
||||
;; keywords, links, macros, references, src-blocks, tables and tables
|
||||
;; of contents are implemented.
|
||||
|
||||
;;;; For Footnotes
|
||||
|
||||
;; `org-export-collect-footnote-definitions' is a tool to list
|
||||
;; actually used footnotes definitions in the whole parse tree, or in
|
||||
;; an headline, in order to add footnote listings throughout the
|
||||
;; transcoded data.
|
||||
|
||||
;; `org-export-footnote-first-reference-p' is a predicate used by some
|
||||
;; back-ends, when they need to attach the footnote definition only to
|
||||
;; the first occurrence of the corresponding label.
|
||||
|
||||
;; `org-export-get-footnote-definition' and
|
||||
;; `org-export-get-footnote-number' provide easier access to
|
||||
;; additional information relative to a footnote reference.
|
||||
|
||||
(defun org-export-collect-footnote-definitions (data info)
|
||||
"Return an alist between footnote label and its definition.
|
||||
|
||||
DATA is the parse tree from which definitions are collected.
|
||||
INFO is the plist used as a communication channel.
|
||||
|
||||
As anonymous footnotes have no label, the key used is that case
|
||||
is their beginning position.
|
||||
|
||||
Definitions are sorted by order of references. They either
|
||||
appear as Org data \(transcoded with `org-export-data'\) or as
|
||||
a secondary string for inlined footnotes \(transcoded with
|
||||
`org-export-secondary-string'\). Unreferenced definitions are
|
||||
ignored."
|
||||
(org-element-map
|
||||
data 'footnote-reference
|
||||
(lambda (footnote local)
|
||||
(cond
|
||||
;; Definition already collected.
|
||||
((not (org-export-footnote-first-reference-p footnote local)) nil)
|
||||
;; Reference has a label: Use it as a key, and get the
|
||||
;; corresponding definition.
|
||||
((org-element-get-property :label footnote)
|
||||
(cons (org-element-get-property :label footnote)
|
||||
(org-export-get-footnote-definition footnote local)))
|
||||
;; No label: This is an anonymous footnote. Use beginning
|
||||
;; position as the key and inline definition (a secondary
|
||||
;; string) as its value.
|
||||
(t (cons (org-element-get-property :begin footnote)
|
||||
(org-element-get-property :inline-definition footnote)))))
|
||||
info))
|
||||
|
||||
(defun org-export-footnote-first-reference-p (footnote-reference info)
|
||||
"Non-nil when a footnote reference is the first one for its label.
|
||||
|
||||
FOOTNOTE-REFERENCE is the footnote reference being considered.
|
||||
INFO is the plist used as a communication channel."
|
||||
(let ((label (org-element-get-property :label footnote-reference)))
|
||||
(not (and label (member label (plist-get info :footnote-seen-labels))))))
|
||||
|
||||
(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."
|
||||
(let ((label (org-element-get-property :label footnote-reference)))
|
||||
(or (org-element-get-property :inline-definition footnote-reference)
|
||||
(cdr (assoc label (plist-get info :footnote-definition-alist))))))
|
||||
|
||||
(defun org-export-get-footnote-number (footnote-reference info)
|
||||
"Return footnote number associated to FOOTNOTE-REFERENCE.
|
||||
INFO is the plist used as a communication channel."
|
||||
(let* ((all-seen (plist-get info :footnote-seen-labels))
|
||||
(label (org-element-get-property :label footnote-reference))
|
||||
;; Anonymous footnotes are always new footnotes.
|
||||
(seenp (and label (member label all-seen))))
|
||||
(if seenp (length seenp) (1+ (length all-seen)))))
|
||||
|
||||
|
||||
;;;; For Headlines
|
||||
|
|
Loading…
Reference in New Issue