forked from mirrors/org-mode
Compare commits
151 Commits
8384289762
...
3edac8fcc6
Author | SHA1 | Date |
---|---|---|
TEC | 3edac8fcc6 | |
TEC | ed9893898f | |
TEC | 579f748af9 | |
TEC | c9a8f74cbe | |
TEC | f308ecfbab | |
TEC | b49cefc7ea | |
TEC | 8284cec27e | |
TEC | fee79ce34f | |
TEC | 775ed43c90 | |
Karthik Chikmagalur | 43b925a712 | |
TEC | 5ee791d0af | |
TEC | 21476abcce | |
TEC | dccc392855 | |
TEC | f9772da05c | |
Karthik Chikmagalur | 45cedee0a9 | |
TEC | 72b829cd90 | |
TEC | 4e9d89a431 | |
TEC | ea636c27d2 | |
TEC | 96c0c34875 | |
TEC | cf3c6152ee | |
TEC | 34891ff59e | |
TEC | 07545b4ca4 | |
TEC | 5553b040fb | |
TEC | 34f0dd395d | |
TEC | 5b6b97a264 | |
Karthik Chikmagalur | 5caf6d9e91 | |
Karthik Chikmagalur | bf3f7e3c02 | |
Karthik Chikmagalur | d4d050380a | |
TEC | d4d644c2e2 | |
TEC | 1652e5402c | |
TEC | 45de17ef08 | |
Karthik Chikmagalur | 787508d284 | |
TEC | 0c5b3c29c7 | |
TEC | 1354b2d084 | |
TEC | eddf27e32f | |
TEC | a76be67517 | |
TEC | 90bee079e0 | |
TEC | 9a36397a75 | |
TEC | d3c1243a60 | |
TEC | dd4d16b886 | |
TEC | 6259461f04 | |
TEC | a8f3357bff | |
TEC | f99b1a320a | |
Karthik Chikmagalur | 2b40ffef8d | |
Karthik Chikmagalur | 65bb5ed444 | |
Karthik Chikmagalur | 3fc5787831 | |
Karthik Chikmagalur | c185a6dddb | |
Karthik Chikmagalur | 934a68eb26 | |
Karthik Chikmagalur | ab1229e88b | |
Karthik Chikmagalur | 784d7caa3c | |
Karthik Chikmagalur | ef3788cc65 | |
Karthik Chikmagalur | 3bf3baf4ab | |
Karthik Chikmagalur | 8af00eba7e | |
Karthik Chikmagalur | 08836fb076 | |
Karthik Chikmagalur | 8c0a05c797 | |
Karthik Chikmagalur | 0e95d16a33 | |
Karthik Chikmagalur | 2a52e43301 | |
Karthik Chikmagalur | d84aff830a | |
Karthik Chikmagalur | 453363cb77 | |
Karthik Chikmagalur | e10b8b9a02 | |
Karthik Chikmagalur | 8274613308 | |
Karthik Chikmagalur | b4904f8617 | |
Karthik Chikmagalur | ba691a0c12 | |
Karthik Chikmagalur | d92210ed0e | |
TEC | e100ec8f26 | |
TEC | 0ab7cebbe2 | |
TEC | 23578e25a1 | |
TEC | c65e9ad180 | |
TEC | 5b8286f45b | |
TEC | 530b63464c | |
TEC | 7824b610f4 | |
TEC | 874b7d5ce1 | |
TEC | 4cd9d951df | |
TEC | 4685b6e967 | |
TEC | 5395207923 | |
TEC | 146ce64413 | |
Karthik Chikmagalur | 4a73d55a5b | |
TEC | 9a0251fd8f | |
TEC | beea15f433 | |
TEC | 2d96e36f7d | |
TEC | bbf5274b85 | |
TEC | f6d5440fd9 | |
TEC | 125ea5af68 | |
TEC | 126000dd22 | |
TEC | 64da9ff169 | |
TEC | fa1464b76b | |
TEC | 2da7552b35 | |
Karthik Chikmagalur | 3ff99452c2 | |
TEC | 864ec3e0c9 | |
TEC | 3448ec738f | |
TEC | f486a5ee18 | |
TEC | fe1b32f20e | |
TEC | b54d64f41d | |
Karthik Chikmagalur | 6034fdad7e | |
TEC | 13774486fb | |
TEC | e503794506 | |
Karthik Chikmagalur | 57e7ee0405 | |
TEC | 9146941da4 | |
Karthik Chikmagalur | 9fc61e4b89 | |
TEC | 0635d33702 | |
TEC | a14b864f8e | |
Karthik Chikmagalur | 0e345223aa | |
Karthik Chikmagalur | d570e0dca7 | |
Karthik Chikmagalur | a724c130d2 | |
TEC | 58e2cbc1b4 | |
TEC | 3746b798e4 | |
TEC | 8a3aebb986 | |
TEC | 1c2061b799 | |
Karthik Chikmagalur | 1351cff6eb | |
Karthik Chikmagalur | f4ace4be19 | |
Karthik Chikmagalur | 08c16b034b | |
Karthik Chikmagalur | 2ac83404ff | |
TEC | 327e63f6ea | |
Karthik Chikmagalur | e6c5e45b65 | |
Karthik Chikmagalur | ae1580c34a | |
TEC | 4d70983b88 | |
TEC | a7f52bbc19 | |
Karthik Chikmagalur | 32b3350fb0 | |
TEC | 0dc83ae01f | |
TEC | 9d6973ac8b | |
TEC | 9e8011b335 | |
TEC | 608c3a7bba | |
TEC | 9a3f41c24d | |
Karthik Chikmagalur | 1bc075de32 | |
TEC | d3e297c78b | |
TEC | 2453c8a127 | |
Karthik Chikmagalur | 40fcbd2bd0 | |
Karthik Chikmagalur | 78b94ce83a | |
TEC | e54dfbf4b4 | |
TEC | bd593af82c | |
Karthik Chikmagalur | 2bf81ed249 | |
Karthik Chikmagalur | fa63fc5c8f | |
Karthik Chikmagalur | c4a68d7ab4 | |
Karthik Chikmagalur | beba8515ac | |
TEC | 3bc2a4ff01 | |
Karthik Chikmagalur | b0de57ef71 | |
TEC | f232aab63f | |
TEC | 3ce9f76703 | |
TEC | 5c40409f64 | |
TEC | 57e205306c | |
TEC | 13e7d02b84 | |
TEC | 0db9f1e0de | |
TEC | 1aa997dd57 | |
TEC | b1f9c0bfc8 | |
TEC | fd029fc666 | |
TEC | c78812fb8f | |
Karthik Chikmagalur | 115f3f59a1 | |
Karthik Chikmagalur | fa73360b42 | |
Karthik Chikmagalur | 396718f97f | |
TEC | 97e662057d | |
Karthik Chikmagalur | 9a1cd8df71 |
|
@ -11381,20 +11381,19 @@ lines:
|
|||
:END:
|
||||
#+cindex: @LaTeX{} fragments, preview
|
||||
|
||||
#+vindex: org-latex-preview-default-process
|
||||
#+vindex: org-latex-preview-process-default
|
||||
If you have a working LaTeX installation and =dvipng=, =dvisvgm= or
|
||||
=convert= installed[fn:38], LaTeX fragments can be processed to
|
||||
produce images of the typeset expressions to be used for inclusion
|
||||
while exporting to HTML (see [[*LaTeX fragments]]), or for inline
|
||||
previewing within Org mode.
|
||||
|
||||
#+vindex: org-latex-preview-options
|
||||
#+vindex: org-latex-preview-appearance-options
|
||||
#+vindex: org-latex-preview-header
|
||||
You can customize the variables ~org-latex-preview-options~ and
|
||||
You can customize the variables ~org-latex-preview-appearance-options~ and
|
||||
~org-latex-preview-header~ to influence some aspects of the preview.
|
||||
In particular, the ~:scale~ (and for HTML export, ~:html-scale~)
|
||||
property of the former can be used to adjust the size of the preview
|
||||
images.
|
||||
In particular, the ~:scale~ and ~:zoom~ properties of the former can
|
||||
be used to adjust the size of the preview images.
|
||||
|
||||
- {{{kbd(C-c C-x C-l)}}} (~org-latex-preview~) ::
|
||||
#+kindex: C-c C-x C-l
|
||||
|
@ -11418,6 +11417,24 @@ To disable it, simply use
|
|||
|
||||
: #+STARTUP: nolatexpreview
|
||||
|
||||
#+vindex: org-latex-preview-numbered
|
||||
When generating previews, Org mode can track equation numbers and keep
|
||||
them consistent by regenerating previews when necessary. This
|
||||
behavior is controlled by the variable ~org-latex-preview-numbered~.
|
||||
|
||||
Org mode can automatically preview LaTeX fragments as you type them,
|
||||
and hide and reveal preview images as the cursor moves into or out of
|
||||
them. To enable this, turn on the minor mode
|
||||
~org-latex-preview-auto-mode~.
|
||||
|
||||
|
||||
- (~org-latex-preview-auto-mode~) ::
|
||||
#+findex: org-latex-preview-auto-mode
|
||||
|
||||
Generate previews of LaTeX fragments as they are entered in the
|
||||
buffer. Previews will be generated when there is any change to the
|
||||
buffer that includes the insertion of a LaTeX environment or
|
||||
fragment.
|
||||
*** Using CDLaTeX to enter math
|
||||
:PROPERTIES:
|
||||
:DESCRIPTION: Speed up entering of formulas.
|
||||
|
@ -23279,7 +23296,7 @@ used to create images, any LaTeX environment is handled.
|
|||
[fn:38] These are respectively available at
|
||||
[[https://sourceforge.net/projects/dvipng/]], [[http://dvisvgm.bplaced.net/]]
|
||||
and from the ImageMagick suite. Choose the converter by setting the
|
||||
variable ~org-latex-preview-default-process~ accordingly.
|
||||
variable ~org-latex-preview-process-default~ accordingly.
|
||||
|
||||
[fn:39] This works automatically for the HTML backend (it requires
|
||||
version 1.34 of the =htmlize.el= package, which you need to install).
|
||||
|
|
151
etc/ORG-NEWS
151
etc/ORG-NEWS
|
@ -325,6 +325,157 @@ constant.
|
|||
If you still want to use python-mode with ob-python, you might
|
||||
consider [[https://gitlab.com/jackkamm/ob-python-mode-mode][ob-python-mode-mode]], where the code to support python-mode
|
||||
has been ported to.
|
||||
*** The LaTeX preview system has been overhauled
|
||||
|
||||
Org's LaTeX preview system has been overhauled
|
||||
|
||||
|
||||
Org mode's LaTeX preview system has been rewritten with several improvements and new features.
|
||||
|
||||
- LaTeX Previews are generated in bulk, and hundreds of LaTeX fragments can be processed per second.
|
||||
- Images are placed in the buffer continuously as they are generated.
|
||||
- Preview generation is asynchronous and will not block Emacs.
|
||||
- Inline previews are aligned and scaled to match the font baseline and size.
|
||||
- Previews scale along with text when the text scale is changed.
|
||||
- Previews are coloured to match surrounding text and the active theme.
|
||||
- SVG previews automatically change colors when the active theme changes.
|
||||
- Error encountered when compiling LaTeX fragments can be accessed by mousing over preview images.
|
||||
- Preview overlays can hide and show themselves dynamically based on cursor position.
|
||||
- Org mode can auto-generate LaTeX previews as you type or edit the text of existing ones.
|
||||
- Org mode can keep equation numbering consistent by regenerating previews as needed.
|
||||
|
||||
**** New features
|
||||
|
||||
***** New minor mode ~org-latex-preview-auto-mode~
|
||||
|
||||
When this mode is turned on, LaTeX preview overlays in the buffer can be temporarily disabled by moving the cursor into them. Moving the cursor out will display the LaTeX preview image overlay again. Additionally, editing LaTeX fragments that have previews will cause the preview images to be updated.
|
||||
|
||||
If the option ~org-latex-preview-auto-track-inserts~ is non-nil (which see), previews for LaTeX fragments will be auto-generated as you type.
|
||||
|
||||
|
||||
**** New options
|
||||
|
||||
***** A new option ~org-latex-preview-compiler-command-map~ for setting precompile commands
|
||||
|
||||
This alist maps compilers in ~org-latex-compilers~ to command strings
|
||||
used for LaTeX precompilation when creating previews or LaTeX exports.
|
||||
|
||||
***** New option ~org-latex-preview-cache~ to enable preview image caching
|
||||
|
||||
When set to =persist=, images produced using ~org-latex-preview~ will
|
||||
be cached and persisted across Emacs sessions using
|
||||
~org-persist~. Temporary or custom directories can also be used.
|
||||
|
||||
***** New option ~org-latex-preview-persist-expiry~ to set persistence period
|
||||
|
||||
This is the number of days for which LaTeX preview images will be
|
||||
cached, assuming persistence is turned on with
|
||||
~org-latex-preview-cache~.
|
||||
|
||||
***** New option ~org-latex-preview-process-active-indicator~ to indicate preview processing for LaTeX fragments
|
||||
|
||||
This option controls the style of visual indicator for LaTeX fragments
|
||||
currently being processed.
|
||||
|
||||
***** New option ~org-latex-preview-numbered~ to automatically renumber previewed LaTeX environments
|
||||
|
||||
When non-nil, previewed LaTeX environments in the buffer are
|
||||
renumbered automatically as required.
|
||||
|
||||
***** New option =:page-width= in ~org-latex-preview-appearance-options~ to control the text width for LaTeX fragment previews
|
||||
|
||||
This option controls the width of text in preview images. This is
|
||||
relevant for displaymath-type LaTeX environments, and can be specified
|
||||
in multiple ways.
|
||||
|
||||
***** New option ~org-latex-preview-process-precompiled~ to control LaTeX precompilation
|
||||
|
||||
This option controls whether LaTeX headers for buffers are precompiled
|
||||
when generating the first preview for the buffer. Precompilation can
|
||||
speed up preview generation by a moderate to large amount depending on
|
||||
the complexity of the header.
|
||||
|
||||
***** New option ~org-latex-preview-auto-track-inserts~ to auto-generate LaTeX previews when typing
|
||||
|
||||
When using ~org-latex-preview-auto-mode~ (which see), setting this option to a non-nil value will cause LaTeX previews to be rendered as you type LaTeX fragments. This works however new text is added to the buffer, for example by yanking. When this option is nil and ~org-latex-preview-auto-mode~ is on, existing previews for LaTeX fragments will still be auto-regenerated when edited but no new ones will be auto-generated.
|
||||
|
||||
**** Removed or renamed functions and variables
|
||||
|
||||
***** Mark ~org-format-latex-options~ obsolete
|
||||
|
||||
Use ~org-latex-preview-appearance-options~ instead. The replacement acts in the
|
||||
same way, except that
|
||||
- the preview image render size and display size can be independently
|
||||
controlled with the =:scale= and =:zoom= plist keys, and
|
||||
- the HTML export-specific parameters =:html-scale=,
|
||||
=:html-foreground= and =:html-background= have been moved to
|
||||
~org-html-latex-image-options~, which see.
|
||||
- the new option =:page-width= (mentioned earlier)
|
||||
|
||||
***** Mark ~org-format-latex-header~ obsolete
|
||||
|
||||
Use ~org-latex-preview-header~ instead. The replacement variable
|
||||
behaves the exact same way and is renamed for consistency.
|
||||
|
||||
***** Mark ~org-preview-latex-default-process~ obsolete
|
||||
|
||||
Use ~org-latex-preview-process-default~ instead. The replacement
|
||||
variable behaves the exact same way and is renamed for consistency.
|
||||
|
||||
***** Mark ~org-preview-latex-process-alist~ obsolete
|
||||
|
||||
Use ~org-latex-preview-process-alist~ instead. The replacement
|
||||
variable acts in the same way, except that =:latex-compiler= must now
|
||||
be a single command or a list containing a single command. The
|
||||
placeholder ="%S"= in the format string for =:latex-compiler= is
|
||||
ignored.
|
||||
|
||||
***** Mark ~org-clear-latex-preview~ obsolete
|
||||
|
||||
Use ~org-latex-preview-clear-overlays~ instead. The replacement
|
||||
function acts in the exact same way and is renamed for consistency.
|
||||
|
||||
***** Mark ~org-place-formula-image~ obsolete
|
||||
|
||||
This functionality is replaced with ~org-latex-preview-place-image~
|
||||
(for images) and ~org-latex-preview-place-image-link~ (for links).
|
||||
|
||||
***** Mark ~org-latex-color-format~ obsolete
|
||||
|
||||
Use ~org-latex-preview--format-color~ instead. The replacement
|
||||
function acts in the exact same way and is renamed for consistency.
|
||||
|
||||
***** Mark ~org-latex-color~ obsolete
|
||||
|
||||
Use ~org-latex-preview--attr-color~ instead. The replacement function
|
||||
acts in the exact same way and is renamed for consistency.
|
||||
|
||||
***** Mark ~org-normalize-color~ obsolete
|
||||
|
||||
Use ~org-latex-preview--normalize-color~ instead. The replacement
|
||||
function acts in the exact same way and is renamed for consistency.
|
||||
|
||||
***** Mark ~org-latex-to-mathml-jar-file~ obsolete
|
||||
|
||||
Use ~org-mathml-converter-jar-file~ instead. The replacement variable
|
||||
acts in the exact same way and is renamed for consistency.
|
||||
|
||||
***** Mark ~org-latex-to-mathml-convert-command~ obsolete
|
||||
|
||||
Use ~org-mathml-convert-command~ instead. The replacement variable
|
||||
acts in the exact same way and is renamed for consistency.
|
||||
|
||||
***** Mark ~org-format-latex-mathml-available-p~ obsolete
|
||||
|
||||
Use ~org-mathml-converter-available-p~ instead. The replacement
|
||||
function acts in the exact same way and is renamed for consistency.
|
||||
|
||||
***** Mark ~org-create-math-formula~ obsolete
|
||||
|
||||
Use ~org-mathml-convert-latex~ instead. The replacement function acts
|
||||
in the exact same way and is renamed for consistency.
|
||||
|
||||
|
||||
|
||||
*** =ox-icalendar.el= line ending fix may affect downstream packages
|
||||
|
||||
|
|
|
@ -48,10 +48,10 @@
|
|||
(defvar org-babel-tangle-lang-exts)
|
||||
(add-to-list 'org-babel-tangle-lang-exts '("latex" . "tex"))
|
||||
|
||||
(defvar org-latex-preview-header) ; From org-latex-preview.el
|
||||
(defvar org-latex-preview-options) ; From org-latex-preview.el
|
||||
(defvar org-latex-default-packages-alist) ; From org-latex-preview.el
|
||||
(defvar org-latex-packages-alist) ; From org-latex-preview.el
|
||||
(defvar org-latex-preview-header) ; From org-latex-preview.el
|
||||
(defvar org-latex-preview-appearance-options) ; From org-latex-preview.el
|
||||
(defvar org-latex-default-packages-alist) ; From org-latex-preview.el
|
||||
(defvar org-latex-packages-alist) ; From org-latex-preview.el
|
||||
|
||||
(defvar org-babel-default-header-args:latex
|
||||
'((:results . "latex") (:exports . "results"))
|
||||
|
@ -171,7 +171,7 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(concat org-latex-preview-header "\n"
|
||||
(mapconcat #'identity headers "\n"))))
|
||||
(org-latex-preview-create-image
|
||||
body out-file org-latex-preview-options in-buffer)))
|
||||
body out-file org-latex-preview-appearance-options in-buffer)))
|
||||
((string= "svg" extension)
|
||||
(with-temp-file tex-file
|
||||
(insert (concat (funcall org-babel-latex-preamble params)
|
||||
|
|
24
lisp/ol.el
24
lisp/ol.el
|
@ -1068,6 +1068,9 @@ and then used in capture templates."
|
|||
if store-func
|
||||
collect store-func))
|
||||
|
||||
(defvar org-link--abbrev-functions nil
|
||||
"Alist of abbrev link expressions and functions.")
|
||||
|
||||
(defun org-link-expand-abbrev (link)
|
||||
"Replace link abbreviations in LINK string.
|
||||
Abbreviations are defined in `org-link-abbrev-alist'."
|
||||
|
@ -1082,14 +1085,27 @@ Abbreviations are defined in `org-link-abbrev-alist'."
|
|||
(setq rpl (cdr as))
|
||||
(cond
|
||||
((symbolp rpl) (funcall rpl tag))
|
||||
((string-match "%(\\([^)]+\\))" rpl)
|
||||
((string-match "%(\\([^) ]+\\))" rpl) ; %(function)
|
||||
(replace-match
|
||||
(save-match-data
|
||||
(funcall (intern-soft (match-string 1 rpl)) tag))
|
||||
t t rpl))
|
||||
((string-match "%s" rpl) (replace-match (or tag "") t t rpl))
|
||||
((string-match "%h" rpl)
|
||||
(replace-match (url-hexify-string (or tag "")) t t rpl))
|
||||
((string-match "%(\\(.+\\))" rpl) ; %(sexpr using tag)
|
||||
(replace-match
|
||||
(save-match-data
|
||||
(funcall (or (cdr (assoc (match-string 1 rpl)
|
||||
org-link--abbrev-functions))
|
||||
(cdar (push (cons (match-string 1 rpl)
|
||||
(eval (read (format
|
||||
"(lambda (tag) (%s))"
|
||||
(match-string 1 rpl)))))
|
||||
org-link--abbrev-functions)))
|
||||
tag))
|
||||
t t rpl))
|
||||
((string-match-p "%[0-<>^_]?[0-9]*\\(?:\\.[0-9]+\\)?s" rpl)
|
||||
(format-spec rpl `((?s . ,(or tag "")))))
|
||||
((string-match-p "%[0-<>^_]?[0-9]*\\(?:\\.[0-9]+\\)?h" rpl)
|
||||
(format-spec rpl `((?h . ,(url-hexify-string (or tag ""))))))
|
||||
(t (concat rpl tag)))))))
|
||||
|
||||
(defun org-link-open (link &optional arg)
|
||||
|
|
|
@ -650,29 +650,60 @@ Counting starts at 1."
|
|||
"9.0")
|
||||
|
||||
(define-obsolete-variable-alias
|
||||
'org-format-latex-options 'org-latex-preview-options "9.7")
|
||||
'org-format-latex-options 'org-latex-preview-appearance-options "9.7")
|
||||
(make-obsolete-variable
|
||||
'org-format-latex-signal-error "no longer used" "9.7")
|
||||
(define-obsolete-variable-alias
|
||||
'org-format-latex-header 'org-latex-preview-preamble "9.7")
|
||||
(define-obsolete-variable-alias
|
||||
'org-preview-latex-default-process 'org-latex-preview-default-process "9.7")
|
||||
'org-preview-latex-default-process 'org-latex-preview-process-default "9.7")
|
||||
(define-obsolete-variable-alias
|
||||
'org-preview-latex-process-alist 'org-latex-preview-process-alist "9.7")
|
||||
;; (make-obsolete-variable
|
||||
;; 'org-preview-latex-image-directory "replaced with org-persist" "9.7")
|
||||
(define-obsolete-function-alias
|
||||
'org-clear-latex-preview 'org-latex-preview-clear-overlays "9.7")
|
||||
(make-obsolete
|
||||
'org-place-formula-image "replaced with org-latex-preview-place-image and org-latex-preview-place-image-link" "9.7")
|
||||
(define-obsolete-function-alias
|
||||
'org-create-formula-image 'org-latex-preview-create-image "9.7")
|
||||
'org-place-formula-image "no longer used" "9.7")
|
||||
(define-obsolete-function-alias
|
||||
'org-latex-color-format 'org-latex-preview--format-color "9.7")
|
||||
(define-obsolete-function-alias
|
||||
'org-latex-color 'org-latex-preview--attr-color "9.7")
|
||||
;; MathML related functions from org-latex-preview.el
|
||||
(define-obsolete-variable-alias
|
||||
'org-latex-to-mathml-jar-file 'org-mathml-converter-jar-file "9.7")
|
||||
(define-obsolete-variable-alias
|
||||
'org-latex-to-mathml-convert-command 'org-mathml-convert-command "9.7")
|
||||
(define-obsolete-function-alias
|
||||
'org-normalize-color 'org-latex-preview--normalize-color "9.7")
|
||||
'org-format-latex-mathml-available-p 'org-mathml-converter-available-p "9.7")
|
||||
(define-obsolete-function-alias
|
||||
'org-create-math-formula 'org-mathml-convert-latex "9.7")
|
||||
|
||||
;; FIXME: Unused; obsoleted; to be removed.
|
||||
(defun org-format-latex-as-mathml (latex-frag latex-frag-type
|
||||
prefix &optional dir)
|
||||
(let* ((absprefix (expand-file-name prefix dir))
|
||||
(print-length nil) (print-level nil)
|
||||
(formula-id (concat
|
||||
"formula-"
|
||||
(sha1
|
||||
(prin1-to-string
|
||||
(list latex-frag
|
||||
org-latex-to-mathml-convert-command)))))
|
||||
(formula-cache (format "%s-%s.mathml" absprefix formula-id))
|
||||
(formula-cache-dir (file-name-directory formula-cache)))
|
||||
(unless (file-directory-p formula-cache-dir)
|
||||
(make-directory formula-cache-dir t))
|
||||
(unless (file-exists-p formula-cache)
|
||||
(org-mathml-convert-latex latex-frag formula-cache))
|
||||
(if (file-exists-p formula-cache)
|
||||
;; Successful conversion. Return the link to MathML file.
|
||||
(org-add-props
|
||||
(format "[[file:%s]]" (file-relative-name formula-cache dir))
|
||||
(list 'org-latex-src (replace-regexp-in-string "\"" "" latex-frag)
|
||||
'org-latex-src-embed-type (if latex-frag-type
|
||||
'paragraph 'character)))
|
||||
;; Failed conversion. Return the LaTeX fragment verbatim
|
||||
latex-frag)))
|
||||
(make-obsolete #'org-format-latex-as-mathml "to be removed" "9.7")
|
||||
|
||||
;; FIXME: Unused; obsoleted; to be removed.
|
||||
(defun org-dvipng-color (attr)
|
||||
|
@ -690,6 +721,321 @@ Counting starts at 1."
|
|||
(make-obsolete
|
||||
'org-dvipng-color-format "to be removed" "9.7")
|
||||
|
||||
;; FIXME: Unused; obsoleted; to be removed.
|
||||
(defun org-normalize-color (value)
|
||||
"Return string to be used as color value for an RGB component."
|
||||
(format "%g" (/ value 65535.0)))
|
||||
(make-obsolete 'org-normalize-color "to be removed" "9.7")
|
||||
|
||||
;; FIXME: Unused; obsoleted; to be removed.
|
||||
(defcustom org-preview-latex-image-directory "ltximg/"
|
||||
"Path to store latex preview images.
|
||||
A relative path here creates many directories relative to the
|
||||
processed Org files paths. An absolute path puts all preview
|
||||
images at the same place."
|
||||
:group 'org-latex
|
||||
:version "26.1"
|
||||
:package-version '(Org . "9.0")
|
||||
:type 'string)
|
||||
|
||||
(make-obsolete-variable
|
||||
'org-preview-latex-image-directory "replaced with org-persist" "9.7")
|
||||
|
||||
;; FIXME: Unused; obsoleted; to be removed.
|
||||
(defun org-format-latex
|
||||
(prefix &optional beg end dir overlays msg forbuffer processing-type)
|
||||
"Replace LaTeX fragments with links to an image.
|
||||
|
||||
The function takes care of creating the replacement image.
|
||||
|
||||
Only consider fragments between BEG and END when those are
|
||||
provided.
|
||||
|
||||
When optional argument OVERLAYS is non-nil, display the image on
|
||||
top of the fragment instead of replacing it.
|
||||
|
||||
PROCESSING-TYPE is the conversion method to use, as a symbol.
|
||||
|
||||
Some of the options can be changed using the variable
|
||||
`org-format-latex-options', which see."
|
||||
(when (and overlays (fboundp 'clear-image-cache)) (clear-image-cache))
|
||||
(unless (eq processing-type 'verbatim)
|
||||
(let* ((math-regexp "\\$\\|\\\\[([]\\|^[ \t]*\\\\begin{[A-Za-z0-9*]+}")
|
||||
(cnt 0)
|
||||
checkdir-flag)
|
||||
(goto-char (or beg (point-min)))
|
||||
;; Optimize overlay creation: (info "(elisp) Managing Overlays").
|
||||
(when (and overlays (memq processing-type '(dvipng imagemagick)))
|
||||
(overlay-recenter (or end (point-max))))
|
||||
(while (re-search-forward math-regexp end t)
|
||||
(unless (and overlays
|
||||
(eq (get-char-property (point) 'org-overlay-type)
|
||||
'org-latex-overlay))
|
||||
(let* ((context (org-element-context))
|
||||
(type (org-element-type context)))
|
||||
(when (memq type '(latex-environment latex-fragment))
|
||||
(let ((block-type (eq type 'latex-environment))
|
||||
(value (org-element-property :value context))
|
||||
(beg (org-element-property :begin context))
|
||||
(end (save-excursion
|
||||
(goto-char (org-element-property :end context))
|
||||
(skip-chars-backward " \r\t\n")
|
||||
(point))))
|
||||
(cond
|
||||
((eq processing-type 'mathjax)
|
||||
;; Prepare for MathJax processing.
|
||||
(if (not (string-match "\\`\\$\\$?" value))
|
||||
(goto-char end)
|
||||
(delete-region beg end)
|
||||
(if (string= (match-string 0 value) "$$")
|
||||
(insert "\\[" (substring value 2 -2) "\\]")
|
||||
(insert "\\(" (substring value 1 -1) "\\)"))))
|
||||
((eq processing-type 'html)
|
||||
(goto-char beg)
|
||||
(delete-region beg end)
|
||||
(insert (org-format-latex-as-html value)))
|
||||
((assq processing-type org-preview-latex-process-alist)
|
||||
;; Process to an image.
|
||||
(cl-incf cnt)
|
||||
(goto-char beg)
|
||||
(let* ((processing-info
|
||||
(cdr (assq processing-type org-preview-latex-process-alist)))
|
||||
(face (face-at-point))
|
||||
;; Get the colors from the face at point.
|
||||
(fg
|
||||
(let ((color (plist-get org-format-latex-options
|
||||
:foreground)))
|
||||
(if forbuffer
|
||||
(cond
|
||||
((eq color 'auto)
|
||||
(face-attribute face :foreground nil 'default))
|
||||
((eq color 'default)
|
||||
(face-attribute 'default :foreground nil))
|
||||
(t color))
|
||||
color)))
|
||||
(bg
|
||||
(let ((color (plist-get org-format-latex-options
|
||||
:background)))
|
||||
(if forbuffer
|
||||
(cond
|
||||
((eq color 'auto)
|
||||
(face-attribute face :background nil 'default))
|
||||
((eq color 'default)
|
||||
(face-attribute 'default :background nil))
|
||||
(t color))
|
||||
color)))
|
||||
(hash (sha1 (prin1-to-string
|
||||
(list org-format-latex-header
|
||||
org-latex-default-packages-alist
|
||||
org-latex-packages-alist
|
||||
org-format-latex-options
|
||||
forbuffer value fg bg))))
|
||||
(imagetype (or (plist-get processing-info :image-output-type) "png"))
|
||||
(absprefix (expand-file-name prefix dir))
|
||||
(linkfile (format "%s_%s.%s" prefix hash imagetype))
|
||||
(movefile (format "%s_%s.%s" absprefix hash imagetype))
|
||||
(sep (and block-type "\n\n"))
|
||||
(link (concat sep "[[file:" linkfile "]]" sep))
|
||||
(options
|
||||
(org-combine-plists
|
||||
org-format-latex-options
|
||||
`(:foreground ,fg :background ,bg))))
|
||||
(when msg (message msg cnt))
|
||||
(unless checkdir-flag ; Ensure the directory exists.
|
||||
(setq checkdir-flag t)
|
||||
(let ((todir (file-name-directory absprefix)))
|
||||
(unless (file-directory-p todir)
|
||||
(make-directory todir t))))
|
||||
(unless (file-exists-p movefile)
|
||||
(org-create-formula-image
|
||||
value movefile options forbuffer processing-type))
|
||||
(org-place-formula-image link block-type beg end value overlays movefile imagetype)))
|
||||
((eq processing-type 'mathml)
|
||||
;; Process to MathML.
|
||||
(unless (org-format-latex-mathml-available-p)
|
||||
(user-error "LaTeX to MathML converter not configured"))
|
||||
(cl-incf cnt)
|
||||
(when msg (message msg cnt))
|
||||
(goto-char beg)
|
||||
(delete-region beg end)
|
||||
(insert (org-format-latex-as-mathml
|
||||
value block-type prefix dir)))
|
||||
(t
|
||||
(error "Unknown conversion process %s for LaTeX fragments"
|
||||
processing-type)))))))))))
|
||||
|
||||
;; FIXME: Unused; obsoleted; to be removed.
|
||||
(defun org-place-formula-image (link block-type beg end value overlays movefile imagetype)
|
||||
"Place an overlay from BEG to END showing MOVEFILE.
|
||||
The overlay will be above BEG if OVERLAYS is non-nil."
|
||||
(if overlays
|
||||
(progn
|
||||
(dolist (o (overlays-in beg end))
|
||||
(when (eq (overlay-get o 'org-overlay-type)
|
||||
'org-latex-overlay)
|
||||
(delete-overlay o)))
|
||||
(let ((ov (make-overlay beg end))
|
||||
(imagetype (or (intern imagetype) 'png)))
|
||||
(overlay-put ov 'org-overlay-type 'org-latex-overlay)
|
||||
(overlay-put ov 'evaporate t)
|
||||
(overlay-put ov
|
||||
'modification-hooks
|
||||
(list (lambda (o _flag _beg _end &optional _l)
|
||||
(delete-overlay o))))
|
||||
(overlay-put ov
|
||||
'display
|
||||
(list 'image :type imagetype :file movefile :ascent 'center)))
|
||||
(goto-char end))
|
||||
(delete-region beg end)
|
||||
(insert
|
||||
(org-add-props link
|
||||
(list 'org-latex-src
|
||||
(replace-regexp-in-string "\"" "" value)
|
||||
'org-latex-src-embed-type
|
||||
(if block-type 'paragraph 'character))))))
|
||||
|
||||
|
||||
;; FIXME: Unused; obsoleted; to be removed.
|
||||
(defun org-create-formula-image
|
||||
(string tofile options buffer &optional processing-type)
|
||||
"Create an image from LaTeX source using external processes.
|
||||
|
||||
The LaTeX STRING is saved to a temporary LaTeX file, then
|
||||
converted to an image file by process PROCESSING-TYPE defined in
|
||||
`org-preview-latex-process-alist'. A nil value defaults to
|
||||
`org-preview-latex-default-process'.
|
||||
|
||||
The generated image file is eventually moved to TOFILE.
|
||||
|
||||
The OPTIONS argument controls the size, foreground color and
|
||||
background color of the generated image.
|
||||
|
||||
When BUFFER non-nil, this function is used for LaTeX previewing.
|
||||
Otherwise, it is used to deal with LaTeX snippets showed in
|
||||
a HTML file."
|
||||
(let* ((processing-type (or processing-type
|
||||
org-preview-latex-default-process))
|
||||
(processing-info
|
||||
(cdr (assq processing-type org-preview-latex-process-alist)))
|
||||
(programs (plist-get processing-info :programs))
|
||||
(error-message (or (plist-get processing-info :message) ""))
|
||||
(image-input-type (plist-get processing-info :image-input-type))
|
||||
(image-output-type (plist-get processing-info :image-output-type))
|
||||
(post-clean (or (plist-get processing-info :post-clean)
|
||||
'(".dvi" ".xdv" ".pdf" ".tex" ".aux" ".log"
|
||||
".svg" ".png" ".jpg" ".jpeg" ".out")))
|
||||
(latex-header
|
||||
(or (plist-get processing-info :latex-header)
|
||||
(org-latex-make-preamble
|
||||
(org-export-get-environment (org-export-get-backend 'latex))
|
||||
org-format-latex-header
|
||||
'snippet)))
|
||||
(latex-compiler (plist-get processing-info :latex-compiler))
|
||||
(tmpdir temporary-file-directory)
|
||||
(texfilebase (make-temp-name
|
||||
(expand-file-name "orgtex" tmpdir)))
|
||||
(texfile (concat texfilebase ".tex"))
|
||||
(image-size-adjust (or (plist-get processing-info :image-size-adjust)
|
||||
'(1.0 . 1.0)))
|
||||
(scale (* (if buffer (car image-size-adjust) (cdr image-size-adjust))
|
||||
(or (plist-get options (if buffer :scale :html-scale)) 1.0)))
|
||||
(dpi (* scale (if (and buffer (display-graphic-p)) (org--get-display-dpi) 140.0)))
|
||||
(fg (or (plist-get options (if buffer :foreground :html-foreground))
|
||||
"Black"))
|
||||
(bg (or (plist-get options (if buffer :background :html-background))
|
||||
"Transparent"))
|
||||
(image-converter
|
||||
(or (and (string= bg "Transparent")
|
||||
(plist-get processing-info :transparent-image-converter))
|
||||
(plist-get processing-info :image-converter)))
|
||||
(log-buf (get-buffer-create "*Org Preview LaTeX Output*"))
|
||||
(resize-mini-windows nil)) ;Fix Emacs flicker when creating image.
|
||||
(dolist (program programs)
|
||||
(org-check-external-command program error-message))
|
||||
(if (eq fg 'default)
|
||||
(setq fg (org-latex-color :foreground))
|
||||
(setq fg (org-latex-color-format fg)))
|
||||
(setq bg (cond
|
||||
((eq bg 'default) (org-latex-color :background))
|
||||
((string= bg "Transparent") nil)
|
||||
(t (org-latex-color-format bg))))
|
||||
;; Remove TeX \par at end of snippet to avoid trailing space.
|
||||
(if (string-suffix-p string "\n")
|
||||
(aset string (1- (length string)) ?%)
|
||||
(setq string (concat string "%")))
|
||||
(with-temp-file texfile
|
||||
(insert latex-header)
|
||||
(insert "\n\\begin{document}\n"
|
||||
"\\definecolor{fg}{rgb}{" fg "}%\n"
|
||||
(if bg
|
||||
(concat "\\definecolor{bg}{rgb}{" bg "}%\n"
|
||||
"\n\\pagecolor{bg}%\n")
|
||||
"")
|
||||
"\n{\\color{fg}\n"
|
||||
string
|
||||
"\n}\n"
|
||||
"\n\\end{document}\n"))
|
||||
(let* ((err-msg (format "Please adjust `%s' part of \
|
||||
`org-preview-latex-process-alist'."
|
||||
processing-type))
|
||||
(image-input-file
|
||||
(org-compile-file
|
||||
texfile latex-compiler image-input-type err-msg log-buf))
|
||||
(image-output-file
|
||||
(org-compile-file
|
||||
image-input-file image-converter image-output-type err-msg log-buf
|
||||
`((?D . ,(shell-quote-argument (format "%s" dpi)))
|
||||
(?S . ,(shell-quote-argument (format "%s" (/ dpi 140.0))))))))
|
||||
(copy-file image-output-file tofile 'replace)
|
||||
(dolist (e post-clean)
|
||||
(when (file-exists-p (concat texfilebase e))
|
||||
(delete-file (concat texfilebase e))))
|
||||
image-output-file)))
|
||||
|
||||
;; FIXME: Unused; obsoleted; to be removed.
|
||||
(defun org-html-format-latex (latex-frag processing-type info)
|
||||
"Format a LaTeX fragment LATEX-FRAG into HTML.
|
||||
PROCESSING-TYPE designates the tool used for conversion. It can
|
||||
be `mathjax', `verbatim', `html', nil, t or symbols in
|
||||
`org-preview-latex-process-alist', e.g., `dvipng', `dvisvgm' or
|
||||
`imagemagick'. See `org-html-with-latex' for more information.
|
||||
INFO is a plist containing export properties."
|
||||
(let ((cache-relpath "") (cache-dir ""))
|
||||
(unless (or (eq processing-type 'mathjax)
|
||||
(eq processing-type 'html))
|
||||
(let ((bfn (or (buffer-file-name)
|
||||
(make-temp-name
|
||||
(expand-file-name "latex" temporary-file-directory))))
|
||||
(latex-header
|
||||
(let ((header (plist-get info :latex-header)))
|
||||
(and header
|
||||
(concat (mapconcat
|
||||
(lambda (line) (concat "#+LATEX_HEADER: " line))
|
||||
(org-split-string header "\n")
|
||||
"\n")
|
||||
"\n")))))
|
||||
(setq cache-relpath
|
||||
(concat (file-name-as-directory org-preview-latex-image-directory)
|
||||
(file-name-sans-extension
|
||||
(file-name-nondirectory bfn)))
|
||||
cache-dir (file-name-directory bfn))
|
||||
;; Re-create LaTeX environment from original buffer in
|
||||
;; temporary buffer so that dvipng/imagemagick can properly
|
||||
;; turn the fragment into an image.
|
||||
(setq latex-frag (concat latex-header latex-frag))))
|
||||
(org-export-with-buffer-copy
|
||||
:to-buffer (get-buffer-create " *Org HTML Export LaTeX*")
|
||||
:drop-visibility t :drop-narrowing t :drop-contents t
|
||||
(erase-buffer)
|
||||
(insert latex-frag)
|
||||
(org-format-latex cache-relpath nil nil cache-dir nil
|
||||
"Creating LaTeX Image..." nil processing-type)
|
||||
(buffer-string))))
|
||||
|
||||
(make-obsolete #'org-format-latex "to be removed" "9.7")
|
||||
(make-obsolete #'org-create-formula-image "to be removed" "9.7")
|
||||
(make-obsolete #'org-html-format-latex "to be removed" "9.7")
|
||||
|
||||
;; FIXME: Unused; obsoleted; to be removed.
|
||||
(defun org-let (list &rest body) ;FIXME: So many kittens are suffering here.
|
||||
(declare (indent 1) (obsolete cl-progv "2021"))
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -359,10 +359,20 @@ If EXCLUDE-TMP is non-nil, ignore temporary buffers."
|
|||
;;; Async stack
|
||||
|
||||
(defvar org-async--stack nil
|
||||
"List of (%PROCESS :start-time %FLOAT :success %FUN :failure %FUN :timeout %FLOAT :buffer %BUFFER) forms.")
|
||||
"List of async currently running task forms.
|
||||
Each running task is represented by a list with the following structure:
|
||||
(%PROCESS :success %FUN :failure %FUN
|
||||
:filter %FUN :buffer %BUFFER
|
||||
:timeout %FLOAT :start-time %FLOAT
|
||||
:info %SEXP)")
|
||||
|
||||
(defvar org-async--wait-queue nil
|
||||
"List of (%PROCESS :success %FUN :failure %FUN :timeout %FLOAT :buffer %BUFFER) forms.")
|
||||
"List of async queued task forms.
|
||||
Each queued task is represented by a list with the following structure:
|
||||
(%PROCESS :success %FUN :failure %FUN
|
||||
:filter %FUN :buffer %BUFFER
|
||||
:info %SEXP :dir %STRING
|
||||
:timeout %FLOAT :coding %SYMBOL)")
|
||||
|
||||
(defvar org-async-process-limit 4
|
||||
"Maximum number of processes to run at once.")
|
||||
|
@ -375,8 +385,8 @@ If EXCLUDE-TMP is non-nil, ignore temporary buffers."
|
|||
|
||||
(defvar org-async--counter 0)
|
||||
|
||||
(cl-defun org-async-call (proc &key success failure filter buffer info timeout now
|
||||
(dir default-directory))
|
||||
(cl-defun org-async-call (proc &key success failure filter buffer info timeout now process-variables
|
||||
(dir default-directory) (coding 'utf-8))
|
||||
"Start PROC and register it with callbacks SUCCESS and FAILURE.
|
||||
|
||||
PROC can be a process, string, or list. A string will be run as
|
||||
|
@ -403,9 +413,13 @@ namely:
|
|||
process-buffer, and INFO as arguments.
|
||||
- A function, which is called with exit-code, process-buffer,
|
||||
and INFO as arguments.
|
||||
- A list, which is used as an argument list for a new `org-async-call' invocation.
|
||||
- A list, which is used as an argument list for a new `org-async-call' call.
|
||||
- nil, which does nothing.
|
||||
|
||||
When PROC succeeds by exiting with an exit code of zero, the SUCCESS
|
||||
callback will be run. Should PROC fail, or be killed, or the process
|
||||
runs for more than TIMEOUT seconds, the FAILURE callback will be run.
|
||||
|
||||
A function FILTER can be provided, in which case it will be
|
||||
called in the same manner as a normal procecss filter, however
|
||||
the function FILTER will be called with INFO as a third argument.
|
||||
|
@ -415,12 +429,20 @@ When BUFFER is non-nil, there are two other major differences:
|
|||
- Note that `point' is left alone and is not moved by this.
|
||||
- The process buffer is the current buffer when FILTER is called.
|
||||
|
||||
When PROC succeeds by exiting with an exit code of zero, the SUCCESS
|
||||
callback will be run. Should PROC fail, or be killed, or the process
|
||||
runs for more than TIMEOUT seconds, the FAILURE callback will be run.
|
||||
When CODING is non-nil, both the process encode and decode system
|
||||
will be set to CODING. If unset, UTF-8 is used.
|
||||
|
||||
When NOW is non-nil, the PROC is started immediately, regardless
|
||||
of `org-async-process-limit'."
|
||||
of `org-async-process-limit'.
|
||||
|
||||
For improved performance, PROCESS-VARIABLES is a list of
|
||||
let-style bindings that should be applied to the process.
|
||||
Variables are supported on an individual basis (i.e. only certain
|
||||
variables can be set), with the default value being equivalent to:
|
||||
|
||||
:process-variables ((process-adaptive-read-buffering nil)
|
||||
(process-connection-type nil)
|
||||
(read-process-output-max 65536))"
|
||||
(cond
|
||||
;; Called with a task (as can be used with callbacks), so re-call
|
||||
;; with expanded arguments.
|
||||
|
@ -430,7 +452,13 @@ of `org-async-process-limit'."
|
|||
;; Start the async process now.
|
||||
((or now (< (length org-async--stack) org-async-process-limit))
|
||||
(let ((proc
|
||||
(let ((default-directory (or dir default-directory)))
|
||||
(let ((default-directory (or dir default-directory))
|
||||
(process-adaptive-read-buffering ; No by default
|
||||
(cadr (or (assoc 'process-adaptive-read-buffering process-variables) nil)))
|
||||
(process-connection-type ; Use a pipe by default
|
||||
(cadr (or (assoc 'process-connection-type process-variables) nil)))
|
||||
(read-process-output-max ; Can be worth changing depending on the process
|
||||
(or (assq 'read-process-output-max process-variables) read-process-output-max)))
|
||||
(cond ((processp proc) proc)
|
||||
((stringp proc)
|
||||
(start-process-shell-command
|
||||
|
@ -447,15 +475,17 @@ of `org-async-process-limit'."
|
|||
(set-process-sentinel proc #'org-async--sentinel)
|
||||
(when filter
|
||||
(set-process-filter proc #'org-async--filter))
|
||||
(when coding
|
||||
(set-process-coding-system proc coding coding))
|
||||
(push (list proc
|
||||
:success success
|
||||
:failure failure
|
||||
:filter filter
|
||||
:timeout timeout
|
||||
:buffer (if (eq buffer t)
|
||||
(cons :temp (generate-new-buffer " *temp*" t))
|
||||
buffer)
|
||||
:info info
|
||||
:timeout timeout
|
||||
:start-time (float-time))
|
||||
org-async--stack)
|
||||
(org-async--monitor t)
|
||||
|
@ -467,13 +497,24 @@ of `org-async-process-limit'."
|
|||
(list (list proc
|
||||
:success success
|
||||
:failure failure
|
||||
:dir dir
|
||||
:info info
|
||||
:filter filter
|
||||
:buffer buffer
|
||||
:info info
|
||||
:dir dir
|
||||
:timeout timeout
|
||||
:filter filter))))
|
||||
:coding coding))))
|
||||
(last org-async--wait-queue))))
|
||||
|
||||
(defvar org-async--blocking-tasks nil
|
||||
"List of async tasks currently being waited on.")
|
||||
|
||||
(defun org-async-wait-for (&rest tasks)
|
||||
"Block until every task of TASKS has finished (including callback tasks)."
|
||||
(setq org-async--blocking-tasks tasks)
|
||||
(while org-async--blocking-tasks
|
||||
(dolist (task org-async--blocking-tasks)
|
||||
(accept-process-output (car task)))))
|
||||
|
||||
(defun org-async--filter (process string)
|
||||
"After PROCESS recieves STRING, call the async filter.
|
||||
This is implementated to satisfy the filter function documentation in
|
||||
|
@ -510,9 +551,13 @@ Otherwise, the failure callback is run."
|
|||
(when (assq process org-async--stack)
|
||||
(let* ((proc-info (cdr (assq process org-async--stack)))
|
||||
(buffer-val (plist-get proc-info :buffer))
|
||||
(proc-buf (if (consp buffer-val) (cdr buffer-val) buffer-val)))
|
||||
(proc-buf (if (consp buffer-val) (cdr buffer-val) buffer-val))
|
||||
(blocking-p (cl-member process org-async--blocking-tasks :key #'car)))
|
||||
(setq org-async--stack
|
||||
(delq (assq process org-async--stack) org-async--stack))
|
||||
;; Ensure that any filter is called on the final output
|
||||
;; prior to the callbacks.
|
||||
(while (accept-process-output process))
|
||||
(org-async--execute-callback
|
||||
(plist-get
|
||||
proc-info
|
||||
|
@ -521,14 +566,18 @@ Otherwise, the failure callback is run."
|
|||
:success :failure))
|
||||
(process-exit-status process)
|
||||
proc-buf
|
||||
(plist-get proc-info :info))
|
||||
(plist-get proc-info :info)
|
||||
blocking-p)
|
||||
(when blocking-p
|
||||
(setq org-async--blocking-tasks
|
||||
(cl-delete process org-async--blocking-tasks :key #'car)))
|
||||
(when (and (consp buffer-val) (eq :temp (car buffer-val)))
|
||||
(kill-buffer proc-buf)))
|
||||
(when (and org-async--wait-queue
|
||||
(< org-async-process-limit (length org-async--stack)))
|
||||
(apply #'org-async-call (pop org-async--wait-queue)))))
|
||||
|
||||
(defun org-async--execute-callback (callback exit-code process-buffer info)
|
||||
(defun org-async--execute-callback (callback exit-code process-buffer info &optional blocking)
|
||||
"Run CALLBACK with EXIT-CODE, PROCESS-BUFFER, and INFO.
|
||||
CALLBACK can take one of four forms:
|
||||
- A string, which is used a `message' string with EXIT-CODE,
|
||||
|
@ -539,7 +588,9 @@ CALLBACK can take one of four forms:
|
|||
- An (org-async-task ...) structure, which passed to an
|
||||
`org-async-call' invocation.
|
||||
- A list of callbacks, which are individually evaluated.
|
||||
- nil, which does nothing."
|
||||
- nil, which does nothing.
|
||||
|
||||
When BLOCKING is set, all callback tasks are made blocking."
|
||||
(cond
|
||||
((stringp callback)
|
||||
(message callback exit-code process-buffer info))
|
||||
|
@ -547,9 +598,11 @@ CALLBACK can take one of four forms:
|
|||
(funcall callback exit-code process-buffer info))
|
||||
((consp callback)
|
||||
(if (eq (car callback) 'org-async-task)
|
||||
(org-async-call callback)
|
||||
(if blocking
|
||||
(push (org-async-call callback) org-async--blocking-tasks)
|
||||
(org-async-call callback))
|
||||
(dolist (clbk callback)
|
||||
(org-async--execute-callback clbk exit-code process-buffer info))))
|
||||
(org-async--execute-callback clbk exit-code process-buffer info blocking))))
|
||||
((null callback)) ; Do nothing.
|
||||
(t (message "Ignoring invalid `org-async-call' callback: %S" callback))))
|
||||
|
||||
|
|
|
@ -602,22 +602,27 @@ MISC, if non-nil will be appended to the collection. It must be a plist."
|
|||
|
||||
;;;; Reading container data.
|
||||
|
||||
(defvar org-persist--inhibit-container-normalization nil
|
||||
"Prevent `org-persist--normalize-container' from doing anything.")
|
||||
|
||||
(defun org-persist--normalize-container (container &optional inner)
|
||||
"Normalize CONTAINER representation into (type . settings).
|
||||
|
||||
When INNER is non-nil, do not try to match as list of containers."
|
||||
(pcase container
|
||||
((or `elisp `elisp-data `version `file `index `url)
|
||||
`(,container nil))
|
||||
((or (pred keywordp) (pred stringp) `(quote . ,_))
|
||||
`(elisp-data ,container))
|
||||
((pred symbolp)
|
||||
`(elisp ,container))
|
||||
(`(,(or `elisp `elisp-data `version `file `index `url) . ,_)
|
||||
container)
|
||||
((and (pred listp) (guard (not inner)))
|
||||
(mapcar (lambda (c) (org-persist--normalize-container c 'inner)) container))
|
||||
(_ (error "org-persist: Unknown container type: %S" container))))
|
||||
(if org-persist--inhibit-container-normalization
|
||||
container
|
||||
(pcase container
|
||||
((or `elisp `elisp-data `version `file `index `url)
|
||||
`(,container nil))
|
||||
((or (pred keywordp) (pred stringp) `(quote . ,_))
|
||||
`(elisp-data ,container))
|
||||
((pred symbolp)
|
||||
`(elisp ,container))
|
||||
(`(,(or `elisp `elisp-data `version `file `index `url) . ,_)
|
||||
container)
|
||||
((and (pred listp) (guard (not inner)))
|
||||
(mapcar (lambda (c) (org-persist--normalize-container c 'inner)) container))
|
||||
(_ (error "org-persist: Unknown container type: %S" container)))))
|
||||
|
||||
(defvar org-persist--associated-buffer-cache (make-hash-table :weakness 'key)
|
||||
"Buffer hash cache.")
|
||||
|
@ -823,20 +828,23 @@ COLLECTION is the plist holding data collection."
|
|||
(defun org-persist-write:file (c collection)
|
||||
"Write file container C according to COLLECTION."
|
||||
(org-persist-collection-let collection
|
||||
(when (or (and path (file-exists-p path))
|
||||
(and (stringp (cadr c)) (file-exists-p (cadr c))))
|
||||
(when (and (stringp (cadr c)) (file-exists-p (cadr c)))
|
||||
(setq path (cadr c)))
|
||||
(let* ((persist-file (plist-get collection :persist-file))
|
||||
(ext (file-name-extension path))
|
||||
(file-copy (org-file-name-concat
|
||||
org-persist-directory
|
||||
(format "%s-%s.%s" persist-file (md5 path) ext))))
|
||||
(unless (file-exists-p file-copy)
|
||||
(unless (file-exists-p (file-name-directory file-copy))
|
||||
(make-directory (file-name-directory file-copy) t))
|
||||
(copy-file path file-copy 'overwrite))
|
||||
(format "%s-%s.%s" persist-file (md5 path) ext)))))
|
||||
(if (or (and path (file-exists-p path))
|
||||
(and (stringp (cadr c)) (file-exists-p (cadr c))))
|
||||
(progn
|
||||
(when (and (stringp (cadr c)) (file-exists-p (cadr c)))
|
||||
(setq path (cadr c)))
|
||||
(let* ((persist-file (plist-get collection :persist-file))
|
||||
(ext (file-name-extension path))
|
||||
(file-copy (org-file-name-concat
|
||||
org-persist-directory
|
||||
(format "%s-%s.%s" persist-file (md5 path) ext))))
|
||||
(unless (file-exists-p file-copy)
|
||||
(unless (file-exists-p (file-name-directory file-copy))
|
||||
(make-directory (file-name-directory file-copy) t))
|
||||
(copy-file path file-copy 'overwrite))
|
||||
(format "%s-%s.%s" persist-file (md5 path) ext)))
|
||||
(when-let ((file-copy (org-persist-read c associated)))
|
||||
(file-relative-name file-copy org-persist-directory)))))
|
||||
|
||||
(defun org-persist-write:url (c collection)
|
||||
"Write url container C according to COLLECTION."
|
||||
|
@ -941,26 +949,27 @@ VALUE pairs.
|
|||
When WRITE-IMMEDIATELY is non-nil, the return value will be the same
|
||||
with `org-persist-write'."
|
||||
(unless org-persist--index (org-persist--load-index))
|
||||
(setq container (org-persist--normalize-container container))
|
||||
(when inherit
|
||||
(setq inherit (org-persist--normalize-container inherit))
|
||||
(let ((inherited-collection (org-persist--get-collection inherit associated))
|
||||
new-collection)
|
||||
(unless (member container (plist-get inherited-collection :container))
|
||||
(setq new-collection
|
||||
(plist-put (copy-sequence inherited-collection) :container
|
||||
(cons container (plist-get inherited-collection :container))))
|
||||
(org-persist--remove-from-index inherited-collection)
|
||||
(org-persist--add-to-index new-collection))))
|
||||
(let ((collection (org-persist--get-collection container associated misc)))
|
||||
(when (and expiry (not inherit))
|
||||
(when expiry (plist-put collection :expiry expiry))))
|
||||
(when (or (bufferp associated) (bufferp (plist-get associated :buffer)))
|
||||
(with-current-buffer (if (bufferp associated)
|
||||
associated
|
||||
(plist-get associated :buffer))
|
||||
(add-hook 'kill-buffer-hook #'org-persist-write-all-buffer nil 'local)))
|
||||
(when write-immediately (org-persist-write container associated)))
|
||||
(let ((container (org-persist--normalize-container container))
|
||||
(inherit (and inherit (org-persist--normalize-container inherit)))
|
||||
(org-persist--inhibit-container-normalization t))
|
||||
(when inherit
|
||||
(let ((inherited-collection (org-persist--get-collection inherit associated))
|
||||
new-collection)
|
||||
(unless (member container (plist-get inherited-collection :container))
|
||||
(setq new-collection
|
||||
(plist-put (copy-sequence inherited-collection) :container
|
||||
(cons container (plist-get inherited-collection :container))))
|
||||
(org-persist--remove-from-index inherited-collection)
|
||||
(org-persist--add-to-index new-collection))))
|
||||
(let ((collection (org-persist--get-collection container associated misc)))
|
||||
(when (and expiry (not inherit))
|
||||
(when expiry (plist-put collection :expiry expiry))))
|
||||
(when (or (bufferp associated) (bufferp (plist-get associated :buffer)))
|
||||
(with-current-buffer (if (bufferp associated)
|
||||
associated
|
||||
(plist-get associated :buffer))
|
||||
(add-hook 'kill-buffer-hook #'org-persist-write-all-buffer nil 'local)))
|
||||
(when write-immediately (org-persist-write container associated))))
|
||||
|
||||
(cl-defun org-persist-unregister (container &optional associated &key remove-related)
|
||||
"Unregister CONTAINER in ASSOCIATED to be persistent.
|
||||
|
@ -1075,6 +1084,9 @@ have the same meaning as in `org-persist-read'."
|
|||
"Call `org-persist-load-all' in current buffer."
|
||||
(org-persist-load-all (current-buffer)))
|
||||
|
||||
(defvar org-persist--inhibit-write nil
|
||||
"Whether `org-persist-write' should be inhibited.")
|
||||
|
||||
(defun org-persist-write (container &optional associated ignore-return)
|
||||
"Save CONTAINER according to ASSOCIATED.
|
||||
ASSOCIATED can be a plist, a buffer, or a string.
|
||||
|
@ -1084,31 +1096,33 @@ The return value is nil when writing fails and the written value (as
|
|||
returned by `org-persist-read') on success.
|
||||
When IGNORE-RETURN is non-nil, just return t on success without calling
|
||||
`org-persist-read'."
|
||||
(setq associated (org-persist--normalize-associated associated))
|
||||
;; Update hash
|
||||
(when (and (plist-get associated :file)
|
||||
(plist-get associated :hash)
|
||||
(get-file-buffer (plist-get associated :file)))
|
||||
(setq associated (org-persist--normalize-associated (get-file-buffer (plist-get associated :file)))))
|
||||
(let ((collection (org-persist--get-collection container associated)))
|
||||
(setf collection (plist-put collection :associated associated))
|
||||
(unless (or
|
||||
;; Prevent data leakage from encrypted files.
|
||||
;; We do it in somewhat paranoid manner and do not
|
||||
;; allow anything related to encrypted files to be
|
||||
;; written.
|
||||
(and (plist-get associated :file)
|
||||
(string-match-p epa-file-name-regexp (plist-get associated :file)))
|
||||
(seq-find (lambda (v)
|
||||
(run-hook-with-args-until-success 'org-persist-before-write-hook v associated))
|
||||
(plist-get collection :container)))
|
||||
(when (or (file-exists-p org-persist-directory) (org-persist--save-index))
|
||||
(let ((file (org-file-name-concat org-persist-directory (plist-get collection :persist-file)))
|
||||
(data (mapcar (lambda (c) (cons c (org-persist-write:generic c collection)))
|
||||
(plist-get collection :container))))
|
||||
(puthash file data org-persist--write-cache)
|
||||
(org-persist--write-elisp-file file data)
|
||||
(or ignore-return (org-persist-read container associated)))))))
|
||||
(unless org-persist--inhibit-write
|
||||
(setq associated (org-persist--normalize-associated associated))
|
||||
;; Update hash
|
||||
(when (and (plist-get associated :file)
|
||||
(plist-get associated :hash)
|
||||
(get-file-buffer (plist-get associated :file)))
|
||||
(setq associated (org-persist--normalize-associated (get-file-buffer (plist-get associated :file)))))
|
||||
(let ((collection (org-persist--get-collection container associated))
|
||||
(org-persist--inhibit-write t))
|
||||
(setf collection (plist-put collection :associated associated))
|
||||
(unless (or
|
||||
;; Prevent data leakage from encrypted files.
|
||||
;; We do it in somewhat paranoid manner and do not
|
||||
;; allow anything related to encrypted files to be
|
||||
;; written.
|
||||
(and (plist-get associated :file)
|
||||
(string-match-p epa-file-name-regexp (plist-get associated :file)))
|
||||
(cl-some (lambda (v)
|
||||
(run-hook-with-args-until-success 'org-persist-before-write-hook v associated))
|
||||
(plist-get collection :container)))
|
||||
(when (or (file-exists-p org-persist-directory) (org-persist--save-index))
|
||||
(let ((file (org-file-name-concat org-persist-directory (plist-get collection :persist-file)))
|
||||
(data (mapcar (lambda (c) (cons c (org-persist-write:generic c collection)))
|
||||
(plist-get collection :container))))
|
||||
(puthash file data org-persist--write-cache)
|
||||
(org-persist--write-elisp-file file data)
|
||||
(or ignore-return (org-persist-read container associated))))))))
|
||||
|
||||
(defun org-persist-write-all (&optional associated)
|
||||
"Save all the persistent data.
|
||||
|
|
|
@ -808,9 +808,42 @@ as `org-src-fontify-natively' is non-nil."
|
|||
(1+ pt) (1- (point)) 'face 'org-inline-src-block)))
|
||||
(font-lock-append-text-property
|
||||
(1- (point)) (point) 'face '(org-inline-src-block shadow))
|
||||
(setq pt (point)))))
|
||||
(setq pt (point)))
|
||||
(when (and org-inline-src-prettify-results
|
||||
(re-search-forward "\\= {{{results(" limit t))
|
||||
(font-lock-append-text-property pt (1+ pt) 'face 'org-inline-src-block)
|
||||
(goto-char pt))))
|
||||
t)))
|
||||
|
||||
(defun org-fontify-inline-src-results (limit)
|
||||
"Apply prettify-symbols modifications to inline results blocks.
|
||||
Performed according to `org-inline-src-prettify-results'."
|
||||
(when (and org-inline-src-prettify-results
|
||||
(re-search-forward "{{{results(\\(.+?\\))}}}" limit t))
|
||||
(remove-list-of-text-properties (match-beginning 0) (point)
|
||||
'(composition
|
||||
prettify-symbols-start
|
||||
prettify-symbols-end))
|
||||
(font-lock-append-text-property (match-beginning 0) (match-end 0)
|
||||
'face 'org-block)
|
||||
(let ((start (match-beginning 0)) (end (match-beginning 1)))
|
||||
(with-silent-modifications
|
||||
(compose-region start end (if (eq org-inline-src-prettify-results t)
|
||||
"(" (car org-inline-src-prettify-results)))
|
||||
(add-text-properties start end `(prettify-symbols-start ,start prettify-symbols-end ,end))))
|
||||
(let ((start (match-end 1)) (end (point)))
|
||||
(with-silent-modifications
|
||||
(compose-region start end (if (eq org-inline-src-prettify-results t)
|
||||
")" (cdr org-inline-src-prettify-results)))
|
||||
(add-text-properties start end `(prettify-symbols-start ,start prettify-symbols-end ,end))))
|
||||
t))
|
||||
|
||||
(defun org-toggle-inline-results-display ()
|
||||
"Toggle the literal or contracted display of inline src blocks results."
|
||||
(interactive)
|
||||
(setq org-inline-src-prettify-results (not org-inline-src-prettify-results))
|
||||
(org-restart-font-lock))
|
||||
|
||||
|
||||
;;; Escape contents
|
||||
|
||||
|
|
61
lisp/org.el
61
lisp/org.el
|
@ -4738,7 +4738,7 @@ The following commands are available:
|
|||
(org-unmodified
|
||||
(when org-startup-with-beamer-mode (org-beamer-mode))
|
||||
(when org-startup-with-inline-images (org-display-inline-images))
|
||||
(when org-startup-with-latex-preview (org-latex-preview '(16)))
|
||||
(when org-startup-with-latex-preview (org-latex-preview 'buffer))
|
||||
(unless org-inhibit-startup-visibility-stuff (org-cycle-set-startup-visibility))
|
||||
(when org-startup-truncated (setq truncate-lines t))
|
||||
(when org-startup-numerated (require 'org-num) (org-num-mode 1))
|
||||
|
@ -5179,6 +5179,15 @@ by a #."
|
|||
:version "24.1"
|
||||
:group 'org-appearance)
|
||||
|
||||
(defcustom org-inline-src-prettify-results t
|
||||
"Whether to use (ab)use prettify-symbols-mode on {{{results(...)}}}.
|
||||
Either t or a cons cell of strings which are used as substitutions
|
||||
for the start and end of inline results, respectively."
|
||||
:type '(choice boolean (cons string string))
|
||||
:package-version '(Org . "9.5")
|
||||
:group 'org-appearance
|
||||
:group 'org-babel)
|
||||
|
||||
(defun org-fontify-meta-lines-and-blocks (limit)
|
||||
(condition-case-unless-debug nil
|
||||
(org-fontify-meta-lines-and-blocks-1 limit)
|
||||
|
@ -5439,7 +5448,7 @@ Result depends on variable `org-highlight-latex-and-related'."
|
|||
(re-latex
|
||||
(when (or (memq 'latex org-highlight-latex-and-related)
|
||||
(memq 'native org-highlight-latex-and-related))
|
||||
(let ((matchers (plist-get org-latex-preview-options :matchers)))
|
||||
(let ((matchers (plist-get org-latex-preview-appearance-options :matchers)))
|
||||
(delq nil
|
||||
(mapcar (lambda (x)
|
||||
(and (member (car x) matchers) (nth 1 x)))
|
||||
|
@ -5453,6 +5462,9 @@ Result depends on variable `org-highlight-latex-and-related'."
|
|||
(append re-latex re-entities re-sub)
|
||||
"\\|"))))
|
||||
|
||||
(defvar org-latex-preview-appearance-options) ; Defined in org-latex-preview.el.
|
||||
(declare-function org-latex-preview--face-around "org-latex-preview" (start end))
|
||||
|
||||
(defun org-do-latex-and-related (limit)
|
||||
"Highlight LaTeX snippets and environments, entities and sub/superscript.
|
||||
Stop at first highlighted object, if any. Return t if some
|
||||
|
@ -5493,6 +5505,17 @@ highlighting was done, nil otherwise."
|
|||
'face 'org-latex-and-related))
|
||||
(add-text-properties (+ offset (match-beginning 0)) (match-end 0)
|
||||
'(font-lock-multiline t))
|
||||
;; Refresh the face of LaTeX previews (when applicable).
|
||||
(when (eq (plist-get org-latex-preview-appearance-options :foreground)
|
||||
'auto)
|
||||
(dolist (ov (overlays-at start))
|
||||
(when (and (eq (overlay-get ov 'org-overlay-type)
|
||||
'org-latex-overlay)
|
||||
(overlay-get ov 'face)
|
||||
(not (eq (overlay-get ov 'face) 'error)))
|
||||
(overlay-put ov 'face
|
||||
(org-latex-preview--face-around
|
||||
(overlay-start ov) (overlay-end ov))))))
|
||||
(throw 'found t)))))
|
||||
nil))))
|
||||
|
||||
|
@ -5653,6 +5676,10 @@ needs to be inserted at a specific position in the font-lock sequence.")
|
|||
(list (concat "\\<" org-clock-string) '(0 'org-special-keyword t))
|
||||
;; Emphasis
|
||||
(when org-fontify-emphasized-text '(org-do-emphasis-faces))
|
||||
;; Semantic seperator
|
||||
(when org-fontify-semantic-seperator
|
||||
`("\u200b"
|
||||
(0 '(face shadow display ,org-semantic-seperator-displayed))))
|
||||
;; Checkboxes
|
||||
`(,org-list-full-item-re 3 'org-checkbox prepend lax)
|
||||
(when (cdr (assq 'checkbox org-list-automatic-rules))
|
||||
|
@ -5773,6 +5800,23 @@ needs to be inserted at a specific position in the font-lock sequence.")
|
|||
(throw 'match t))))
|
||||
nil))))
|
||||
|
||||
(defcustom org-fontify-semantic-seperator t
|
||||
"Whether to prettify the semantic seperator.
|
||||
When non-nil, `org-semantic-seperator-displayed' will be displayed in place of the semantic seperator."
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom org-semantic-seperator-displayed
|
||||
#("┃" 0 1 (display ((raise -0.3) (height 0.3))))
|
||||
"String that should be displayed in place of the semantic seperator.
|
||||
This is only relevant when `org-fontify-semantic-seperator' is non-nil."
|
||||
:type 'string)
|
||||
|
||||
(defun org-toggle-semantic-seperator-display ()
|
||||
"Toggle display of the semantic seperator."
|
||||
(interactive)
|
||||
(cl-callf not org-fontify-semantic-seperator)
|
||||
(user-error "TODO make this work better"))
|
||||
|
||||
(defun org-fontify-like-in-org-mode (s &optional odd-levels)
|
||||
"Fontify string S like in Org mode."
|
||||
(with-temp-buffer
|
||||
|
@ -15553,8 +15597,6 @@ environment remains unintended."
|
|||
|
||||
;;;; LaTeX fragments
|
||||
|
||||
(require 'org-latex-preview)
|
||||
|
||||
(defun org-inside-LaTeX-fragment-p (&optional element)
|
||||
"Test if point is inside a LaTeX fragment or environment.
|
||||
|
||||
|
@ -19101,12 +19143,23 @@ a footnote definition, try to fill the first paragraph within."
|
|||
(save-excursion
|
||||
(goto-char beg)
|
||||
(let ((cuts (list beg)))
|
||||
;; Cut fill on line breaks.
|
||||
(while (re-search-forward "\\\\\\\\[ \t]*\n" end t)
|
||||
(when (org-element-type-p
|
||||
(save-excursion (backward-char)
|
||||
(org-element-context))
|
||||
'line-break)
|
||||
(push (point) cuts)))
|
||||
;; Cut fill on displayed equations.
|
||||
(while (re-search-forward "^[ \t]*\\\\\\[" end t)
|
||||
(let ((el (org-element-context)))
|
||||
(when (eq 'latex-fragment (org-element-type el))
|
||||
(setf cuts (append
|
||||
(list (org-element-property :end el)
|
||||
(- (org-element-property :end el) 2)
|
||||
(+ (org-element-property :begin el) 2)
|
||||
(org-element-property :begin el))
|
||||
cuts)))))
|
||||
(dolist (c (delq end cuts))
|
||||
(fill-region-as-paragraph c end justify)
|
||||
(setq end c))))
|
||||
|
|
364
lisp/ox-html.el
364
lisp/ox-html.el
|
@ -39,6 +39,8 @@
|
|||
(require 'ox)
|
||||
(require 'ox-publish)
|
||||
(require 'table)
|
||||
(require 'org-latex-preview)
|
||||
(require 'ox-mathml)
|
||||
|
||||
|
||||
;;; Function Declarations
|
||||
|
@ -107,7 +109,8 @@
|
|||
(verbatim . org-html-verbatim)
|
||||
(verse-block . org-html-verse-block))
|
||||
:filters-alist '((:filter-options . org-html-infojs-install-script)
|
||||
(:filter-parse-tree . org-html-image-link-filter)
|
||||
(:filter-parse-tree org-html-image-link-filter
|
||||
org-html-prepare-latex-images)
|
||||
(:filter-final-output . org-html-final-function))
|
||||
:menu-entry
|
||||
'(?h "Export to HTML"
|
||||
|
@ -155,6 +158,7 @@
|
|||
(:html-infojs-template nil nil org-html-infojs-template)
|
||||
(:html-inline-image-rules nil nil org-html-inline-image-rules)
|
||||
(:html-link-org-files-as-html nil nil org-html-link-org-files-as-html)
|
||||
(:html-latex-image-options nil nil org-html-latex-image-options)
|
||||
(:html-mathjax-options nil nil org-html-mathjax-options)
|
||||
(:html-mathjax-template nil nil org-html-mathjax-template)
|
||||
(:html-metadata-timestamp-format nil nil org-html-metadata-timestamp-format)
|
||||
|
@ -319,7 +323,7 @@ This affects IDs that are determined from the ID property.")
|
|||
pre.src-awk:before { content: 'Awk'; }
|
||||
pre.src-authinfo::before { content: 'Authinfo'; }
|
||||
pre.src-C:before { content: 'C'; }
|
||||
/* pre.src-C++ doesn't work in CSS */
|
||||
pre.src-C\\+\\+:before { content: 'C++'; }
|
||||
pre.src-clojure:before { content: 'Clojure'; }
|
||||
pre.src-css:before { content: 'CSS'; }
|
||||
pre.src-D:before { content: 'D'; }
|
||||
|
@ -1168,6 +1172,25 @@ See `format-time-string' for more information on its components."
|
|||
:package-version '(Org . "8.0")
|
||||
:type 'string)
|
||||
|
||||
(defcustom org-html-latex-image-options
|
||||
'(:foreground "Black" :background "Transparent"
|
||||
:page-width 1.0 :scale 1.0 :image-dir "ltximg" :inline nil)
|
||||
"LaTeX preview options that apply to generated images.
|
||||
This is a HTML-specific counterpart to
|
||||
`org-latex-preview-appearance-options', which see.
|
||||
|
||||
This supports two extra properties,
|
||||
:image-dir an html-export counterpart of `org-latex-preview-cache', and
|
||||
:inline a list of image formats (or single format symbol) that
|
||||
should not be saved according to :image-dir, but instead
|
||||
inlined in the generated HTML. Valid format symbols are:
|
||||
- png, to inline png images using <img> with a data URI
|
||||
- svg, to inline svg images using <img> with a data URI
|
||||
- svg-embed, to inline svg images using an <svg> element"
|
||||
:group 'org-export-html
|
||||
:package-version '(Org . "9.7")
|
||||
:type 'plist)
|
||||
|
||||
;;;; Template :: Mathjax
|
||||
|
||||
(defcustom org-html-mathjax-options
|
||||
|
@ -1653,6 +1676,31 @@ https://developer.mozilla.org/en-US/docs/Mozilla/Mobile/Viewport_meta_tag"
|
|||
:package-version '(Org . "9.1")
|
||||
:type 'string)
|
||||
|
||||
;;;; LaTeX Fragments
|
||||
|
||||
(defcustom org-latex-to-html-convert-command nil
|
||||
"Command to convert LaTeX fragments to HTML.
|
||||
This command is very open-ended: the output of the command will
|
||||
directly replace the LaTeX fragment in the resulting HTML.
|
||||
Replace format-specifiers in the command as noted below and use
|
||||
`shell-command' to convert LaTeX to HTML.
|
||||
%i: The LaTeX fragment to be converted.
|
||||
|
||||
For example, this could be used with LaTeXML as
|
||||
\"latexmlc \\='literal:%i\\=' --profile=math --preload=siunitx.sty 2>/dev/null\"."
|
||||
:group 'org-latex
|
||||
:package-version '(Org . "9.4")
|
||||
:type '(choice
|
||||
(const :tag "None" nil)
|
||||
(string :tag "Shell command")))
|
||||
|
||||
(defun org-format-latex-as-html (latex-fragment)
|
||||
"Convert LATEX-FRAGMENT to HTML.
|
||||
This uses `org-latex-to-html-convert-command', which see."
|
||||
(let ((cmd (format-spec org-latex-to-html-convert-command
|
||||
`((?i . ,latex-fragment)))))
|
||||
(message "Running %s" cmd)
|
||||
(shell-command-to-string cmd)))
|
||||
|
||||
;;;; Todos
|
||||
|
||||
|
@ -1777,11 +1825,7 @@ a communication channel."
|
|||
(org-html--make-attribute-string
|
||||
(org-combine-plists
|
||||
(list :src source
|
||||
:alt (if (string-match-p
|
||||
(concat "^" org-preview-latex-image-directory) source)
|
||||
(org-html-encode-plain-text
|
||||
(org-find-text-property-in-string 'org-latex-src source))
|
||||
(file-name-nondirectory source)))
|
||||
:alt (file-name-nondirectory source))
|
||||
(if (string= "svg" (file-name-extension source))
|
||||
(org-combine-plists '(:class "org-svg") attributes '(:fallback nil))
|
||||
attributes)))
|
||||
|
@ -2991,58 +3035,102 @@ CONTENTS is nil. INFO is a plist holding contextual information."
|
|||
|
||||
;;;; LaTeX Environment
|
||||
|
||||
(defun org-html-format-latex (latex-frag processing-type info)
|
||||
"Format a LaTeX fragment LATEX-FRAG into HTML.
|
||||
PROCESSING-TYPE designates the tool used for conversion. It can
|
||||
be `mathjax', `verbatim', `html', nil, t or symbols in
|
||||
`org-latex-preview-process-alist', e.g., `dvipng', `dvisvgm' or
|
||||
`imagemagick'. See `org-html-with-latex' for more information.
|
||||
INFO is a plist containing export properties."
|
||||
(let ((cache-relpath "") (cache-dir ""))
|
||||
(unless (or (eq processing-type 'mathjax)
|
||||
(eq processing-type 'html))
|
||||
(let ((bfn (or (buffer-file-name)
|
||||
(make-temp-name
|
||||
(expand-file-name "latex" temporary-file-directory))))
|
||||
(latex-header
|
||||
(let ((header (plist-get info :latex-header)))
|
||||
(and header
|
||||
(concat (mapconcat
|
||||
(lambda (line) (concat "#+LATEX_HEADER: " line))
|
||||
(org-split-string header "\n")
|
||||
"\n")
|
||||
"\n")))))
|
||||
(setq cache-relpath
|
||||
(concat (file-name-as-directory org-preview-latex-image-directory)
|
||||
(file-name-sans-extension
|
||||
(file-name-nondirectory bfn)))
|
||||
cache-dir (file-name-directory bfn))
|
||||
;; Re-create LaTeX environment from original buffer in
|
||||
;; temporary buffer so that dvipng/imagemagick can properly
|
||||
;; turn the fragment into an image.
|
||||
(setq latex-frag (concat latex-header latex-frag))))
|
||||
(org-export-with-buffer-copy
|
||||
:to-buffer (get-buffer-create " *Org HTML Export LaTeX*")
|
||||
:drop-visibility t :drop-narrowing t :drop-contents t
|
||||
(erase-buffer)
|
||||
(insert latex-frag)
|
||||
(org-latex-preview-replace-fragments
|
||||
cache-relpath processing-type cache-dir "Creating LaTeX Image...")
|
||||
(buffer-string))))
|
||||
(defun org-html-prepare-latex-images (parse-tree _backend info)
|
||||
"Make sure that appropriate preview images exist for all LaTeX.
|
||||
TODO."
|
||||
(when (assq (plist-get info :with-latex) org-latex-preview-process-alist)
|
||||
(let* ((latex-preamble
|
||||
(or org-latex-preview--preamble-content
|
||||
(setq org-latex-preview--preamble-content
|
||||
(org-latex-preview--get-preamble))))
|
||||
(elements
|
||||
(org-element-map parse-tree
|
||||
'(latex-fragment latex-environment)
|
||||
#'identity
|
||||
info))
|
||||
(entries-and-numbering
|
||||
(org-latex-preview--construct-entries
|
||||
elements t parse-tree))
|
||||
(processing-type (plist-get info :with-latex))
|
||||
(processing-info
|
||||
(cdr (assq processing-type org-latex-preview-process-alist)))
|
||||
(imagetype (or (plist-get processing-info :image-output-type) "png"))
|
||||
(numbering-offsets (cons nil (cadr entries-and-numbering)))
|
||||
(html-options (plist-get info :html-latex-image-options))
|
||||
(element-hash-table (make-hash-table :test #'eq :size (length elements)))
|
||||
fragment-info prev-fg prev-bg)
|
||||
(cl-loop
|
||||
for entry in (car entries-and-numbering)
|
||||
for element in elements
|
||||
do
|
||||
(pcase-let* ((`(,beg ,end ,provided-value) entry)
|
||||
(value (or provided-value
|
||||
(buffer-substring-no-properties beg end)))
|
||||
(fg (plist-get html-options :foreground))
|
||||
(bg (plist-get html-options :background))
|
||||
(number (car (setq numbering-offsets (cdr numbering-offsets))))
|
||||
(hash (org-latex-preview--hash
|
||||
processing-type latex-preamble value imagetype fg bg number))
|
||||
(options (org-combine-plists
|
||||
org-latex-preview-appearance-options
|
||||
html-options
|
||||
(list :number number
|
||||
:continue-color
|
||||
(and (equal prev-bg bg)
|
||||
(equal prev-fg fg))))))
|
||||
(puthash element hash element-hash-table)
|
||||
(unless (org-latex-preview--get-cached hash)
|
||||
(push (list :string (org-latex-preview--tex-styled
|
||||
processing-type value options)
|
||||
:overlay (org-latex-preview--ensure-overlay beg end)
|
||||
:key hash)
|
||||
fragment-info))
|
||||
(setq prev-fg fg prev-bg bg)))
|
||||
(when fragment-info
|
||||
(apply #'org-async-wait-for
|
||||
(org-latex-preview--create-image-async
|
||||
processing-type
|
||||
(nreverse fragment-info)
|
||||
:latex-preamble latex-preamble
|
||||
:appearance-options html-options)))
|
||||
(plist-put info :html-latex-preview-hash-table element-hash-table)
|
||||
nil)))
|
||||
|
||||
(defun org-html--wrap-latex-environment (contents _ &optional caption label)
|
||||
(defun org-html--as-latex (element info &optional content)
|
||||
(let ((content (or content (org-element-property :value element))))
|
||||
(pcase (plist-get info :with-latex)
|
||||
('verbatim ; Do nothing.
|
||||
content)
|
||||
((or 't 'mathjax)
|
||||
(cond ; Prepare for MathJax processing.
|
||||
((string-match-p "\\`\\$\\$" content)
|
||||
(concat "\\[" (substring content 2 -2) "\\]"))
|
||||
((string-match-p "\\`\\$" content)
|
||||
(concat "\\(" (substring content 1 -1) "\\)"))
|
||||
(t content)))
|
||||
('html
|
||||
(org-format-latex-as-html content))
|
||||
('mathml
|
||||
(if-let ((path (org-mathml-convert-latex-cached content)))
|
||||
(with-temp-buffer
|
||||
(insert-file-contents path)
|
||||
(buffer-string))
|
||||
content))
|
||||
((and ptype (guard (assq ptype org-latex-preview-process-alist)))
|
||||
(org-html-latex-image element info))
|
||||
(processing-type
|
||||
(warn "LaTeX fragment processor `%s' is unknown" processing-type)
|
||||
content))))
|
||||
|
||||
(defun org-html--wrap-latex-environment (contents &optional label)
|
||||
"Wrap CONTENTS string within appropriate environment for equations.
|
||||
When optional arguments CAPTION and LABEL are given, use them for
|
||||
caption and \"id\" attribute."
|
||||
(format "\n<div%s class=\"equation-container\">\n%s%s\n</div>"
|
||||
(format "\n<div%s class=\"equation-container\">\n%s\n</div>"
|
||||
;; ID.
|
||||
(if (org-string-nw-p label) (format " id=\"%s\"" label) "")
|
||||
;; Contents.
|
||||
(format "<span class=\"equation\">\n%s\n</span>" contents)
|
||||
;; Caption.
|
||||
(if (not (org-string-nw-p caption)) ""
|
||||
(format "\n<span class=\"equation-label\">\n%s\n</span>"
|
||||
caption))))
|
||||
(format "<span class=\"equation\">\n%s\n</span>" contents)))
|
||||
|
||||
(defun org-html--math-environment-p (element &optional _)
|
||||
"Non-nil when ELEMENT is a LaTeX math environment.
|
||||
|
@ -3074,57 +3162,141 @@ For instance, change an `equation' environment to `equation*'."
|
|||
"Transcode a LATEX-ENVIRONMENT element from Org to HTML.
|
||||
CONTENTS is nil. INFO is a plist holding contextual information."
|
||||
(let ((processing-type (plist-get info :with-latex))
|
||||
(latex-frag (org-remove-indentation
|
||||
(org-element-property :value latex-environment)))
|
||||
(attributes (org-export-read-attribute :attr_html latex-environment))
|
||||
(label (org-html--reference latex-environment info t))
|
||||
(caption (and (org-html--latex-environment-numbered-p latex-environment)
|
||||
(number-to-string
|
||||
(org-export-get-ordinal
|
||||
latex-environment info nil
|
||||
(lambda (l _)
|
||||
(and (org-html--math-environment-p l)
|
||||
(org-html--latex-environment-numbered-p l))))))))
|
||||
(cond
|
||||
((memq processing-type '(t mathjax))
|
||||
(org-html-format-latex
|
||||
(if (org-string-nw-p label)
|
||||
(replace-regexp-in-string "\\`.*"
|
||||
(format "\\&\n\\\\label{%s}" label)
|
||||
latex-frag)
|
||||
latex-frag)
|
||||
'mathjax info))
|
||||
((assq processing-type org-latex-preview-process-alist)
|
||||
(let ((formula-link
|
||||
(org-html-format-latex
|
||||
(org-html--unlabel-latex-environment latex-frag)
|
||||
processing-type info)))
|
||||
(when (and formula-link (string-match "file:\\([^]]*\\)" formula-link))
|
||||
(let ((source (org-export-file-uri (match-string 1 formula-link))))
|
||||
(org-html--wrap-latex-environment
|
||||
(org-html--format-image source attributes info)
|
||||
info caption label)))))
|
||||
(t (org-html--wrap-latex-environment latex-frag info caption label)))))
|
||||
(latex-frag (org-remove-indentation
|
||||
(org-element-property :value latex-environment)))
|
||||
(label (org-html--reference latex-environment info t)))
|
||||
(if (memq processing-type '(t mathjax))
|
||||
(org-html--as-latex
|
||||
latex-environment info
|
||||
(if (org-string-nw-p label)
|
||||
(replace-regexp-in-string "\\`.*"
|
||||
(format "\\&\n\\\\label{%s}" label)
|
||||
latex-frag)
|
||||
latex-frag))
|
||||
(org-html--wrap-latex-environment
|
||||
(org-html--as-latex latex-environment info latex-frag)
|
||||
label))))
|
||||
|
||||
;;;; LaTeX Fragment
|
||||
|
||||
(defun org-html-latex-fragment (latex-fragment _contents info)
|
||||
"Transcode a LATEX-FRAGMENT object from Org to HTML.
|
||||
CONTENTS is nil. INFO is a plist holding contextual information."
|
||||
(let ((latex-frag (org-element-property :value latex-fragment))
|
||||
(processing-type (plist-get info :with-latex)))
|
||||
(org-html--as-latex latex-fragment info))
|
||||
|
||||
(defun org-html-latex-image (element info)
|
||||
"Transcode the LaTeX fragment or environment ELEMENT from Org to HTML.
|
||||
INFO is a plist holding contextual information, and it is assumed
|
||||
that an image for ELEMENT already exists within it."
|
||||
(let* ((hash (or (gethash element (plist-get info :html-latex-preview-hash-table))
|
||||
(error "Expected LaTeX preview hash to exist for element, but none found")))
|
||||
(path-info (or (org-latex-preview--get-cached hash)
|
||||
(error "Expected LaTeX preview %S to exist in the cache" hash)))
|
||||
(image-options (plist-get info :html-latex-image-options))
|
||||
(block-p (memq (aref (org-element-property :value element) 1) '(?$ ?\[)))
|
||||
(image-source
|
||||
(org-html-latex-image--data path-info hash info block-p)))
|
||||
(unless (and (plist-get (cdr path-info) :height)
|
||||
(plist-get (cdr path-info) :depth))
|
||||
(error "Something went wrong during image generation"))
|
||||
(if (and (eq (plist-get image-options :inline) 'svg-embed)
|
||||
(eq (plist-get (cdr path-info) :image-type) 'svg))
|
||||
image-source
|
||||
(let ((scaling (org-html-latex-image--scaling path-info info)))
|
||||
(org-html-close-tag
|
||||
"img"
|
||||
(org-html--make-attribute-string
|
||||
(list :src image-source
|
||||
:alt (org-html-encode-plain-text
|
||||
(org-element-property :value element))
|
||||
:style (if block-p
|
||||
(format "height: %.4fem; display: block" (plist-get scaling :height))
|
||||
(format "height: %.4fem; vertical-align: -%.4fem; display: inline-block"
|
||||
(plist-get scaling :height) (plist-get scaling :depth)))
|
||||
:class (format "org-latex org-latex-%s" (if block-p "block" "inline"))))
|
||||
info)))))
|
||||
|
||||
(defun org-html-latex-image--scaling (image-path-info info)
|
||||
"Determine the appropriate (<height> . <depth>) of IMAGE-PATH-INFO given INFO."
|
||||
(let* ((image-options (plist-get info :html-latex-image-options))
|
||||
(rescale-factor (if (eq (plist-get (cdr image-path-info) :image-type) 'svg)
|
||||
(plist-get image-options :scale)
|
||||
1)))
|
||||
(list :height (* rescale-factor (plist-get (cdr image-path-info) :height))
|
||||
:depth (* rescale-factor (plist-get (cdr image-path-info) :depth)))))
|
||||
|
||||
(defun org-html-latex-image--data (image-path-info hash info &optional block-p)
|
||||
"Obtaine the image source for IMAGE-PATH-INFO as a string.
|
||||
This can take the form of a path, data URI, or <svg> element
|
||||
depending on HASH and INFO. BLOCK-P signals that the image
|
||||
should be a block element."
|
||||
(let* ((image-options (plist-get info :html-latex-image-options))
|
||||
(inline-condition (plist-get image-options :inline))
|
||||
(image-dir (plist-get image-options :image-dir))
|
||||
(image-format (plist-get (cdr image-path-info) :image-type))
|
||||
(source-file (car image-path-info)))
|
||||
(cond
|
||||
((memq processing-type '(t mathjax))
|
||||
(org-html-format-latex latex-frag 'mathjax info))
|
||||
((memq processing-type '(t html))
|
||||
(org-html-format-latex latex-frag 'html info))
|
||||
((assq processing-type org-latex-preview-process-alist)
|
||||
(let ((formula-link
|
||||
(org-html-format-latex latex-frag processing-type info)))
|
||||
(when (and formula-link (string-match "file:\\([^]]*\\)" formula-link))
|
||||
(let ((source (org-export-file-uri (match-string 1 formula-link))))
|
||||
(org-html--format-image source nil info)))))
|
||||
(t latex-frag))))
|
||||
((or inline-condition
|
||||
(member (file-name-extension source-file)
|
||||
(org-ensure-list inline-condition)))
|
||||
(let ((coding-system-for-read 'utf-8)
|
||||
(file-name-handler-alist nil))
|
||||
(with-temp-buffer
|
||||
(insert-file-contents-literally source-file)
|
||||
(cond
|
||||
((and (eq inline-condition 'svg-embed)
|
||||
(eq image-format 'svg))
|
||||
(goto-char (point-min))
|
||||
(let ((svg-closing-tag (and (search-forward "<svg" nil t)
|
||||
(search-forward ">" nil t))))
|
||||
|
||||
(dolist (search '("<!-- This file was generated by dvisvgm [^\n]+ -->"
|
||||
" height=['\"][^\"']+[\"']"
|
||||
" width=['\"][^\"']+[\"']"))
|
||||
(goto-char (point-min))
|
||||
(when (re-search-forward search svg-closing-tag t)
|
||||
(replace-match "")))
|
||||
(goto-char (point-min))
|
||||
(when (re-search-forward "viewBox=['\"][^\"']+[\"']" svg-closing-tag t)
|
||||
(insert
|
||||
" style=\""
|
||||
(let ((scaling (org-html-latex-image--scaling image-path-info info)))
|
||||
(if block-p
|
||||
(format "height: %.4fem; display: block" (plist-get scaling :height))
|
||||
(format "height: %.4fem; vertical-align: -%.4fem; display: inline-block"
|
||||
(plist-get scaling :height) (plist-get scaling :depth))))
|
||||
"\" class=\"org-latex org-latex-"
|
||||
(if block-p "block" "inline")
|
||||
"\"")))
|
||||
(buffer-string))
|
||||
((eq image-format 'svg)
|
||||
;; Modelled after <https://codepen.io/tigt/post/optimizing-svgs-in-data-uris>.
|
||||
(concat "data:image/svg+xml,"
|
||||
(url-hexify-string
|
||||
(subst-char-in-string ?\" ?\' (buffer-string))
|
||||
'(?a ?b ?c ?d ?e ?f ?g ?h ?i ?j ?k ?l ?m ?n
|
||||
?o ?p ?q ?r ?s ?t ?u ?v ?w ?x ?y ?z ?A ?B
|
||||
?C ?D ?E ?F ?G ?H ?I ?J ?K ?L ?M ?N ?O ?P
|
||||
?Q ?R ?S ?T ?U ?V ?W ?X ?Y ?Z ?0 ?1 ?2 ?3
|
||||
?4 ?5 ?6 ?7 ?8 ?9 ?- ?_ ?. ?~
|
||||
;;Special additions
|
||||
?\s ?= ?: ?/))))
|
||||
(t
|
||||
(base64-encode-region (point-min) (point-max))
|
||||
(goto-char (point-min))
|
||||
(insert "data:image/" (symbol-name image-format) ";base64,")
|
||||
(buffer-string))))))
|
||||
((stringp image-dir)
|
||||
(let* ((image-dir (expand-file-name image-dir))
|
||||
(image-path (file-name-with-extension
|
||||
(file-name-concat image-dir (substring hash 0 11))
|
||||
(file-name-extension source-file))))
|
||||
(unless (file-directory-p image-dir)
|
||||
(mkdir image-dir t))
|
||||
(unless (file-exists-p image-path)
|
||||
(copy-file source-file image-path))
|
||||
image-path))
|
||||
(t source-file))))
|
||||
|
||||
;;;; Line Break
|
||||
|
||||
|
|
293
lisp/ox-latex.el
293
lisp/ox-latex.el
|
@ -48,6 +48,7 @@
|
|||
(defvar engrave-faces-latex-output-style)
|
||||
(defvar engrave-faces-current-preset-style)
|
||||
(defvar engrave-faces-latex-mathescape)
|
||||
(defvar engrave-faces-latex-colorbox-strut)
|
||||
|
||||
|
||||
;;; Define Backend
|
||||
|
@ -1286,9 +1287,10 @@ will produce
|
|||
|
||||
% Define a Code environment to prettily wrap the fontified code.
|
||||
\\usepackage[breakable,xparse]{tcolorbox}
|
||||
\\providecommand{\\codefont}{\\footnotesize}
|
||||
\\DeclareTColorBox[]{Code}{o}%
|
||||
{colback=EfD!98!EFD, colframe=EfD!95!EFD,
|
||||
fontupper=\\footnotesize\\setlength{\\fboxsep}{0pt},
|
||||
fontupper=\\setlength{\\fboxsep}{0pt}\\codefont,
|
||||
colupper=EFD,
|
||||
IfNoValueTF={#1}%
|
||||
{boxsep=2pt, arc=2.5pt, outer arc=2.5pt,
|
||||
|
@ -1312,7 +1314,9 @@ as long as it:
|
|||
In the default value the colors \"EFD\" and \"EfD\" are provided
|
||||
as they are respectively the foreground and background colors,
|
||||
just in case they aren't provided by the generated preamble, so
|
||||
we can assume they are always set.
|
||||
we can assume they are always set. The command \"\\codefont\" is
|
||||
also provided (defaulting to \"\\footnotesize\"), to allow the
|
||||
font used in \"Code\" environments to be easily tweaked.
|
||||
|
||||
Within this preamble there are two recognized macro-like placeholders:
|
||||
|
||||
|
@ -1408,7 +1412,19 @@ default values of which are given by `org-latex-engraved-preamble' and
|
|||
(alist-get 'default
|
||||
(if theme
|
||||
(engrave-faces-get-theme (intern theme))
|
||||
engrave-faces-current-preset-style)))))))
|
||||
engrave-faces-current-preset-style))))))
|
||||
(gen-theme-command
|
||||
(lambda (theme)
|
||||
(format "\n\\newcommand{\\engravedtheme%s}{%%\n%s\n}"
|
||||
(replace-regexp-in-string
|
||||
"[^A-Za-z]" "" (symbol-name theme))
|
||||
(replace-regexp-in-string
|
||||
"\\\\newcommand\\\\efstrut[^\n]*\n" ""
|
||||
(replace-regexp-in-string
|
||||
"\\\\newcommand{\\(.+?\\)}\\[1\\]" "\\\\long\\\\def\\1##1"
|
||||
(replace-regexp-in-string
|
||||
"#1" "##1"
|
||||
(funcall gen-theme-spec theme))))))))
|
||||
(when (stringp engraved-theme)
|
||||
(setq engraved-theme (intern engraved-theme)))
|
||||
(when (string-match "^[ \t]*\\[FVEXTRA-SETUP\\][ \t]*\n?" engraved-preamble)
|
||||
|
@ -1443,26 +1459,24 @@ default values of which are given by `org-latex-engraved-preamble' and
|
|||
(if (require 'engrave-faces-latex nil t)
|
||||
(if engraved-themes
|
||||
(concat
|
||||
;; We don't want to re-define the efstrut, so we now need to
|
||||
;; define it seperately.
|
||||
(format "\\newcommand\\efstrut{%s}\n\n"
|
||||
engrave-faces-latex-colorbox-strut)
|
||||
;; Define default theme
|
||||
(funcall gen-theme-command engraved-theme)
|
||||
"\n"
|
||||
;; Define other themes
|
||||
(mapconcat
|
||||
(lambda (theme)
|
||||
(format
|
||||
"\n\\newcommand{\\engravedtheme%s}{%%\n%s\n}"
|
||||
(replace-regexp-in-string "[^A-Za-z]" "" (symbol-name theme))
|
||||
(replace-regexp-in-string
|
||||
"newcommand" "renewcommand"
|
||||
(replace-regexp-in-string
|
||||
"#" "##"
|
||||
(funcall gen-theme-spec theme)))))
|
||||
engraved-themes
|
||||
gen-theme-command
|
||||
(cl-remove-if (lambda (theme) (string= theme (symbol-name engraved-theme)))
|
||||
engraved-themes)
|
||||
"\n")
|
||||
"\n\n"
|
||||
(cond
|
||||
((memq engraved-theme engraved-themes)
|
||||
(concat "\\engravedtheme"
|
||||
(replace-regexp-in-string
|
||||
"[^A-Za-z]" "" engraved-theme)
|
||||
"\n"))
|
||||
(t (funcall gen-theme-spec engraved-theme))))
|
||||
;; Load the default theme
|
||||
"\n\n\\engravedtheme"
|
||||
(replace-regexp-in-string
|
||||
"[^A-Za-z]" "" (symbol-name engraved-theme))
|
||||
"\n")
|
||||
(funcall gen-theme-spec engraved-theme))
|
||||
(warn "Cannot engrave source blocks. Consider installing `engrave-faces'.")
|
||||
"% WARNING syntax highlighting unavailable as engrave-faces-latex was missing.\n")
|
||||
|
@ -1478,7 +1492,13 @@ default values of which are given by `org-latex-engraved-preamble' and
|
|||
(bibliography-biblatex
|
||||
:condition (eq (org-cite-processor info) 'biblatex)
|
||||
:when bibliography
|
||||
:snippet org-cite-biblatex--generate-latex-preamble)
|
||||
:snippet org-cite-biblatex--generate-latex-usepackage)
|
||||
(bibliography-biblatex-resources
|
||||
:condition (eq (org-cite-processor info) 'biblatex)
|
||||
:when bibliography
|
||||
:snippet org-cite-biblatex--generate-latex-bibresources
|
||||
:no-precompile t
|
||||
:order 90)
|
||||
(bibliography-natbib
|
||||
:condition (eq (org-cite-processor info) 'natbib)
|
||||
:when bibliography
|
||||
|
@ -2072,7 +2092,13 @@ specified in `org-latex-default-packages-alist' or
|
|||
"^[ \t]*\\\\documentclass\\(\\(\\[[^]]*\\]\\)?\\)"
|
||||
class-options header t nil 1))))
|
||||
(user-error "Unknown LaTeX class `%s'" class)))
|
||||
generated-preamble)
|
||||
(header-split (format "\n%%--org-latex-header-temp-split-%d--\n" (random 10000)))
|
||||
(header (concat (org-element-normalize-string (plist-get info :latex-header))
|
||||
header-split
|
||||
(and (not snippet?)
|
||||
(org-element-normalize-string
|
||||
(plist-get info :latex-header-extra)))))
|
||||
generated-preamble preamble-nonprecompilable)
|
||||
(plist-put info :latex-full-header
|
||||
(org-element-normalize-string
|
||||
(org-splice-latex-header
|
||||
|
@ -2080,32 +2106,79 @@ specified in `org-latex-default-packages-alist' or
|
|||
(org-latex--remove-packages org-latex-default-packages-alist info)
|
||||
(org-latex--remove-packages org-latex-packages-alist info)
|
||||
snippet?
|
||||
(mapconcat #'org-element-normalize-string
|
||||
(list (plist-get info :latex-header)
|
||||
(and (not snippet?)
|
||||
(plist-get info :latex-header-extra)))
|
||||
""))))
|
||||
(setq generated-preamble
|
||||
(if snippet?
|
||||
header)))
|
||||
(if snippet?
|
||||
(setq generated-preamble
|
||||
(progn
|
||||
(org-latex-guess-inputenc info)
|
||||
(org-latex-guess-babel-language info)
|
||||
(org-latex-guess-polyglossia-language info)
|
||||
"\n% Generated preamble omitted for snippets.")
|
||||
"\n% Generated preamble omitted for snippets."))
|
||||
(let (impl-precomp impl-noprecomp)
|
||||
(dolist (impl (plist-get info :feature-implementations))
|
||||
(message "LaTeX feature: %s" (car impl))
|
||||
(if (or impl-noprecomp (plist-get (cdr impl) :no-precompile))
|
||||
(push impl impl-noprecomp)
|
||||
(push impl impl-precomp)))
|
||||
(message "Precomp feats: %S" (reverse (mapcar #'car impl-precomp)))
|
||||
(message "No precomp feats: %S" (reverse (mapcar #'car impl-noprecomp)))
|
||||
(setq generated-preamble
|
||||
(string-join
|
||||
(org-export-expand-feature-snippets
|
||||
info (nreverse impl-precomp))
|
||||
"\n\n")
|
||||
preamble-nonprecompilable
|
||||
(string-join
|
||||
(org-export-expand-feature-snippets
|
||||
info (nreverse impl-noprecomp))
|
||||
"\n\n"))))
|
||||
(let* ((header-parts
|
||||
(split-string (plist-get info :latex-full-header)
|
||||
(regexp-quote header-split)))
|
||||
(header-main (car header-parts))
|
||||
(header-extra (cadr header-parts))
|
||||
(preamble
|
||||
(concat
|
||||
(org-latex--insert-compiler info)
|
||||
header-main
|
||||
"\n"
|
||||
(string-join
|
||||
(org-export-expand-feature-snippets info)
|
||||
"\n\n")
|
||||
"\n")))
|
||||
(concat
|
||||
;; Time-stamp.
|
||||
(and (plist-get info :time-stamp-file)
|
||||
(format-time-string "%% Created %Y-%m-%d %a %H:%M\n"))
|
||||
;; LaTeX compiler.
|
||||
(org-latex--insert-compiler info)
|
||||
(plist-get info :latex-full-header)
|
||||
generated-preamble)))
|
||||
generated-preamble
|
||||
"\n"))
|
||||
(format-file
|
||||
(and org-latex-precompile
|
||||
;; Precompilation is disabled for xelatex/lualatex for now.
|
||||
(if (member (plist-get info :latex-compiler)
|
||||
'("xelatex" "lualatex"))
|
||||
(progn
|
||||
(display-warning
|
||||
'(org latex-export disable-local-precompile)
|
||||
(format "%s does not support precompilation, disabling LaTeX precompile in this buffer.\n To re-enable, run `(setq-local org-latex-precompile t)' or reopen this buffer."
|
||||
(plist-get info :latex-compiler)))
|
||||
(setf (buffer-local-value
|
||||
'org-latex-precompile (get-buffer (plist-get info :input-buffer)))
|
||||
nil))
|
||||
(org-latex--precompile
|
||||
info preamble
|
||||
(string-match-p "\\(?:\\\\input{\\|\\\\include{\\)[^/]" preamble))))))
|
||||
(when (and format-file (not snippet?))
|
||||
(let ((preamble-parts (split-string preamble (regexp-quote header-split))))
|
||||
(setq preamble (car preamble-parts)
|
||||
preamble-nonprecompilable
|
||||
(concat preamble-nonprecompilable
|
||||
(cadr preamble-parts)))))
|
||||
(concat (and format-file
|
||||
(concat "%& " (file-name-sans-extension format-file) "\n"))
|
||||
(and (plist-get info :time-stamp-file)
|
||||
(format-time-string "%% Created %Y-%m-%d %a %H:%M\n"))
|
||||
preamble
|
||||
(and format-file
|
||||
"\n% end precompiled preamble\n\\ifcsname endofdump\\endcsname\\endofdump\\fi\n")
|
||||
"\n"
|
||||
preamble-nonprecompilable
|
||||
(and preamble-nonprecompilable
|
||||
(not (string-empty-p preamble-nonprecompilable))
|
||||
"\n")
|
||||
header-extra))))
|
||||
|
||||
(defun org-latex-template (contents info)
|
||||
"Return complete document string after LaTeX conversion.
|
||||
|
@ -2178,6 +2251,118 @@ holding export options."
|
|||
;; Document end.
|
||||
"\\end{document}")))
|
||||
|
||||
(defvar org-latex-precompile t
|
||||
"Precompile the preamble during export.
|
||||
This requires the LaTeX package \"mylatexformat\" to be installed.")
|
||||
|
||||
(defconst org-latex--precompile-log "*Org LaTeX Precompilation*")
|
||||
|
||||
(defvar org-latex-precompile-command
|
||||
"%l -output-directory %o -ini -jobname=%b \"&%L\" mylatexformat.ltx %f")
|
||||
|
||||
(defvar org-latex-precompile-compiler-map
|
||||
'(("pdflatex" . "latex")
|
||||
("xelatex" . "xelatex -no-pdf")
|
||||
("lualatex" . "dvilualatex")))
|
||||
|
||||
(defun org-latex--precompile (info preamble &optional tempfile-p)
|
||||
"Precompile/dump LaTeX PREAMBLE text.
|
||||
|
||||
The path to the format file (.fmt) is returned. If the format
|
||||
file could not be found in the persist cache, it is generated
|
||||
according to PROCESSING-INFO and stored. INFO is a plist used as
|
||||
a communication channel.
|
||||
|
||||
If TEMPFILE-P is non-nil, then it is assumed the preamble does
|
||||
not contain any relative references to other files.
|
||||
|
||||
This is intended to speed up Org's LaTeX preview generation
|
||||
process."
|
||||
(let ((preamble-hash
|
||||
(thread-first
|
||||
preamble
|
||||
(concat
|
||||
(plist-get info :latex-compiler)
|
||||
(if tempfile-p "-temp"
|
||||
default-directory))
|
||||
(sha1)))
|
||||
(default-directory
|
||||
(if tempfile-p temporary-file-directory default-directory)))
|
||||
(or (cadr
|
||||
(org-persist-read "LaTeX format file cache"
|
||||
(list :key preamble-hash)
|
||||
nil nil :read-related t))
|
||||
(when-let ((dump-file
|
||||
(org-latex--precompile-preamble
|
||||
info preamble (expand-file-name preamble-hash temporary-file-directory))))
|
||||
(cadr
|
||||
(org-persist-register `(,"LaTeX format file cache"
|
||||
(file ,dump-file))
|
||||
(list :key preamble-hash)
|
||||
:write-immediately t))))))
|
||||
|
||||
(defun org-latex--remove-cached-preamble (latex-compiler preamble &optional tempfile-p)
|
||||
"Remove the cached preamble file for PREAMBLE compiled with LATEX-COMPILER.
|
||||
TEMPFILE-P should be set to mirror the caching `org-latex--precompile' call
|
||||
which is intended to be evicted from the cache."
|
||||
(let ((preamble-hash
|
||||
(thread-first
|
||||
preamble
|
||||
(concat
|
||||
latex-compiler
|
||||
(if tempfile-p "-temp"
|
||||
default-directory))
|
||||
(sha1))))
|
||||
(org-persist-unregister "LaTeX format file cache"
|
||||
(list :key preamble-hash)
|
||||
:remove-related t)))
|
||||
|
||||
(defun org-latex--precompile-preamble (info preamble basepath)
|
||||
"Precompile PREAMBLE with \"mylatexformat\".
|
||||
The PREAMBLE string is placed in BASEPATH.tex and compiled
|
||||
according to PROCESSING-INFO. If compilation and dumping
|
||||
succeeded, BASEPATH.fmt will be returned.
|
||||
|
||||
Should any errors occur during compilation, nil will be returned,
|
||||
and appropriate warnings may be emitted."
|
||||
(let ((dump-file (concat basepath ".fmt"))
|
||||
(preamble-file (concat basepath ".tex"))
|
||||
(precompile-buffer
|
||||
(with-current-buffer
|
||||
(get-buffer-create org-latex--precompile-log)
|
||||
(erase-buffer)
|
||||
(current-buffer))))
|
||||
(with-temp-file preamble-file
|
||||
(insert preamble "\n\\endofdump\n"))
|
||||
(message "Precompiling Org LaTeX preamble...")
|
||||
(condition-case nil
|
||||
(org-compile-file
|
||||
preamble-file (list org-latex-precompile-command)
|
||||
"fmt" nil precompile-buffer
|
||||
(or (plist-get info :precompile-format-spec)
|
||||
`((?l . ,(plist-get info :latex-compiler))
|
||||
(?L . ,(plist-get info :latex-compiler)))))
|
||||
(:success
|
||||
(kill-buffer precompile-buffer)
|
||||
(delete-file preamble-file)
|
||||
dump-file)
|
||||
(error
|
||||
(unless (= 0 (call-process "kpsewhich" nil nil nil "mylatexformat.ltx"))
|
||||
(display-warning
|
||||
'(org latex-preview preamble-precompilation)
|
||||
"The LaTeX package \"mylatexformat\" is required for precompilation, but could not be found")
|
||||
:warning)
|
||||
(unless (= 0 (call-process "kpsewhich" nil nil nil "preview.sty"))
|
||||
(display-warning
|
||||
'(org latex-preview preamble-precompilation)
|
||||
"The LaTeX package \"preview\" is required for precompilation, but could not be found")
|
||||
:warning)
|
||||
(display-warning
|
||||
'(org latex-preview preamble-precompilation)
|
||||
(format "Failed to precompile preamble (%s), see the \"%s\" buffer."
|
||||
preamble-file precompile-buffer)
|
||||
:warning)
|
||||
nil))))
|
||||
|
||||
|
||||
;;; Transcode Functions
|
||||
|
@ -2562,8 +2747,11 @@ INFO, CODE, and LANG are provided by `org-latex-inline-src-block'."
|
|||
(defun org-latex-inline-src-block--engraved (info code lang)
|
||||
"Transcode an inline src block's content from Org to LaTeX, using engrave-faces.
|
||||
INFO, CODE, and LANG are provided by `org-latex-inline-src-block'."
|
||||
(org-latex-src--engrave-code
|
||||
code lang nil (plist-get info :latex-engraved-options) t))
|
||||
(let ((engraved-theme (plist-get info :latex-engraved-theme)))
|
||||
(org-latex-src--engrave-code
|
||||
code lang
|
||||
(and engraved-theme (intern engraved-theme)) nil
|
||||
(plist-get info :latex-engraved-options) t)))
|
||||
|
||||
(defun org-latex-inline-src-block--listings (info code lang)
|
||||
"Transcode an inline src block's content from Org to LaTeX, using lstlistings.
|
||||
|
@ -3608,7 +3796,7 @@ and FLOAT are extracted from SRC-BLOCK and INFO in `org-latex-src-block'."
|
|||
(when (eq mathescape 'yes)
|
||||
(or engrave-faces-latex-mathescape t)))))
|
||||
|
||||
(defun org-latex-src--engrave-code (content lang &optional theme options inline)
|
||||
(defun org-latex-src--engrave-code (content lang &optional theme explicit-theme-p options inline)
|
||||
"Engrave CONTENT to LaTeX in a LANG-mode buffer, and give the result.
|
||||
When the THEME symbol is non-nil, that theme will be used.
|
||||
|
||||
|
@ -3649,12 +3837,12 @@ to the Verbatim environment or Verb command."
|
|||
(concat "\\begin{Code}\n\\begin{Verbatim}" engraved-options "\n"
|
||||
engraved-code "\n\\end{Verbatim}\n\\end{Code}"))))
|
||||
(kill-buffer engraved-buffer)
|
||||
(if theme
|
||||
(concat "{\\engravedtheme"
|
||||
(if (and theme explicit-theme-p)
|
||||
(concat "\\begingroup\\engravedtheme"
|
||||
(replace-regexp-in-string "[^A-Za-z]" ""
|
||||
(symbol-name theme))
|
||||
engraved-wrapped
|
||||
"}")
|
||||
"\\endgroup")
|
||||
engraved-wrapped))
|
||||
(user-error "Cannot engrave code as `engrave-faces-latex' is unavailable.")))
|
||||
|
||||
|
@ -3688,7 +3876,9 @@ and FLOAT are extracted from SRC-BLOCK and INFO in `org-latex-src-block'."
|
|||
`(("linenos")
|
||||
("firstnumber" ,(number-to-string (1+ num-start)))))
|
||||
(and local-options `((,local-options))))))
|
||||
(engraved-theme (plist-get attributes :engraved-theme))
|
||||
(engraved-doc-theme (plist-get info :latex-engraved-theme))
|
||||
(engraved-theme (or (plist-get attributes :engraved-theme)
|
||||
engraved-doc-theme))
|
||||
(content
|
||||
(let* ((code-info (org-export-unravel-code src-block))
|
||||
(max-width
|
||||
|
@ -3714,7 +3904,8 @@ and FLOAT are extracted from SRC-BLOCK and INFO in `org-latex-src-block'."
|
|||
(org-latex-src--engrave-mathescape-p info options)))
|
||||
(org-latex-src--engrave-code
|
||||
content lang
|
||||
(when engraved-theme (intern engraved-theme))
|
||||
(and engraved-theme (intern engraved-theme))
|
||||
(not (eq engraved-theme engraved-doc-theme))
|
||||
options))))
|
||||
(concat (car float-env) body (cdr float-env))))
|
||||
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
;;; ox-mathml.el --- Support for MathML exports -*- lexical-binding: t; -*-
|
||||
;;
|
||||
;; Copyright (C) 2023 TEC
|
||||
;;
|
||||
;; Author: TEC <contact@tecosaur.net>
|
||||
;; Maintainer: TEC <contact@tecosaur.net>
|
||||
;; Created: February 27, 2023
|
||||
;; Modified: February 27, 2023
|
||||
;; Version: 0.0.1
|
||||
;; Keywords: abbrev bib c calendar comm convenience data docs emulations extensions faces files frames games hardware help hypermedia i18n internal languages lisp local maint mail matching mouse multimedia news outlines processes terminals tex tools unix vc wp
|
||||
;; Homepage: https://github.com/tecosaur/ox-mathml
|
||||
;; Package-Requires: ((emacs "24.3"))
|
||||
;;
|
||||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; Support for MathML exports
|
||||
;;
|
||||
;;; Code:
|
||||
|
||||
(defgroup org-mathml nil
|
||||
"Options for generation of MathML representations of LaTeX math."
|
||||
:tag "Org MathML export"
|
||||
:group 'org-export)
|
||||
|
||||
(defcustom org-mathml-converter-jar-file nil
|
||||
"Value of\"%j\" in `org-mathml-convert-command'.
|
||||
Use this to specify additional executable file say a jar file.
|
||||
|
||||
When using MathToWeb as the converter, specify the full-path to
|
||||
your mathtoweb.jar file."
|
||||
:group 'org-mathml
|
||||
:version "24.1"
|
||||
:type '(choice
|
||||
(const :tag "None" nil)
|
||||
(file :tag "JAR file" :must-match t)))
|
||||
|
||||
(defcustom org-mathml-convert-command nil
|
||||
"Command to convert LaTeX fragments to MathML.
|
||||
Replace format-specifiers in the command as noted below and use
|
||||
`shell-command' to convert LaTeX to MathML.
|
||||
%j: Executable file in fully expanded form as specified by
|
||||
`org-latex-to-mathml-jar-file'.
|
||||
%I: Input LaTeX file in fully expanded form.
|
||||
%i: The latex fragment to be converted.
|
||||
%o: Output MathML file.
|
||||
|
||||
This command is used by `org-mathml-convert-latex'.
|
||||
|
||||
When using MathToWeb as the converter, set this option to
|
||||
\"java -jar %j -unicode -force -df %o %I\".
|
||||
|
||||
When using LaTeXML set this option to
|
||||
\"latexmlmath \"%i\" --preload=amsmath.sty --preload=amssymb.sty --presentationmathml=%o\"."
|
||||
:group 'org-mathml
|
||||
:version "24.1"
|
||||
:type '(choice
|
||||
(const :tag "None" nil)
|
||||
(string :tag "\nShell command")))
|
||||
|
||||
(defun org-mathml-converter-available-p ()
|
||||
"Return t if `org-mathml-convert-command' is usable."
|
||||
(save-match-data
|
||||
(when (and (boundp 'org-mathml-convert-command)
|
||||
org-mathml-convert-command)
|
||||
(let ((executable (car (split-string
|
||||
org-mathml-convert-command))))
|
||||
(when (executable-find executable)
|
||||
(if (string-match
|
||||
"%j" org-mathml-convert-command)
|
||||
(file-readable-p org-mathml-converter-jar-file)
|
||||
t))))))
|
||||
|
||||
(defun org-mathml-convert-latex (latex-frag &optional mathml-file)
|
||||
"Convert LATEX-FRAG to MathML and store it in MATHML-FILE.
|
||||
Use `org-latex-to-mathml-convert-command'. If the conversion is
|
||||
successful, return the portion between \"<math...> </math>\"
|
||||
elements otherwise return nil. When MATHML-FILE is specified,
|
||||
write the results in to that file. When invoked as an
|
||||
interactive command, prompt for LATEX-FRAG, with initial value
|
||||
set to the current active region and echo the results for user
|
||||
inspection."
|
||||
(interactive (list (let ((frag (when (org-region-active-p)
|
||||
(buffer-substring-no-properties
|
||||
(region-beginning) (region-end)))))
|
||||
(read-string "LaTeX Fragment: " frag nil frag))))
|
||||
(unless latex-frag (user-error "Invalid LaTeX fragment"))
|
||||
(let* ((tmp-in-file
|
||||
(let ((file (file-relative-name
|
||||
(make-temp-name (expand-file-name "ltxmathml-in")))))
|
||||
(write-region latex-frag nil file)
|
||||
file))
|
||||
(tmp-out-file (file-relative-name
|
||||
(make-temp-name (expand-file-name "ltxmathml-out"))))
|
||||
(cmd (format-spec
|
||||
org-mathml-convert-command
|
||||
`((?j . ,(and org-mathml-converter-jar-file
|
||||
(shell-quote-argument
|
||||
(expand-file-name
|
||||
org-mathml-converter-jar-file))))
|
||||
(?I . ,(shell-quote-argument tmp-in-file))
|
||||
(?i . ,latex-frag)
|
||||
(?o . ,(shell-quote-argument tmp-out-file)))))
|
||||
mathml shell-command-output)
|
||||
(when (called-interactively-p 'any)
|
||||
(unless (org-mathml-converter-available-p)
|
||||
(user-error "LaTeX to MathML converter not configured")))
|
||||
(message "Running %s" cmd)
|
||||
(setq shell-command-output (shell-command-to-string cmd))
|
||||
(setq mathml
|
||||
(when (file-readable-p tmp-out-file)
|
||||
(with-current-buffer (find-file-noselect tmp-out-file t)
|
||||
(goto-char (point-min))
|
||||
(when (re-search-forward
|
||||
(format "<math[^>]*?%s[^>]*?>\\(.\\|\n\\)*</math>"
|
||||
(regexp-quote
|
||||
"xmlns=\"http://www.w3.org/1998/Math/MathML\""))
|
||||
nil t)
|
||||
(prog1 (match-string 0) (kill-buffer))))))
|
||||
(cond
|
||||
(mathml
|
||||
(setq mathml
|
||||
(concat "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" mathml))
|
||||
(when mathml-file
|
||||
(write-region mathml nil mathml-file))
|
||||
(when (called-interactively-p 'any)
|
||||
(message mathml)))
|
||||
((warn "LaTeX to MathML conversion failed")
|
||||
(message shell-command-output)))
|
||||
(delete-file tmp-in-file)
|
||||
(when (file-exists-p tmp-out-file)
|
||||
(delete-file tmp-out-file))
|
||||
mathml))
|
||||
|
||||
(defun org-mathml-convert-latex-cached (latex-frag)
|
||||
"Use `org-mathml-convert-latex' but check local cache first."
|
||||
(let ((latex-hash-path
|
||||
(expand-file-name
|
||||
(concat
|
||||
"org-mathml-formula-"
|
||||
(sha1
|
||||
(prin1-to-string
|
||||
(list latex-frag
|
||||
org-mathml-convert-command)))
|
||||
".mathml")
|
||||
temporary-file-directory))
|
||||
print-length print-level)
|
||||
(unless (file-exists-p latex-hash-path)
|
||||
(org-mathml-convert-latex latex-frag latex-hash-path))
|
||||
(and (file-exists-p latex-hash-path)
|
||||
latex-hash-path)))
|
||||
|
||||
(provide 'ox-mathml)
|
||||
;;; ox-mathml.el ends here
|
249
lisp/ox-odt.el
249
lisp/ox-odt.el
|
@ -34,6 +34,7 @@
|
|||
(require 'org-macs)
|
||||
(require 'ox)
|
||||
(require 'table nil 'noerror)
|
||||
(require 'ox-mathml)
|
||||
|
||||
(declare-function org-at-heading-p "org" (&optional _))
|
||||
(declare-function org-back-to-heading "org" (&optional invisible-ok))
|
||||
|
@ -3711,113 +3712,147 @@ contextual information."
|
|||
|
||||
(defun org-odt--translate-latex-fragments (tree _backend info)
|
||||
(let ((processing-type (plist-get info :with-latex))
|
||||
(count 0)
|
||||
(count 0)
|
||||
(warning nil))
|
||||
;; Normalize processing-type to one of dvipng, mathml or verbatim.
|
||||
;; If the desired converter is not available, force verbatim
|
||||
;; processing.
|
||||
(cl-case processing-type
|
||||
((t mathml)
|
||||
(if (and (fboundp 'org-format-latex-mathml-available-p)
|
||||
(org-format-latex-mathml-available-p))
|
||||
(setq processing-type 'mathml)
|
||||
(setq warning "`org-odt-with-latex': LaTeX to MathML converter not available. Falling back to verbatim.")
|
||||
(setq processing-type 'verbatim)))
|
||||
((dvipng imagemagick)
|
||||
(unless (and (org-check-external-command "latex" "" t)
|
||||
(org-check-external-command
|
||||
(if (eq processing-type 'dvipng) "dvipng" "convert") "" t))
|
||||
(setq warning "`org-odt-with-latex': LaTeX to PNG converter not available. Falling back to verbatim.")
|
||||
(setq processing-type 'verbatim)))
|
||||
(otherwise
|
||||
(setq warning "`org-odt-with-latex': Unknown LaTeX option. Forcing verbatim.")
|
||||
(setq processing-type 'verbatim)))
|
||||
|
||||
;; Display warning if the selected PROCESSING-TYPE is not
|
||||
;; available, but there are fragments to be converted.
|
||||
(when warning
|
||||
(org-element-map tree '(latex-fragment latex-environment)
|
||||
(lambda (_) (warn warning))
|
||||
info 'first-match nil t))
|
||||
|
||||
;; Store normalized value for later use.
|
||||
(when (plist-get info :with-latex)
|
||||
(plist-put info :with-latex processing-type))
|
||||
(message "Formatting LaTeX using %s" processing-type)
|
||||
|
||||
;; Convert `latex-fragment's and `latex-environment's.
|
||||
(when (memq processing-type '(mathml dvipng imagemagick))
|
||||
(org-element-map tree '(latex-fragment latex-environment)
|
||||
(lambda (latex-*)
|
||||
(cl-incf count)
|
||||
(let* ((latex-frag (org-element-property :value latex-*))
|
||||
(input-file (plist-get info :input-file))
|
||||
(cache-dir (file-name-directory input-file))
|
||||
(cache-subdir (concat
|
||||
(cl-case processing-type
|
||||
((dvipng imagemagick)
|
||||
org-preview-latex-image-directory)
|
||||
(mathml "ltxmathml/"))
|
||||
(file-name-sans-extension
|
||||
(file-name-nondirectory input-file))))
|
||||
(display-msg
|
||||
(cl-case processing-type
|
||||
((dvipng imagemagick)
|
||||
(format "Creating LaTeX Image %d..." count))
|
||||
(mathml (format "Creating MathML snippet %d..." count))))
|
||||
;; Get an Org-style link to PNG image or the MathML
|
||||
;; file.
|
||||
(link
|
||||
(with-temp-buffer
|
||||
(insert latex-frag)
|
||||
(delay-mode-hooks (let ((org-inhibit-startup t)) (org-mode)))
|
||||
;; When converting to a PNG image, make sure to
|
||||
;; copy all LaTeX header specifications from the
|
||||
;; Org source.
|
||||
(unless (eq processing-type 'mathml)
|
||||
(let ((h (plist-get info :latex-header)))
|
||||
(when h
|
||||
(insert "\n"
|
||||
(replace-regexp-in-string
|
||||
"^" "#+LATEX_HEADER: " h)))))
|
||||
(org-latex-preview-replace-fragments
|
||||
cache-subdir processing-type cache-dir display-msg)
|
||||
(goto-char (point-min))
|
||||
(skip-chars-forward " \t\n")
|
||||
(org-element-link-parser))))
|
||||
(if (not (org-element-type-p link 'link))
|
||||
(message "LaTeX Conversion failed.")
|
||||
;; Conversion succeeded. Parse above Org-style link to
|
||||
;; a `link' object.
|
||||
(let ((replacement
|
||||
(cl-case (org-element-type latex-*)
|
||||
;;LaTeX environment. Mimic a "standalone image
|
||||
;; or formula" by enclosing the `link' in
|
||||
;; a `paragraph'. Copy over original
|
||||
;; attributes, captions to the enclosing
|
||||
;; paragraph.
|
||||
(latex-environment
|
||||
(org-element-adopt
|
||||
(list 'paragraph
|
||||
(list :style "OrgFormula"
|
||||
:name
|
||||
(org-element-property :name latex-*)
|
||||
:caption
|
||||
(org-element-property :caption latex-*)))
|
||||
link))
|
||||
;; LaTeX fragment. No special action.
|
||||
(latex-fragment link))))
|
||||
;; Note down the object that link replaces.
|
||||
(org-element-put-property replacement :replaces
|
||||
(list (org-element-type latex-*)
|
||||
(list :value latex-frag)))
|
||||
;; Restore blank after initial element or object.
|
||||
(org-element-put-property
|
||||
replacement :post-blank
|
||||
(org-element-property :post-blank latex-*))
|
||||
;; Replace now.
|
||||
(org-element-set latex-* replacement)))))
|
||||
info nil nil t)))
|
||||
;; MathML will be handled seperately.
|
||||
(if (and (memq processing-type '(t mathml))
|
||||
(fboundp 'org-format-latex-mathml-available-p)
|
||||
(org-format-latex-mathml-available-p)
|
||||
(plist-put info :with-latex 'mathml))
|
||||
(org-element-map tree '(latex-fragment latex-environment)
|
||||
(lambda (latex)
|
||||
(cl-incf count)
|
||||
(if-let ((latex-frag (org-element-property :value latex))
|
||||
(path (org-mathml-convert-latex-cached latex-frag))
|
||||
(link (list 'link
|
||||
(list :type "file"
|
||||
:path path
|
||||
:format 'bracket
|
||||
:raw-link (format "file:%s" path))))
|
||||
(replacement
|
||||
(if (eq (org-element-type latex) 'latex-environment)
|
||||
;;LaTeX environment. Mimic a "standalone image
|
||||
;; or formula" by enclosing the `link' in
|
||||
;; a `paragraph'. Copy over original
|
||||
;; attributes, captions to the enclosing
|
||||
;; paragraph.
|
||||
(org-element-adopt-elements
|
||||
(list 'paragraph
|
||||
(list :style "OrgFormula"
|
||||
:name
|
||||
(org-element-property :name latex)
|
||||
:caption
|
||||
(org-element-property :caption latex)))
|
||||
link)
|
||||
link)))
|
||||
(progn
|
||||
;; Note down the object that link replaces.
|
||||
(org-element-put-property replacement :replaces
|
||||
(list (org-element-type latex)
|
||||
(list :value latex-frag)))
|
||||
;; Restore blank after initial element or object.
|
||||
(org-element-put-property
|
||||
replacement :post-blank
|
||||
(org-element-property :post-blank latex))
|
||||
;; Replace now.
|
||||
(org-element-set-element latex replacement))
|
||||
(setq warning "Conversion of LaTeX to MathML failed. Falling back to verbatim.")))
|
||||
info nil nil)
|
||||
;; Normalize processing-type to one of dvipng or verbatim.
|
||||
;; If the desired converter is not available, force verbatim
|
||||
;; processing.
|
||||
(cl-case processing-type
|
||||
((t mathml)
|
||||
(setq warning "LaTeX to MathML converter not available. Falling back to verbatim."
|
||||
processing-type 'verbatim))
|
||||
((dvipng imagemagick)
|
||||
(unless (and (org-check-external-command "latex" "" t)
|
||||
(org-check-external-command
|
||||
(if (eq processing-type 'dvipng) "dvipng" "convert") "" t))
|
||||
(setq warning "LaTeX to PNG converter not available. Falling back to verbatim."
|
||||
processing-type 'verbatim)))
|
||||
(otherwise
|
||||
(setq warning "Unknown LaTeX option. Forcing verbatim."
|
||||
processing-type 'verbatim)))
|
||||
;; Display warning if the selected PROCESSING-TYPE is not
|
||||
;; available, but there are fragments to be converted.
|
||||
(when warning
|
||||
(org-element-map tree '(latex-fragment latex-environment)
|
||||
(lambda (_) (warn warning))
|
||||
info 'first-match nil t))
|
||||
;; Store normalized value for later use.
|
||||
(when (plist-get info :with-latex)
|
||||
(plist-put info :with-latex processing-type))
|
||||
(message "Formatting LaTeX using %s" processing-type)
|
||||
;; Convert `latex-fragment's and `latex-environment's.
|
||||
(when (memq processing-type '(dvipng imagemagick))
|
||||
(org-element-map tree '(latex-fragment latex-environment)
|
||||
(lambda (latex-*)
|
||||
(cl-incf count)
|
||||
(let* ((latex-frag (org-element-property :value latex-*))
|
||||
(input-file (plist-get info :input-file))
|
||||
(cache-dir (file-name-directory input-file))
|
||||
(cache-subdir (concat
|
||||
(cl-case processing-type
|
||||
((dvipng imagemagick)
|
||||
org-preview-latex-image-directory))
|
||||
(file-name-sans-extension
|
||||
(file-name-nondirectory input-file))))
|
||||
(display-msg
|
||||
(cl-case processing-type
|
||||
((dvipng imagemagick)
|
||||
(format "Creating LaTeX Image %d..." count))))
|
||||
;; Get an Org-style link to PNG image.
|
||||
(link
|
||||
(with-temp-buffer
|
||||
(insert latex-frag)
|
||||
(delay-mode-hooks (let ((org-inhibit-startup t)) (org-mode)))
|
||||
;; When converting to a PNG image, make sure to
|
||||
;; copy all LaTeX header specifications from the
|
||||
;; Org source.
|
||||
(let ((h (plist-get info :latex-header)))
|
||||
(when h
|
||||
(insert "\n"
|
||||
(replace-regexp-in-string
|
||||
"^" "#+LATEX_HEADER: " h))))
|
||||
(org-latex-preview-replace-fragments
|
||||
cache-subdir processing-type cache-dir display-msg)
|
||||
(goto-char (point-min))
|
||||
(skip-chars-forward " \t\n")
|
||||
(org-element-link-parser))))
|
||||
(if (not (eq 'link (org-element-type link)))
|
||||
(message "LaTeX Conversion failed.")
|
||||
;; Conversion succeeded. Parse above Org-style link to
|
||||
;; a `link' object.
|
||||
(let ((replacement
|
||||
(cl-case (org-element-type latex-*)
|
||||
;;LaTeX environment. Mimic a "standalone image
|
||||
;; or formula" by enclosing the `link' in
|
||||
;; a `paragraph'. Copy over original
|
||||
;; attributes, captions to the enclosing
|
||||
;; paragraph.
|
||||
(latex-environment
|
||||
(org-element-adopt-elements
|
||||
(list 'paragraph
|
||||
(list :style "OrgFormula"
|
||||
:name
|
||||
(org-element-property :name latex-*)
|
||||
:caption
|
||||
(org-element-property :caption latex-*)))
|
||||
link))
|
||||
;; LaTeX fragment. No special action.
|
||||
(latex-fragment link))))
|
||||
;; Note down the object that link replaces.
|
||||
(org-element-put-property replacement :replaces
|
||||
(list (org-element-type latex-*)
|
||||
(list :value latex-frag)))
|
||||
;; Restore blank after initial element or object.
|
||||
(org-element-put-property
|
||||
replacement :post-blank
|
||||
(org-element-property :post-blank latex-*))
|
||||
;; Replace now.
|
||||
(org-element-set-element latex-* replacement)))))
|
||||
info nil nil t))))
|
||||
tree)
|
||||
|
||||
|
||||
|
@ -4144,7 +4179,7 @@ MathML source to kill ring depending on the value of
|
|||
(save-buffer-coding-system 'utf-8))
|
||||
(set-buffer buffer)
|
||||
(set-buffer-file-coding-system coding-system-for-write)
|
||||
(let ((mathml (org-create-math-formula latex-frag)))
|
||||
(let ((mathml (org-mathml-convert-latex-cached latex-frag)))
|
||||
(unless mathml (error "No Math formula created"))
|
||||
(insert mathml)
|
||||
;; Add MathML to kill ring, if needed.
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
#+latex_header: \usepackage{amsmath}
|
||||
#+latex_header: \usepackage{amssymb}
|
||||
|
||||
* Inline fragments and LaTeX environments
|
||||
:PROPERTIES:
|
||||
:ID: 0b3807b3-69af-40cb-a27a-b380d54879cc
|
||||
:END:
|
||||
|
||||
The LQR problem for a time-periodic system of the form
|
||||
\begin{align}
|
||||
\dot{x} = A(t) x + B(t) u, \quad t \in [0, \infty), \quad x(0) = x_i \label{eq:time-varying-system}\\
|
||||
A(t+T) = A(t),\ B(t + T) = B(t) \nonumber
|
||||
\end{align}
|
||||
is as follows. With a quadratic form defined on \( (x,u) \) pairs
|
||||
\begin{align}
|
||||
\label{eq:quadratic-form}
|
||||
\mathbf{q}(x, u) := \lim_{t_f \to \infty} \int_{0}^{t_f} \begin{bmatrix} x \\ u \end{bmatrix}^{\star} \begin{bmatrix}
|
||||
Q & 0 \\
|
||||
0 & r
|
||||
\end{bmatrix} \begin{bmatrix} x \\ u \end{bmatrix} =: \lim_{t_f \to \infty} \int_{0}^{t_f} q(x,u) dt
|
||||
\end{align}
|
||||
with \( q \ge 0 \) and \( r \ge 0 \), find the infimum of the quadratic form \( \mathbf{q} \) subject to the dynamics:
|
||||
\[
|
||||
\inf_{x,u} \mathbf{q}(x,u).
|
||||
\]
|
||||
\begin{align}
|
||||
\label{eq:lqr-inf-via-duality}
|
||||
\inf_{x, u} \mathbf{q}(x, u) = x_i^{\star} \bar{\lambda}(0) x_i,
|
||||
\end{align}
|
||||
where \( \bar{\lambda} \) is the maximal solution of the differential linear matrix inequality over \( [0, t] \).
|
|
@ -0,0 +1,344 @@
|
|||
;;; test-org-latex-preview.el --- tests for org-latex-preview.el -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (c) 2023 Karthik Chikmagalur
|
||||
;; Authors: Karthik Chikmagalur
|
||||
|
||||
;; This file is not part of GNU Emacs.
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Code:
|
||||
(unless (featurep 'org-latex-preview)
|
||||
(signal 'missing-test-dependency "Support for LaTeX previews"))
|
||||
(require 'org-latex-preview)
|
||||
(require 'cl-lib)
|
||||
|
||||
(ert-deftest test-org-latex-preview/assert ()
|
||||
(should t))
|
||||
|
||||
|
||||
;; Test for executables required for preview generation
|
||||
(org-test-for-executable "latex")
|
||||
(org-test-for-executable "dvisvgm")
|
||||
(org-test-for-executable "dvipng")
|
||||
;; Should we test imagemagick?
|
||||
;; (org-test-for-executable "convert")
|
||||
|
||||
|
||||
;; fragment pre-processing tests
|
||||
|
||||
;;; Collect fragments
|
||||
(ert-deftest test-org-latex-preview/collect-fragments-inline ()
|
||||
"Test LaTeX fragment collection"
|
||||
(let ((elements
|
||||
'((latex-fragment
|
||||
(:value "\\( q \\ge 0 \\)" :begin 770 :end 784 :post-blank 1 :parent
|
||||
(paragraph
|
||||
(:begin 765 :end 918 :contents-begin 765 :contents-end 918 :post-blank 0 :post-affiliated 765 :mode nil :granularity element :parent
|
||||
(section
|
||||
(:begin 118 :end 1154 :contents-begin 118 :contents-end 1154 :robust-begin 118 :robust-end 1152 :post-blank 0 :post-affiliated 118 :mode section :granularity element :parent
|
||||
(headline
|
||||
(:raw-value "Inline fragments and LaTeX environments" :begin 76 :end 1154 :pre-blank 0 :contents-begin 118 :contents-end 1154 :robust-begin 184 :robust-end 1152 :level 1 :priority nil :tags nil :todo-keyword nil :todo-type nil :post-blank 0 :footnote-section-p nil :archivedp nil :commentedp nil :post-affiliated 76 :ID "0b3807b3-69af-40cb-a27a-b380d54879cc" :title "Inline fragments and LaTeX environments"))))))))
|
||||
(latex-fragment
|
||||
(:value "\\( r \\ge 0 \\)" :begin 788 :end 801 :post-blank 0 :parent
|
||||
(paragraph
|
||||
(:begin 765 :end 918 :contents-begin 765 :contents-end 918 :post-blank 0 :post-affiliated 765 :mode nil :granularity element :parent
|
||||
(section
|
||||
(:begin 118 :end 1154 :contents-begin 118 :contents-end 1154 :robust-begin 118 :robust-end 1152 :post-blank 0 :post-affiliated 118 :mode section :granularity element :parent
|
||||
(headline
|
||||
(:raw-value "Inline fragments and LaTeX environments" :begin 76 :end 1154 :pre-blank 0 :contents-begin 118 :contents-end 1154 :robust-begin 184 :robust-end 1152 :level 1 :priority nil :tags nil :todo-keyword nil :todo-type nil :post-blank 0 :footnote-section-p nil :archivedp nil :commentedp nil :post-affiliated 76 :ID "0b3807b3-69af-40cb-a27a-b380d54879cc" :title "Inline fragments and LaTeX environments")))))))))))
|
||||
(org-test-at-id
|
||||
"0b3807b3-69af-40cb-a27a-b380d54879cc"
|
||||
(should
|
||||
(equal (org-latex-preview-collect-fragments 765 807) elements))
|
||||
(should
|
||||
(equal (org-latex-preview--construct-entries elements)
|
||||
'(((770 783 "\\( q \\ge 0 \\)")
|
||||
(788 801 "\\( r \\ge 0 \\)"))
|
||||
nil)))
|
||||
(should
|
||||
(equal (org-latex-preview--construct-entries elements)
|
||||
(org-latex-preview--construct-entries elements 'with-numbering))))))
|
||||
|
||||
(ert-deftest test-org-latex-preview/collect-fragments-environment ()
|
||||
"Test LaTeX fragment collection"
|
||||
(let ((elements
|
||||
'((latex-environment
|
||||
(:begin 241 :end 412 :value "\\begin{align}\n\\dot{x} = A(t) x + B(t) u, \\quad t \\in [0, \\infty), \\quad x(0) = x_i \\label{eq:time-varying-system}\\\\\nA(t+T) = A(t),\\ B(t + T) = B(t) \\nonumber\n\\end{align}\n" :post-blank 0 :post-affiliated 241 :mode nil :granularity element :parent
|
||||
(section
|
||||
(:begin 118 :end 1154 :contents-begin 118 :contents-end 1154 :robust-begin 118 :robust-end 1152 :post-blank 0 :post-affiliated 118 :mode section :granularity element :parent
|
||||
(headline
|
||||
(:raw-value "Inline fragments and LaTeX environments" :begin 76 :end 1154 :pre-blank 0 :contents-begin 118 :contents-end 1154 :robust-begin 184 :robust-end 1152 :level 1 :priority nil :tags nil :todo-keyword nil :todo-type nil :post-blank 0 :footnote-section-p nil :archivedp nil :commentedp nil :post-affiliated 76 :ID "0b3807b3-69af-40cb-a27a-b380d54879cc" :title "Inline fragments and LaTeX environments")))))))))
|
||||
(org-test-at-id
|
||||
"0b3807b3-69af-40cb-a27a-b380d54879cc"
|
||||
(should
|
||||
(equal (org-latex-preview-collect-fragments 186 426) elements))
|
||||
(should
|
||||
(equal (org-latex-preview--construct-entries elements)
|
||||
'(((241 411 "\\begin{align}\n\\dot{x} = A(t) x + B(t) u, \\quad t \\in [0, \\infty), \\quad x(0) = x_i \\label{eq:time-varying-system}\\\\\nA(t+T) = A(t),\\ B(t + T) = B(t) \\nonumber\n\\end{align}\n"))
|
||||
nil)))
|
||||
(should
|
||||
(equal (org-latex-preview--construct-entries elements 'with-numbering)
|
||||
'(((241 411 "\\begin{align}\n\\dot{x} = A(t) x + B(t) u, \\quad t \\in [0, \\infty), \\quad x(0) = x_i \\label{eq:time-varying-system}\\\\\nA(t+T) = A(t),\\ B(t + T) = B(t) \\nonumber\n\\end{align}\n"))
|
||||
(1)))))))
|
||||
|
||||
(ert-deftest test-org-latex-preview/collect-fragments-all ()
|
||||
"Test LaTeX fragment collection"
|
||||
(let ((elements
|
||||
'((latex-environment
|
||||
(:begin 241 :end 412 :value "\\begin{align}\n\\dot{x} = A(t) x + B(t) u, \\quad t \\in [0, \\infty), \\quad x(0) = x_i \\label{eq:time-varying-system}\\\\\nA(t+T) = A(t),\\ B(t + T) = B(t) \\nonumber\n\\end{align}\n" :post-blank 0 :post-affiliated 241 :mode nil :granularity element :parent
|
||||
(section
|
||||
(:begin 118 :end 1154 :contents-begin 118 :contents-end 1154 :robust-begin 118 :robust-end 1152 :post-blank 0 :post-affiliated 118 :mode section :granularity element :parent
|
||||
(headline
|
||||
(:raw-value "Inline fragments and LaTeX environments" :begin 76 :end 1154 :pre-blank 0 :contents-begin 118 :contents-end 1154 :robust-begin 184 :robust-end 1152 :level 1 :priority nil :tags nil :todo-keyword nil :todo-type nil :post-blank 0 :footnote-section-p nil :archivedp nil :commentedp nil :post-affiliated 76 :ID "0b3807b3-69af-40cb-a27a-b380d54879cc" :title "Inline fragments and LaTeX environments"))))))
|
||||
(latex-fragment
|
||||
(:value "\\( (x,u) \\)" :begin 460 :end 472 :post-blank 1 :parent
|
||||
(paragraph
|
||||
(:begin 412 :end 478 :contents-begin 412 :contents-end 478 :post-blank 0 :post-affiliated 412 :mode nil :granularity element :parent
|
||||
(section
|
||||
(:begin 118 :end 1154 :contents-begin 118 :contents-end 1154 :robust-begin 118 :robust-end 1152 :post-blank 0 :post-affiliated 118 :mode section :granularity element :parent
|
||||
(headline
|
||||
(:raw-value "Inline fragments and LaTeX environments" :begin 76 :end 1154 :pre-blank 0 :contents-begin 118 :contents-end 1154 :robust-begin 184 :robust-end 1152 :level 1 :priority nil :tags nil :todo-keyword nil :todo-type nil :post-blank 0 :footnote-section-p nil :archivedp nil :commentedp nil :post-affiliated 76 :ID "0b3807b3-69af-40cb-a27a-b380d54879cc" :title "Inline fragments and LaTeX environments"))))))))
|
||||
(latex-environment
|
||||
(:begin 478 :end 765 :value "\\begin{align}\n\\label{eq:quadratic-form}\n\\mathbf{q}(x, u) := \\lim_{t_f \\to \\infty} \\int_{0}^{t_f} \\begin{bmatrix} x \\\\ u \\end{bmatrix}^{\\star} \\begin{bmatrix}\nQ & 0 \\\\\n0 & r\n \\end{bmatrix} \\begin{bmatrix} x \\\\ u \\end{bmatrix} =: \\lim_{t_f \\to \\infty} \\int_{0}^{t_f} q(x,u) dt\n\\end{align}\n" :post-blank 0 :post-affiliated 478 :mode nil :granularity element :parent
|
||||
(section
|
||||
(:begin 118 :end 1154 :contents-begin 118 :contents-end 1154 :robust-begin 118 :robust-end 1152 :post-blank 0 :post-affiliated 118 :mode section :granularity element :parent
|
||||
(headline
|
||||
(:raw-value "Inline fragments and LaTeX environments" :begin 76 :end 1154 :pre-blank 0 :contents-begin 118 :contents-end 1154 :robust-begin 184 :robust-end 1152 :level 1 :priority nil :tags nil :todo-keyword nil :todo-type nil :post-blank 0 :footnote-section-p nil :archivedp nil :commentedp nil :post-affiliated 76 :ID "0b3807b3-69af-40cb-a27a-b380d54879cc" :title "Inline fragments and LaTeX environments"))))))
|
||||
(latex-fragment
|
||||
(:value "\\( q \\ge 0 \\)" :begin 770 :end 784 :post-blank 1 :parent
|
||||
(paragraph
|
||||
(:begin 765 :end 918 :contents-begin 765 :contents-end 918 :post-blank 0 :post-affiliated 765 :mode nil :granularity element :parent
|
||||
(section
|
||||
(:begin 118 :end 1154 :contents-begin 118 :contents-end 1154 :robust-begin 118 :robust-end 1152 :post-blank 0 :post-affiliated 118 :mode section :granularity element :parent
|
||||
(headline
|
||||
(:raw-value "Inline fragments and LaTeX environments" :begin 76 :end 1154 :pre-blank 0 :contents-begin 118 :contents-end 1154 :robust-begin 184 :robust-end 1152 :level 1 :priority nil :tags nil :todo-keyword nil :todo-type nil :post-blank 0 :footnote-section-p nil :archivedp nil :commentedp nil :post-affiliated 76 :ID "0b3807b3-69af-40cb-a27a-b380d54879cc" :title "Inline fragments and LaTeX environments"))))))))
|
||||
(latex-fragment
|
||||
(:value "\\( r \\ge 0 \\)" :begin 788 :end 801 :post-blank 0 :parent
|
||||
(paragraph
|
||||
(:begin 765 :end 918 :contents-begin 765 :contents-end 918 :post-blank 0 :post-affiliated 765 :mode nil :granularity element :parent
|
||||
(section
|
||||
(:begin 118 :end 1154 :contents-begin 118 :contents-end 1154 :robust-begin 118 :robust-end 1152 :post-blank 0 :post-affiliated 118 :mode section :granularity element :parent
|
||||
(headline
|
||||
(:raw-value "Inline fragments and LaTeX environments" :begin 76 :end 1154 :pre-blank 0 :contents-begin 118 :contents-end 1154 :robust-begin 184 :robust-end 1152 :level 1 :priority nil :tags nil :todo-keyword nil :todo-type nil :post-blank 0 :footnote-section-p nil :archivedp nil :commentedp nil :post-affiliated 76 :ID "0b3807b3-69af-40cb-a27a-b380d54879cc" :title "Inline fragments and LaTeX environments"))))))))
|
||||
(latex-fragment
|
||||
(:value "\\( \\mathbf{q} \\)" :begin 842 :end 859 :post-blank 1 :parent
|
||||
(paragraph
|
||||
(:begin 765 :end 918 :contents-begin 765 :contents-end 918 :post-blank 0 :post-affiliated 765 :mode nil :granularity element :parent
|
||||
(section
|
||||
(:begin 118 :end 1154 :contents-begin 118 :contents-end 1154 :robust-begin 118 :robust-end 1152 :post-blank 0 :post-affiliated 118 :mode section :granularity element :parent
|
||||
(headline
|
||||
(:raw-value "Inline fragments and LaTeX environments" :begin 76 :end 1154 :pre-blank 0 :contents-begin 118 :contents-end 1154 :robust-begin 184 :robust-end 1152 :level 1 :priority nil :tags nil :todo-keyword nil :todo-type nil :post-blank 0 :footnote-section-p nil :archivedp nil :commentedp nil :post-affiliated 76 :ID "0b3807b3-69af-40cb-a27a-b380d54879cc" :title "Inline fragments and LaTeX environments"))))))))
|
||||
(latex-fragment
|
||||
(:value "\\[\n\\inf_{x,u} \\mathbf{q}(x,u).\n\\]" :begin 884 :end 917 :post-blank 0 :parent
|
||||
(paragraph
|
||||
(:begin 765 :end 918 :contents-begin 765 :contents-end 918 :post-blank 0 :post-affiliated 765 :mode nil :granularity element :parent
|
||||
(section
|
||||
(:begin 118 :end 1154 :contents-begin 118 :contents-end 1154 :robust-begin 118 :robust-end 1152 :post-blank 0 :post-affiliated 118 :mode section :granularity element :parent
|
||||
(headline
|
||||
(:raw-value "Inline fragments and LaTeX environments" :begin 76 :end 1154 :pre-blank 0 :contents-begin 118 :contents-end 1154 :robust-begin 184 :robust-end 1152 :level 1 :priority nil :tags nil :todo-keyword nil :todo-type nil :post-blank 0 :footnote-section-p nil :archivedp nil :commentedp nil :post-affiliated 76 :ID "0b3807b3-69af-40cb-a27a-b380d54879cc" :title "Inline fragments and LaTeX environments"))))))))
|
||||
(latex-environment
|
||||
(:begin 918 :end 1040 :value "\\begin{align}\n\\label{eq:lqr-inf-via-duality}\n\\inf_{x, u} \\mathbf{q}(x, u) = x_i^{\\star} \\bar{\\lambda}(0) x_i,\n\\end{align}\n" :post-blank 0 :post-affiliated 918 :mode nil :granularity element :parent
|
||||
(section
|
||||
(:begin 118 :end 1154 :contents-begin 118 :contents-end 1154 :robust-begin 118 :robust-end 1152 :post-blank 0 :post-affiliated 118 :mode section :granularity element :parent
|
||||
(headline
|
||||
(:raw-value "Inline fragments and LaTeX environments" :begin 76 :end 1154 :pre-blank 0 :contents-begin 118 :contents-end 1154 :robust-begin 184 :robust-end 1152 :level 1 :priority nil :tags nil :todo-keyword nil :todo-type nil :post-blank 0 :footnote-section-p nil :archivedp nil :commentedp nil :post-affiliated 76 :ID "0b3807b3-69af-40cb-a27a-b380d54879cc" :title "Inline fragments and LaTeX environments"))))))
|
||||
(latex-fragment
|
||||
(:value "\\( \\bar{\\lambda} \\)" :begin 1046 :end 1066 :post-blank 1 :parent
|
||||
(paragraph
|
||||
(:begin 1040 :end 1154 :contents-begin 1040 :contents-end 1154 :post-blank 0 :post-affiliated 1040 :mode nil :granularity element :parent
|
||||
(section
|
||||
(:begin 118 :end 1154 :contents-begin 118 :contents-end 1154 :robust-begin 118 :robust-end 1152 :post-blank 0 :post-affiliated 118 :mode section :granularity element :parent
|
||||
(headline
|
||||
(:raw-value "Inline fragments and LaTeX environments" :begin 76 :end 1154 :pre-blank 0 :contents-begin 118 :contents-end 1154 :robust-begin 184 :robust-end 1152 :level 1 :priority nil :tags nil :todo-keyword nil :todo-type nil :post-blank 0 :footnote-section-p nil :archivedp nil :commentedp nil :post-affiliated 76 :ID "0b3807b3-69af-40cb-a27a-b380d54879cc" :title "Inline fragments and LaTeX environments"))))))))
|
||||
(latex-fragment
|
||||
(:value "\\( [0, t] \\)" :begin 1140 :end 1152 :post-blank 0 :parent
|
||||
(paragraph
|
||||
(:begin 1040 :end 1154 :contents-begin 1040 :contents-end 1154 :post-blank 0 :post-affiliated 1040 :mode nil :granularity element :parent
|
||||
(section
|
||||
(:begin 118 :end 1154 :contents-begin 118 :contents-end 1154 :robust-begin 118 :robust-end 1152 :post-blank 0 :post-affiliated 118 :mode section :granularity element :parent
|
||||
(headline
|
||||
(:raw-value "Inline fragments and LaTeX environments" :begin 76 :end 1154 :pre-blank 0 :contents-begin 118 :contents-end 1154 :robust-begin 184 :robust-end 1152 :level 1 :priority nil :tags nil :todo-keyword nil :todo-type nil :post-blank 0 :footnote-section-p nil :archivedp nil :commentedp nil :post-affiliated 76 :ID "0b3807b3-69af-40cb-a27a-b380d54879cc" :title "Inline fragments and LaTeX environments")))))))))))
|
||||
(org-test-at-id
|
||||
"0b3807b3-69af-40cb-a27a-b380d54879cc"
|
||||
(should
|
||||
(equal (org-latex-preview-collect-fragments) elements))
|
||||
(should (equal (org-latex-preview--construct-entries elements)
|
||||
'(((241 411 "\\begin{align}\n\\dot{x} = A(t) x + B(t) u, \\quad t \\in [0, \\infty), \\quad x(0) = x_i \\label{eq:time-varying-system}\\\\\nA(t+T) = A(t),\\ B(t + T) = B(t) \\nonumber\n\\end{align}\n")
|
||||
(460 471 "\\( (x,u) \\)")
|
||||
(478 764 "\\begin{align}\n\\label{eq:quadratic-form}\n\\mathbf{q}(x, u) := \\lim_{t_f \\to \\infty} \\int_{0}^{t_f} \\begin{bmatrix} x \\\\ u \\end{bmatrix}^{\\star} \\begin{bmatrix}\nQ & 0 \\\\\n0 & r\n \\end{bmatrix} \\begin{bmatrix} x \\\\ u \\end{bmatrix} =: \\lim_{t_f \\to \\infty} \\int_{0}^{t_f} q(x,u) dt\n\\end{align}\n")
|
||||
(770 783 "\\( q \\ge 0 \\)")
|
||||
(788 801 "\\( r \\ge 0 \\)")
|
||||
(842 858 "\\( \\mathbf{q} \\)")
|
||||
(884 917 "\\[\n\\inf_{x,u} \\mathbf{q}(x,u).\n\\]")
|
||||
(918 1039 "\\begin{align}\n\\label{eq:lqr-inf-via-duality}\n\\inf_{x, u} \\mathbf{q}(x, u) = x_i^{\\star} \\bar{\\lambda}(0) x_i,\n\\end{align}\n")
|
||||
(1046 1065 "\\( \\bar{\\lambda} \\)")
|
||||
(1140 1152 "\\( [0, t] \\)"))
|
||||
nil)))
|
||||
(should (equal (org-latex-preview--construct-entries elements 'with-numbering)
|
||||
'(((241 411 "\\begin{align}\n\\dot{x} = A(t) x + B(t) u, \\quad t \\in [0, \\infty), \\quad x(0) = x_i \\label{eq:time-varying-system}\\\\\nA(t+T) = A(t),\\ B(t + T) = B(t) \\nonumber\n\\end{align}\n")
|
||||
(460 471 "\\( (x,u) \\)")
|
||||
(478 764 "\\begin{align}\n\\label{eq:quadratic-form}\n\\mathbf{q}(x, u) := \\lim_{t_f \\to \\infty} \\int_{0}^{t_f} \\begin{bmatrix} x \\\\ u \\end{bmatrix}^{\\star} \\begin{bmatrix}\nQ & 0 \\\\\n0 & r\n \\end{bmatrix} \\begin{bmatrix} x \\\\ u \\end{bmatrix} =: \\lim_{t_f \\to \\infty} \\int_{0}^{t_f} q(x,u) dt\n\\end{align}\n")
|
||||
(770 783 "\\( q \\ge 0 \\)")
|
||||
(788 801 "\\( r \\ge 0 \\)")
|
||||
(842 858 "\\( \\mathbf{q} \\)")
|
||||
(884 917 "\\[\n\\inf_{x,u} \\mathbf{q}(x,u).\n\\]")
|
||||
(918 1039 "\\begin{align}\n\\label{eq:lqr-inf-via-duality}\n\\inf_{x, u} \\mathbf{q}(x, u) = x_i^{\\star} \\bar{\\lambda}(0) x_i,\n\\end{align}\n")
|
||||
(1046 1065 "\\( \\bar{\\lambda} \\)")
|
||||
(1140 1152 "\\( [0, t] \\)"))
|
||||
(1 nil 2 nil nil nil nil 4 nil nil)))))))
|
||||
|
||||
;;; Set up overlays
|
||||
(ert-deftest test-org-latex-preview/ensure-overlay ()
|
||||
(org-test-at-id "0b3807b3-69af-40cb-a27a-b380d54879cc"
|
||||
(org-latex-preview-clear-overlays (point-min) (point-max))
|
||||
(let* ((elements (org-latex-preview-collect-fragments))
|
||||
(entries (car (org-latex-preview--construct-entries elements)))
|
||||
(ov) (all-ovs))
|
||||
(pcase-dolist(`(,beg ,end ,value) entries)
|
||||
(setq ov (org-latex-preview--ensure-overlay beg end))
|
||||
(push ov all-ovs)
|
||||
(should (eq (get-char-property beg 'org-overlay-type) 'org-latex-overlay))
|
||||
(should (eq (overlay-get ov 'org-overlay-type) 'org-latex-overlay))
|
||||
(should (eq (overlay-get ov 'evaporate) t))
|
||||
(should (eq (overlay-get ov 'priority) org-latex-preview--overlay-priority))
|
||||
(should (equal (overlay-get ov 'modification-hooks)
|
||||
(list #'org-latex-preview-auto--mark-overlay-modified)))
|
||||
(should (equal (overlay-get ov 'insert-in-front-hooks)
|
||||
(list #'org-latex-preview-auto--insert-front-handler)))
|
||||
(should (equal (overlay-get ov 'insert-behind-hooks)
|
||||
(list #'org-latex-preview-auto--insert-behind-handler))))
|
||||
(should (eq (length all-ovs) (length elements))))
|
||||
(org-latex-preview-clear-overlays (point-min) (point-max))))
|
||||
|
||||
|
||||
;; Precompilation test
|
||||
;; TODO
|
||||
|
||||
|
||||
;; Process fragments
|
||||
|
||||
;;; No precompilation, no caching
|
||||
(ert-deftest test-org-latex-preview/place-previews-1 ()
|
||||
(org-test-at-id "0b3807b3-69af-40cb-a27a-b380d54879cc"
|
||||
(let ((org-latex-preview-process-precompiled nil)
|
||||
(org-latex-preview-cache 'temp)
|
||||
(org-latex-preview-process-default 'dvisvgm))
|
||||
(org-latex-preview-auto-mode -1)
|
||||
(goto-char 255)
|
||||
(let ((element (org-element-context)))
|
||||
(should (eq (org-element-type element) 'latex-environment))
|
||||
(org-latex-preview-clear-cache (org-element-property :begin element)
|
||||
(org-element-property :end element))
|
||||
(apply #'org-async-wait-for
|
||||
(org-latex-preview--place-from-elements
|
||||
org-latex-preview-process-default
|
||||
(list element)))
|
||||
(let ((ov (cl-some (lambda (o) (and (eq (overlay-get o 'org-overlay-type)
|
||||
'org-latex-overlay)
|
||||
o))
|
||||
(overlays-at (point)))))
|
||||
(should (overlayp ov))
|
||||
(let ((display (overlay-get ov 'display))
|
||||
(face (overlay-get ov 'face))
|
||||
(hidden-face (overlay-get ov 'hidden-face))
|
||||
(preview-image (overlay-get ov 'preview-image)))
|
||||
;; Image properties
|
||||
(should (consp display))
|
||||
(should (eq (car display) 'image))
|
||||
(should (eq (plist-get (cdr display) :type) 'svg))
|
||||
(should (stringp (plist-get (cdr display) :file)))
|
||||
(should (string-suffix-p ".svg" (plist-get (cdr display) :file)))
|
||||
(should (eq preview-image display))
|
||||
;; Face properties
|
||||
(should (eq face 'default))
|
||||
(should (eq hidden-face face))))))))
|
||||
|
||||
(ert-deftest test-org-latex-preview/place-previews-all ()
|
||||
(org-test-at-id "0b3807b3-69af-40cb-a27a-b380d54879cc"
|
||||
(let ((org-latex-preview-process-precompiled nil)
|
||||
(org-latex-preview-cache 'temp)
|
||||
(org-latex-preview-process-default 'dvisvgm))
|
||||
(org-latex-preview-auto-mode -1)
|
||||
(org-latex-preview-clear-cache (point-min) (point-max))
|
||||
(let ((elements (org-latex-preview-collect-fragments)))
|
||||
(apply #'org-async-wait-for
|
||||
(org-latex-preview--place-from-elements
|
||||
org-latex-preview-process-default
|
||||
elements))
|
||||
(dolist (element elements)
|
||||
(let ((ov (cl-some (lambda (o) (and (eq (overlay-get o 'org-overlay-type)
|
||||
'org-latex-overlay)
|
||||
o))
|
||||
(overlays-at (org-element-property :begin element)))))
|
||||
(should (overlayp ov))
|
||||
(let ((display (overlay-get ov 'display))
|
||||
(face (overlay-get ov 'face))
|
||||
(hidden-face (overlay-get ov 'hidden-face))
|
||||
(preview-image (overlay-get ov 'preview-image)))
|
||||
;; Image properties
|
||||
(should (consp display))
|
||||
(should (eq (car display) 'image))
|
||||
(should (eq (plist-get (cdr display) :type) 'svg))
|
||||
(should (stringp (plist-get (cdr display) :file)))
|
||||
(should (string-suffix-p ".svg" (plist-get (cdr display) :file)))
|
||||
(should (eq preview-image display))
|
||||
;; Face properties
|
||||
(should (eq face 'default))
|
||||
(should (eq hidden-face face)))))
|
||||
(org-latex-preview-clear-cache (point-min) (point-max))))))
|
||||
|
||||
;; TODO: Test with precompilation
|
||||
;; TODO: Test with caching
|
||||
|
||||
|
||||
;; dvisvgm filter+callback test
|
||||
;; dvipng filter+callback test
|
||||
;; imagemagick filter+callback test
|
||||
;; TODO
|
||||
|
||||
|
||||
;; Color extraction
|
||||
;; TODO
|
||||
|
||||
|
||||
;; Scaling
|
||||
;; TODO
|
||||
|
||||
|
||||
;; Caching
|
||||
;; TODO
|
||||
|
||||
;;; clear-cache test
|
||||
|
||||
|
||||
;; Numbering
|
||||
;; TODO
|
||||
|
||||
|
||||
;; org-latex-preview-auto-mode
|
||||
;; TODO
|
||||
|
||||
|
||||
;; live previews
|
||||
;; TODO
|
||||
|
||||
|
||||
;; lualatex-specific tests
|
||||
|
||||
|
||||
;; xelatex-specific tests
|
||||
|
||||
(provide 'test-org-latex-preview)
|
||||
;;; test-org-latex-preview.el ends here
|
Loading…
Reference in New Issue