|
|
- ;;; org-re-reveal.el --- Org export to reveal.js presentations -*- lexical-binding: t; -*-
-
- ;; SPDX-License-Identifier: GPL-3.0-or-later
- ;; Copyright (C) 2013-2018 Yujie Wen and contributors to org-reveal, see:
- ;; https://github.com/yjwen/org-reveal/commits/master
- ;; Copyright (C) 2017-2019 Jens Lechtenbörger
- ;; Copyright (C) 2019 Naoya Yamashita <conao3@gmail.com>
- ;; Copyright (C) 2019 Ayush Goyal <perfectayush@gmail.com>
-
- ;; URL: https://gitlab.com/oer/org-re-reveal
- ;; Version: 2.12.0
- ;; Package-Requires: ((emacs "24.4") (org "8.3") (htmlize "1.34"))
- ;; Keywords: tools, outlines, hypermedia, slideshow, presentation, OER
-
- ;; This file is not part of GNU Emacs.
-
- ;;; License:
- ;; 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 GNU Emacs; see the file COPYING.
- ;; If not, see http://www.gnu.org/licenses/ or write to the
- ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- ;; Boston, MA 02110-1301, USA.
-
- ;;; Commentary:
- ;; This package provides Org export functionality to generate HTML
- ;; presentations with the presentation framework reveal.js.
- ;;
- ;; Quickstart:
- ;; 0. Install reveal.js: https://revealjs.com/
- ;; 1. Activate org-re-reveal.
- ;; (a) Place this directory into your load path or install it from MELPA
- ;; (https://melpa.org/#/getting-started).
- ;; (b) Load package manually ("M-x load-library" followed by
- ;; "org-re-reveal") or place "(require 'org-re-reveal)" into your
- ;; ~/.emacs and restart or customize org-export-backends by adding
- ;; the symbol re-reveal.
- ;; 2. Load an Org file and export it to HTML.
- ;; (a) Make sure that reveal.js is available in your current directory
- ;; (e.g., as sub-directory or symbolic link).
- ;; (b) Load "Readme.org" (coming with org-re-reveal).
- ;; (c) Export to HTML: Press "C-c C-e v v" (write HTML file) or
- ;; "C-c C-e v b" (write HTML file and open in browser)
- ;; See "Readme.org" for introduction, details, and features added to
- ;; org-reveal.
- ;;
- ;; Note that emacs-reveal offers a project that embeds org-re-reveal,
- ;; reveal.js, and various reveal.js plugins:
- ;; https://gitlab.com/oer/emacs-reveal
- ;; Its howto, generated from Org source file in GitLab CI environment:
- ;; https://oer.gitlab.io/emacs-reveal-howto/howto.html
- ;;
- ;; The package org-re-reveal grew out of a forked version of org-reveal
- ;; when upstream development stopped:
- ;; https://github.com/yjwen/org-reveal/issues/349
- ;; https://github.com/yjwen/org-reveal/issues/342
-
- ;;; Code:
-
- (require 'ox-html)
- (require 'cl-lib) ; cl-mapcar and autoloads for:
- ; cl-loop, cl-letf, cl-assert, cl-case, cl-every,
- ; cl-delete-duplicates, cl-remove-if
- (require 'subr-x) ; string-trim
- (require 'url-parse)
- (require 'url-util)
-
- (defvar org-re-reveal-keys) ; Silence byte compiler
-
- (defun org-re-reveal-define-backend ()
- "Define the back-end for export as reveal.js presentation."
- (org-export-define-derived-backend 're-reveal 'html
-
- :menu-entry
- `(,(nth 0 org-re-reveal-keys) "Export to reveal.js HTML Presentation"
- ((,(nth 1 org-re-reveal-keys)
- "To file" org-re-reveal-export-to-html)
- (,(nth 2 org-re-reveal-keys)
- "To file and browse" org-re-reveal-export-to-html-and-browse)
- (,(nth 3 org-re-reveal-keys)
- "Current subtree to file" org-re-reveal-export-current-subtree)))
-
- :options-alist ; See org-export-options-alist for meaning of parts.
- '((:reveal-center nil "reveal_center" org-re-reveal-center t)
- (:reveal-control nil "reveal_control" org-re-reveal-control t)
- (:reveal-defaulttiming nil "reveal_defaulttiming" org-re-reveal-defaulttiming t)
- (:reveal-fragmentinurl nil "reveal_fragmentinurl" org-re-reveal-fragmentinurl t)
- (:reveal-generate-ids nil "reveal_generate_ids" org-re-reveal-generate-custom-ids t)
- (:reveal-hashonebasedindex nil "reveal_hashonebasedindex" org-re-reveal-hashonebasedindex t)
- (:reveal-height nil "reveal_height" org-re-reveal-height t)
- (:reveal-history nil "reveal_history" org-re-reveal-history t)
- (:reveal-inter-presentation-links nil "reveal_inter_presentation_links" org-re-reveal-inter-presentation-links t)
- (:reveal-keyboard nil "reveal_keyboard" org-re-reveal-keyboard t)
- (:reveal-klipsify-src nil "reveal_klipsify_src" org-re-reveal-klipsify-src t)
- (:reveal-mousewheel nil "reveal_mousewheel" org-re-reveal-mousewheel t)
- (:reveal-overview nil "reveal_overview" org-re-reveal-overview t)
- (:reveal-pdfseparatefragments nil "reveal_pdfseparatefragments" org-re-reveal-pdfseparatefragments t)
- (:reveal-progress nil "reveal_progress" org-re-reveal-progress t)
- (:reveal-rolling-links nil "reveal_rolling_links" org-re-reveal-rolling-links t)
- (:reveal-single-file nil "reveal_single_file" org-re-reveal-single-file t)
- (:reveal-slide-global-footer nil "reveal_global_footer" org-re-reveal-global-footer t)
- (:reveal-slide-global-header nil "reveal_global_header" org-re-reveal-global-header t)
- (:reveal-slide-number nil "reveal_slide_number" org-re-reveal-slide-number t)
- (:reveal-slide-toc-footer nil "reveal_toc_footer" org-re-reveal-toc-footer t)
- (:reveal-subtree-with-title-slide nil "reveal_subtree_with_title_slide" org-re-reveal-subtree-with-title-slide t)
- (:reveal-width nil "reveal_width" org-re-reveal-width t)
- (:reveal-academic-title "REVEAL_ACADEMIC_TITLE" nil nil t)
- (:reveal-codemirror-config "REVEAL_CODEMIRROR_CONFIG" nil org-re-reveal-klipse-codemirror newline)
- (:reveal-default-frag-style "REVEAL_DEFAULT_FRAG_STYLE" nil org-re-reveal-default-frag-style t)
- (:reveal-default-slide-background "REVEAL_DEFAULT_SLIDE_BACKGROUND" nil nil t)
- (:reveal-default-slide-background-position "REVEAL_DEFAULT_SLIDE_BACKGROUND_POSITION" nil nil t)
- (:reveal-default-slide-background-repeat "REVEAL_DEFAULT_SLIDE_BACKGROUND_REPEAT" nil nil t)
- (:reveal-default-slide-background-size "REVEAL_DEFAULT_SLIDE_BACKGROUND_SIZE" nil nil t)
- (:reveal-default-slide-background-transition "REVEAL_DEFAULT_SLIDE_BACKGROUND_TRANSITION" nil nil t)
- (:reveal-external-plugins "REVEAL_EXTERNAL_PLUGINS" nil org-re-reveal-external-plugins t)
- (:reveal-extra-attr "REVEAL_EXTRA_ATTR" nil org-re-reveal-extra-attr nil)
- (:reveal-extra-css "REVEAL_EXTRA_CSS" nil org-re-reveal-extra-css newline)
- (:reveal-extra-js "REVEAL_EXTRA_JS" nil org-re-reveal-extra-js nil)
- (:reveal-extra-options "REVEAL_EXTRA_OPTIONS" nil org-re-reveal-extra-options t)
- (:reveal-extra-scripts "REVEAL_EXTRA_SCRIPTS" nil org-re-reveal-extra-scripts nil)
- (:reveal-head-preamble "REVEAL_HEAD_PREAMBLE" nil org-re-reveal-head-preamble newline)
- (:reveal-highlight-css "REVEAL_HIGHLIGHT_CSS" nil org-re-reveal-highlight-css nil)
- (:reveal-highlight-url "REVEAL_HIGHLIGHT_URL" nil org-re-reveal-highlight-url nil)
- (:reveal-hlevel "REVEAL_HLEVEL" nil nil t)
- (:reveal-init-script "REVEAL_INIT_SCRIPT" nil org-re-reveal-init-script space)
- (:reveal-klipse-css-url "REVEAL_KLIPSE_CSS_URL" nil org-re-reveal-klipse-css t)
- (:reveal-klipse-extra-config "REVEAL_KLIPSE_EXTRA_CONFIG" nil org-re-reveal-klipse-extra-config newline)
- (:reveal-klipse-js-url "REVEAL_KLIPSE_JS_URL" nil org-re-reveal-klipse-js t)
- (:reveal-klipse-setup "REVEAL_KLIPSE_SETUP" nil org-re-reveal-klipse-setup t)
- (:reveal-margin "REVEAL_MARGIN" nil org-re-reveal-margin t)
- (:reveal-mathjax-url "REVEAL_MATHJAX_URL" nil org-re-reveal-mathjax-url t)
- (:reveal-max-scale "REVEAL_MAX_SCALE" nil org-re-reveal-max-scale t)
- (:reveal-min-scale "REVEAL_MIN_SCALE" nil org-re-reveal-min-scale t)
- (:reveal-miscinfo "REVEAL_MISCINFO" nil nil t)
- (:reveal-multiplex-id "REVEAL_MULTIPLEX_ID" nil org-re-reveal-multiplex-id nil)
- (:reveal-multiplex-secret "REVEAL_MULTIPLEX_SECRET" nil org-re-reveal-multiplex-secret nil)
- (:reveal-multiplex-socketio-url "REVEAL_MULTIPLEX_SOCKETIO_URL" nil org-re-reveal-multiplex-socketio-url nil)
- (:reveal-multiplex-url "REVEAL_MULTIPLEX_URL" nil org-re-reveal-multiplex-url nil)
- (:reveal-plugins "REVEAL_PLUGINS" nil org-re-reveal-plugins t)
- (:reveal-postamble "REVEAL_POSTAMBLE" nil org-re-reveal-postamble t)
- (:reveal-preamble "REVEAL_PREAMBLE" nil org-re-reveal-preamble t)
- (:reveal-root "REVEAL_ROOT" nil org-re-reveal-root t)
- (:reveal-script-files "REVEAL_SCRIPT_FILES" nil org-re-reveal-script-files t)
- (:reveal-slide-footer "REVEAL_SLIDE_FOOTER" nil org-re-reveal-slide-footer t)
- (:reveal-slide-header "REVEAL_SLIDE_HEADER" nil org-re-reveal-slide-header t)
- (:reveal-speed "REVEAL_SPEED" nil org-re-reveal-transition-speed t)
- (:reveal-talk-qr-code "REVEAL_TALK_QR_CODE" nil nil t)
- (:reveal-talk-url "REVEAL_TALK_URL" nil nil t)
- (:reveal-theme "REVEAL_THEME" nil org-re-reveal-theme t)
- (:reveal-title-slide "REVEAL_TITLE_SLIDE" nil org-re-reveal-title-slide newline)
- (:reveal-title-slide-background "REVEAL_TITLE_SLIDE_BACKGROUND" nil nil t)
- (:reveal-title-slide-background-position "REVEAL_TITLE_SLIDE_BACKGROUND_POSITION" nil nil t)
- (:reveal-title-slide-background-repeat "REVEAL_TITLE_SLIDE_BACKGROUND_REPEAT" nil nil t)
- (:reveal-title-slide-background-size "REVEAL_TITLE_SLIDE_BACKGROUND_SIZE" nil nil t)
- (:reveal-title-slide-background-transition "REVEAL_TITLE_SLIDE_BACKGROUND_TRANSITION" nil nil t)
- (:reveal-title-slide-state "REVEAL_TITLE_SLIDE_STATE" nil nil t)
- (:reveal-title-slide-timing "REVEAL_TITLE_SLIDE_TIMING" nil nil t)
- (:reveal-toc-slide-class "REVEAL_TOC_SLIDE_CLASS" nil nil t)
- (:reveal-toc-slide-state "REVEAL_TOC_SLIDE_STATE" nil nil t)
- (:reveal-toc-slide-title "REVEAL_TOC_SLIDE_TITLE" nil org-re-reveal-toc-slide-title t)
- (:reveal-trans "REVEAL_TRANS" nil org-re-reveal-transition t))
-
- :translate-alist
- '((headline . org-re-reveal-headline)
- (inner-template . org-re-reveal-inner-template)
- (item . org-re-reveal-item)
- (keyword . org-re-reveal-keyword)
- (link . org-re-reveal-link)
- (latex-environment . org-re-reveal-latex-environment)
- (latex-fragment . (lambda (frag contents info)
- (setq info (plist-put info :reveal-mathjax t))
- (org-html-latex-fragment frag contents info)))
- (plain-list . org-re-reveal-plain-list)
- (quote-block . org-re-reveal-quote-block)
- (section . org-re-reveal-section)
- (src-block . org-re-reveal-src-block)
- (special-block . org-re-reveal-special-block)
- (template . org-re-reveal-template))
-
- :filters-alist '((:filter-parse-tree . org-re-reveal-filter-parse-tree))))
-
- (defun org-re-reveal-define-menu (symbol value)
- "Define back-end with (new) key bindings.
- SYMBOL must be `org-re-reveal-keys' and VALUE its new value."
- (let ((standard (eval (car (get symbol 'standard-value)))))
- (cl-assert
- (eq symbol 'org-re-reveal-keys) nil
- (format "Symbol in org-re-reveal-define-menu unexpected: %s" symbol))
- (cl-assert
- (= (length standard) (length value))
- (format "Value for org-re-reveal-keys must have length %s (same as standard), not %s"
- (length standard) (length value)))
- (set-default symbol value)
- (org-re-reveal-define-backend)))
-
- (defgroup org-export-re-reveal nil
- "Options for exporting Org files to reveal.js HTML pressentations."
- :tag "Org Export Reveal"
- :group 'org-export)
-
- (defcustom org-re-reveal-keys '(?v ?v ?b ?s)
- "Define keys for export with org-re-reveal.
- This list must contain four characters: The first one triggers export
- with org-re-reveal (after \\<org-mode-map> \\[org-export-dispatch]).
- The remaining three charaters each invoke a different export variant.
- One of those characters must be typed after the first one; the
- variants are, in sequence: Export to file, export to file followed by
- browsing that file, subtree export to file."
- :group 'org-export-re-reveal
- :type '(list (character :tag "Key to trigger export with org-re-reveal")
- (character :tag "Key for export to file")
- (character :tag "Key to browse file after export")
- (character :tag "Key for subtree export to file"))
- :set #'org-re-reveal-define-menu)
-
- (defcustom org-re-reveal-root "./reveal.js"
- "Specify root directory of reveal.js containing js/reveal.js."
- :group 'org-export-re-reveal
- :type '(radio (const :tag "Online at https://revealjs.com" "https://revealjs.com")
- (string :tag "Other directory path")))
-
- (defcustom org-re-reveal-script-files '("lib/js/head.min.js" "js/reveal.js")
- "Specify files to initialize reveal.js.
- Note that file names here are relative under `org-re-reveal-root'.
- On 2018-10-04, head.min.js was removed on the dev branch of reveal.js.
- If you are using a version including that removal, customize this variable
- to remove the first file name."
- :group 'org-export-re-reveal
- :type '(repeat string))
-
- (defcustom org-re-reveal-hlevel 1
- "Specify minimum level of headings for grouping into vertical slides."
- :group 'org-export-re-reveal
- :type 'integer)
-
- (defun org-re-reveal--get-hlevel (info)
- "Get HLevel value safely for INFO.
- If option \"REVEAL_HLEVEL\" is set, retrieve integer value from it,
- else get value from custom variable `org-re-reveal-hlevel'."
- (let ((hlevel-str (plist-get info :reveal-hlevel)))
- (if hlevel-str (string-to-number hlevel-str)
- org-re-reveal-hlevel)))
-
- (defcustom org-re-reveal-title-slide 'auto
- "If nil or empty string, do not insert a title slide.
- Otherwise (`auto' or non-empty string), insert title slide.
- When `auto', generate automatic title slide.
- When set to a string, use this string as format string for the title
- slide, where the following escaping elements are allowed:
-
- %t for the title.
- %s for the subtitle.
- %a for the author's name.
- %e for the author's email.
- %d for the date.
- %A for the author's academic title (set with #+REVEAL_ACADEMIC_TITLE).
- %q for the name of a file to a QR code (set with #+REVEAL_TALK_QR_CODE).
- %u for the URL of the presentation (set with #+REVEAL_TALK_URL).
- %m for misc information (set with #+REVEAL_MISCINFO).
- %% for a literal %.
-
- Alternatively, the string can also be the name of a file with the title
- slide's HTML code (containing the above escape sequences)."
- :group 'org-export-re-reveal
- :type '(choice (const :tag "No title slide" nil)
- (const :tag "Auto title slide" 'auto)
- (string :tag "Custom title slide")))
-
- (defcustom org-re-reveal-transition "convex"
- "Reveal transistion style."
- :group 'org-export-re-reveal
- :type '(radio (const "none")
- (const "fade")
- (const "slide")
- (const "convex")
- (const "concave")
- (const "zoom")
- (string :tag "Other transition")))
-
- (defcustom org-re-reveal-transition-speed "default"
- "Reveal transistion speed."
- :group 'org-export-re-reveal
- :type '(radio (const "default")
- (const "fast")
- (const "slow")
- (string :tag "Other transition speed")))
-
- (defcustom org-re-reveal-theme "black"
- "Reveal theme.
- Note that most themes load fonts from remote servers, which (a)
- obviously limits offline use of presentations and (b) is not privacy
- friendly. See URL `https://github.com/hakimel/reveal.js/issues/2491'
- and URL `https://github.com/google/fonts/issues/1495'."
- :group 'org-export-re-reveal
- :type '(radio (const "beige")
- (const "black")
- (const "blood")
- (const "league")
- (const "moon")
- (const "night")
- (const "serif")
- (const "simple")
- (const "sky")
- (const "solarized")
- (const "white")
- (string :tag "Other theme"))
- :package-version '(org-re-reveal . "2.8.1"))
-
- (defcustom org-re-reveal-extra-js ""
- "URL to extra JS file.
- If you use this variable, please take the time to report your current
- usage at URL `https://gitlab.com/oer/org-re-reveal/issues/31'."
- :group 'org-export-re-reveal
- :type 'string)
-
- (defcustom org-re-reveal-extra-scripts nil
- "List of extra scripts.
- Each list element can be the filename or URL of a JavaScript file or an
- entire HTML script element.
- If relative filenames are used, they must be relative to the presentation's
- HTML file."
- :group 'org-export-re-reveal
- :type '(repeat string)
- :package-version '(org-re-reveal . "2.10.0"))
- (make-obsolete-variable 'org-re-reveal-extra-js
- 'org-re-reveal-extra-scripts "org-re-reveal 2.9.0")
-
- (defcustom org-re-reveal-extra-attr nil
- "Global Reveal Extra Attrs for all slides."
- :group 'org-export-re-reveal
- :type '(choice
- string
- (const nil)))
-
- (defcustom org-re-reveal-extra-css ""
- "URL to extra css file."
- :group 'org-export-re-reveal
- :type 'string)
-
- (defcustom org-re-reveal-multiplex-id ""
- "The ID to use for multiplexing.
- E.g., per README of reveal.js 3.8.0, generate id and secrete by visiting
- URL `https://reveal-js-multiplex-ccjbegmaii.now.sh/'.
- To enable multiplex, see `org-re-reveal-plugins'."
- :group 'org-export-re-reveal
- :type 'string)
-
- (defcustom org-re-reveal-multiplex-secret ""
- "The secret to use for the master presentation.
- E.g., per README of reveal.js 3.8.0, generate id and secrete by visiting
- URL `https://reveal-js-multiplex-ccjbegmaii.now.sh/'.
- To enable multiplex, see `org-re-reveal-plugins'."
- :group 'org-export-re-reveal
- :type 'string)
-
- (defcustom org-re-reveal-multiplex-url
- "https://reveal-js-multiplex-ccjbegmaii.now.sh"
- "The url of the socketio server.
- To enable multiplex, see `org-re-reveal-plugins'."
- :group 'org-export-re-reveal
- :type 'string
- :package-version '(org-re-reveal . "2.1.0"))
-
- (defcustom org-re-reveal-multiplex-socketio-url
- "https://cdn.socket.io/socket.io-1.3.5.js"
- "The url of the socketio.js library.
- To enable multiplex, see `org-re-reveal-plugins'."
- :group 'org-export-re-reveal
- :type 'string
- :package-version '(org-re-reveal . "2.1.0"))
-
- (defcustom org-re-reveal-client-multiplex-filter nil
- "If non-nil, a regular expression to filter multiplex client publication.
- When using `org-re-reveal-publish-to-reveal-client', by default all Org
- files are also published as multiplex client files (which roughly
- doubles the amount of time necessary for publication). If you have got
- a mix of Org files that use multiplexing and that do not, set to this
- variable to a regular expression matching files for which a multiplex
- client file should be generated."
- :group 'org-export-re-reveal
- :type '(choice
- regexp
- (const nil))
- :package-version '(org-re-reveal . "2.12.0"))
-
- (defcustom org-re-reveal-control t
- "Reveal control applet."
- :group 'org-export-re-reveal
- :type 'boolean)
-
- (defcustom org-re-reveal-progress t
- "Reveal progress applet."
- :group 'org-export-re-reveal
- :type 'boolean)
-
- (defcustom org-re-reveal-history nil
- "Reveal history applet."
- :group 'org-export-re-reveal
- :type 'boolean)
-
- (defcustom org-re-reveal-center t
- "Reveal center applet."
- :group 'org-export-re-reveal
- :type 'boolean)
-
- (defcustom org-re-reveal-rolling-links nil
- "Reveal use rolling links."
- :group 'org-export-re-reveal
- :type 'boolean)
-
- (defcustom org-re-reveal-slide-number "c"
- "Reveal showing slide numbers."
- :group 'org-export-re-reveal
- :type '(radio (const :tag "horizontal . vertical slide number" "h.v")
- (const :tag "horizontal / vertical slide number" "h/v")
- (const :tag "flattened slide number" "c")
- (const :tag "flattened slide number / total slides" "c/t")
- (string :tag "Other slide number format")))
-
- (defcustom org-re-reveal-keyboard t
- "Reveal use keyboard navigation."
- :group 'org-export-re-reveal
- :type 'boolean)
-
- (defcustom org-re-reveal-mousewheel nil
- "Reveal use mousewheel navigation."
- :group 'org-export-re-reveal
- :type 'boolean)
-
- (defcustom org-re-reveal-fragmentinurl nil
- "Reveal use fragmentInURL setting."
- :group 'org-export-re-reveal
- :type 'boolean)
-
- (defcustom org-re-reveal-hashonebasedindex nil
- "Reveal use hashOneBasedIndex setting."
- :group 'org-export-re-reveal
- :type 'boolean)
-
- (defcustom org-re-reveal-pdfseparatefragments t
- "Reveal disable pdfSeparateFragments setting."
- :group 'org-export-re-reveal
- :type 'boolean)
-
- (defcustom org-re-reveal-defaulttiming nil
- "If non-nil, use defaultTiming for speaker notes view.
- For indivual timing of specific slides, use \"REVEAL_TITLE_SLIDE_TIMING\" for
- the title slide, and assign data-timing attributes to other headlines/slides."
- :group 'org-export-re-reveal
- :type '(choice integer (const nil)))
-
- (defcustom org-re-reveal-overview t
- "Reveal show overview."
- :group 'org-export-re-reveal
- :type 'boolean)
-
- (defcustom org-re-reveal-subtree-with-title-slide nil
- "If t, export title slide also for subtree exports."
- :group 'org-export-re-reveal
- :type 'boolean)
-
- (defcustom org-re-reveal-width nil
- "Slide width as positive integer (pixels) or string (percentage) or nil."
- :group 'org-export-re-reveal
- :type '(choice integer string (const nil))
- :package-version '(org-re-reveal . "1.1.4"))
-
- (defcustom org-re-reveal-height nil
- "Slide height as positive integer (pixels) or string (percentage) or nil."
- :group 'org-export-re-reveal
- :type '(choice integer string (const nil))
- :package-version '(org-re-reveal . "1.1.4"))
-
- (defcustom org-re-reveal-margin "-1"
- "Slide margin (in a string)."
- :group 'org-export-re-reveal
- :type 'string)
-
- (defcustom org-re-reveal-min-scale "-1"
- "Minimum bound for scaling slide (in a string)."
- :group 'org-export-re-reveal
- :type 'string)
-
- (defcustom org-re-reveal-max-scale "-1"
- "Maximum bound for scaling slide (in a string)."
- :group 'org-export-re-reveal
- :type 'string)
-
- (defcustom org-re-reveal-extra-options nil
- "Extra options to be passed to Reveal.initialize().
- Useful to specify options without keyword in org-re-reveal, e.g.,
- \"controlsTutorial: false, controlsLayout: 'edges'\".
- Individual options are separated by comma.
- For the current list of reveal.js options, see URL
- `https://github.com/hakimel/reveal.js/#configuration.'"
- :group 'org-export-re-reveal
- :type '(choice string (const nil)))
-
- (defcustom org-re-reveal-mathjax-url
- "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_HTMLorMML"
- "Default MathJax URL."
- :group 'org-export-re-reveal
- :type 'string)
-
- (defcustom org-re-reveal-preamble nil
- "Preamble contents."
- :group 'org-export-re-reveal
- :type '(choice (const nil) string))
-
- (defcustom org-re-reveal-head-preamble nil
- "Preamble contents for head part."
- :group 'org-export-re-reveal
- :type '(choice (const nil) string))
-
- (defcustom org-re-reveal-postamble nil
- "Postamble contents."
- :group 'org-export-re-reveal
- :type '(choice (const nil) string))
-
- (defcustom org-re-reveal-body-attrs nil
- "Attribute string to assign to body element.
- By default, no attributes are assigned."
- :group 'org-export-re-reveal
- :type '(choice (const nil) string))
-
- (defcustom org-re-reveal-slide-header nil
- "HTML content used as Reveal.js slide header."
- :group 'org-export-re-reveal
- :type '(choice (const nil) string))
-
- (defcustom org-re-reveal-slide-header-html "<div class=\"slide-header\">%s</div>\n"
- "HTML format string to construct slide footer."
- :group 'org-export-re-reveal
- :type 'string)
-
- (defcustom org-re-reveal-global-header nil
- "If non nil, display slide header also on title and toc slide.
- Header is defined by `org-re-reveal-slide-header'."
- :group 'org-export-re-reveal
- :type 'boolean)
-
- (defcustom org-re-reveal-global-footer nil
- "If non nil, display slide footer also on title and toc slide.
- Footer is defined by `org-re-reveal-slide-footer'."
- :group 'org-export-re-reveal
- :type 'boolean)
-
- (defcustom org-re-reveal-toc-footer nil
- "If non nil, display slide footer also on toc slide.
- Footer is defined by `org-re-reveal-slide-footer'."
- :group 'org-export-re-reveal
- :type 'boolean)
-
- (defcustom org-re-reveal-slide-footer nil
- "Specify HTML content used as Reveal.js slide footer."
- :group 'org-export-re-reveal
- :type '(choice (const nil) string))
-
- (defcustom org-re-reveal-slide-footer-html "<div class=\"slide-footer\">%s</div>\n"
- "HTML format string to construct slide footer.
- Must constain exactly one %-sequence \"%s\"."
- :group 'org-export-re-reveal
- :type 'string)
-
- (defcustom org-re-reveal-toc-slide-title "Table of Contents"
- "String to display as title of toc slide."
- :group 'org-export-re-reveal
- :type 'string)
-
- (defcustom org-re-reveal-default-frag-style nil
- "Default fragment style."
- :group 'org-export-re-reveal
- :type '(choice (const nil) string))
-
- (defcustom org-re-reveal-plugins
- '(markdown notes search zoom)
- "Default builtin plugins.
-
- By default, variables related to multiplex are hidden.
- Include 'multiplex in this variable to enable it.
-
- This variable, like any other variable, can be overridden
- in the org buffer comments as follows:
- #+REVEAL_PLUGINS: (markdown zoom notes multiplex)"
- :group 'org-export-re-reveal
- :type '(set
- (const markdown)
- (const highlight)
- (const zoom)
- (const notes)
- (const search)
- (const multiplex)
- (const :tag "classList (absent from modern reveal.js)" classList)
- (const :tag "remotes (absent from modern reveal.js)" remotes))
- :package-version '(org-re-reveal . "1.1.11"))
-
- (defcustom org-re-reveal-external-plugins nil
- "Additional third-party plugins to load with reveal.js.
- This is either an alist or a filename.
- In case of an alist, each entry should contain a name and an expression
- of the following form:
- \"{src: '%srelative/path/from/reveal/root', async:true/false,
- condition: jscallbackfunction(){}}\"
- In case of a file, its lines must be expressions of the above form.
- Note that some plugins have dependencies such as jquery; these must be
- included here as well, BEFORE the plugins that depend on them."
- :group 'org-export-re-reveal
- :type '(choice alist file))
-
- (defcustom org-re-reveal-single-file nil
- "Export presentation into one single HTML file.
- That file embeds JS scripts and pictures."
- :group 'org-export-re-reveal
- :type 'boolean)
-
- (defcustom org-re-reveal-inter-presentation-links nil
- "If non nil, try to convert links between presentations."
- :group 'org-export-re-reveal
- :type 'boolean)
-
- (defcustom org-re-reveal-init-script nil
- "Custom script to be passed to Reveal.initialize."
- :group 'org-export-re-reveal
- :type '(choice (const nil) string))
-
- (defcustom org-re-reveal-highlight-css "%r/lib/css/zenburn.css"
- "Hightlight.js CSS file."
- :group 'org-export-re-reveal
- :type 'string)
-
- (defcustom org-re-reveal-highlight-url nil
- "Location of Hightlight.js.
- If nil (default), the local plugin file is used."
- :group 'org-export-re-reveal
- :type '(choice (const nil) string))
-
- (defcustom org-re-reveal-note-key-char "n"
- "If not nil, register key for Org structure completion for speaker notes.
- When `<' followed by the key character are
- typed and then the completion key is pressed, which is usually
- `TAB', \"#+BEGIN_NOTES\" and \"#+END_NOTES\" is inserted (maybe in
- lower-case). See \"Readme.org\" how to make this work with Org version
- 9.2 or later.
-
- The default value is \"n\". Set the variable to nil to disable
- registering the completion."
- :group 'org-export-re-reveal
- :type '(choice (const nil) string))
-
- (defcustom org-re-reveal-no-htmlize-src nil
- "For syntax highlighting with org-re-reveal, three options exist:
- 1. Use reveal.js plugin highlight for syntax highlighting with highlight.js.
- This applies to all source code blocks.
- 2. If plugin highlight is not enabled, by default the library htmlize
- is used.
- 3. Do not use highlight and customize this variable to t.
- This disables syntax highlighting but you can activate htmlize for
- individual source code blocks with attributes:
- \"#+ATTR_REVEAL: :htmlize t\""
- :group 'org-export-re-reveal
- :type 'boolean)
-
- (defcustom org-re-reveal-klipsify-src nil
- "Set to non-nil to enable live code execution with klipse.
- See test-cases/test-klipsify.org in the source repository for examples.
- To export a source code block without klipse, use the following:
- \"#+ATTR_REVEAL: :no-klipsify t\""
- :group 'org-export-re-reveal
- :type 'boolean)
-
- (defcustom org-re-reveal-klipse-css "https://storage.googleapis.com/app.klipse.tech/css/codemirror.css"
- "Location of the codemirror css file for use with klipse."
- :group 'org-export-re-reveal
- :type 'string)
-
- (defcustom org-re-reveal-klipse-extra-css "<style>
- /* Position computations of klipse get confused by reveal.js's scaling.
- Hence, scaling should be disabled with this code. Fix height of code area
- with scrollbar (use overflow instead of overflow-y to restore CodeMirror
- setting afterwards): */
- .reveal section pre { max-height: 70vh; height: auto; overflow: auto; }
- /* Reset some reveal.js and oer-reveal settings: */
- .reveal section pre .CodeMirror pre { font-size: 2em; box-shadow: none; width: auto; padding: 0.4em; display: block; overflow: visible; }
- /* Enlarge cursor: */
- .CodeMirror-cursor { border-left: 3px solid black; }
- </style>\n"
- "CSS string to ensure compatibility between klipse and reveal.js."
- :group 'org-export-re-reveal
- :type 'string
- :package-version '(org-re-reveal . "2.0.1"))
-
- (defcustom org-re-reveal-klipse-codemirror nil
- "If not nil, a string to pass as CodeMirror options to \"klipse_setting\"."
- :group 'org-export-re-reveal
- :type '(choice (const nil) string))
-
- (defcustom org-re-reveal-klipse-js
- "https://storage.googleapis.com/app.klipse.tech/plugin/js/klipse_plugin.js"
- "Location of the klipse js source code.
- The minified version may not work, see URL
- `https://github.com/viebel/klipse/issues/334'."
- :group 'org-export-re-reveal
- :type 'string
- :package-version '(org-re-reveal . "1.1.11"))
-
- (defcustom org-re-reveal-klipse-setup
- '(("clojure" "selector" "language-klipse")
- ("html" "selector_eval_html" "language-klipse-html")
- ("javascript" "selector_eval_js" "language-klipse-javascript")
- ("js" "selector_eval_js" "language-klipse-js")
- ("php" "selector_eval_php" "language-klipse-php")
- ("python" "selector_eval_python_client" "language-klipse-python")
- ("ruby" "selector_eval_ruby" "language-klipse-ruby")
- ("scheme" "selector_eval_scheme" "language-klipse-scheme")
- ("sql" "selector_sql" "language-klipse-sql"))
- "Supported klipse languages with selectors.
- This is a list of triples (language selectorname selectorvalue).
- Each language needs to be the language of an Org source block.
- For existing names of klipse selectors, see URL
- `https://github.com/viebel/klipse/blob/master/README.md#page-level-configuration'.
- If additional languages work for you, maybe you could report that in issue #23
- at URL `https://gitlab.com/oer/org-re-reveal/issues/23'?"
- :group 'org-export-re-reveal
- :type '(repeat
- (list
- (string :tag "Language")
- (string :tag "Selector name")
- (string :tag "CSS class")))
- :package-version '(org-re-reveal . "1.1.11"))
-
- (defvar org-re-reveal-klipse-languages
- (mapcar #'car org-re-reveal-klipse-setup)
- "List of languages supported by org-re-reveal.")
-
- (defcustom org-re-reveal-klipse-extra-config nil
- "If not nil, extra JavaScript string to execute for klipse initialization.
- E.g., window.klipse_settings.editor_type = \"html\"; for SQL."
- :group 'org-export-re-reveal
- :type '(choice (const nil) string))
-
- (defcustom org-re-reveal-generate-custom-ids t
- "If t, generate CUSTOM_IDs for headings that don't have one.
- Set to nil to revert to old behavior, where HTML section elements have
- content hashes as \"id\" attributes, which change when slide contents
- change. With the default of t, generate CUSTOM_ID for headlines
- missing such a property, by using the value of the headline's number.
- This results in more stable URLs when working on presentations and
- reloading slides. You may want to set \"#+OPTIONS: reveal_history:t\"
- to see the section identifiers as URL fragments in the address bar,
- and you should not disable section numbering (for unnumbered
- headlines, hash IDs are used unless a CUSTOM_ID is present).
- For CSS code to hide section numbers if necessary, see
- URL `https://github.com/yjwen/org-reveal/pull/284'."
- :group 'org-export-re-reveal
- :type 'boolean
- :package-version '(org-re-reveal . "1.1.3"))
-
- (defvar org-re-reveal--slide-id-prefix "slide-"
- "Prefix to use in ID attributes of slide elements.")
-
- (defvar org-re-reveal--href-fragment-prefix
- (concat "/" org-re-reveal--slide-id-prefix)
- "Prefix to use when linking to specific slides.
- The default uses a slash between hash sign and slide ID,
- which leads to broken links that are not understood outside reveal.js.
- See there: https://github.com/hakimel/reveal.js/issues/2276")
-
- (defun org-re-reveal--if-format (fmt val)
- "Apply `format' to FMT and VAL if VAL is a non-empty string.
- Otherwise, return empty string."
- (if (and (stringp val) (> (length val) 0)) (format fmt val) ""))
-
- (defun org-re-reveal--frag-style (frag info)
- "Return fragment string according to FRAG and the default fragment style.
- FRAG is the fragment style set on element, INFO is a plist
- holding contextual information."
- (cond
- ((string= frag t)
- (let ((default-frag-style (plist-get info :reveal-default-frag-style)))
- (if default-frag-style (format "fragment %s" default-frag-style)
- "fragment")))
- (t (format "fragment %s" frag))))
-
- (defun org-re-reveal--frag-class (frag info)
- "Return proper HTML string description of fragment style.
- FRAG is the fragment style set on element, INFO is a plist
- holding contextual information."
- (and frag
- (format " class=\"%s\"" (org-re-reveal--frag-style frag info))))
-
- (defun org-re-reveal--frag-index (index)
- "Return attribute string for fragment INDEX if set."
- (and index
- (format " data-fragment-index=\"%s\"" index)))
-
- (defun org-re-reveal-special-block (special-block contents info)
- "Transcode a SPECIAL-BLOCK element from Org to Reveal.
- CONTENTS holds the contents of the block. INFO is a plist
- holding contextual information.
-
- If the block type is 'NOTES' (case-insensitive), transcode the block
- into a Reveal.js slide note. Otherwise, export the block as by the HTML
- exporter."
- (let ((block-type (org-element-property :type special-block)))
- (if (string= (downcase block-type) "notes")
- (format "<aside class=\"notes\">\n%s\n</aside>\n" contents)
- (org-html-special-block special-block contents info))))
-
- (defun org-re-reveal--add-class (elem value)
- "Add VALUE as \"class\" attribute in HTML header element ELEM.
- Do nothing if \"class\" attribute is already present."
- (let ((match (string-match "\\`<h[1-9][^>]+>" elem)))
- (unless match (error "Element no headline: %s" elem))
- (let ((tag (match-string 0 elem)))
- (if (string-match "class" tag)
- elem
- (replace-regexp-in-string "\\`\\(<h[1-9][^>]+\\)>"
- (format "\\1 class=\"%s\">" value)
- elem)))))
-
- (defun org-re-reveal--fix-html-headline (headline contents info)
- "Convert HEADLINE with CONTENTS and INFO to HTML.
- Call `org-html-headline' to generate initial HTML, remove surrounding
- \"div\" tags, and add class attribute to h-element if
- \":HTML_HEADLINE_CLASS\" property is present.
-
- Adding a class attribute in ox-reveal.el is a hack which is only
- necessary until that functionality has arrived in ox-html.el:
- https://lists.gnu.org/archive/html/emacs-orgmode/2018-12/msg00016.html
- As that patch has been accepted, the property is called
- \":HTML_HEADLINE_CLASS\". Otherwise, \":REVEAL_HEADLINE_CLASS\" would
- have been appropriate..."
- (let* ((class (org-element-property :HTML_HEADLINE_CLASS headline))
- (html (org-html-headline headline contents info))
- (nodiv
- (if (string-prefix-p "<div" html)
- ;; Remove the first <div> and the last </div> tags from html
- (concat "<"
- (mapconcat 'identity
- (butlast (cdr (split-string html "<" t)))
- "<"))
- ;; Return the HTML content unchanged
- html)))
- (if class
- (org-re-reveal--add-class nodiv class)
- nodiv)))
-
- (defun org-re-reveal--section-attrs (headline info)
- "Compute attributes for section element of HEADLINE with INFO.
- Return empty string or one starting with a space character."
- (let* ((default-slide-background (plist-get info :reveal-default-slide-background))
- (default-slide-background-size (plist-get info :reveal-default-slide-background-size))
- (default-slide-background-position (plist-get info :reveal-default-slide-background-position))
- (default-slide-background-repeat (plist-get info :reveal-default-slide-background-repeat))
- (default-slide-background-transition (plist-get info :reveal-default-slide-background-transition))
- (attrs (org-html--make-attribute-string
- `(:data-transition ,(org-element-property :REVEAL_DATA_TRANSITION headline)
- :data-state ,(org-element-property :REVEAL_DATA_STATE headline)
- :data-background ,(or (org-element-property :REVEAL_BACKGROUND headline)
- default-slide-background)
- :data-background-size ,(or (org-element-property :REVEAL_BACKGROUND_SIZE headline)
- default-slide-background-size)
- :data-background-position ,(or (org-element-property :REVEAL_BACKGROUND_POSITION headline)
- default-slide-background-position)
- :data-background-repeat ,(or (org-element-property :REVEAL_BACKGROUND_REPEAT headline)
- default-slide-background-repeat)
- :data-background-transition ,(or (org-element-property :REVEAL_BACKGROUND_TRANS headline)
- default-slide-background-transition)))))
- (if (> (length attrs) 0) (format " %s" attrs) "")))
-
- ;; Copied from org-html-headline and modified to embed org-re-reveal
- ;; specific attributes.
- (defun org-re-reveal-headline (headline contents info)
- "Transcode a HEADLINE element from Org to HTML.
- CONTENTS holds the contents of the headline. INFO is a plist
- holding contextual information."
- (unless (org-element-property :footnote-section-p headline)
- (if (or (org-export-low-level-p headline info)
- (org-element-property :NOSLIDE headline))
- ;; This is a deep sub-tree: export it as in ox-html.
- (org-html-headline headline contents info)
- ;; Standard headline. Export it as a slide
- (let* ((level (org-export-get-relative-level headline info))
- (preferred-id (or (org-element-property :CUSTOM_ID headline)
- (and (fboundp 'org-export-get-reference)
- (org-export-get-reference headline info))
- (org-element-property :ID headline)))
- (hlevel (org-re-reveal--get-hlevel info))
- (header (plist-get info :reveal-slide-header))
- (header-div (if header (format org-re-reveal-slide-header-html header) ""))
- (footer (plist-get info :reveal-slide-footer))
- (footer-div (if footer (format org-re-reveal-slide-footer-html footer) ""))
- (first-sibling (org-export-first-sibling-p headline info))
- (attrs (org-re-reveal--section-attrs headline info))
- (extra-attrs (or (org-element-property :REVEAL_EXTRA_ATTR headline)
- (plist-get info :reveal-extra-attr)))
- (slide-section-tag (format "<section id=\"%s\"%s%s>\n"
- (format "%s%s" org-re-reveal--slide-id-prefix preferred-id)
- attrs
- (if extra-attrs (format " %s" extra-attrs) "")))
- (ret (concat
- (if (or (/= level 1) (not first-sibling))
- ;; Not the first heading. Close previous slide.
- (concat
- ;; Slide footer if any.
- footer-div
- ;; Close previous slide.
- "</section>\n"
- (if (<= level hlevel)
- ;; Close previous vertical slide group.
- "</section>\n")))
- (if (<= level hlevel)
- ;; Add an extra "<section>" to group following slides
- ;; into vertical slide group. Transition override
- ;; attributes are attached at this level, too.
- (let ((attrs
- (org-html--make-attribute-string
- `(:data-transition ,(org-element-property :REVEAL_DATA_TRANSITION headline)))))
- (if (string= attrs "")
- "<section>\n"
- (format "<section %s>\n" attrs))))
- ;; Start a new slide.
- slide-section-tag
- ;; Slide header if any.
- header-div
- ;; The HTML content of the headline
- (org-re-reveal--fix-html-headline headline contents info)
- (if (and (= level 1)
- (org-export-last-sibling-p headline info))
- ;; Last head 1. Close all slides.
- (concat
- ;; Slide footer if any
- footer-div
- "</section>\n</section>\n")))))
- ret))))
-
- (defun org-re-reveal--read-list (thing)
- "Return THING if it is a list.
- Otherwise, `read' THING and return value if it is a list.
- Otherwise, raise an error."
- (if (listp thing)
- thing
- (let ((lthing (read thing)))
- (if (listp lthing)
- lthing
- (error "Expected a list, but got: %s" thing)))))
-
- (defun org-re-reveal--parse-listoption (info option)
- "Parse and return OPTION in INFO.
- That value for OPTION may be a list or a string representing a list."
- (org-re-reveal--read-list (plist-get info option)))
-
- (defun org-re-reveal--read-file (file)
- "Return the content of FILE."
- (with-temp-buffer
- (insert-file-contents-literally file)
- (buffer-string)))
-
- (defun org-re-reveal--file-url-to-path (url)
- "Convert URL that points to local files to file path."
- (replace-regexp-in-string
- (if (string-equal system-type "windows-nt") "^file:///" "^file://")
- "" url))
-
- (defun org-re-reveal--css-label (in-single-file file-name style-id)
- "Generate HTML code to include CSS file FILE-NAME.
- If IN-SINGLE-FILE is t, the content of FILE-NAME is embedded;
- otherwise, a `<link>' label is generated."
- (when (and file-name (not (string= file-name "")))
- (if in-single-file
- ;; Single-file
- (let ((local-file-name (org-re-reveal--file-url-to-path file-name)))
- (if (file-readable-p local-file-name)
- (concat "<style type=\"text/css\">\n"
- (org-re-reveal--read-file local-file-name)
- "\n</style>\n")
- ;; But file is not readable.
- (error "Cannot read %s" file-name)))
- ;; Not in-single-file
- (concat "<link rel=\"stylesheet\" href=\"" file-name "\""
- (if style-id (format " id=\"%s\"" style-id))
- "/>\n"))))
-
- (defun org-re-reveal--klipsify-header (info)
- "Return code (CSS and JavaScript) to activate klipse when indicated by INFO."
- (if (plist-get info :reveal-klipsify-src)
- (concat (format "<link rel=\"stylesheet\" href=\"%s\"/>\n"
- (plist-get info :reveal-klipse-css-url))
- org-re-reveal-klipse-extra-css
- (format "<script>
- window.klipse_settings = {
- %s%s
- };\n"
- (org-re-reveal--if-format
- "%s,\n" (plist-get info :reveal-codemirror-config))
- (mapconcat (lambda (elem)
- (format " %s: '.%s'"
- (nth 1 elem) (nth 2 elem)))
- (org-re-reveal--parse-listoption
- info :reveal-klipse-setup)
- ",\n"))
- (org-re-reveal--if-format
- " %s\n" (plist-get info :reveal-klipse-extra-config))
- "</script>\n")
- ""))
-
- (defun org-re-reveal--klipsify-script (info)
- "Return script element for klipse when indicated by INFO."
- (if (plist-get info :reveal-klipsify-src)
- (format "<script src=\"%s\"></script>
- <script>
- /* Recompute layout upon changes by klipse. Code fragment from
- asciidoctor-revealjs-klipse by Timothy Pratley under GPLv3:
- https://github.com/timothypratley/asciidoctor-revealjs-klipse/blob/master/docs/docinfo-footer.html */
- Reveal.addEventListener( 'slidechanged', function( event ) {
- window.dispatchEvent( new Event('resize') );
- } );
- </script>\n" (plist-get info :reveal-klipse-js-url))
- ""))
-
- (defun org-re-reveal-stylesheets (info)
- "Return HTML code for reveal stylesheets using INFO and `org-re-reveal-root'."
- (let* ((root-path (file-name-as-directory (plist-get info :reveal-root)))
- (reveal-css (concat root-path "css/reveal.css"))
- (theme (plist-get info :reveal-theme))
- (theme-css (concat root-path "css/theme/" theme ".css"))
- (extra-css (plist-get info :reveal-extra-css))
- (in-single-file (plist-get info :reveal-single-file)))
- (concat
- ;; Default embedded style sheets
- "<style type=\"text/css\">
- .underline { text-decoration: underline; }
- </style>
- "
- ;; stylesheets
- (mapconcat (lambda (elem) (org-re-reveal--css-label
- in-single-file (car elem) (cdr elem)))
- (append (list (cons reveal-css nil)
- (cons theme-css "theme"))
- (mapcar (lambda (a) (cons a nil))
- (cl-delete-duplicates
- (split-string extra-css "\n" t)
- :test #'equal)))
- "\n")
-
- ;; Include CSS for highlight.js if necessary
- (if (org-re-reveal--using-highlight.js info)
- (format "<link rel=\"stylesheet\" href=\"%s\"/>\n"
- (format-spec (plist-get info :reveal-highlight-css)
- `((?r . ,(directory-file-name root-path)))))
- "")
-
- ;; Include CSS for klipse if necessary
- (org-re-reveal--klipsify-header info)
-
- ;; print-pdf
- (if in-single-file ""
- (format "\n<!-- If the query includes 'print-pdf', include the PDF print sheet -->
- <script>
- if( window.location.search.match( /print-pdf/gi ) ) {
- var link = document.createElement( 'link' );
- link.rel = 'stylesheet';
- link.type = 'text/css';
- link.href = '%scss/print/pdf.css';
- document.getElementsByTagName( 'head' )[0].appendChild( link );
- }
- </script>
- "
- root-path)))))
-
- (defun org-re-reveal-mathjax-scripts (info)
- "Return HTML code for declaring MathJax scripts for INFO."
- (if (plist-get info :reveal-mathjax)
- ;; MathJax enabled.
- (format "<script type=\"text/javascript\" src=\"%s\"></script>\n"
- (plist-get info :reveal-mathjax-url))))
-
- (defun org-re-reveal--read-file-as-string (filename)
- "If FILENAME exists as file, return its contents as string.
- Otherwise, return nil."
- (when (and (stringp filename)
- (file-readable-p filename)
- (not (file-directory-p filename)))
- (with-temp-buffer
- (insert-file-contents-literally filename)
- (buffer-string))))
-
- (defun org-re-reveal--external-plugins-maybe-from-file (info)
- "Create list of plugin dependencies from INFO.
- In INFO, `:reveal-external-plugins' can be a list or a filename.
- If it is a filename, split lines to produce a list."
- (let* ((external-plugins (plist-get info :reveal-external-plugins))
- (file-contents (org-re-reveal--read-file-as-string external-plugins)))
- (if file-contents
- (mapcar (lambda (line) (cons 'dummy line))
- (split-string (string-trim file-contents) "\n"))
- (org-re-reveal--read-list external-plugins))))
-
- (defun org-re-reveal--external-plugin-init (info root-path)
- "Build initialization strings for plugins of INFO under ROOT-PATH.
- Parameter INFO determines plugins and their initializations
- based on `org-re-reveal-external-plugins'."
- (let ((plugins (org-re-reveal--external-plugins-maybe-from-file info)))
- (cl-loop for (nil . value) in plugins
- collect (format value root-path))))
-
- (defvar org-re-reveal-client-multiplex nil
- "Used to cause generation of client html file for multiplex.")
-
- (defun org-re-reveal-scripts--libraries (info)
- "Internal function to generate script tags with INFO.
- This includes reveal.js libraries in `org-re-reveal-script-files' under
- `org-re-reveal-root', and libraries in `org-re-reveal-extra-scripts'."
- (let* ((root-path (file-name-as-directory (plist-get info :reveal-root)))
- (script-files (org-re-reveal--parse-listoption
- info :reveal-script-files))
- (root-libs (mapcar (lambda (file) (concat root-path file))
- script-files))
- (extra-scripts (org-re-reveal--parse-listoption
- info :reveal-extra-scripts))
- ;; Treat extra scripts not starting with <script> as filenames.
- (extra-script-files
- (cl-remove-if (lambda (s) (string-prefix-p "<script>" s))
- extra-scripts))
- ;; Treat extra scripts starting with <script> as elements.
- (extra-script-elements
- (cl-remove-if-not (lambda (s) (string-prefix-p "<script>" s))
- extra-scripts))
- (in-single-file (plist-get info :reveal-single-file)))
- (concat
- (if in-single-file
- (let* ((local-root-path (org-re-reveal--file-url-to-path root-path))
- (local-libs (append (mapcar (lambda (file)
- (concat local-root-path file))
- script-files)
- extra-script-files))
- (local-libs-exist-p (cl-every #'file-readable-p local-libs)))
- (if local-libs-exist-p
- ;; Embed contents of files.
- (mapconcat (lambda (file)
- (format "<script>\n%s\n</script>\n"
- (org-re-reveal--read-file file)))
- local-libs "")
- (error
- (concat "Cannot read "
- (mapconcat 'identity
- (cl-remove-if #'file-readable-p local-libs)
- ", ")))))
- ;; Embed script files with src.
- (mapconcat (lambda (file)
- (concat "<script src=\"" file "\"></script>\n"))
- (append root-libs extra-script-files) ""))
- ;; Embed script tags.
- (mapconcat 'identity extra-script-elements "\n")
- (if extra-script-elements "\n" ""))))
-
- (defun org-re-reveal-scripts--reveal-options (info)
- "Internal function for `org-re-reveal-scripts' with INFO."
- (format "
- controls: %s,
- progress: %s,
- history: %s,
- center: %s,
- slideNumber: %s,
- rollingLinks: %s,
- keyboard: %s,
- mouseWheel: %s,
- fragmentInURL: %s,
- hashOneBasedIndex: %s,
- pdfSeparateFragments: %s,
- %s
- overview: %s,
- "
- (if (plist-get info :reveal-control) "true" "false")
- (if (plist-get info :reveal-progress) "true" "false")
- (if (plist-get info :reveal-history) "true" "false")
- (if (plist-get info :reveal-center) "true" "false")
- (let ((slide-number (plist-get info :reveal-slide-number)))
- (if slide-number (format "'%s'" slide-number)
- "false"))
- (if (plist-get info :reveal-rolling-links) "true" "false")
- (if (plist-get info :reveal-keyboard) "true" "false")
- (if (plist-get info :reveal-mousewheel) "true" "false")
- (if (plist-get info :reveal-fragmentinurl) "true" "false")
- (if (plist-get info :reveal-hashonebasedindex) "true" "false")
- (if (plist-get info :reveal-pdfseparatefragments) "true" "false")
- (let ((timing (plist-get info :reveal-defaulttiming)))
- (if timing (format "defaultTiming: %s," timing)
- ""))
- (if (plist-get info :reveal-overview) "true" "false")))
-
- (defun org-re-reveal--to-string (option)
- "Return OPTION as string.
- If OPTION is an integer > 0, return as string.
- If OPTION is a string, embed in quotation marks.
- If OPTION is nil, return nil (not the empty string).
- Otherwise, raise error."
- (cond ((and (integerp option) (> option 0)) (format "%d" option))
- ((stringp option) (format "\"%s\"" option))
- ((eq option nil) nil)
- (t (error "Option »%s« must be string, positive integer, or nil; not %s"
- option (type-of option)))))
-
- (defun org-re-reveal-scripts--main-configures (info)
- "Internal function for `org-re-reveal-scripts' with INFO."
- (concat
- ;; slide width
- (let ((width (plist-get info :reveal-width)))
- (org-re-reveal--if-format "width: %s,\n"
- (org-re-reveal--to-string width)))
-
- ;; slide height
- (let ((height (plist-get info :reveal-height)))
- (org-re-reveal--if-format "height: %s,\n"
- (org-re-reveal--to-string height)))
-
- ;; slide margin
- (let ((margin (string-to-number (plist-get info :reveal-margin))))
- (if (>= margin 0) (format "margin: %.2f,\n" margin) ""))
-
- ;; slide minimum scaling factor
- (let ((min-scale (string-to-number (plist-get info :reveal-min-scale))))
- (if (> min-scale 0) (format "minScale: %.2f,\n" min-scale) ""))
-
- ;; slide maximux scaling factor
- (let ((max-scale (string-to-number (plist-get info :reveal-max-scale))))
- (if (> max-scale 0) (format "maxScale: %.2f,\n" max-scale) ""))
-
- ;; thems and transitions
- (format "
- theme: Reveal.getQueryHash().theme, // available themes are in /css/theme
- transition: Reveal.getQueryHash().transition || '%s', // see README of reveal.js for options
- transitionSpeed: '%s',\n"
- (plist-get info :reveal-trans)
- (plist-get info :reveal-speed))
-
- (let ((options (plist-get info :reveal-extra-options)))
- (org-re-reveal--if-format "%s,\n" options))))
-
- (defun org-re-reveal-scripts--multiplex (info)
- "Internal function for `org-re-reveal-scripts' with INFO."
- (let ((enabled-builtin-plugins
- (org-re-reveal--parse-listoption info :reveal-plugins)))
- (when (memq 'multiplex enabled-builtin-plugins)
- (format
- "multiplex: {
- secret: %s, // null if client
- id: '%s', // id, obtained from socket.io server
- url: '%s' // Location of socket.io server
- },\n"
- (if (eq org-re-reveal-client-multiplex nil)
- (format "'%s'" (plist-get info :reveal-multiplex-secret))
- (format "null"))
- (plist-get info :reveal-multiplex-id)
- (plist-get info :reveal-multiplex-url)))))
-
- (defun org-re-reveal-scripts--dependencies (info)
- "Internal function for `org-re-reveal-scripts' with INFO."
- (let* ((root-path (file-name-as-directory (plist-get info :reveal-root)))
- (in-single-file (plist-get info :reveal-single-file))
- (enabled-builtin-plugins (org-re-reveal--parse-listoption
- info :reveal-plugins)))
- ;; optional JS library heading
- (if in-single-file ""
- (concat
- "
- // Optional libraries used to extend reveal.js
- dependencies: [
- "
- ;; JS libraries
- (let* ((highlight-url (plist-get info :reveal-highlight-url))
- (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 ,(if highlight-url
- (format " { src: '%s', async: true, callback: function() { hljs.initHighlightingOnLoad(); } }" highlight-url)
- (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 ,(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 defvar org-re-reveal-client-multiplex value state
- (if (not org-re-reveal-client-multiplex)
- (progn
- (if (not (string= "" (plist-get info :reveal-multiplex-secret)))
- (setq org-re-reveal-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) (plist-get builtins p)) enabled-builtin-plugins))
- (external-plugins
- (org-re-reveal--external-plugin-init info 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\n"))))
-
- (defun org-re-reveal-scripts--init-script (info)
- "Internal function for `org-re-reveal-scripts' with INFO."
- (let ((init-script (plist-get info :reveal-init-script))
- (in-single-file (plist-get info :reveal-single-file)))
- (if (and (stringp init-script) (> (length init-script) 0))
- (concat (if in-single-file "" ",") init-script)
- "")))
-
- (defun org-re-reveal-scripts (info)
- "Return necessary scripts to initialize reveal.js.
- Use INFO and custom variable `org-re-reveal-root'."
- (concat
- ;; Libraries in script tags, including reveal.js itself.
- (org-re-reveal-scripts--libraries info)
-
- ;; Create <script> tag for Reveal.initialize(...).
- "<script>
- // Full list of configuration options available here:
- // https://github.com/hakimel/reveal.js#configuration
- Reveal.initialize({
- "
- ;; plugin configures/frags
- (org-re-reveal-scripts--reveal-options info)
-
- ;; reveal.js main configures
- (org-re-reveal-scripts--main-configures info)
-
- ;; multiplexing - depends on defvar 'org-re-reveal-client-multiplex'
- (org-re-reveal-scripts--multiplex info)
-
- ;; load dependency js
- (org-re-reveal-scripts--dependencies info)
-
- ;; init-script
- (org-re-reveal-scripts--init-script info)
-
- ;; end of <script> tag
- "});\n</script>\n"))
-
- (defun org-re-reveal-toc (depth info)
- "Build a slide of table of contents with DEPTH and INFO."
- (let ((toc (org-html-toc depth info)))
- (org-re-reveal-toc-1 toc info)))
-
- (defun org-re-reveal-toc-1 (toc info)
- "Build table of contents with TOC and INFO."
- (when toc
- (let* ((toc-slide-with-header (plist-get info :reveal-slide-global-header))
- (toc-slide-with-footer (or
- (plist-get info :reveal-slide-global-footer)
- (plist-get info :reveal-slide-toc-footer)))
- (toc-slide-state (plist-get info :reveal-toc-slide-state))
- (toc-slide-class (plist-get info :reveal-toc-slide-class))
- (toc-slide-title (plist-get info :reveal-toc-slide-title))
- (toc (replace-regexp-in-string
- "<a href=\"#"
- (concat "<a href=\"#" org-re-reveal--href-fragment-prefix) toc))
- (toc (replace-regexp-in-string
- (org-html--translate "Table of Contents" info)
- toc-slide-title toc)))
- (concat "<section id=\"table-of-contents-section\""
- (when toc-slide-state
- (format " data-state=\"%s\"" toc-slide-state))
- ">\n"
- (when toc-slide-with-header
- (let ((header (plist-get info :reveal-slide-header)))
- (when header (format org-re-reveal-slide-header-html header))))
- (if toc-slide-class
- (replace-regexp-in-string
- "<h\\([1-3]\\)>"
- (format "<h\\1 class=\"%s\">" toc-slide-class)
- toc)
- toc)
- (when toc-slide-with-footer
- (let ((footer (plist-get info :reveal-slide-footer)))
- (when footer (format org-re-reveal-slide-footer-html footer))))
- "</section>\n"))))
-
- (defun org-re-reveal-inner-template (contents info)
- "Return body of document string after HTML conversion.
- CONTENTS is the transcoded contents string. INFO is a plist
- holding export options."
- (concat
- ;; Table of contents.
- (let ((depth (plist-get info :with-toc)))
- (when (and depth
- (not (plist-get info :reveal-subtree)))
- (org-re-reveal-toc depth info)))
- ;; Document contents.
- contents))
-
- (defun org-re-reveal-parse-keyword-value (value footer keyword info)
- "According to VALUE of KEYWORD and INFO, return HTML tags to split slides.
- Currently, only the keyword \"split\" is implemented, and VALUE must
- start with \"split\". Any following text is inserted literally into
- the section tag.
- The possibly empty FOOTER is inserted at the end of the slide."
- (cl-assert (string-prefix-p "split" value) nil
- (format "Unknown REVEAL keyword. Expected \"split\", got: %s"
- value))
- (let* ((headline (org-export-get-parent-headline keyword))
- (split-attrs (substring value 5)) ; Everything after "split"
- (real-attrs (if (< 0 (length split-attrs))
- split-attrs
- (org-re-reveal--section-attrs headline info))))
- (format "%s</section>\n<section%s>"
- footer real-attrs)))
-
- ;; Copied from org-html-format-list-item. Overwrite HTML class
- ;; attribute when there is attr_html attributes.
- (defun org-re-reveal-format-list-item (contents type checkbox attributes info
- &optional term-counter-id
- headline)
- "Format a list item into HTML based on INFO.
- Item has CONTENTS, TYPE, may be a CHECKBOX, have ATTRIBUTES, and may have
- TERM-COUNTER-ID and HEADLINE."
- (let ((attr-html (cond (attributes (format " %s" (org-html--make-attribute-string attributes)))
- (checkbox (format " class=\"%s\"" (symbol-name checkbox)))
- (t "")))
- (checkbox (concat (org-html-checkbox checkbox info)
- (and checkbox " ")))
- (br (org-html-close-tag "br" nil info)))
- (concat
- (cl-case type
- (ordered
- (let* ((counter term-counter-id)
- (extra (if counter (format " value=\"%s\"" counter) "")))
- (concat
- (format "<li%s%s>" attr-html extra)
- (when headline (concat headline br)))))
- (unordered
- (let* ((id term-counter-id)
- (extra (if id (format " id=\"%s\"" id) "")))
- (concat
- (format "<li%s%s>" attr-html extra)
- (when headline (concat headline br)))))
- (descriptive
- (let* ((term term-counter-id))
- (setq term (or term "(no term)"))
- ;; Check-boxes in descriptive lists are associated to tag.
- (concat (format "<dt%s>%s</dt>"
- attr-html (concat checkbox term))
- (format "<dd%s>" attr-html)))))
- (unless (eq type 'descriptive) checkbox)
- (and contents (org-trim contents))
- (cl-case type
- (ordered "</li>")
- (unordered "</li>")
- (descriptive "</dd>")))))
-
- ;; Copied from org-html-item, changed to call
- ;; org-re-reveal-format-list-item.
- (defun org-re-reveal-item (item contents info)
- "Transcode an ITEM element from Org to Reveal.
- CONTENTS holds the contents of the item. INFO is a plist holding
- contextual information."
- (let* ((plain-list (org-export-get-parent item))
- (type (org-element-property :type plain-list))
- (counter (org-element-property :counter item))
- (attributes (org-export-read-attribute :attr_html item))
- (checkbox (org-element-property :checkbox item))
- (tag (let ((tag (org-element-property :tag item)))
- (and tag (org-export-data tag info)))))
- (org-re-reveal-format-list-item
- contents type checkbox attributes info (or tag counter))))
-
- (defun org-re-reveal-keyword (keyword contents info)
- "Transcode a KEYWORD element from Org to Reveal.
- May change custom variables as SIDE EFFECT.
- CONTENTS is nil. INFO is a plist holding contextual information."
- (let* ((key (org-element-property :key keyword))
- (value (org-element-property :value keyword))
- (footer (plist-get info :reveal-slide-footer))
- (footer-div (if footer
- (format org-re-reveal-slide-footer-html footer) "")))
- (cl-case (intern key)
- (REVEAL (org-re-reveal-parse-keyword-value value footer-div keyword info))
- (REVEAL_HTML value)
- (HTML value)
- ;; Handling of TOC at arbitrary position is a hack.
- ;; We end the previous section by inserting a closing section tag,
- ;; which will *break* the presentation if other tags are still open.
- ;; To avoid unbalanced tags, remove the TOC's closing tag.
- ;; If slide footers are used, insert it before closing the section.
- ;; In any case, if footers are used, the one of the closed section
- ;; is sufficient, and the one contained in the TOC needs to be removed.
- (TOC (message "Please use #+REVEAL_TOC instead of #+TOC. See Readme.")
- (sit-for 2)
- (concat footer-div
- "</section>\n"
- (replace-regexp-in-string
- (format "</section>\\|%s"
- (format org-re-reveal-slide-footer-html ".*"))
- ""
- (org-re-reveal-toc-1
- (org-html-keyword keyword contents info) info))))
- (REVEAL_TOC
- ;; Following code stiched together with snippets from
- ;; org-html-keyword and org-html-toc.
- (when (string-match "\\<headlines\\>" value)
- (let* ((depth (and (string-match "\\<[0-9]+\\>" value)
- (string-to-number (match-string 0 value))))
- (toc-entries
- (mapcar (lambda (headline)
- (cons (org-html--format-toc-headline headline info)
- (org-export-get-relative-level headline info)))
- (org-export-collect-headlines info depth))))
- (when toc-entries
- (let ((toc (concat "<div id=\"text-table-of-contents\">"
- (org-html--toc-text toc-entries)
- "</div>\n")))
- ;; Use link format of reveal.js.
- (replace-regexp-in-string
- "<a href=\"#"
- (concat "<a href=\"#" org-re-reveal--href-fragment-prefix)
- toc)))))))))
-
- (defun org-re-reveal-embedded-svg (path)
- "Embed the SVG content at PATH into Reveal HTML."
- (with-temp-buffer
- (insert-file-contents-literally path)
- (let ((start (re-search-forward "<[ \t\n]*svg[ \t\n]"))
- (end (re-search-forward "<[ \t\n]*/svg[ \t\n]*>")))
- (concat "<svg " (buffer-substring-no-properties start end)))))
-
- (defun org-re-reveal--format-image-data-uri (link path info)
- "Generate the data URI for the image referenced by LINK at PATH with INFO."
- (let* ((ext (downcase (file-name-extension path))))
- (if (string= ext "svg")
- (org-re-reveal-embedded-svg path)
- (org-html-close-tag
- "img"
- (org-html--make-attribute-string
- (org-combine-plists
- (list :src
- (concat
- "data:image/"
- ;; Image type
- ext
- ";base64,"
- ;; Base64 content
- (with-temp-buffer
- (insert-file-contents-literally path)
- (base64-encode-region 1 (point-max))
- (buffer-string))))
- ;; Get attribute list from parent element
- ;; Copied from ox-html.el
- (let* ((parent (org-export-get-parent-element link))
- (link (let ((container (org-export-get-parent link)))
- (if (and (eq (org-element-type container) 'link)
- (org-html-inline-image-p link info))
- container
- link))))
- (and (eq (org-element-map parent 'link 'identity info t) link)
- (org-export-read-attribute :attr_html parent)))))
- info))))
-
- (defun org-re-reveal--maybe-replace-in-link (link allow-inter-link)
- "Replace hash sign in LINK, affected by ALLOW-INTER-LINK.
-
- If ALLOW-INTER-LINK is nil, only replace hash signs if URL in LINK starts
- with it. Otherwise, also replace if the URL does not contain a hostname;
- such links are assumed to point into other presentations."
- (if (and allow-inter-link
- (string-match "<a href=\"\\([^\"]*\\)\"" link))
- (let* ((url (match-string 1 link))
- (obj (url-generic-parse-url url))
- (host (url-host obj)))
- (if host
- link
- (replace-regexp-in-string
- "<a href=\"\\([^#]*\\)#"
- (concat "<a href=\"\\1#" org-re-reveal--href-fragment-prefix)
- link)))
- (replace-regexp-in-string
- "<a href=\"#"
- (concat "<a href=\"#" org-re-reveal--href-fragment-prefix)
- link)))
-
- (defun org-re-reveal--internal-link-class (link info)
- "Check if LINK is internal, given INFO, and maybe assign class.
- The direction of the link is assigned as class attribute to the link
- and to its parent via \"attr_html\":
- If link points backward (to previous content), class \"backwardlink\"
- is assigned, else \"forwardlink\".
- Assigning the class to \"attr_html\" of parent is based on a hack in
- `org-html-link', while use of \"attr_html\" of the link itself
- requires a version of org-mode as of 2018-12-08 or newer."
- (let ((target (or (ignore-errors (org-export-resolve-id-link link info))
- (ignore-errors (org-export-resolve-fuzzy-link link info)))))
- (when target
- (let* ((lbegin (org-element-property :begin link))
- (tbegin (org-element-property :begin target))
- (direction (if (< tbegin lbegin)
- "backwardlink"
- "forwardlink"))
- (parent (org-export-get-parent-element link))
- (attrs (org-combine-plists
- (org-export-read-attribute :attr_html parent)
- (org-export-read-attribute :attr_html link)))
- (class (plist-get attrs :class))
- (newclass (if class (concat direction " " class) direction))
- (newattrs (mapconcat (lambda (elem) (format "%s" elem))
- (plist-put attrs :class newclass)
- " ")))
- (org-element-put-property parent :attr_html (list newattrs))
- (org-element-put-property link :attr_html (list newattrs))))))
-
- (defun org-re-reveal-link (link desc info)
- "Transcode a LINK object with DESC and INFO from Org to Reveal.
- The result is identical to ox-html expect for image links.
- When `org-re-reveal-single-file' is t,
- the result is the Data URI of the referenced image."
- (let* ((want-embed-image (and (plist-get info :reveal-single-file)
- (plist-get info :html-inline-images)
- (string= "file" (org-element-property :type link))
- (org-export-inline-image-p
- link (plist-get info :html-inline-image-rules))))
- (allow-inter-link (plist-get info :reveal-inter-presentation-links))
- (raw-path (org-element-property :path link))
- (clean-path (org-re-reveal--file-url-to-path raw-path))
- (can-embed-image (and want-embed-image
- (file-readable-p clean-path))))
- (if can-embed-image
- (org-re-reveal--format-image-data-uri link clean-path info)
- (if want-embed-image
- (error "Cannot embed image %s" raw-path)
- (org-re-reveal--internal-link-class link info)
- (org-re-reveal--maybe-replace-in-link (org-html-link link desc info)
- allow-inter-link)))))
-
- (defun org-re-reveal-latex-environment (latex-env contents info)
- "Transcode a LaTeX environment from Org to Reveal.
- LATEX-ENV is the Org element. CONTENTS is the contents of the environment.
- INFO is a plist holding contextual information."
- (setq info (plist-put info :reveal-mathjax t))
- (let ((attrs (org-export-read-attribute :attr_html latex-env)))
- (format "<div%s>\n%s\n</div>\n"
- (if attrs (concat " " (org-html--make-attribute-string attrs)) "")
- (org-html-latex-environment latex-env contents info))))
-
- (defun org-re-reveal-plain-list (plain-list contents info)
- "Transcode a PLAIN-LIST element from Org to Reveal.
- CONTENTS is the contents of the list. INFO is a plist holding
- contextual information.
- Extract and set `attr_html' to plain-list tag attributes."
- (ignore info) ; Silence byte compiler
- (let ((tag (cl-case (org-element-property :type plain-list)
- (ordered "ol")
- (unordered "ul")
- (descriptive "dl")))
- (attrs (org-export-read-attribute :attr_html plain-list)))
- (format "%s<%s%s>\n%s\n</%s>%s"
- (if (string= org-html-checkbox-type 'html) "<form>" "")
- tag
- (if attrs (concat " " (org-html--make-attribute-string attrs)) "")
- contents
- tag
- (if (string= org-html-checkbox-type 'html) "</form>" ""))))
-
- (defun org-re-reveal-format-spec (info)
- "Return format specification with INFO.
- Formatting extends `org-html-format-spec' as follows:
- misc information and academic title."
- (append (org-html-format-spec info)
- `((?A . ,(org-export-data
- (plist-get info :reveal-academic-title) info))
- (?m . ,(org-export-data
- (plist-get info :reveal-miscinfo) info))
- (?q . ,(url-encode-url
- (org-export-data
- (plist-get info :reveal-talk-qr-code) info)))
- (?u . ,(url-encode-url
- (org-export-data
- (plist-get info :reveal-talk-url) info))))))
-
- (defun org-re-reveal--build-pre-postamble (type info)
- "Depending on TYPE, return preamble or postamble for INFO as string, or nil."
- (let ((section (plist-get info (intern (format ":reveal-%s" type))))
- (spec (org-re-reveal-format-spec info)))
- (when section
- (let ((section-contents
- (if (functionp (intern section)) (funcall (intern section) info)
- ;; else section is a string.
- (format-spec section spec))))
- (when (org-string-nw-p section-contents)
- (org-element-normalize-string section-contents))))))
-
-
- (defun org-re-reveal-section (section contents info)
- "Transcode a SECTION element from Org to Reveal.
- CONTENTS holds the contents of the section. INFO is a plist
- holding contextual information."
- ;; Just return the contents. No "<div>" tags.
- (ignore section info) ; Silence byte compiler
- contents)
-
- (defun org-re-reveal--using-highlight.js (info)
- "Check with INFO whether highlight.js plugin is enabled."
- (let ((reveal-plugins (condition-case nil
- (car (read-from-string (plist-get info :reveal-plugins)))
- (end-of-file nil)
- (wrong-type-argument nil))))
- (memq 'highlight (or (and reveal-plugins (listp reveal-plugins) reveal-plugins)
- org-re-reveal-plugins))))
-
- (defun org-re-reveal--buffer-substring-html-escape (start end)
- "Convert buffer substring characters from plain text to HTML equivalent.
- START and END are character positions as used by `buffer-substring'.
- Conversion is done by escaping special HTML chars."
- (org-html-encode-plain-text (buffer-substring start end)))
-
- (defun org-re-reveal-src-block (src-block contents info)
- "Transcode a SRC-BLOCK element from Org to Reveal.
- INFO is a plist holding contextual information. CONTENTS is unused."
- (ignore contents) ; Silence byte compiler
- (if (org-export-read-attribute :attr_html src-block :textarea)
- (org-html--textarea-block src-block)
- (let* ((use-highlight (org-re-reveal--using-highlight.js info))
- (use-htmlize (or (not org-re-reveal-no-htmlize-src)
- (org-export-read-attribute
- :attr_reveal src-block :htmlize)))
- (lang (org-element-property :language src-block))
- (caption (org-export-get-caption src-block))
- (code (if (and (not use-highlight) use-htmlize)
- (org-html-format-code src-block info)
- (cl-letf (((symbol-function
- 'org-html-htmlize-region-for-paste)
- #'org-re-reveal--buffer-substring-html-escape))
- (org-html-format-code src-block info))))
- (frag (org-export-read-attribute :attr_reveal src-block :frag))
- (findex (org-export-read-attribute :attr_reveal src-block :frag_idx))
- (code-attribs (or (org-export-read-attribute
- :attr_reveal src-block :code_attribs) ""))
- (label (let ((lbl (org-element-property :name src-block)))
- (if (not lbl) ""
- (format " id=\"%s\"" lbl))))
- (klipse-setup (org-re-reveal--parse-listoption
- info :reveal-klipse-setup))
- (klipsify (and (member lang (mapcar #'car klipse-setup))
- (plist-get info :reveal-klipsify-src)
- (not (org-export-read-attribute
- :attr_reveal src-block :no-klipsify)))))
- (if (not lang)
- (format "<pre %s%s>\n%s</pre>"
- (or (org-re-reveal--frag-class frag info) " class=\"example\"")
- label
- code)
- (if klipsify
- (let* ((triple (assoc lang klipse-setup))
- (selectorclass (nth 2 triple)))
- (concat
- "<pre><code class=\"" selectorclass "\" " code-attribs ">\n"
- (if (string= lang "html")
- (replace-regexp-in-string
- "'" "'"
- (replace-regexp-in-string
- "<" "<"
- (replace-regexp-in-string
- ">" ">"
- (replace-regexp-in-string
- "&" "&"
- (cl-letf (((symbol-function
- 'org-html-htmlize-region-for-paste)
- #'buffer-substring))
- (org-html-format-code src-block info))))))
- (replace-regexp-in-string "'" "'" code))
- "</code></pre>\n"))
- (format
- "<div class=\"org-src-container\">\n%s%s\n</div>"
- (if (not caption) ""
- (format "<label class=\"org-src-name\">%s</label>"
- (org-export-data caption info)))
- (if use-highlight
- (format "\n<pre%s%s><code class=\"%s %s\" %s>%s</code></pre>"
- (or (org-re-reveal--frag-class frag info) "")
- (or (org-re-reveal--frag-index findex) "")
- label lang code-attribs code)
- (format "\n<pre %s%s%s>%s</pre>"
- (or (org-re-reveal--frag-class frag info)
- (format " class=\"src src-%s\"" lang))
- (or (org-re-reveal--frag-index findex) "")
- label code))))))))
-
- (defun org-re-reveal-quote-block (quote-block contents info)
- "Transcode a QUOTE-BLOCK element from Org to Reveal.
- CONTENTS holds the contents of the block INFO is a plist holding
- contextual information."
- (format "<blockquote%s>\n%s</blockquote>"
- (let ((frag (org-re-reveal--frag-class
- (org-export-read-attribute
- :attr_reveal quote-block :frag) info)))
- (if frag
- (concat " " frag)
- ""))
- contents))
-
-
- (defun org-re-reveal--auto-title-slide-template (info)
- "Generate the automatic title slide template with INFO."
- (let* ((spec (org-re-reveal-format-spec info))
- (title (org-export-data (plist-get info :title) info))
- (author (cdr (assq ?a spec)))
- (email (cdr (assq ?e spec)))
- (date (cdr (assq ?d spec))))
- (concat
- (when (and (plist-get info :with-title)
- (org-string-nw-p title))
- (concat "<h1 class=\"title\">" title "</h1>"))
- (when (and (plist-get info :with-author)
- (org-string-nw-p author))
- (concat "<h2 class=\"author\">" author "</h2>"))
- (when (and (plist-get info :with-email)
- (org-string-nw-p email))
- (concat "<h2 class=\"email\">" email "</h2>"))
- (when (and (plist-get info :with-date)
- (org-string-nw-p date))
- (concat "<h2 class=\"date\">" date "</h2>"))
- (when (plist-get info :time-stamp-file)
- (concat "<p class=\"date\">"
- (org-html--translate "Created" info)
- ": "
- (format-time-string
- (plist-get info :html-metadata-timestamp-format))
- "</p>")))))
-
- (defun org-re-reveal-template (contents info)
- "Return complete document string after HTML conversion.
- CONTENTS is the transcoded contents string.
- INFO is a plist holding export options."
- (concat
- (format "<!DOCTYPE html>\n<html%s>\n<head>\n"
- (org-re-reveal--if-format " lang=\"%s\"" (plist-get info :language)))
- "<meta charset=\"utf-8\"/>\n"
- (org-re-reveal--if-format "<title>%s</title>\n"
- (org-export-data (plist-get info :title) info))
- (org-re-reveal--if-format "<meta name=\"author\" content=\"%s\"/>\n"
- (org-element-interpret-data (plist-get info :author)))
- (org-re-reveal--if-format "<meta name=\"description\" content=\"%s\"/>\n"
- (plist-get info :description))
- (org-re-reveal--if-format "<meta name=\"keywords\" content=\"%s\"/>\n"
- (plist-get info :keywords))
- (org-re-reveal-stylesheets info)
- (org-re-reveal-mathjax-scripts info)
- (org-re-reveal--build-pre-postamble 'head-preamble info)
- (org-element-normalize-string (plist-get info :html-head))
- (org-element-normalize-string (plist-get info :html-head-extra))
- "</head>\n<body"
- (org-re-reveal--if-format " %s" org-re-reveal-body-attrs)
- ">\n"
- (org-re-reveal--build-pre-postamble 'preamble info)
- "<div class=\"reveal\">
- <div class=\"slides\">\n"
- ;; Title slides
- (let ((title-slide (plist-get info :reveal-title-slide)))
- (when (and (or (eq 'auto title-slide)
- (and (stringp title-slide) (< 0 (length title-slide))))
- (or (not (plist-get info :reveal-subtree))
- (plist-get info :reveal-subtree-with-title-slide)))
- (let ((title-slide-background (plist-get info :reveal-title-slide-background))
- (title-slide-background-size (plist-get info :reveal-title-slide-background-size))
- (title-slide-background-position (plist-get info :reveal-title-slide-background-position))
- (title-slide-background-repeat (plist-get info :reveal-title-slide-background-repeat))
- (title-slide-background-transition (plist-get info :reveal-title-slide-background-transition))
- (title-slide-state (plist-get info :reveal-title-slide-state))
- (title-slide-timing (plist-get info :reveal-title-slide-timing))
- (title-slide-with-header (plist-get info :reveal-slide-global-header))
- (title-slide-with-footer (plist-get info :reveal-slide-global-footer)))
- (concat "<section id=\"sec-title-slide\""
- (when title-slide-background
- (concat " data-background=\"" title-slide-background "\""))
- (when title-slide-background-size
- (concat " data-background-size=\"" title-slide-background-size "\""))
- (when title-slide-background-position
- (concat " data-background-position=\"" title-slide-background-position "\""))
- (when title-slide-background-repeat
- (concat " data-background-repeat=\"" title-slide-background-repeat "\""))
- (when title-slide-background-transition
- (concat " data-background-transition=\"" title-slide-background-transition "\""))
- (when title-slide-state
- (concat " data-state=\"" title-slide-state "\""))
- (when title-slide-timing
- (concat " data-timing=\"" title-slide-timing "\""))
- ">\n"
- (when title-slide-with-header
- (let ((header (plist-get info :reveal-slide-header)))
- (when header (format org-re-reveal-slide-header-html header))))
- (cond ((eq title-slide nil) nil)
- ((stringp title-slide)
- (let* ((file-contents
- (org-re-reveal--read-file-as-string title-slide))
- (title-string (or file-contents title-slide)))
- (format-spec title-string
- (org-re-reveal-format-spec info))))
- ((eq title-slide 'auto) (org-re-reveal--auto-title-slide-template info)))
- "\n"
- (when title-slide-with-footer
- (let ((footer (plist-get info :reveal-slide-footer)))
- (when footer (format org-re-reveal-slide-footer-html footer))))
- "</section>\n"))))
- contents
- "</div>
- </div>\n"
- (org-re-reveal--build-pre-postamble 'postamble info)
- (org-re-reveal-scripts info)
- (org-re-reveal--klipsify-script info)
- "</body>
- </html>\n"))
-
- (defun org-re-reveal-filter-parse-tree (tree backend info)
- "Do filtering before parsing TREE.
- TREE is the parse tree being exported. BACKEND is the export
- back-end used. INFO is a plist-used as a communication channel.
- BACKEND must be (or be derived from) `re-reveal'.
- Modify the TREE in two ways:
- First, map each `attr_reveal' attribute to corresponding
- `attr_html' attributes.
- Second, if `org-re-reveal-generate-custom-ids' is t (or option
- \"reveal_generate_ids\" is t), generate \"CUSTOM_ID\" values for
- section headings that do not have one already."
- (cl-assert (org-export-derived-backend-p backend 're-reveal) nil
- (format "Function org-re-reveal-filter-parse-tree called on unexpected backend: %s" backend))
- (let ((default-frag-style (plist-get info :reveal-default-frag-style)))
- (org-element-map tree (remq 'item org-element-all-elements)
- (lambda (elem) (org-re-reveal-append-frag elem default-frag-style))))
- (when (plist-get info :reveal-generate-ids)
- (let ((numbering (org-export--collect-headline-numbering tree info)))
- (dolist (pair numbering nil)
- (let ((headline (car pair))
- (number (cdr pair)))
- (when (org-export-numbered-headline-p headline info)
- (let ((section-number (mapconcat #'number-to-string number "-")))
- (when (and (> (length section-number) 0)
- (not (org-element-property :CUSTOM_ID headline)))
- (org-element-put-property headline :CUSTOM_ID section-number))))))))
- ;; Return the updated tree.
- tree)
-
- (defun org-re-reveal--update-attr-html (elem frag default-style
- &optional frag-index frag-audio)
- "Update ELEM's attr_html attribute with reveal's fragment attributes.
- FRAG is the fragment style, a DEFAULT-STYLE may be used;
- optional FRAG-INDEX and FRAG-AUDIO may indicate fragment positions
- and audio files."
- (let ((attr-html (org-element-property :attr_html elem)))
- (when (and frag (not (string= frag "none")))
- (push (if (string= frag t)
- (if default-style (format ":class fragment %s" default-style)
- ":class fragment")
- (format ":class fragment %s" frag))
- attr-html)
- (when frag-index
- ;; Index positions should be numbers or the minus sign.
- (cl-assert (or (integerp frag-index)
- (eq frag-index '-)
- (and (not (listp frag-index))
- (not (char-equal
- (string-to-char frag-index) ?\())))
- nil "Index cannot be a list: %s" frag-index)
- (push (format ":data-fragment-index %s" frag-index) attr-html))
- (when (and frag-audio (not (string= frag-audio "none")))
- (push (format ":data-audio-src %s" frag-audio) attr-html)))
- (org-element-put-property elem :attr_html attr-html)))
-
- (defun org-re-reveal-append-frag (elem default-style)
- "Append transformed fragment from ELEM with DEFAULT-STYLE.
- Read fragment from ELEM and append transformed fragment attribute to ELEM's
- attr_html plist."
- (let ((frag (org-export-read-attribute :attr_reveal elem :frag))
- (frag-index (org-export-read-attribute :attr_reveal elem :frag_idx))
- (frag-audio (org-export-read-attribute :attr_reveal elem :audio)))
- (when frag
- (if (and (string= (org-element-type elem) 'plain-list)
- (char-equal (string-to-char frag) ?\())
- (let* ((items (org-element-contents elem))
- (frag-list (car (read-from-string frag)))
- (frag-list (if default-style
- (mapcar (lambda (s)
- "Replace t with default-style"
- (if (string= s t) default-style
- s))
- frag-list)
- frag-list))
- (itemno (length items))
- (style-list (make-list itemno default-style))
- ;; Make sure that we have enough fragments. Duplicate the
- ;; last element of frag-list so that frag-list and items
- ;; have the same length.
- (last-frag (car (last frag-list)))
- (tail-list (make-list
- (- itemno (length frag-list)) last-frag))
- (frag-list (append frag-list tail-list))
- ;; Concerning index positions and audio files, check later
- ;; that their number is OK.
- (frag-index (if frag-index
- (car (read-from-string frag-index))
- (make-list itemno nil)))
- (frag-audio (when frag-audio
- (car (read-from-string frag-audio)))))
- ;; As we are looking at fragments in lists, we make sure
- ;; that other specs are lists of proper length.
- (cl-assert (listp frag-index) t
- "Must use list for index positions, not: %s")
- (when frag-index
- (cl-assert (= (length frag-index) itemno) nil
- "Use one index per item! %s has %d, need %d"
- frag-index (length frag-index) (length items)))
- (cl-assert (listp frag-audio) t
- "Must use list for audio files! %s")
- (when frag-audio
- (cl-assert (= (length frag-audio) itemno) nil
- "Use one audio file per item! %s has %d, need %d"
- frag-audio (length frag-audio) itemno))
- (if frag-audio
- (cl-mapcar 'org-re-reveal--update-attr-html
- items frag-list style-list frag-index frag-audio)
- (cl-mapcar 'org-re-reveal--update-attr-html
- items frag-list style-list frag-index)))
- (org-re-reveal--update-attr-html
- elem frag default-style frag-index frag-audio))
- elem)))
-
- (defun org-re-reveal-export-to-html
- (&optional async subtreep visible-only body-only ext-plist backend)
- "Export current buffer to a reveal.js HTML file.
- Optional ASYNC, SUBTREEP, VISIBLE-ONLY, BODY-ONLY, EXT-PLIST are passed
- to `org-export-to-file'.
- Optional BACKEND must be `re-reveal' or a backend derived from it."
- (interactive)
- (let* ((backend (or backend 're-reveal))
- (extension (concat "." org-html-extension))
- (file (org-export-output-file-name extension subtreep))
- (clientfile (org-export-output-file-name (concat "_client" extension) subtreep))
- (org-html-container-element "div"))
-
- (setq org-re-reveal-client-multiplex nil)
- (org-export-to-file backend file
- async subtreep visible-only body-only ext-plist)
-
- ;; Export the client HTML file if org-re-reveal-client-multiplex is set true
- ;; by previous call to org-export-to-file
- (if org-re-reveal-client-multiplex
- (org-export-to-file backend clientfile
- async subtreep visible-only body-only ext-plist))
- file))
-
- (defun org-re-reveal-export-to-html-and-browse
- (&optional async subtreep visible-only body-only ext-plist)
- "Export current buffer to a reveal.js and browse HTML file.
- Optional ASYNC, SUBTREEP, VISIBLE-ONLY, BODY-ONLY, EXT-PLIST are passed
- to `org-re-reveal-export-to-html'."
- (interactive)
- (browse-url-of-file
- (expand-file-name
- (org-re-reveal-export-to-html
- async subtreep visible-only body-only ext-plist))))
-
- (defun org-re-reveal-export-current-subtree
- (&optional async subtreep visible-only body-only ext-plist)
- "Export current subtree to a Reveal.js HTML file.
- Optional ASYNC, SUBTREEP, VISIBLE-ONLY, BODY-ONLY, EXT-PLIST are passed
- to `org-re-reveal-export-to-html'."
- (interactive)
- (org-narrow-to-subtree)
- (let ((ret (org-re-reveal-export-to-html
- async subtreep visible-only body-only
- (plist-put ext-plist :reveal-subtree t))))
- (widen)
- ret))
-
- ;;;###autoload
- (defun org-re-reveal-publish-to-reveal
- (plist filename pub-dir &optional backend)
- "Publish an Org file to HTML.
- FILENAME is the filename of the Org file to be published. PLIST
- is the property list for the given project. PUB-DIR is the
- publishing directory. Optional BACKEND may specify a derived export
- backend.
- Return output file name."
- (let ((org-re-reveal-client-multiplex nil))
- (org-publish-org-to
- (or backend 're-reveal) filename ".html" plist pub-dir)))
-
- ;;;###autoload
- (defun org-re-reveal-publish-to-reveal-client
- (plist filename pub-dir &optional backend)
- "Publish an Org file to HTML as multiplex client.
- FILENAME is the filename of the Org file to be published. PLIST
- is the property list for the given project. PUB-DIR is the
- publishing directory. Optional BACKEND may specify a derived export
- backend.
- If `org-re-reveal-client-multiplex-filter' is non-nil, use it as regular
- expression to only publish FILENAME if it matches this regular expression.
- Return output file name."
- (if (or (not org-re-reveal-client-multiplex-filter)
- (string-match org-re-reveal-client-multiplex-filter filename))
- (let ((org-re-reveal-client-multiplex t))
- (org-publish-org-to
- (or backend 're-reveal) filename "_client.html" plist pub-dir))
- (message "File '%s' not published (not matched by '%s')."
- filename org-re-reveal-client-multiplex-filter)
- nil)
- :package-version '(org-re-reveal . "2.12.0"))
-
- ;; Register auto-completion for speaker notes.
- (when org-re-reveal-note-key-char
- (add-to-list 'org-structure-template-alist
- (if (version< org-version "9.2")
- (list org-re-reveal-note-key-char "#+BEGIN_NOTES\n\?\n#+END_NOTES")
- (cons org-re-reveal-note-key-char "notes"))))
-
- ;;; Extract version string.
- ;;;###autoload
- (defun org-re-reveal-version ()
- "Display version string for org-re-reveal from Lisp file."
- (interactive)
- (let ((lisp-file
- (concat (file-name-sans-extension (locate-library "org-re-reveal"))
- ".el")))
- (with-temp-buffer
- (insert-file-contents lisp-file)
- (goto-char (point-min))
- (re-search-forward "^;; Version: \\([0-9.]+\\)$")
- (message "org-re-reveal version %s" (match-string 1)))))
-
- (provide 'org-re-reveal)
- ;;; org-re-reveal.el ends here
|