update packages
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
;;; ox-tufte.el --- Tufte HTML org-mode export backend -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2023 The Bayesians Inc.
|
||||
;; Copyright (C) 2023-2024 The Bayesians Inc.
|
||||
;; Copyright (C) 2016-2022 Matthew Lee Hinman
|
||||
|
||||
;; Author: The Bayesians Inc.
|
||||
@@ -8,8 +8,8 @@
|
||||
;; Maintainer: The Bayesians Inc.
|
||||
;; Description: An org exporter for Tufte HTML
|
||||
;; Keywords: org, tufte, html, outlines, hypermedia, calendar, wp
|
||||
;; Version: 3.0.3
|
||||
;; Package-Requires: ((org "9.5") (emacs "27.1"))
|
||||
;; Package-Version: 4.2.1
|
||||
;; Package-Requires: ((emacs "27.1") (org "9.5"))
|
||||
;; URL: https://github.com/ox-tufte/ox-tufte
|
||||
|
||||
;; This file is not part of GNU Emacs.
|
||||
@@ -39,14 +39,49 @@
|
||||
|
||||
(require 'ox)
|
||||
(require 'ox-html)
|
||||
(eval-when-compile (require 'cl-lib)) ;; for cl-assert
|
||||
|
||||
(org-babel-lob-ingest
|
||||
;;;; initialization:
|
||||
;;;;; marginnote syntax support
|
||||
(org-babel-lob-ingest ;; for marginnote-as-babel-call syntax
|
||||
(concat (file-name-directory (locate-library "ox-tufte")) "src/README.org"))
|
||||
;;;;; reproducible identifiers
|
||||
(require 'org)
|
||||
(require 'ox-html)
|
||||
;; HACK: doing below once seems to be needed if `org-export-as' hasn't been
|
||||
;; invoked previously
|
||||
(org-export-string-as "" 'html t nil)
|
||||
|
||||
|
||||
|
||||
;;; Define Back-End
|
||||
(org-export-define-derived-backend 'tufte-html 'html
|
||||
:menu-entry
|
||||
'(?T "Export to Tufte-HTML"
|
||||
((?H "As HTML buffer" org-tufte-export-as-html)
|
||||
(?h "As HTML file" org-tufte-export-to-html)
|
||||
(?o "As HTML file and open"
|
||||
(lambda (a s v b)
|
||||
(if a (org-tufte-export-to-html t s v b)
|
||||
(org-open-file (org-tufte-export-to-html nil s v b)))))))
|
||||
:options-alist
|
||||
'((:footnotes-section-p nil "footnotes-section-p"
|
||||
org-tufte-include-footnotes-at-bottom)
|
||||
;; Recommended overrides for `ox-html'
|
||||
(:html-checkbox-type nil nil org-tufte-html-checkbox-type)
|
||||
;; Essential overrides: recommended not to alter. Thus their KEYWORDS and
|
||||
;; OPTIONS are set to nil and disabled.
|
||||
(:html-divs nil nil org-tufte-html-sections)
|
||||
(:html-container nil nil "section")
|
||||
(:html-doctype nil nil "html5")
|
||||
(:html-html5-fancy nil nil t))
|
||||
:translate-alist '((footnote-reference . org-tufte-footnote-reference)
|
||||
(link . org-tufte-maybe-margin-note-link)
|
||||
(quote-block . org-tufte-quote-block)
|
||||
(special-block . org-tufte-special-block)
|
||||
(verse-block . org-tufte-verse-block)))
|
||||
|
||||
|
||||
;;; User-Configurable Variables
|
||||
|
||||
(defgroup org-export-tufte nil
|
||||
"Options for exporting Org mode files to Tufte-CSS themed HTML."
|
||||
:tag "Org Export Tufte HTML"
|
||||
@@ -68,110 +103,146 @@ at the bottom."
|
||||
:safe #'booleanp)
|
||||
|
||||
(defcustom org-tufte-margin-note-symbol "⊕"
|
||||
"The symbol that is used as a viewability-toggle on small screens."
|
||||
"The symbol that is used as a viewability-toggle on small screens.
|
||||
Neither marginnote-as-macro nor marginnote-as-babel-call have
|
||||
access to the communication channel (not unless they invoke
|
||||
something like `org-export-get-environment' which could get
|
||||
expensive). As such we don't include this in the
|
||||
`:options-alist' to limit confusion.
|
||||
|
||||
Those wanting to set this option within the Org mode file can
|
||||
enable `org-export-allow-bind-keywords' and then use something
|
||||
like `#+BIND: org-tufte-margin-note-symbol \"replacement\"' to
|
||||
define \"replacement\" as the local value for
|
||||
`org-tufte-margin-note-symbol'."
|
||||
:group 'org-export-tufte
|
||||
:type 'string
|
||||
:safe #'stringp)
|
||||
|
||||
;;;; `ox-html' overrides
|
||||
(defcustom org-tufte-html-checkbox-type 'html
|
||||
"The type of checkboxes to use for Tufte HTML export.
|
||||
See `org-html-checkbox-types' for the values used for each
|
||||
option."
|
||||
:group 'org-export-tufte
|
||||
:package-version '(ox-tufte . "4.0.0")
|
||||
:type '(choice
|
||||
(const :tag "ASCII characters" ascii)
|
||||
(const :tag "Unicode characters" unicode)
|
||||
(const :tag "HTML checkboxes" html)))
|
||||
|
||||
(defcustom org-tufte-html-sections
|
||||
'((preamble "header" "preamble") ;; `header' i/o `div'
|
||||
(content "article" "content") ;; `article' for `tufte.css'
|
||||
(postamble "footer" "postamble")) ;; footer i/o `div'
|
||||
"Alist of the three section elements for Tufte HTML export.
|
||||
The car of each entry is one of `preamble', `content' or `postamble'.
|
||||
The cdrs of each entry are the ELEMENT_TYPE and ID for each
|
||||
section of the exported document.
|
||||
|
||||
Note that changing the default may break the associated CSS. The
|
||||
ELEMENT_TYPE of the `content' entry must be \"article\"."
|
||||
:group 'org-export-tufte
|
||||
:package-version '(ox-tufte . "4.0.0")
|
||||
:type '(list :greedy t
|
||||
(list :tag "Preamble"
|
||||
(const :format "" preamble)
|
||||
(string :tag "element") (string :tag " id"))
|
||||
(list :tag "Content"
|
||||
(const :format "" content)
|
||||
(string :tag "element") (string :tag " id"))
|
||||
(list :tag "Postamble" (const :format "" postamble)
|
||||
(string :tag " id") (string :tag "element"))))
|
||||
;;;###autoload
|
||||
(put 'org-tufte-html-sections 'safe-local-variable
|
||||
(lambda (x)
|
||||
(string= (car (alist-get 'content x))
|
||||
"article")))
|
||||
|
||||
;;;; advanced
|
||||
(defcustom org-tufte-randid-limit 10000000
|
||||
"Upper limit when generating random IDs.
|
||||
|
||||
With default value of 10000000, there is ~0.2% chance of collision with 200
|
||||
references."
|
||||
This has to be a positive integer. With the default value of
|
||||
10000000, there is ~0.2% chance of collision with 200 references."
|
||||
:group 'org-export-tufte
|
||||
:type 'integer
|
||||
:safe #'integerp)
|
||||
|
||||
|
||||
;;; Define Back-End
|
||||
(org-export-define-derived-backend 'tufte-html 'html
|
||||
:menu-entry
|
||||
'(?T "Export to Tufte-HTML"
|
||||
((?H "As HTML buffer" org-tufte-export-as-html)
|
||||
(?h "As HTML file" org-tufte-export-to-html)
|
||||
(?o "As HTML file and open"
|
||||
(lambda (a s v b)
|
||||
(if a (org-tufte-export-to-html t s v b)
|
||||
(org-open-file (org-tufte-export-to-html nil s v b)))))))
|
||||
:options-alist
|
||||
'((:footnotes-section-p nil "footnotes-section-p"
|
||||
org-tufte-include-footnotes-at-bottom))
|
||||
:translate-alist '((footnote-reference . org-tufte-footnote-reference)
|
||||
;; (src-block . org-tufte-src-block)
|
||||
(link . org-tufte-maybe-margin-note-link)
|
||||
(quote-block . org-tufte-quote-block)
|
||||
(special-block . org-tufte-special-block)
|
||||
(verse-block . org-tufte-verse-block)))
|
||||
:safe (lambda (x)
|
||||
(and (integerp x)
|
||||
(> x 0)))
|
||||
:set (lambda (sym val)
|
||||
(if (funcall
|
||||
(plist-get (symbol-plist 'org-tufte-randid-limit)
|
||||
'safe-local-variable)
|
||||
val)
|
||||
(set-default-toplevel-value sym val)
|
||||
(error "`org-tufte-randid-limit' must be a positive integer"))))
|
||||
(defcustom org-tufte-export-as-advice-depth 100
|
||||
"Depth at which to install `org-export-as' advice.
|
||||
The default of 100 ensures that it is the innermost advice.
|
||||
Please use `setopt' in order to modify this value."
|
||||
:group 'org-export-tufte
|
||||
:type 'integer
|
||||
:safe (lambda (x)
|
||||
(and (integerp x)
|
||||
(>= x -100)
|
||||
(<= x 100)))
|
||||
:set (lambda (sym val)
|
||||
(let ((safeval (or
|
||||
(and (funcall
|
||||
(plist-get
|
||||
(symbol-plist 'org-tufte-export-as-advice-depth)
|
||||
'safe-local-variable)
|
||||
val)
|
||||
val)
|
||||
100)))
|
||||
(advice-remove #'org-export-as #'org-tufte-export-as-advice)
|
||||
(advice-add #'org-export-as :around
|
||||
#'org-tufte-export-as-advice `((depth . ,safeval)))
|
||||
(set-default-toplevel-value sym safeval))))
|
||||
|
||||
|
||||
;;; Utility Functions
|
||||
|
||||
(defun ox-tufte--utils-filter-ptags (str)
|
||||
"Remove <p> tags from STR.
|
||||
|
||||
Sidenotes and margin notes must have <p> and </p> tags removed to conform with
|
||||
;;;; marginalia
|
||||
(defun ox-tufte--utils-filter-tags (str)
|
||||
"Remove <p>, <div> and <figure> tags from STR.
|
||||
Sidenotes and margin notes must have these tags removed to conform with
|
||||
the html structure that tufte.css expects."
|
||||
(replace-regexp-in-string "</?p.*?>" "" str))
|
||||
(replace-regexp-in-string "</?p.*?>\\|</?div.*?>\\|</?figure.*?>" "" str))
|
||||
|
||||
(defun ox-tufte--utils-footnotes-section ()
|
||||
"Toggle Footnotes section HTML based on `org-tufte-include-footnotes-at-bottom'."
|
||||
(if org-tufte-include-footnotes-at-bottom
|
||||
org-html-footnotes-section
|
||||
"<!-- %s --><!-- %s -->"))
|
||||
|
||||
(defconst ox-tufte--utils-macros-alist
|
||||
`(("marginnote" .
|
||||
(lambda (&rest args)
|
||||
(let ((note (string-join args "\\\n")))
|
||||
(concat
|
||||
"@@html:"
|
||||
(ox-tufte--utils-margin-note note)
|
||||
"@@")))))
|
||||
"Additional macros that are available during export.")
|
||||
(defun ox-tufte--utils-margin-note-macro (&rest args)
|
||||
"Return HTML snippet treating each arg in ARGS as a separate line."
|
||||
(let ((note (string-join args "\\\n")))
|
||||
(concat
|
||||
"@@html:"
|
||||
(ox-tufte--utils-margin-note note)
|
||||
"@@")))
|
||||
|
||||
(defun ox-tufte--utils-margin-note (desc)
|
||||
"Return HTML snippet after interpreting DESC as a margin note.
|
||||
|
||||
This intended to be called via the `marginnote' library-of-babel function."
|
||||
(if org-tufte-feature-more-expressive-inline-marginnotes
|
||||
(let* ((ox-tufte--mn-macro-templates org-macro-templates)
|
||||
;; ^ copy buffer-local variable
|
||||
(exported-str
|
||||
(progn
|
||||
;; (save-excursion
|
||||
;; (message "HMM: desc = '%s'" desc)
|
||||
;; (message "HMM: buffer-string = '%s'" (buffer-string))
|
||||
;; (goto-char (point-min))
|
||||
;; (let ((end (search-forward desc))
|
||||
;; (beg (match-beginning 0)))
|
||||
;; (narrow-to-region beg end)
|
||||
;; (let ((output-buf (org-html-export-as-html nil nil
|
||||
;; nil t)))
|
||||
;; (widen)
|
||||
;; (with-current-buffer output-buf
|
||||
;; (buffer-string)))))
|
||||
(with-temp-buffer
|
||||
;; FIXME: use narrowing instead to obviate having to add functions
|
||||
;; to library-of-babel in `org-tufte-publish-to-html' etc.
|
||||
(insert desc)
|
||||
(let* ((org-export-global-macros ;; make buffer macros accessible
|
||||
(append ox-tufte--mn-macro-templates org-export-global-macros))
|
||||
;; nested footnotes aren't supported
|
||||
(org-html-footnotes-section "<!-- %s --><!-- %s -->")
|
||||
(output-buf (org-html-export-as-html nil nil nil t)))
|
||||
(with-current-buffer output-buf (buffer-string))))))
|
||||
(exported-newline-fix (replace-regexp-in-string
|
||||
"\n" " "
|
||||
(replace-regexp-in-string
|
||||
"\\\\\n" "<br>"
|
||||
exported-str)))
|
||||
(exported-para-fix (ox-tufte--utils-filter-ptags exported-newline-fix)))
|
||||
;; ^ copy buffer-local variable
|
||||
(exported-str
|
||||
(let* ((org-export-global-macros ;; make buffer macros accessible
|
||||
(append ox-tufte--mn-macro-templates org-export-global-macros))
|
||||
;; footnotes nested within marginalia aren't supported
|
||||
(org-html-footnotes-section "<!-- %s --><!-- %s -->"))
|
||||
(org-export-string-as desc 'html t
|
||||
'(:html-checkbox-type
|
||||
org-tufte-html-checkbox-type))))
|
||||
(exported-newline-fix (replace-regexp-in-string
|
||||
"\n" " "
|
||||
(replace-regexp-in-string
|
||||
"\\\\\n" "<br>"
|
||||
exported-str)))
|
||||
(exported-para-fix (ox-tufte--utils-filter-tags exported-newline-fix)))
|
||||
(ox-tufte--utils-margin-note-snippet exported-para-fix))
|
||||
;; if expressive-inline-marginnotes isn't enabled, silently fail
|
||||
""))
|
||||
|
||||
(defun ox-tufte--utils-margin-note-snippet (text &optional idtag blob)
|
||||
"Generate html snippet for margin-note with TEXT.
|
||||
|
||||
TEXT shouldn't have any <p> tags (or behaviour is undefined). If
|
||||
<p> tags are needed, use BLOB which must be an HTML snippet of a
|
||||
containing element with `marginnote' class. BLOB is ignored
|
||||
@@ -193,74 +264,76 @@ margin-notes visibility-toggle with the margin-note."
|
||||
mnid mnid
|
||||
content)))
|
||||
|
||||
(defun ox-tufte--utils-string-fragment-to-xml (str)
|
||||
"Parse string fragment via `libxml'.
|
||||
STR is the xml fragment.
|
||||
|
||||
For the inverse, use something like `esxml-to-xml' (from package
|
||||
`esxml'). This function is presently never used (an intermediate
|
||||
version of `ox-tufte' used it)."
|
||||
(cl-assert (libxml-available-p))
|
||||
(with-temp-buffer
|
||||
(insert str)
|
||||
;; we really want to use `libxml-parse-xml-region', but that's too
|
||||
;; strict. `libxml-parse-html-region' is more lax (and that's good for us),
|
||||
;; but it creates <html> and <body> tags when missing. since we'll only be
|
||||
;; using this function on html fragments, we can assume these elements are
|
||||
;; always added and thus are safe to strip away
|
||||
(caddr ;; strip <body> tag
|
||||
(caddr ;; strip <html> tag
|
||||
(libxml-parse-html-region (point-min) (point-max))))))
|
||||
|
||||
(defun ox-tufte--utils-randid ()
|
||||
"Give a random number below the `org-tufte-randid-limit'."
|
||||
(random org-tufte-randid-limit))
|
||||
|
||||
|
||||
;;; Common customizations to ensure compatibility with both tufte-css and
|
||||
;;; ox-html
|
||||
|
||||
;;;; ox-html
|
||||
(defvar ox-tufte--sema-in-tufte-export nil
|
||||
"Currently in the midst of an export.")
|
||||
(defvar ox-tufte--store-confirm-babel-evaluate nil
|
||||
"Store value of `org-confirm-babel-evaluate'.")
|
||||
|
||||
(defun ox-tufte--utils-permit-mn-babel-call (lang body)
|
||||
(defun ox-tufte--allow-mn-babel-call-maybe (lang body)
|
||||
"Permit evaluation of marginnote babel-call.
|
||||
LANG is the language of the code block whose text is BODY,"
|
||||
(if (and (string= lang "elisp")
|
||||
(if (and org-tufte-feature-more-expressive-inline-marginnotes
|
||||
(string= lang "elisp")
|
||||
(string= body "(require 'ox-tufte)
|
||||
(ox-tufte--utils-margin-note input)"))
|
||||
nil
|
||||
ox-tufte--store-confirm-babel-evaluate))
|
||||
(defun ox-tufte--utils-entrypoint-funcall (filename function &rest args)
|
||||
"Call FUNCTION with ARGS in a \"normalized\" environment.
|
||||
FILENAME is intended to be the file being processed by one of the
|
||||
entrypoint function (e.g. `org-tufte-publish-to-html')."
|
||||
(let ((ox-tufte--store-confirm-babel-evaluate
|
||||
(if ox-tufte--sema-in-tufte-export
|
||||
ox-tufte--store-confirm-babel-evaluate
|
||||
org-confirm-babel-evaluate))
|
||||
(ox-tufte--sema-in-tufte-export t)
|
||||
(org-html-divs '((preamble "header" "preamble") ;; `header' i/o `div'
|
||||
(content "article" "content") ;; `article' for `tufte.css'
|
||||
(postamble "footer" "postamble")) ;; `footer' i/o `div'
|
||||
)
|
||||
(org-html-container-element "section") ;; consistent with `tufte.css'
|
||||
(org-html-checkbox-type 'html)
|
||||
(org-html-doctype "html5")
|
||||
(org-html-html5-fancy t)
|
||||
(org-confirm-babel-evaluate #'ox-tufte--utils-permit-mn-babel-call)
|
||||
(org-export-global-macros (append org-export-global-macros
|
||||
ox-tufte--utils-macros-alist))
|
||||
(ox-tufte/tmp/lob-pre org-babel-library-of-babel))
|
||||
;; FIXME: could this be obviated for mn-as-macro and mn-as-babelcall syntax?
|
||||
(when org-tufte-feature-more-expressive-inline-marginnotes
|
||||
(let ((inhibit-message t)) ;; silence lob ingestion messages
|
||||
(org-babel-lob-ingest filename))) ;; needed by `ox-tufte--utils-margin-note'
|
||||
(let ((output (apply function args)))
|
||||
(setq org-babel-library-of-babel ox-tufte/tmp/lob-pre)
|
||||
output)))
|
||||
nil ;; i.e., don't seek confirmation from user
|
||||
(if (functionp ox-tufte--store-confirm-babel-evaluate)
|
||||
(funcall ox-tufte--store-confirm-babel-evaluate lang body)
|
||||
ox-tufte--store-confirm-babel-evaluate)))
|
||||
|
||||
(defun org-tufte-export-as-advice (fun backend &optional s v b p)
|
||||
"Evaluate FUN `org-export-as' in appropriate environment.
|
||||
Arguments (S V B P) are the same as the corresponding positional
|
||||
arguments needed by org-export-as. When BACKEND is derived from
|
||||
`tufte-html' this advice ensures the export is carried out in an
|
||||
environment where `ox-tufte--sema-in-tufte-export' is t.
|
||||
Depending on the value of
|
||||
`org-tufte-feature-more-expressive-inline-marginnotes' this
|
||||
advice may additionally temporarily override the value of
|
||||
`org-confirm-babel-evaluate' in order to allow the `marginnote'
|
||||
babel block."
|
||||
(random "ox-tufte") ;; initialize the random seed
|
||||
(let* ((ox-tufte-p (org-export-derived-backend-p backend 'tufte-html))
|
||||
(ox-tufte-first-call-p (and ox-tufte-p
|
||||
(not ox-tufte--sema-in-tufte-export)))
|
||||
(ox-tufte--sema-in-tufte-export (or ox-tufte-p
|
||||
ox-tufte--sema-in-tufte-export))
|
||||
(p+ (if ox-tufte--sema-in-tufte-export
|
||||
(append p ;; later values triumph for this plist
|
||||
'(;; we don't override `:html-divs' and
|
||||
;; `:html-checkbox-type' since it's possible for them
|
||||
;; to still be valid when altered
|
||||
:html-container "section"
|
||||
:html-doctype "html5"
|
||||
:html-html5-fancy t))
|
||||
p))
|
||||
(ox-tufte--sema-in-tufte-export (or ox-tufte-p
|
||||
ox-tufte--sema-in-tufte-export)))
|
||||
(if (not (and ox-tufte-first-call-p
|
||||
org-tufte-feature-more-expressive-inline-marginnotes))
|
||||
(funcall fun backend s v b p+)
|
||||
;; o.w. in first call to tufte-html w/ more-expressive-syntax enabled, so
|
||||
;; setup environment before evaluating
|
||||
(let ((org-export-global-macros ;; could be done in `org-export-before-processing-functions'
|
||||
(cons '("marginnote" . ox-tufte--utils-margin-note-macro)
|
||||
org-export-global-macros))
|
||||
(ox-tufte--store-confirm-babel-evaluate org-confirm-babel-evaluate)
|
||||
(org-confirm-babel-evaluate #'ox-tufte--allow-mn-babel-call-maybe)
|
||||
(ox-tufte/tmp/lob-pre org-babel-library-of-babel))
|
||||
;; allow evaluation of blocks within mn-as-macro or mn-as-babel-call
|
||||
(let ((inhibit-message t)) ;; silence only the lob ingestion messages
|
||||
(org-babel-lob-ingest buffer-file-name))
|
||||
(let ((output (funcall fun backend s v b p+)))
|
||||
(setq org-babel-library-of-babel ox-tufte/tmp/lob-pre)
|
||||
output)))))
|
||||
;; NOTE: ^ no need to `advice-add' `org-tufte-export-as-advice', since it gets
|
||||
;; added by the `org-tufte-export-as-advice-depth' defcustom on load.
|
||||
|
||||
(defun ox-tufte--utils-get-export-output-extension (plist)
|
||||
"Get export filename extension based on PLIST."
|
||||
@@ -272,7 +345,7 @@ entrypoint function (e.g. `org-tufte-publish-to-html')."
|
||||
|
||||
|
||||
;;; Transcode Functions
|
||||
|
||||
;;;; quote-block
|
||||
(defun org-tufte-quote-block (quote-block contents info)
|
||||
"Transform a quote block into an epigraph in Tufte HTML style.
|
||||
QUOTE-BLOCK CONTENTS INFO are as they are in `org-html-quote-block'."
|
||||
@@ -290,6 +363,7 @@ QUOTE-BLOCK CONTENTS INFO are as they are in `org-html-quote-block'."
|
||||
ox-tufte/ox-html-qb-str t t)
|
||||
ox-tufte/ox-html-qb-str)))
|
||||
|
||||
;;;; verse-block
|
||||
(defun org-tufte-verse-block (verse-block contents info)
|
||||
"Transcode a VERSE-BLOCK element from Org to HTML.
|
||||
CONTENTS is verse block contents. INFO is a plist holding
|
||||
@@ -302,18 +376,18 @@ contextual information."
|
||||
(format "<footer>%s</footer>" ox-tufte/vb-caption)
|
||||
"")))
|
||||
(format "<div class='verse'><blockquote>\n%s\n%s</blockquote></div>"
|
||||
ox-tufte/ox-html-vb-str
|
||||
ox-tufte/footer-content)))
|
||||
ox-tufte/ox-html-vb-str
|
||||
ox-tufte/footer-content)))
|
||||
|
||||
(defun org-tufte-footnote-section-advice (fun &rest args)
|
||||
;;;; footnotes as sidenotes
|
||||
(defun org-tufte-footnote-section-advice (fun info)
|
||||
"Modify `org-html-footnote-section' based on `:footnotes-section-p'.
|
||||
FUN is `org-html-footnote-section' and ARGS is single-element
|
||||
list containing the plist (\"communication channel\")."
|
||||
(if ox-tufte--sema-in-tufte-export
|
||||
(let ((switch-p (plist-get (car args) :footnotes-section-p)))
|
||||
(if switch-p (apply fun args)
|
||||
""))
|
||||
(apply fun args)))
|
||||
FUN is `org-html-footnote-section' and INFO is the
|
||||
plist (\"communication channel\")."
|
||||
(if (and ox-tufte--sema-in-tufte-export
|
||||
(not (plist-get info :footnotes-section-p)))
|
||||
""
|
||||
(funcall fun info)))
|
||||
(advice-add 'org-html-footnote-section
|
||||
:around #'org-tufte-footnote-section-advice)
|
||||
;; ox-html: definition: id="fn.<id>"; href="#fnr.<id>"
|
||||
@@ -342,7 +416,7 @@ Modified from `org-html-footnote-reference' in `org-html'."
|
||||
(org-trim (org-export-data ox-tufte/fn-def info)))
|
||||
(ox-tufte/fn-data-unpar
|
||||
;; footnotes must have spurious <p> tags removed or they will not work
|
||||
(ox-tufte--utils-filter-ptags ox-tufte/fn-data)))
|
||||
(ox-tufte--utils-filter-tags ox-tufte/fn-data)))
|
||||
(format
|
||||
(concat
|
||||
"<label id='%s' for='%s' class='margin-toggle sidenote-number'><sup class='numeral'>%s</sup></label>"
|
||||
@@ -352,6 +426,7 @@ Modified from `org-html-footnote-reference' in `org-html'."
|
||||
ox-tufte/fn-inputid
|
||||
ox-tufte/fn-num ox-tufte/fn-data-unpar))))
|
||||
|
||||
;;;; special-block
|
||||
(defun org-tufte-special-block (special-block contents info)
|
||||
"Add support for block margin-note special blocks.
|
||||
Pass SPECIAL-BLOCK CONTENTS and INFO to `org-html-special-block' otherwise."
|
||||
@@ -360,13 +435,16 @@ Pass SPECIAL-BLOCK CONTENTS and INFO to `org-html-special-block' otherwise."
|
||||
((string= block-type "marginnote")
|
||||
(ox-tufte--utils-margin-note-snippet
|
||||
nil nil (org-html-special-block special-block contents info)))
|
||||
;; add support for captions on figures that `ox-html' lacks
|
||||
((and (string= block-type "figure")
|
||||
(org-html--has-caption-p special-block info)
|
||||
(not (member "iframe-wrapper" ;; FIXME: fix tufte-css before enabling
|
||||
;; FIXME: tufte-css v1.8.0 doesn't support captions on iframe-wrapper
|
||||
(not (member "iframe-wrapper"
|
||||
(split-string
|
||||
(plist-get (org-export-read-attribute :attr_html special-block) :class)
|
||||
(plist-get (org-export-read-attribute :attr_html
|
||||
special-block)
|
||||
:class)
|
||||
" "))))
|
||||
;; add support for captions on figures that `ox-html' lacks
|
||||
(let* ((caption (let ((raw (org-export-data
|
||||
(org-export-get-caption special-block) info)))
|
||||
(if (not (org-string-nw-p raw)) raw
|
||||
@@ -383,15 +461,14 @@ Pass SPECIAL-BLOCK CONTENTS and INFO to `org-html-special-block' otherwise."
|
||||
;; raw)
|
||||
)))
|
||||
(figcaption (format "<figcaption>%s</figcaption>" caption))
|
||||
;; using regex because `esxml-to-xml' doesn't put closing iframe
|
||||
;; tag (and also loses some attributes), which results in broken
|
||||
;; html (so cannot do what we do in `org-tufte-quote-block'.
|
||||
;; FIXME: might be more robust to parse-replace-serialize the HTML
|
||||
;; instead.
|
||||
(o-h-sb-str (org-html-special-block special-block contents info)))
|
||||
(replace-regexp-in-string
|
||||
"</figure>\\'"
|
||||
(concat figcaption "</figure>") o-h-sb-str t t)))
|
||||
(replace-regexp-in-string "</figure>\\'" (concat figcaption "</figure>")
|
||||
o-h-sb-str t t)))
|
||||
(t (org-html-special-block special-block contents info)))))
|
||||
|
||||
;;;; margin-note as link
|
||||
(defun org-tufte-maybe-margin-note-link (link desc info)
|
||||
"Render LINK as a margin note if it begins with `mn:'.
|
||||
For example, `[[mn:1][this is some text]]' is margin note 1 that
|
||||
@@ -407,25 +484,23 @@ handled when occurring as regular links and not as angle or plain
|
||||
links. Additionally, it ensures that we only handle margin-notes
|
||||
for HTML backend without having an opinion on how to treat them
|
||||
for other backends."
|
||||
(let ((path (split-string (org-element-property :path link) ":"))
|
||||
(desc (or desc "")))
|
||||
(if (and (string= (org-element-property :type link) "fuzzy")
|
||||
(string= (car path) "mn"))
|
||||
(ox-tufte--utils-margin-note-snippet
|
||||
(ox-tufte--utils-filter-ptags desc)
|
||||
(if (string= (cadr path) "") nil (cadr path)))
|
||||
(if-let ((path (org-element-property :path link))
|
||||
(pathelems (split-string path ":"))
|
||||
(type (downcase (org-element-property :type link)))
|
||||
((and (string= type "fuzzy")
|
||||
(string= (car pathelems) "mn")))
|
||||
(tag (cadr pathelems)))
|
||||
(ox-tufte--utils-margin-note-snippet
|
||||
(ox-tufte--utils-filter-tags (or desc ""))
|
||||
(if (string= tag "") nil tag))
|
||||
(if-let ((fn (plist-get (alist-get type org-link-parameters
|
||||
nil nil #'string=)
|
||||
:export)))
|
||||
(funcall fn path desc 'tufte-html info)
|
||||
(org-html-link link desc info))))
|
||||
|
||||
(defun org-tufte-src-block (src-block _contents info)
|
||||
"Transcode SRC-BLOCK element into Tufte HTML format.
|
||||
CONTENTS is nil. INFO is a plist used as a communication channel.
|
||||
|
||||
NOTE: this is dead code and currently unused."
|
||||
(format "<pre class=\"code\"><code>%s</code></pre>"
|
||||
(org-html-format-code src-block info)))
|
||||
|
||||
|
||||
;;; Export functions
|
||||
;;; Export commands
|
||||
|
||||
;;;###autoload
|
||||
(defun org-tufte-export-as-html
|
||||
@@ -459,11 +534,18 @@ Export is done in a buffer named \"*Org Tufte Export*\", which will
|
||||
be displayed when `org-export-show-temporary-export-buffer' is
|
||||
non-nil."
|
||||
(interactive)
|
||||
(ox-tufte--utils-entrypoint-funcall
|
||||
buffer-file-name
|
||||
#'org-export-to-buffer 'tufte-html "*Org Tufte Export*"
|
||||
async subtreep visible-only body-only ext-plist
|
||||
(lambda () (set-auto-mode t))))
|
||||
(org-export-to-buffer 'tufte-html "*Org Tufte Export*"
|
||||
async subtreep visible-only body-only ext-plist
|
||||
(lambda () (set-auto-mode t))))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-tufte-convert-region-to-html ()
|
||||
"Assume the current region has Org syntax, and convert it to Tufte HTML.
|
||||
This can be used in any buffer. For example, you can write an
|
||||
itemized list in Org syntax in an HTML buffer and use this command
|
||||
to convert it."
|
||||
(interactive)
|
||||
(org-export-replace-region-by 'tufte-html))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-tufte-export-to-html
|
||||
@@ -498,13 +580,11 @@ Return output file's name."
|
||||
(let ((file (org-export-output-file-name
|
||||
(ox-tufte--utils-get-export-output-extension ext-plist)
|
||||
subtreep)))
|
||||
(ox-tufte--utils-entrypoint-funcall
|
||||
buffer-file-name
|
||||
#'org-export-to-file 'tufte-html file
|
||||
async subtreep visible-only body-only ext-plist)))
|
||||
(org-export-to-file 'tufte-html file
|
||||
async subtreep visible-only body-only ext-plist)))
|
||||
|
||||
|
||||
;;; publishing function
|
||||
;;; Publishing function
|
||||
|
||||
;;;###autoload
|
||||
(defun org-tufte-publish-to-html (plist filename pub-dir)
|
||||
@@ -515,9 +595,8 @@ the filename of the Org file to be published. PUB-DIR is the
|
||||
publishing directory.
|
||||
|
||||
Return output file name."
|
||||
(ox-tufte--utils-entrypoint-funcall
|
||||
filename
|
||||
#'org-publish-org-to 'tufte-html filename
|
||||
(org-publish-org-to
|
||||
'tufte-html filename
|
||||
(ox-tufte--utils-get-export-output-extension plist)
|
||||
plist pub-dir))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user