Skip to content

Commit 2e0dbad

Browse files
committed
feat(docs): add asset:* links for image previews
...with better error tolerance than the built-in Org image previewer (which breaks org-mode if an image preview link 404s). This could be more succinctly accomplished with an `org--create-inline-image` advice (and I will revisit that idea later), but for now, the priority was backwards compatibility. The `org-link-preview` library (and `:preview` link parameter) was only introduced in 9.8+, while 29.1 (the earliest version of Emacs interactive Doom supports) ships with 9.6.6.
1 parent 5434015 commit 2e0dbad

1 file changed

Lines changed: 70 additions & 0 deletions

File tree

lisp/doom-docs.el

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,69 @@ Returns PROP if specified, the context otherwise."
256256
id))))
257257

258258

259+
;;; ** Backwards-compatible link previews
260+
261+
(defun doom-docs--link-asset-follow (path _)
262+
(find-file (doom-docs--link-asset-download path)))
263+
264+
(defun doom-docs--link-asset-download (path)
265+
"Return a local file for asset PATH, downloading URLs into the cache."
266+
(if (string-match-p "\\`https?://" path)
267+
(let* ((cache-dir (doom-cache-dir "doom-docs"))
268+
(cache-file (doom-path cache-dir (md5 path))))
269+
(unless (file-exists-p cache-file)
270+
(make-directory cache-dir t)
271+
(dlet ((recentf-exclude '(always))
272+
(projectile-enable-caching nil))
273+
(url-copy-file path cache-file)))
274+
cache-file)
275+
(expand-file-name path doom-docs-dir)))
276+
277+
(defun doom-docs--link-asset-image (path link)
278+
"Return an image object for asset PATH, or nil."
279+
(let ((file
280+
(with-demoted-errors "Asset error: %s"
281+
(doom-docs--link-asset-download path))))
282+
(when (and file (file-exists-p file))
283+
(if (fboundp 'org--create-inline-image)
284+
(org--create-inline-image
285+
file (and (fboundp 'org-display-inline-image--width)
286+
(org-display-inline-image--width link)))
287+
(create-image file nil nil :max-width (window-body-width nil t))))))
288+
289+
;; For Org 9.6-9.8
290+
(defun doom-docs--org-display-inline-images-a (&optional _ _ beg end)
291+
"Advice for `org-display-inline-images' to display previews of asset:* links."
292+
(when (display-graphic-p)
293+
(org-with-point-at (or beg (point-min))
294+
(let ((end (or end (point-max))))
295+
(while (re-search-forward "\\[\\[asset:" end t)
296+
(let ((link (save-match-data (org-element-context))))
297+
(when (and (eq (org-element-type link) 'link)
298+
(equal (org-element-property :type link) "asset")
299+
(not (get-char-property (point) 'org-image-overlay)))
300+
(let ((ov (make-overlay
301+
(org-element-property :begin link)
302+
(- (org-element-property :end link)
303+
(or (org-element-property :post-blank link) 0)))))
304+
(if-let* ((img (doom-docs--link-asset-image
305+
(org-element-property :path link) link)))
306+
(progn
307+
(overlay-put ov 'display img)
308+
(overlay-put ov 'org-image-overlay t)
309+
(overlay-put ov 'modification-hooks '(org-display-inline-remove-overlay))
310+
(push ov org-inline-image-overlays))
311+
(overlay-put ov 'display (propertize "<image not found>" 'face 'error)))))))))))
312+
313+
;; For Org 9.8+
314+
(defun doom-docs--link-asset-preview (ov path link)
315+
"Preview function for asset: links (Org 9.8+ API).
316+
Put the image on OV and return non-nil; returning nil deletes OV."
317+
(when-let* ((img (doom-docs--link-asset-image path link)))
318+
(overlay-put ov 'display img)
319+
t))
320+
321+
259322
;;; ** Navbar
260323

261324
(defun doom-docs--file-type (&optional dir)
@@ -1147,6 +1210,13 @@ This primes `org-mode' for reading."
11471210
:activate-func #'doom-docs-link-activate-func
11481211
:face 'doom-docs-shell-command)
11491212

1213+
(org-link-set-parameters "asset" :follow #'doom-docs--link-asset-follow)
1214+
(if (fboundp 'org-link-preview)
1215+
;; Org 9.8+
1216+
(org-link-set-parameters "asset" :preview #'doom-docs--link-asset-preview)
1217+
;; Org 9.6 – 9.8+
1218+
(advice-add #'org-display-inline-images :after #'doom-docs--org-display-inline-images-a))
1219+
11501220
(org-link-set-parameters
11511221
"var"
11521222
:follow (call #'describe-variable)

0 commit comments

Comments
 (0)