forked from mirrors/org-mode
org-latex-preview: Skip blank fragments
* lisp/org-latex-preview.el (org-latex-preview--construct-entries, org-latex-preview-auto--regenerate-overlay): Blank fragments produce invisible previews, which is at best silly and at worst confusing. It's much better to simply not produce a preview image of blank fragments. We also now avoid exessive re-numbering calculations when repeatadly generating live previews.
This commit is contained in:
parent
de4fb9de11
commit
fdaeb38609
|
@ -789,21 +789,34 @@ image. The preview image is regenerated if necessary."
|
|||
(overlay-put ov 'display (overlay-get ov 'preview-image)))
|
||||
(run-hook-with-args 'org-latex-preview-overlay-close-functions ov))))
|
||||
|
||||
(defun org-latex-preview-auto--regenerate-overlay (ov)
|
||||
"Regenerate the LaTeX fragment under overlay OV."
|
||||
(defun org-latex-preview-auto--regenerate-overlay (ov &optional inhibit-renumbering)
|
||||
"Regenerate the LaTeX fragment under overlay OV.
|
||||
|
||||
When `org-latex-preview-numbered' is non-nil, and the overlay
|
||||
being updated is for an environment, other numbered environments
|
||||
will be updated should their numbering change.
|
||||
|
||||
Numbering checking and updating can be prevented by setting
|
||||
INHIBIT-RENUMBERING to a non-nil value."
|
||||
(with-current-buffer (overlay-buffer ov)
|
||||
(let* ((fragment (save-excursion
|
||||
(goto-char (overlay-start ov))
|
||||
(let* ((start (overlay-start ov))
|
||||
(end (overlay-end ov))
|
||||
(fragment (save-excursion
|
||||
(goto-char start)
|
||||
(org-element-context)))
|
||||
(others (and org-latex-preview-numbered
|
||||
(not inhibit-renumbering)
|
||||
(eq (org-element-type fragment) 'latex-environment)
|
||||
(org-latex-preview--get-numbered-environments
|
||||
(overlay-end ov) nil))))
|
||||
(org-latex-preview--get-numbered-environments end nil))))
|
||||
(if (memq (org-element-type fragment)
|
||||
'(latex-fragment latex-environment))
|
||||
(org-latex-preview--place-from-elements
|
||||
org-latex-preview-process-default
|
||||
(cons fragment others))
|
||||
(if (org-latex-preview--empty-fragment-p
|
||||
(org-element-property :value fragment))
|
||||
(progn (delete-overlay ov)
|
||||
(org-latex-preview--ensure-overlay start end))
|
||||
(org-latex-preview--place-from-elements
|
||||
org-latex-preview-process-default
|
||||
(cons fragment others)))
|
||||
(delete-overlay ov)
|
||||
(when others
|
||||
(org-latex-preview--place-from-elements
|
||||
|
@ -1068,6 +1081,7 @@ BOX-FACE is the face to apply in addition."
|
|||
(let ((props (get-char-property-and-overlay (point) 'org-overlay-type)))
|
||||
(and (eq (car props) 'org-latex-overlay)
|
||||
(cdr props)))))
|
||||
(image (overlay-get ov 'preview-image))
|
||||
(end (overlay-end ov)))
|
||||
(let ((latex-env-p
|
||||
(progn
|
||||
|
@ -1093,8 +1107,7 @@ BOX-FACE is the face to apply in addition."
|
|||
(concat (and latex-env-p "\n") " "))
|
||||
(overlay-put ov 'view-text t)
|
||||
(overlay-put ov 'after-string org-latex-preview-live--docstring)))
|
||||
(org-latex-preview-live--update-props
|
||||
(overlay-get ov 'preview-image) '(:box t))))))
|
||||
(org-latex-preview-live--update-props image '(:box t))))))
|
||||
|
||||
(defun org-latex-preview-live--update-overlay (ov)
|
||||
"Update the live LaTeX preview for overlay OV."
|
||||
|
@ -1476,32 +1489,45 @@ protection against placing doubled up overlays."
|
|||
"Constuct a well formatted list of entries and (optinally) numbering offsets.
|
||||
This operates by processing ELEMENTS. When CONSTRUCT-NUMBERING-P is non-nil,
|
||||
the number offsets will also be calculated, using PARSE-TREE if given."
|
||||
(let* ((numbering-table (and construct-numbering-p
|
||||
(cl-find 'latex-environment elements
|
||||
:key #'org-element-type :test #'eq)
|
||||
(org-latex-preview--environment-numbering-table
|
||||
parse-tree)))
|
||||
(numbering-offsets
|
||||
(and numbering-table
|
||||
(mapcar
|
||||
(lambda (element)
|
||||
(and numbering-table
|
||||
(eq (org-element-type element) 'latex-environment)
|
||||
(gethash element numbering-table)))
|
||||
elements)))
|
||||
(entries
|
||||
(mapcar
|
||||
(lambda (element)
|
||||
(list (or (org-element-property :post-affiliated element)
|
||||
(org-element-property :begin element))
|
||||
(- (org-element-property :end element)
|
||||
(or (org-element-property :post-blank element) 0)
|
||||
(if (eq (char-before (org-element-property :end element))
|
||||
?\n)
|
||||
1 0))
|
||||
(org-element-property :value element)))
|
||||
elements)))
|
||||
(list entries numbering-offsets)))
|
||||
(let ((numbering-table (and construct-numbering-p
|
||||
(cl-find 'latex-environment elements
|
||||
:key #'org-element-type :test #'eq)
|
||||
(org-latex-preview--environment-numbering-table
|
||||
parse-tree)))
|
||||
entries numbering-offsets)
|
||||
(dolist (element elements)
|
||||
(let ((beg (or (org-element-property :post-affiliated element)
|
||||
(org-element-property :begin element)))
|
||||
(end (- (org-element-property :end element)
|
||||
(or (org-element-property :post-blank element) 0)
|
||||
(if (eq (char-before (org-element-property :end element))
|
||||
?\n)
|
||||
1 0)))
|
||||
(content (org-element-property :value element)))
|
||||
(push (list beg end content) entries)
|
||||
(when numbering-table
|
||||
(push (and (eq (org-element-type element) 'latex-environment)
|
||||
(gethash element numbering-table))
|
||||
numbering-offsets))))
|
||||
(list (nreverse entries) (nreverse numbering-offsets))))
|
||||
|
||||
(defun org-latex-preview--empty-fragment-p (content)
|
||||
"Test if the LaTeX string CONTENT is an empty LaTeX fragment (e.g. \\[\\])."
|
||||
(let ((content-point 0)
|
||||
(content-max (1- (length content)))
|
||||
(only-blanks t))
|
||||
(cond
|
||||
((eq (aref content 0) ?$)
|
||||
(if (eq (aref content 1) ?$)
|
||||
(setq content-point 2 content-max (- content-max 2))
|
||||
(setq content-point 1 content-max (- content-max 1))))
|
||||
((eq (aref content 0) ?\\)
|
||||
(setq content-point 2 content-max (- content-max 2))))
|
||||
(while (and only-blanks (<= content-point content-max))
|
||||
(if (memq (aref content content-point) '(?\s ?\t ?\n ?\r))
|
||||
(cl-incf content-point)
|
||||
(setq only-blanks nil)))
|
||||
only-blanks))
|
||||
|
||||
(defun org-latex-preview--place-from-elements (processing-type elements)
|
||||
"Preview LaTeX math fragments ELEMENTS using PROCESSING-TYPE."
|
||||
|
@ -1551,11 +1577,12 @@ is either the substring between BEG and END or (when provided) VALUE."
|
|||
(org-latex-preview--update-overlay
|
||||
(org-latex-preview--ensure-overlay beg end)
|
||||
path-info)
|
||||
(push (list :string (org-latex-preview--tex-styled
|
||||
processing-type value options)
|
||||
:overlay (org-latex-preview--ensure-overlay beg end)
|
||||
:key hash)
|
||||
fragment-info))
|
||||
(unless (org-latex-preview--empty-fragment-p value)
|
||||
(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
|
||||
(org-latex-preview--create-image-async
|
||||
|
|
109
lisp/ox-html.el
109
lisp/ox-html.el
|
@ -1184,6 +1184,7 @@ This supports two extra properties,
|
|||
:inline images that should not be saved according to :image-dir,
|
||||
but instead inlined in the generated HTML. This can be:
|
||||
- t, to inline all images
|
||||
- svg, to inline all images, using <svg> with SVGs
|
||||
- nil, to never inline images
|
||||
- an extension or list of extensions, for images that
|
||||
should be inline (e.g. \"svg\")"
|
||||
|
@ -3207,54 +3208,80 @@ that an image for ELEMENT already exists within it."
|
|||
(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))
|
||||
(image-dir (plist-get image-options :image-dir))
|
||||
(inline-condition (plist-get image-options :inline))
|
||||
(rescale-factor (if (eq (plist-get (cdr path-info) :image-type) 'svg)
|
||||
(plist-get image-options :scale)
|
||||
1))
|
||||
(image-source
|
||||
(cond
|
||||
((or (eq inline-condition 't)
|
||||
(member (file-name-extension (car path-info))
|
||||
(org-ensure-list inline-condition)))
|
||||
(let ((coding-system-for-read 'utf-8)
|
||||
(file-name-handler-alist nil))
|
||||
(with-temp-buffer
|
||||
(insert-file-contents-literally (car path-info))
|
||||
(base64-encode-region (point-min) (point-max))
|
||||
(goto-char (point-min))
|
||||
(insert "data:image/svg+xml;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 (car path-info)))))
|
||||
(unless (file-directory-p image-dir)
|
||||
(mkdir image-dir t))
|
||||
(unless (file-exists-p image-path)
|
||||
(copy-file (car path-info) image-path))
|
||||
image-path))
|
||||
(t (car path-info)))))
|
||||
(org-html-latex-image--data (car path-info) hash info)))
|
||||
(unless (and (plist-get (cdr path-info) :height)
|
||||
(plist-get (cdr path-info) :depth))
|
||||
(error "Something went wrong during image generation"))
|
||||
(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 (eq (org-element-type element) 'latex-environment)
|
||||
(format "height: %.4fem"
|
||||
(* rescale-factor (plist-get (cdr path-info) :height)))
|
||||
(format "height: %.4fem; vertical-align: -%.4fem; display: inline-block"
|
||||
(* rescale-factor (plist-get (cdr path-info) :height))
|
||||
(* rescale-factor (plist-get (cdr path-info) :depth))))
|
||||
:class (if (eq (org-element-type element) 'latex-environment)
|
||||
"org-latex org-latex-environment"
|
||||
"org-latex org-latex-fragment")))
|
||||
info)))
|
||||
(if (and (eq (plist-get image-options :inline) 'svg)
|
||||
(string= (file-name-extension (car path-info)) "svg"))
|
||||
image-source
|
||||
(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 (eq (org-element-type element) 'latex-environment)
|
||||
(format "height: %.4fem"
|
||||
(* rescale-factor (plist-get (cdr path-info) :height)))
|
||||
(format "height: %.4fem; vertical-align: -%.4fem; display: inline-block"
|
||||
(* rescale-factor (plist-get (cdr path-info) :height))
|
||||
(* rescale-factor (plist-get (cdr path-info) :depth))))
|
||||
:class (if (eq (org-element-type element) 'latex-environment)
|
||||
"org-latex org-latex-environment"
|
||||
"org-latex org-latex-fragment")))
|
||||
info))))
|
||||
|
||||
(defun org-html-latex-image--data (source-file hash info)
|
||||
"Obtaine the image source for SOURCE-FILE as a string, based on HASH and INFO.
|
||||
This can take the form of a path, data URI, or <svg> 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)))
|
||||
(cond
|
||||
((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)
|
||||
(string= (file-name-extension source-file) "svg"))
|
||||
(buffer-string))
|
||||
((string= (file-name-extension source-file) "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/" (file-name-extension source-file) ";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
|
||||
|
||||
|
|
Loading…
Reference in New Issue