org-e-odt.el: Handle links to target, list items

This commit is contained in:
Jambunathan K 2012-12-23 02:24:55 +05:30 committed by Bastien Guerry
parent d06f326f20
commit dcd5c81dc4

View file

@ -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))))