forked from mirrors/org-mode
org-e-odt.el: Handle links to target, list items
This commit is contained in:
parent
d06f326f20
commit
dcd5c81dc4
|
@ -2602,13 +2602,95 @@ Return nil, otherwise."
|
|||
(= (incf inline-image-count) 1)))
|
||||
(t nil))))))))
|
||||
|
||||
(defun org-e-odt-resolve-numbered-paragraph (element info)
|
||||
(when (eq (org-element-type element) 'item)
|
||||
(let ((el element) ordinal)
|
||||
(while (eq (org-element-type el) 'item)
|
||||
(push (1+ (length (org-export-get-previous-element el info t))) ordinal)
|
||||
(setq el (org-export-get-parent (org-export-get-parent el))))
|
||||
ordinal)))
|
||||
(defun org-e-odt-link--infer-description (destination info)
|
||||
;; DESTINATION is a HEADLINE, a "<<target>>" or an element (like
|
||||
;; paragraph, verse-block etc) to which a "#+NAME: label" can be
|
||||
;; attached. Note that labels that are attached to captioned
|
||||
;; entities - inline images, math formulae and tables - get resolved
|
||||
;; as part of `org-e-odt-format-label' and `org-e-odt--enumerate'.
|
||||
|
||||
;; Create a cross-reference to DESTINATION but make best-efforts to
|
||||
;; create a *meaningful* description. Check item numbers, section
|
||||
;; number and section title in that order.
|
||||
|
||||
;; NOTE: Counterpart of `org-export-get-ordinal'.
|
||||
;; FIXME: Handle footnote-definition footnote-reference?
|
||||
(let* ((genealogy (org-export-get-genealogy destination))
|
||||
(data (reverse genealogy))
|
||||
(label (case (org-element-type destination)
|
||||
(headline
|
||||
(format "sec-%s" (mapconcat 'number-to-string
|
||||
(org-export-get-headline-number
|
||||
destination info) "-")))
|
||||
(target
|
||||
(org-element-property :value destination))
|
||||
(t (error "FIXME: Resolve %S" destination)))))
|
||||
(or
|
||||
(let* ( ;; Locate top-level list.
|
||||
(top-level-list
|
||||
(loop for x on data
|
||||
when (eq (org-element-type (car x)) 'plain-list)
|
||||
return x))
|
||||
;; Get list item nos.
|
||||
(item-numbers
|
||||
(loop for (plain-list item . rest) on top-level-list by #'cddr
|
||||
until (not (eq (org-element-type plain-list) 'plain-list))
|
||||
collect (when (eq (org-element-property :type
|
||||
plain-list)
|
||||
'ordered)
|
||||
(1+ (length (org-export-get-previous-element
|
||||
item info t))))))
|
||||
;; Locate top-most listified headline.
|
||||
(listified-headlines
|
||||
(loop for x on data
|
||||
when (and (eq (org-element-type (car x)) 'headline)
|
||||
(org-export-low-level-p (car x) info))
|
||||
return x))
|
||||
;; Get listified headline numbers.
|
||||
(listified-headline-nos
|
||||
(loop for el in listified-headlines
|
||||
when (eq (org-element-type el) 'headline)
|
||||
collect (when (org-export-numbered-headline-p el info)
|
||||
(1+ (length (org-export-get-previous-element
|
||||
el info t)))))))
|
||||
;; Combine item numbers from both the listified headlines and
|
||||
;; regular list items.
|
||||
|
||||
;; Case 1: Check if all the parents of list item are numbered.
|
||||
;; If yes, link to the item proper.
|
||||
(let ((item-numbers (append listified-headline-nos item-numbers)))
|
||||
(when (and item-numbers (not (memq nil item-numbers)))
|
||||
(format "<text:bookmark-ref text:reference-format=\"number-all-superior\" text:ref-name=\"%s\">%s</text:bookmark-ref>"
|
||||
(org-export-solidify-link-text label)
|
||||
(mapconcat (lambda (n) (if (not n) " "
|
||||
(concat (number-to-string n) ".")))
|
||||
item-numbers "")))))
|
||||
;; Case 2: Locate a regular and numbered headline in the
|
||||
;; hierarchy. Display it's section number.
|
||||
(let ((headline (loop for el in (cons destination genealogy)
|
||||
when (and (eq (org-element-type el) 'headline)
|
||||
(not (org-export-low-level-p el info))
|
||||
(org-export-numbered-headline-p el info))
|
||||
return el)))
|
||||
;; We found one.
|
||||
(when headline
|
||||
(format "<text:bookmark-ref text:reference-format=\"chapter\" text:ref-name=\"OrgXref.%s\">%s</text:bookmark-ref>"
|
||||
(org-export-solidify-link-text label)
|
||||
(mapconcat 'number-to-string (org-export-get-headline-number
|
||||
headline info) "."))))
|
||||
;; Case 4: Locate a regular headline in the hierarchy. Display
|
||||
;; it's title.
|
||||
(let ((headline (loop for el in (cons destination genealogy)
|
||||
when (and (eq (org-element-type el) 'headline)
|
||||
(not (org-export-low-level-p el info)))
|
||||
return el)))
|
||||
;; We found one.
|
||||
(when headline
|
||||
(format "<text:bookmark-ref text:reference-format=\"text\" text:ref-name=\"OrgXref.%s\">%s</text:bookmark-ref>"
|
||||
(org-export-solidify-link-text label)
|
||||
(let ((title (org-element-property :title headline)))
|
||||
(org-export-data title info)))))
|
||||
(error "FIXME?"))))
|
||||
|
||||
(defun org-e-odt-link (link desc info)
|
||||
"Transcode a LINK object from Org to ODT.
|
||||
|
@ -2653,90 +2735,63 @@ INFO is a plist holding contextual information. See
|
|||
;; Links pointing to an headline: Find destination and build
|
||||
;; appropriate referencing command.
|
||||
((member type '("custom-id" "fuzzy" "id"))
|
||||
(let ((destination (if (string= type "fuzzy")
|
||||
(org-export-resolve-fuzzy-link link info)
|
||||
(org-export-resolve-id-link link info))))
|
||||
(case (org-element-type destination)
|
||||
;; Fuzzy link points nowhere.
|
||||
('nil
|
||||
(let* ((destination (if (string= type "fuzzy")
|
||||
(org-export-resolve-fuzzy-link link info)
|
||||
(org-export-resolve-id-link link info))))
|
||||
(or
|
||||
;; Case 1: Fuzzy link points nowhere.
|
||||
(when (null (org-element-type destination))
|
||||
(format "<text:span text:style-name=\"%s\">%s</text:span>"
|
||||
"Emphasis" (or desc (org-export-data
|
||||
(org-element-property
|
||||
:raw-link link) info))))
|
||||
;; Fuzzy link points to an invisible target.
|
||||
(keyword nil)
|
||||
;; LINK points to an headline. Check if LINK should display
|
||||
;; section numbers.
|
||||
(headline
|
||||
(let* ((headline-no (org-export-get-headline-number destination info))
|
||||
(label (format "sec-%s" (mapconcat 'number-to-string
|
||||
headline-no "-"))))
|
||||
;; Case 2: Fuzzy link points to an invisible target. Strip it.
|
||||
(when (eq (org-element-type destination) 'keyword) "")
|
||||
;; Case 3: LINK points to an headline.
|
||||
(when (eq (org-element-type destination) 'headline)
|
||||
;; Case 3.1: LINK has a custom description that is
|
||||
;; different from headline's title. Create a hyperlink.
|
||||
(when (and desc
|
||||
(let ((link-desc (org-element-contents link)))
|
||||
(not (string= (org-element-interpret-data link-desc)
|
||||
(org-element-property :raw-value
|
||||
destination)))))
|
||||
(let* ((headline-no (org-export-get-headline-number
|
||||
destination info))
|
||||
(label (format "sec-%s" (mapconcat 'number-to-string
|
||||
headline-no "-"))))
|
||||
(format "<text:a xlink:type=\"simple\" xlink:href=\"#%s\">%s</text:a>"
|
||||
label desc))))
|
||||
;; Case 4: LINK points to an Inline image, Math formula or a Table.
|
||||
(let ((label-reference (ignore-errors (org-e-odt-format-label
|
||||
destination info 'reference))))
|
||||
(when label-reference
|
||||
(cond
|
||||
;; Case 1: LINK has a custom description that is
|
||||
;; different from headline's title. Create a hyperlink
|
||||
;; that display LINK's description.
|
||||
((and desc
|
||||
(let ((link-desc (org-element-contents link)))
|
||||
(not (string=
|
||||
(org-element-interpret-data link-desc)
|
||||
(org-element-property :raw-value destination))))
|
||||
(format "<text:a xlink:type=\"simple\" xlink:href=\"#%s\">%s</text:a>"
|
||||
label desc)))
|
||||
;; Case 2: LINK has no custom description and HEADLINE
|
||||
;; is numbered. Display section number.
|
||||
((org-export-numbered-headline-p destination info)
|
||||
(format "<text:bookmark-ref text:reference-format=\"chapter\" text:ref-name=\"OrgXref.%s\">%s</text:bookmark-ref>"
|
||||
label (mapconcat 'number-to-string headline-no ".")))
|
||||
;; Case 3: LINK has no custom descripiton and HEADLINE
|
||||
;; is un-numbered. Display headline's title.
|
||||
(t (let ((title (org-element-property :title destination)))
|
||||
(format "<text:bookmark-ref text:reference-format=\"text\" text:ref-name=\"OrgXref.%s\">%s</text:bookmark-ref>"
|
||||
label (org-export-data title info)))))))
|
||||
;; Fuzzy link points to a target. Do as above.
|
||||
(target
|
||||
;; Identify nearest meaningful container
|
||||
(let ((container
|
||||
(loop for parent in (org-export-get-genealogy destination)
|
||||
when
|
||||
(memq
|
||||
(org-element-type parent)
|
||||
'(footnote-definition footnote-reference headline item
|
||||
table))
|
||||
return parent)))
|
||||
;; There is a meaningful container
|
||||
(when container
|
||||
(case (org-element-type container)
|
||||
;; Container is item
|
||||
(item
|
||||
(format
|
||||
"<text:bookmark-ref text:reference-format=\"number-all-superior\" text:ref-name=\"OrgXref.%s\">%s</text:bookmark-ref>"
|
||||
(org-export-solidify-link-text path)
|
||||
(mapconcat 'number-to-string
|
||||
(org-e-odt-resolve-numbered-paragraph
|
||||
container info) ".")))))))
|
||||
(otherwise
|
||||
(let ((label-reference (ignore-errors
|
||||
(org-e-odt-format-label destination info
|
||||
'reference))))
|
||||
(cond
|
||||
;; Case 1: Destination is a captioned/enumerated entity.
|
||||
;; But LINK has no description. Display the sequence
|
||||
;; number.
|
||||
((and label-reference (not desc)) label-reference)
|
||||
;; Case 2: Destination is a captioned/enumerated entity
|
||||
;; and LINK has description. Insert a cross-reference
|
||||
;; Case 4.1: LINK has no description. Create a
|
||||
;; cross-reference showing entity's sequence number.
|
||||
((not desc) label-reference)
|
||||
;; Case 4.2: LINK has description. Insert a hyperlink
|
||||
;; with user-provided description.
|
||||
(label-reference
|
||||
(let* ((caption-from (case (org-element-type destination)
|
||||
(link (org-export-get-parent-element
|
||||
destination))
|
||||
(t destination)))
|
||||
;; Get label and caption.
|
||||
(label (org-element-property :name caption-from)))
|
||||
(format "<text:a xlink:type=\"simple\" xlink:href=\"#%s\">%s</text:a>"
|
||||
(org-export-solidify-link-text label) desc)))
|
||||
;; Case 3: Link is ending up in a no-man's land.
|
||||
(t (error "FIXME: Link to no-man's land."))))))))
|
||||
(t (let* ((caption-from (case (org-element-type destination)
|
||||
(link (org-export-get-parent-element
|
||||
destination))
|
||||
(t destination)))
|
||||
;; Get label and caption.
|
||||
(label (org-element-property :name caption-from)))
|
||||
(format "<text:a xlink:type=\"simple\" xlink:href=\"#%s\">%s</text:a>"
|
||||
(org-export-solidify-link-text label) desc))))))
|
||||
;; Case 5: Fuzzy link points to a TARGET.
|
||||
(when (eq (org-element-type destination) 'target)
|
||||
;; Case 5.1: LINK has description. Create a hyperlink.
|
||||
(when desc
|
||||
(let ((label (org-element-property :value destination)))
|
||||
(format "<text:a xlink:type=\"simple\" xlink:href=\"#%s\">%s</text:a>"
|
||||
(org-export-solidify-link-text label) desc))))
|
||||
;; LINK has no description. It points to either a HEADLINE, a
|
||||
;; TARGET or an ELEMENT with a #+NAME: LABEL attached to it.
|
||||
;; LINK to DESTINATION, but make a best effort to provide a
|
||||
;; *meaningful* description.
|
||||
(org-e-odt-link--infer-description destination info))))
|
||||
;; Coderef: replace link with the reference name or the
|
||||
;; equivalent line number.
|
||||
((string= type "coderef")
|
||||
|
@ -2761,7 +2816,7 @@ INFO is a plist holding contextual information. See
|
|||
desc-element org-e-odt-inline-image-rules))))
|
||||
;; Format link as a clickable image.
|
||||
(format "\n<draw:a xlink:type=\"simple\" xlink:href=\"%s\">\n%s\n</draw:a>"
|
||||
path desc)
|
||||
path desc)
|
||||
;; Otherwise, format it as a regular link.
|
||||
(format "<text:a xlink:type=\"simple\" xlink:href=\"%s\">%s</text:a>"
|
||||
path desc))))
|
||||
|
|
Loading…
Reference in a new issue