Pārlūkot izejas kodu

ox-md.el: Export footnotes section as Markdown

* lisp/ox-md.el (org-md--headline-title): New function.
(org-md-headline): Use `org-md-headline-title' to generate section
headers.
(org-md--footnote-formatted): New function.
(org-md--footnote-section): New function.
(org-md-inner-template): Update to use `org-md-footnote-section'.
(org-md-footnotes-section): New customizable variable.
(org-md-footnote-format): New customizable variable.

Update ox-md.el to export the Footnotes section as Markdown, using HTML
only where necessary - namely, in footnote and footnote reference links.
Jake Romer 9 gadi atpakaļ
vecāks
revīzija
d4a073f5be
3 mainītis faili ar 90 papildinājumiem un 17 dzēšanām
  1. 3 1
      doc/org.texi
  2. 5 0
      etc/ORG-NEWS
  3. 82 16
      lisp/ox-md.el

+ 3 - 1
doc/org.texi

@@ -14442,7 +14442,9 @@ however, override everything.
 
 
 @subsubheading Markdown specific properties
 @subsubheading Markdown specific properties
 
 
-@multitable {@code{:md-headline-style}} {@code{org-md-headline-style}}
+@multitable {@code{:md-footnotes-section}} {@code{org-md-footnotes-section}}
+@item @code{:md-footnote-format} @tab @code{org-md-footnote-format}
+@item @code{:md-footnotes-section} @tab @code{org-md-footnotes-section}
 @item @code{:md-headline-style} @tab @code{org-md-headline-style}
 @item @code{:md-headline-style} @tab @code{org-md-headline-style}
 @end multitable
 @end multitable
 
 

+ 5 - 0
etc/ORG-NEWS

@@ -219,6 +219,11 @@ SVG images exported in HTML are now by default assigned a CSS class
 ~org-svg~ if no CSS class is specified with the ~:class~ attribute. By
 ~org-svg~ if no CSS class is specified with the ~:class~ attribute. By
 default, the CSS styling of class ~org-svg~ specifies an image width
 default, the CSS styling of class ~org-svg~ specifies an image width
 of 90\thinsp{}% of the container the image.
 of 90\thinsp{}% of the container the image.
+**** Markdown footnote export customization
+Variables ~org-md-footnotes-section~ and ~org-md-footnote-format~
+introduced for =ox-md.el=.  Both new variables define template strings
+which can be used to customize the format of the exported footnotes
+section and individual footnotes, respectively.
 *** Babel
 *** Babel
 **** Blocks with coderefs labels can now be evaluated
 **** Blocks with coderefs labels can now be evaluated
 The labels are removed prior to evaluating the block.
 The labels are removed prior to evaluating the block.

+ 82 - 16
lisp/ox-md.el

@@ -51,6 +51,25 @@ This variable can be set to either `atx' or `setext'."
 	  (const :tag "Use \"Setext\" style" setext)))
 	  (const :tag "Use \"Setext\" style" setext)))
 
 
 
 
+;;;; Footnotes
+
+(defcustom org-md-footnotes-section "%s%s"
+  "Format string for the footnotes section.
+The first %s placeholder will be replaced with the localized Footnotes section
+heading, the second with the contents of the Footnotes section."
+ :group 'org-export-md
+ :type 'string
+ :version "25.1"
+ :package-version '(Org . "9.0"))
+
+(defcustom org-md-footnote-format "<sup>%s</sup>"
+  "Format string for the footnote reference.
+The %s will be replaced by the footnote reference itself."
+  :group 'org-export-md
+  :type 'string
+  :version "25.1"
+  :package-version '(Org . "9.0"))
+
 
 
 ;;; Define Back-End
 ;;; Define Back-End
 
 
@@ -89,7 +108,10 @@ This variable can be set to either `atx' or `setext'."
 		     (src-block . org-md-example-block)
 		     (src-block . org-md-example-block)
 		     (template . org-md-template)
 		     (template . org-md-template)
 		     (verbatim . org-md-verbatim))
 		     (verbatim . org-md-verbatim))
-  :options-alist '((:md-headline-style nil nil org-md-headline-style)))
+  :options-alist
+  '((:md-footnote-format nil nil org-md-footnote-format)
+    (:md-footnotes-section nil nil org-md-footnotes-section)
+    (:md-headline-style nil nil org-md-headline-style)))
 
 
 
 
 ;;; Filters
 ;;; Filters
@@ -215,20 +237,29 @@ a communication channel."
 			  (car (last (org-export-get-headline-number
 			  (car (last (org-export-get-headline-number
 				      headline info))))
 				      headline info))))
 			 "."))))
 			 "."))))
