diff --git a/Readme.org b/Readme.org index d518f7b..4457590 100644 --- a/Readme.org +++ b/Readme.org @@ -569,26 +569,16 @@ supported options. Check the head part of this document for an example. ** Third-Party Plugins Reveal.js is also extensible through third-party plugins. Org-reveal -now includes a mechanism to load these as well, either for all org buffers -by defining variable, or for local org buffer by setting option line. - -*** By Defining Variable -Store the names and loading instructions for each plugin in the -customizable variable ~org-reveal-external-plugins~. This variable is -an associative list. The first element of each Assoc cell is a symbol --- the name of the plugin -- and the second is the string of the code -for enabling the plugin. The string can have ONE optional ~%s~, which -will be replaced by `reveal-root`. - -So, this second element should have the form ~"{src: -\"%srelative/path/toplugin/from/reveal/root.js\"}~. If you need the -async or callback parameters, include those too. Ox-reveal will add -the plugin to the dependencies parameter when Reveal is initialized. - -*** By Local Option Line -Specify the plugin by option line ~#+REVEAL_EXTERNAL_PLUGINS: string -of code~. Similar to the global plugin definition, the string of code -can have one optional ~%s~ to be replaced by ~reveal-root~. +provides a customizable variable ~org-reveal-external-plugins~ for +defining available third-party plugins. This variable is an +associative list. The first element of each Assoc cell is a symbol +same as the name of the plugin and the second is a string specifying +the location of the plugin script. The string can have ONE optional +~%s~, which will be replaced by `reveal-root`. Code below is an +example. +#+begin_src lisp +(setq org-reveal-external-plugins '((menu . "path/to/reveal.js-menu/menu.js")) +#+end_src ** Highlight Source Code diff --git a/ox-reveal.el b/ox-reveal.el index 8059d9f..a9ffc8d 100644 --- a/ox-reveal.el +++ b/ox-reveal.el @@ -270,11 +270,10 @@ embedded into Reveal.initialize()." :type 'string) (defcustom org-reveal-plugins - '(classList markdown zoom notes) + '(markdown zoom notes) "Default builtin plugins" :group 'org-export-reveal :type '(set - (const classList) (const markdown) (const highlight) (const zoom) @@ -668,6 +667,53 @@ using custom variable `org-reveal-root'." (or (and buffer-plugins (listp buffer-plugins) buffer-plugins) org-reveal-plugins))) +(defun org-reveal--legacy-dependency (root-path plugins info) + (concat + " +// Optional libraries used to extend on reveal.js +dependencies: [ +" + ;; JS libraries + (let* ((builtins + (list + classList (format " { src: '%slib/js/classList.js', condition: function() { return !document.body.classList; } }" root-path) + markdown (format " { src: '%splugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, + { src: '%splugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }" root-path root-path) + highlight (format " { src: '%splugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } }" root-path) + zoom (format " { src: '%splugin/zoom-js/zoom.js', async: true, condition: function() { return !!document.body.classList; } }" root-path) + notes (format " { src: '%splugin/notes/notes.js', async: true, condition: function() { return !!document.body.classList; } }" root-path) + search (format " { src: '%splugin/search/search.js', async: true, condition: function() { return !!document.body.classList; } }" root-path) + remotes (format " { src: '%splugin/remotes/remotes.js', async: true, condition: function() { return !!document.body.classList; } }" root-path) + ;; multiplex setup for reveal.js 3.x + multiplex (format " { src: '%s', async: true },\n%s" + (plist-get info :reveal-multiplex-socketio-url) + ; following ensures that either client.js or master.js is included depending on defva client-multiplex value state + (if (not client-multiplex) + (progn + (if (plist-get info :reveal-multiplex-secret) + (setq client-multiplex t)) + (format " { src: '%splugin/multiplex/master.js', async: true }" root-path)) + (format " { src: '%splugin/multiplex/client.js', async: true }" root-path))))) + (builtin-codes + (mapcar (lambda (p) + (eval (plist-get builtins p))) + plugins)) + (external-plugins + (append + ;; Global setting + (cl-loop for (key . value) in org-reveal-external-plugins + collect (format value root-path )) + ;; Local settings + (let ((local-plugins (plist-get info :reveal-external-plugins))) + (and local-plugins + (list (format local-plugins root-path)))))) + + (all-plugins (if external-plugins (append external-plugins builtin-codes) builtin-codes)) + (extra-codes (plist-get info :reveal-extra-js)) + (total-codes + (if (string= "" extra-codes) all-plugins (append (list extra-codes) all-plugins)))) + (mapconcat 'identity total-codes ",\n")) + "]\n")) (defun org-reveal-scripts (info) "Return the necessary scripts for initializing reveal.js using custom variable `org-reveal-root'." @@ -677,8 +723,9 @@ custom variable `org-reveal-root'." ;; Local files (local-root-path (org-reveal--file-url-to-path root-path)) (local-reveal-js (org-reveal--choose-path local-root-path version "dist/reveal.js" "js/reveal.js")) - (reveal-4-plugin (if (eq 4 (org-reveal--get-reveal-js-version info)) - (org-reveal-plugin-scripts-4 info) + (plugins (org-reveal--get-plugins info)) + (reveal-4-plugin (if (eq 4 version) + (org-reveal-plugin-scripts-4 plugins info) (cons nil nil))) (in-single-file (plist-get info :reveal-single-file))) (concat @@ -701,140 +748,108 @@ custom variable `org-reveal-root'." "\n")) ;; plugin headings (if-format "%s\n" (car reveal-4-plugin)) - " - " - ;; JS libraries - (let* ((builtins - '(classList (format " { src: '%slib/js/classList.js', condition: function() { return !document.body.classList; } }" root-path) - markdown (format " { src: '%splugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, - { src: '%splugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }" root-path root-path) - highlight (format " { src: '%splugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } }" root-path) - zoom (format " { src: '%splugin/zoom-js/zoom.js', async: true, condition: function() { return !!document.body.classList; } }" root-path) - notes (format " { src: '%splugin/notes/notes.js', async: true, condition: function() { return !!document.body.classList; } }" root-path) - search (format " { src: '%splugin/search/search.js', async: true, condition: function() { return !!document.body.classList; } }" root-path) - remotes (format " { src: '%splugin/remotes/remotes.js', async: true, condition: function() { return !!document.body.classList; } }" root-path) - ;; multiplex setup for reveal.js 3.x - multiplex (format " { src: '%s', async: true },\n%s" - (plist-get info :reveal-multiplex-socketio-url) - ; following ensures that either client.js or master.js is included depending on defva client-multiplex value state - (if (not client-multiplex) - (progn - (if (plist-get info :reveal-multiplex-secret) - (setq client-multiplex t)) - (format " { src: '%splugin/multiplex/master.js', async: true }" root-path)) - (format " { src: '%splugin/multiplex/client.js', async: true }" root-path))))) - (builtin-codes - (let ((plugins (org-reveal--get-plugins info))) - (if (eq version 4) - ;; For reveal.js 4.x, skip the builtin plug-in - ;; codes except multiplex as all other plug-ins - ;; in 4.x are specified by separate \n"))) - -(defun org-reveal-plugin-scripts-4 (info) +(defun org-reveal-plugin-scripts-4 (plugins info) "Return scripts for initializing reveal.js 4.x builtin scripts" - (let ((plugins (org-reveal--get-plugins info))) - (if (not (null plugins)) - ;; Generate plugin scripts - (let* ((available-plugins - '(highlight ("RevealHighlight" . "highlight/highlight.js") - markdown ("RevealMarkdown" . "markdown/markdown.js") - search ("RevealSearch" . "search/search.js") - notes ("RevealNotes" . "notes/notes.js") - math ("RevealMath" . "math/math.js") - zoom ("RevealZoom" . "zoom/zoom.js"))) - (plugin-info (seq-filter 'identity - (seq-map (lambda (p) - (plist-get available-plugins p)) - plugins)))) - (if (not (null plugin-info)) - (cons - ;; Plugin initialization script - (let ((root-path (file-name-as-directory (plist-get info :reveal-root)))) - (mapconcat - (lambda (p) - (format "\n" root-path (cdr p))) - plugin-info - "")) - ;; Reveal initialization for plugins - (format "plugins: [%s]" - (mapconcat #'car plugin-info ","))) - ;; No available plugin info found. Perhaps wrong plugin - ;; names are given - (cons nil nil))) - ;; No plugins, return empty string - (cons nil nil)))) + (if (not (null plugins)) + ;; Generate plugin scripts + (let* ((plugins (mapcar + (lambda (p) + ;; Convert legacy + ;; plugin names into + ;; reveal.js 4.0 ones + (cond + ((eq p 'highlight) 'RevealHighlight) + ((eq p 'markdown) 'RevealMarkdown) + ((eq p 'search) 'RevealSearch) + ((eq p 'notes) 'RevealNotes) + ((eq p 'math) 'RevealMath) + ((eq p 'zoom) 'RevealZoom) + (t p))) + plugins)) + (available-plugins + (append '((RevealHighlight . "%splugin/highlight/highlight.js") + (RevealMarkdown . "%splugin/markdown/markdown.js") + (RevealSearch . "%splugin/search/search.js") + (RevealNotes . "%splugin/notes/notes.js") + (RevealMath . "%splugin/math/math.js") + (RevealZoom . "%splugin/zoom/zoom.js")) + org-reveal-external-plugins)) + (plugin-js (seq-filter 'identity ;; Filter out nil + (mapcar (lambda (p) + (cdr (assoc p available-plugins))) + plugins)))) + (if (not (null plugin-js)) + (cons + ;; Plugin initialization script + (let ((root-path (file-name-as-directory (plist-get info :reveal-root)))) + (mapconcat + (lambda (p) + (format "\n" + (format p root-path))) + plugin-js + "")) + ;; Reveal initialization for plugins + (format "plugins: [%s]" + (mapconcat 'symbol-name plugins ", "))) + ;; No available plugin info found. Perhaps wrong plugin + ;; names are given + (cons nil nil))) + ;; No plugins, return empty string + (cons nil nil))) (defun org-reveal-toc (depth info) "Build a slide of table of contents." (let ((toc (org-html-toc depth info)))