add org-preview-html
This commit is contained in:
15
lisp/org-preview-html/org-preview-html-pkg.el
Normal file
15
lisp/org-preview-html/org-preview-html-pkg.el
Normal file
@@ -0,0 +1,15 @@
|
||||
(define-package "org-preview-html" "20220809.1033" "Automatically preview org-exported HTML files within Emacs"
|
||||
'((emacs "25.1")
|
||||
(org "8.0"))
|
||||
:commit "785e1f5c99c0f2d76a9a6611a06b4552a343e221" :authors
|
||||
'(("Jake B" . "jakebox0@protonmail.com"))
|
||||
:maintainers
|
||||
'(("Jake B" . "jakebox0@protonmail.com"))
|
||||
:maintainer
|
||||
'("Jake B" . "jakebox0@protonmail.com")
|
||||
:keywords
|
||||
'("org" "convenience" "outlines")
|
||||
:url "https://github.com/jakebox/org-preview-html")
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
238
lisp/org-preview-html/org-preview-html.el
Normal file
238
lisp/org-preview-html/org-preview-html.el
Normal file
@@ -0,0 +1,238 @@
|
||||
;;; org-preview-html.el --- Automatically preview org-exported HTML files within Emacs -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2021 Jake B <jakebox0@protonmail.com>
|
||||
|
||||
;; Author: Jake B <jakebox0@protonmail.com>
|
||||
;; Original author of org-preview-html (until 2021-09): DarkSun <lujun9972@gmail.com>
|
||||
;; Url: https://github.com/jakebox/org-preview-html
|
||||
;; Keywords: Org, convenience, outlines
|
||||
;; Version: 0.3.1
|
||||
;; Package-Requires: ((emacs "25.1") (org "8.0"))
|
||||
|
||||
;; 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/>.
|
||||
|
||||
;;; Commentary:
|
||||
;; This minor mode provides a side-by-side preview of your org-exported HTML
|
||||
;; files using the either the eww or xwidget browsers. The update frequency of
|
||||
;; the preview can be configured to suit your preference.
|
||||
;;
|
||||
;; Quick start:
|
||||
;; Put this file under your load path.
|
||||
;; Enable the minor mode in an Org buffer:
|
||||
;; M-x org-preview-html-mode
|
||||
;; Configure options with M-x customize-group org-preview-html
|
||||
;;
|
||||
;; Source code
|
||||
;; org-preview-html's code can be found here:
|
||||
;; http://github.com/jakebox/org-preview-html
|
||||
|
||||
;;; Code:
|
||||
|
||||
;;;; Requirements
|
||||
(require 'org)
|
||||
(require 'xwidget)
|
||||
(require 'eww)
|
||||
|
||||
|
||||
(defgroup org-preview-html nil
|
||||
"Automatically preview org-exported HTML files within Emacs."
|
||||
:group 'org-mode
|
||||
:link '(url-link :tag "Homepage" "https://github.com/jakebox/org-preview-html/"))
|
||||
|
||||
(defcustom org-preview-html-refresh-configuration 'save
|
||||
"Specifies how often the HTML preview will be refreshed.
|
||||
|
||||
If `manual', update manually by running `org-preview-html-refresh'.
|
||||
If `save', update on save (default).
|
||||
If `export', update on manual export \(using `org-html-export-to-html').
|
||||
If `timer', update preview on timer (`org-preview-html-timer-interval')."
|
||||
:type '(choice
|
||||
(symbol :tag "Update preview manually" manual)
|
||||
(symbol :tag "Update preview on save" save)
|
||||
(symbol :tag "Update preview on export" export)
|
||||
(symbol :tag "Update preview on a timer" timer))
|
||||
:group 'org-preview-html)
|
||||
|
||||
(defcustom org-preview-html-timer-interval 2
|
||||
"Integer seconds to wait between exports when in 'timer mode."
|
||||
:type 'integer
|
||||
:group 'org-preview-html)
|
||||
|
||||
(defcustom org-preview-html-viewer 'eww
|
||||
"Which Emacs browser `org-preview-html-mode' will use.
|
||||
|
||||
If `eww', use eww browser (default).
|
||||
If `xwidget', use xwidget browser."
|
||||
:type '(choice
|
||||
(symbol :tag "Use eww" eww)
|
||||
(symbol :tag "Use xwidget" xwidget))
|
||||
:group 'org-preview-html)
|
||||
|
||||
(define-obsolete-variable-alias 'org-preview-html/body-only 'org-preview-html-subtree-only "Version 0.3")
|
||||
|
||||
(defcustom org-preview-html-subtree-only nil
|
||||
"If non-nil, scope the preview to the current subtree."
|
||||
:type 'boolean
|
||||
:group 'org-preview-html)
|
||||
|
||||
(defcustom org-preview-html/body-only nil
|
||||
"Scope the preview to the body or include the entire document.
|
||||
Obselete as of version 0.3, instead use `org-preview-html-subtree-only'."
|
||||
:type 'boolean
|
||||
:group 'org-preview-html)
|
||||
|
||||
|
||||
;; Internal variables
|
||||
(defvar org-preview-html--browser-buffer nil)
|
||||
(defvar org-preview-html--previewed-buffer-name nil)
|
||||
(defvar org-preview-html--refresh-timer nil)
|
||||
(defvar-local org-preview-html--html-file nil)
|
||||
|
||||
|
||||
;; https://emacs.stackexchange.com/questions/7116/pop-a-window-into-a-frame
|
||||
(defun org-preview-html-pop-window-to-frame ()
|
||||
"Pop a window to a frame."
|
||||
(interactive)
|
||||
(let ((buffer (current-buffer)))
|
||||
(unless (one-window-p)
|
||||
(delete-window))
|
||||
(display-buffer-pop-up-frame buffer nil)))
|
||||
|
||||
;; Taken from frame.el Emacs 27.1, copied here for better version compatibility.
|
||||
;; Without this here 27.1 required. With, 25.1.
|
||||
(defun org-preview-html--previous-window-any-frame ()
|
||||
(select-window (previous-window (selected-window)
|
||||
(> (minibuffer-depth) 0)
|
||||
0))
|
||||
(select-frame-set-input-focus (selected-frame)))
|
||||
|
||||
(defun org-preview-html-refresh ()
|
||||
"Exports the org file to HTML and refreshes the preview."
|
||||
(interactive)
|
||||
(when (eq org-preview-html-refresh-configuration 'manual)
|
||||
(pop-to-buffer org-preview-html--previewed-buffer-name nil t))
|
||||
(org-preview-html--org-export-html)
|
||||
(org-preview-html--reload-preview))
|
||||
|
||||
(defun org-preview-html--org-export-html ()
|
||||
"Silently export org to HTML."
|
||||
(let ((standard-output 'ignore))
|
||||
(org-export-to-file 'html org-preview-html--html-file
|
||||
nil org-preview-html-subtree-only nil nil nil nil)))
|
||||
|
||||
(defun org-preview-html--reload-preview ()
|
||||
"Reload preview."
|
||||
(save-selected-window
|
||||
(pop-to-buffer org-preview-html--browser-buffer)
|
||||
(cond ((eq org-preview-html-viewer 'xwidget) (xwidget-webkit-reload))
|
||||
((eq org-preview-html-viewer 'eww)
|
||||
(with-selected-window (selected-window)
|
||||
;; This stuff is to keep eww window scrolled at same point
|
||||
(let ((eww-point (point))
|
||||
(eww-window-start (window-start)))
|
||||
(eww-reload)
|
||||
(goto-char eww-point)
|
||||
(set-window-start nil eww-window-start)))))))
|
||||
|
||||
(defun org-preview-html--kill-preview-buffer ()
|
||||
"Kill the preview buffer and pop back to the previewed org buffer."
|
||||
;; Only do these things if the preview is around
|
||||
(when (bound-and-true-p org-preview-html--browser-buffer)
|
||||
;; If preview is visible we first delete the window, otherwise
|
||||
;; just kill the preview buffer
|
||||
(if (get-buffer-window org-preview-html--browser-buffer 'visible)
|
||||
(delete-window (get-buffer-window org-preview-html--browser-buffer)))
|
||||
(let ((kill-buffer-query-functions nil))
|
||||
(kill-buffer org-preview-html--browser-buffer))
|
||||
(pop-to-buffer org-preview-html--previewed-buffer-name)))
|
||||
|
||||
(defun org-preview-html--run-with-timer ()
|
||||
"Configure timer to refresh preview for `timer' mode."
|
||||
(setq org-preview-html--refresh-timer
|
||||
(run-at-time 1 org-preview-html-timer-interval #'org-preview-html-refresh)))
|
||||
|
||||
(defun org-preview-html--config ()
|
||||
"Configure buffer for preview: add exit hooks; configure refresh hooks."
|
||||
(setq org-preview-html--previewed-buffer-name (buffer-name))
|
||||
(dolist (hook '(kill-buffer-hook kill-emacs-hook)) ;; Configure exit hooks
|
||||
(add-hook hook #'org-preview-html--stop-preview nil t))
|
||||
(let ((conf org-preview-html-refresh-configuration))
|
||||
(cond
|
||||
((eq conf 'manual))
|
||||
((eq conf 'save) ;; On save
|
||||
(add-hook 'after-save-hook #'org-preview-html-refresh nil t))
|
||||
((eq conf 'timer) ;; every X seconds
|
||||
(org-preview-html--run-with-timer))
|
||||
((eq conf 'export) ;; On export using org-html-export-html command manually
|
||||
(advice-add 'org-html-export-to-html :after #'org-preview-html--reload-preview)))))
|
||||
|
||||
(defun org-preview-html--unconfig ()
|
||||
"Unconfigure 'org-preview-html-mode' (remove hooks and advice)."
|
||||
(let ((conf org-preview-html-refresh-configuration))
|
||||
(cond ((eq conf 'save)
|
||||
(remove-hook 'after-save-hook #'org-preview-html-refresh t))
|
||||
((eq conf 'timer)
|
||||
(cancel-timer org-preview-html--refresh-timer))
|
||||
((eq conf 'export)
|
||||
(advice-remove 'org-html-export-to-html #'org-preview-html--reload-preview))))
|
||||
(dolist (hook '(kill-buffer-hook kill-emacs-hook)) ;; Remove hooks
|
||||
(remove-hook hook #'org-preview-html--stop-preview t))
|
||||
;; Reset variables
|
||||
(dolist (var '(org-preview-html--browser-buffer org-preview-html--previewed-buffer-name))
|
||||
(set var nil)))
|
||||
|
||||
(defun org-preview-html--open-browser ()
|
||||
"Open a browser to preview the exported HTML file."
|
||||
;; Store the exported HTML filename
|
||||
(setq-local org-preview-html--html-file (concat (file-name-sans-extension buffer-file-name) ".html"))
|
||||
(org-preview-html--org-export-html) ;; Export the org file to HTML
|
||||
;; Procedure to open the side-by-side preview
|
||||
(split-window-right)
|
||||
(other-window 1)
|
||||
(let ((file org-preview-html--html-file))
|
||||
(cond ((eq org-preview-html-viewer 'xwidget) (xwidget-webkit-browse-url (concat "file://" file)))
|
||||
((eq org-preview-html-viewer 'eww) (eww-open-file file))))
|
||||
(setq org-preview-html--browser-buffer (get-buffer (buffer-name)))
|
||||
(org-preview-html--previous-window-any-frame))
|
||||
|
||||
(defun org-preview-html--start-preview ()
|
||||
"Begin the org-preview-html preview."
|
||||
(when buffer-file-name
|
||||
(cond ((derived-mode-p 'org-mode)
|
||||
(message "org-preview-html has recieved a major update - xwidgets support, refresh configurations and more! \n M-x customize-group org-preview-html-mode")
|
||||
(org-preview-html--open-browser)
|
||||
(org-preview-html--config))
|
||||
(t
|
||||
(org-preview-html-mode -1)
|
||||
(user-error "`%s' not supported by org-preview-html preview, only `org mode'!" major-mode)))))
|
||||
|
||||
(defun org-preview-html--stop-preview ()
|
||||
"Stop the org-preview-html preview."
|
||||
(org-preview-html--kill-preview-buffer)
|
||||
(org-preview-html--unconfig))
|
||||
|
||||
|
||||
;;;###autoload
|
||||
(define-minor-mode org-preview-html-mode
|
||||
"(Optionally) live preview for Org exports to HTML."
|
||||
:lighter " org-preview-html"
|
||||
(if org-preview-html-mode
|
||||
(org-preview-html--start-preview)
|
||||
(org-preview-html--stop-preview)))
|
||||
|
||||
(provide 'org-preview-html)
|
||||
|
||||
;;; org-preview-html.el ends here
|
||||
Reference in New Issue
Block a user