-	  (concat bullet (make-string (- 4 (length bullet)) ?\s) heading tags
-		  "\n\n"
-		  (and contents
-		       (replace-regexp-in-string "^" "    " contents)))))
-       ;; Use "Setext" style.
-       ((eq style 'setext)
-	(concat heading tags anchor "\n"
-		(make-string (length heading) (if (= level 1) ?= ?-))
-		"\n\n"
-		contents))
-       ;; Use "atx" style.
-       (t (concat (make-string level ?#) " " heading tags anchor "\n\n"
-		  contents))))))
-
+	  (concat bullet (make-string (- 4 (length bullet)) ?\s) heading tags "\n\n"
+		  (and contents (replace-regexp-in-string "^" "    " contents)))))
+       (t (concat (org-md--headline-title style level title anchor tags) contents))))))
+
+
+;; Headline Title
+
+(defun org-md--headline-title (style level title &optional anchor tags)
+  "Generate a headline title in the preferred Markdown headline style.
+STYLE is the preferred style (`atx' or `setext').  LEVEL is the
+header level.  TITLE is the headline title.  ANCHOR is the HTML
+anchor tag for the section as a string.  TAGS are the tags set on
+the section."
+  (let ((anchor-lines (and anchor (concat anchor "\n\n"))))
+    ;; Use "Setext" style
+    (if (and (eq style 'setext) (< level 3))
+        (let* ((underline-char (if (= level 1) ?= ?-))
+               (underline (concat (make-string (length title) underline-char)
+				  "\n")))
+          (concat "\n" anchor-lines title tags "\n" underline "\n"))
+        ;; Use "Atx" style
+        (let ((level-mark (make-string level ?#)))
+          (concat "\n" anchor-lines level-mark " " title tags "\n\n")))))
 
 
 ;;;; Horizontal Rule
 ;;;; Horizontal Rule
 
 
@@ -467,13 +498,48 @@ a communication channel."
 
 
 ;;;; Template
 ;;;; Template
 
 
+(defun org-md--footnote-formatted (footnote info)
+  "Formats a single footnote entry FOOTNOTE.
+FOOTNOTE is a cons cell of the form (number . definition).
+INFO is a plist with contextual information."
+  (let* ((fn-num (car footnote))
+         (fn-text (cdr footnote))
+         (fn-format (plist-get info :md-footnote-format))
+         (fn-anchor (format "fn.%d" fn-num))
+         (fn-href (format " href=\"#fnr.%d\"" fn-num))
+         (fn-link-to-ref (org-html--anchor fn-anchor fn-num fn-href info)))
+    (concat (format fn-format fn-link-to-ref) " " fn-text "\n")))
+
+(defun org-md--footnote-section (info)
+  "Format the footnote section.
+INFO is a plist used as a communication channel."
+  (let* ((fn-alist (org-export-collect-footnote-definitions info))
+         (fn-alist (cl-loop for (n type raw) in fn-alist collect
+                            (cons n (org-trim (org-export-data raw info)))))
+         (headline-style (plist-get info :md-headline-style))
+         (section-title (org-html--translate "Footnotes" info)))
+    (when fn-alist
+      (format (plist-get info :md-footnotes-section)
+              (org-md--headline-title headline-style 1 section-title)
+              (mapconcat (lambda (fn) (org-md--footnote-formatted fn info))
+                         fn-alist
+                         "\n")))))
+
 (defun org-md-inner-template (contents info)
 (defun org-md-inner-template (contents info)
   "Return body of document after converting it to Markdown syntax.
   "Return body of document after converting it to Markdown syntax.
 CONTENTS is the transcoded contents string.  INFO is a plist
 CONTENTS is the transcoded contents string.  INFO is a plist
 holding export options."
 holding export options."
   ;; Make sure CONTENTS is separated from table of contents and
   ;; Make sure CONTENTS is separated from table of contents and
   ;; footnotes with at least a blank line.
   ;; footnotes with at least a blank line.
-  (org-trim (org-html-inner-template (concat "\n" contents "\n") info)))
+  (concat
+   ;; Table of contents.
+   (let ((depth (plist-get info :with-toc)))
+     (when depth (org-html-toc depth info)))
+   ;; Document contents.
+   contents
+   "\n"
+   ;; Footnotes section.
+   (org-md-footnote--section info)))
 
 
 (defun org-md-template (contents _info)
 (defun org-md-template (contents _info)
   "Return complete document string after Markdown conversion.
   "Return complete document string after Markdown conversion.