Klimi's new dotfiles with stow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2140 lines
98 KiB

4 years ago
  1. ;;; org-re-reveal.el --- Org export to reveal.js presentations -*- lexical-binding: t; -*-
  2. ;; SPDX-License-Identifier: GPL-3.0-or-later
  3. ;; Copyright (C) 2013-2018 Yujie Wen and contributors to org-reveal, see:
  4. ;; https://github.com/yjwen/org-reveal/commits/master
  5. ;; Copyright (C) 2017-2019 Jens Lechtenbörger
  6. ;; Copyright (C) 2019 Naoya Yamashita <conao3@gmail.com>
  7. ;; Copyright (C) 2019 Ayush Goyal <perfectayush@gmail.com>
  8. ;; URL: https://gitlab.com/oer/org-re-reveal
  9. ;; Version: 2.12.0
  10. ;; Package-Requires: ((emacs "24.4") (org "8.3") (htmlize "1.34"))
  11. ;; Keywords: tools, outlines, hypermedia, slideshow, presentation, OER
  12. ;; This file is not part of GNU Emacs.
  13. ;;; License:
  14. ;; This program is free software; you can redistribute it and/or modify
  15. ;; it under the terms of the GNU General Public License as published by
  16. ;; the Free Software Foundation, either version 3 of the License, or
  17. ;; (at your option) any later version.
  18. ;; This program is distributed in the hope that it will be useful,
  19. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. ;; GNU General Public License for more details.
  22. ;; You should have received a copy of the GNU General Public License
  23. ;; along with GNU Emacs; see the file COPYING.
  24. ;; If not, see http://www.gnu.org/licenses/ or write to the
  25. ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  26. ;; Boston, MA 02110-1301, USA.
  27. ;;; Commentary:
  28. ;; This package provides Org export functionality to generate HTML
  29. ;; presentations with the presentation framework reveal.js.
  30. ;;
  31. ;; Quickstart:
  32. ;; 0. Install reveal.js: https://revealjs.com/
  33. ;; 1. Activate org-re-reveal.
  34. ;; (a) Place this directory into your load path or install it from MELPA
  35. ;; (https://melpa.org/#/getting-started).
  36. ;; (b) Load package manually ("M-x load-library" followed by
  37. ;; "org-re-reveal") or place "(require 'org-re-reveal)" into your
  38. ;; ~/.emacs and restart or customize org-export-backends by adding
  39. ;; the symbol re-reveal.
  40. ;; 2. Load an Org file and export it to HTML.
  41. ;; (a) Make sure that reveal.js is available in your current directory
  42. ;; (e.g., as sub-directory or symbolic link).
  43. ;; (b) Load "Readme.org" (coming with org-re-reveal).
  44. ;; (c) Export to HTML: Press "C-c C-e v v" (write HTML file) or
  45. ;; "C-c C-e v b" (write HTML file and open in browser)
  46. ;; See "Readme.org" for introduction, details, and features added to
  47. ;; org-reveal.
  48. ;;
  49. ;; Note that emacs-reveal offers a project that embeds org-re-reveal,
  50. ;; reveal.js, and various reveal.js plugins:
  51. ;; https://gitlab.com/oer/emacs-reveal
  52. ;; Its howto, generated from Org source file in GitLab CI environment:
  53. ;; https://oer.gitlab.io/emacs-reveal-howto/howto.html
  54. ;;
  55. ;; The package org-re-reveal grew out of a forked version of org-reveal
  56. ;; when upstream development stopped:
  57. ;; https://github.com/yjwen/org-reveal/issues/349
  58. ;; https://github.com/yjwen/org-reveal/issues/342
  59. ;;; Code:
  60. (require 'ox-html)
  61. (require 'cl-lib) ; cl-mapcar and autoloads for:
  62. ; cl-loop, cl-letf, cl-assert, cl-case, cl-every,
  63. ; cl-delete-duplicates, cl-remove-if
  64. (require 'subr-x) ; string-trim
  65. (require 'url-parse)
  66. (require 'url-util)
  67. (defvar org-re-reveal-keys) ; Silence byte compiler
  68. (defun org-re-reveal-define-backend ()
  69. "Define the back-end for export as reveal.js presentation."
  70. (org-export-define-derived-backend 're-reveal 'html
  71. :menu-entry
  72. `(,(nth 0 org-re-reveal-keys) "Export to reveal.js HTML Presentation"
  73. ((,(nth 1 org-re-reveal-keys)
  74. "To file" org-re-reveal-export-to-html)
  75. (,(nth 2 org-re-reveal-keys)
  76. "To file and browse" org-re-reveal-export-to-html-and-browse)
  77. (,(nth 3 org-re-reveal-keys)
  78. "Current subtree to file" org-re-reveal-export-current-subtree)))
  79. :options-alist ; See org-export-options-alist for meaning of parts.
  80. '((:reveal-center nil "reveal_center" org-re-reveal-center t)
  81. (:reveal-control nil "reveal_control" org-re-reveal-control t)
  82. (:reveal-defaulttiming nil "reveal_defaulttiming" org-re-reveal-defaulttiming t)
  83. (:reveal-fragmentinurl nil "reveal_fragmentinurl" org-re-reveal-fragmentinurl t)
  84. (:reveal-generate-ids nil "reveal_generate_ids" org-re-reveal-generate-custom-ids t)
  85. (:reveal-hashonebasedindex nil "reveal_hashonebasedindex" org-re-reveal-hashonebasedindex t)
  86. (:reveal-height nil "reveal_height" org-re-reveal-height t)
  87. (:reveal-history nil "reveal_history" org-re-reveal-history t)
  88. (:reveal-inter-presentation-links nil "reveal_inter_presentation_links" org-re-reveal-inter-presentation-links t)
  89. (:reveal-keyboard nil "reveal_keyboard" org-re-reveal-keyboard t)
  90. (:reveal-klipsify-src nil "reveal_klipsify_src" org-re-reveal-klipsify-src t)
  91. (:reveal-mousewheel nil "reveal_mousewheel" org-re-reveal-mousewheel t)
  92. (:reveal-overview nil "reveal_overview" org-re-reveal-overview t)
  93. (:reveal-pdfseparatefragments nil "reveal_pdfseparatefragments" org-re-reveal-pdfseparatefragments t)
  94. (:reveal-progress nil "reveal_progress" org-re-reveal-progress t)
  95. (:reveal-rolling-links nil "reveal_rolling_links" org-re-reveal-rolling-links t)
  96. (:reveal-single-file nil "reveal_single_file" org-re-reveal-single-file t)
  97. (:reveal-slide-global-footer nil "reveal_global_footer" org-re-reveal-global-footer t)
  98. (:reveal-slide-global-header nil "reveal_global_header" org-re-reveal-global-header t)
  99. (:reveal-slide-number nil "reveal_slide_number" org-re-reveal-slide-number t)
  100. (:reveal-slide-toc-footer nil "reveal_toc_footer" org-re-reveal-toc-footer t)
  101. (:reveal-subtree-with-title-slide nil "reveal_subtree_with_title_slide" org-re-reveal-subtree-with-title-slide t)
  102. (:reveal-width nil "reveal_width" org-re-reveal-width t)
  103. (:reveal-academic-title "REVEAL_ACADEMIC_TITLE" nil nil t)
  104. (:reveal-codemirror-config "REVEAL_CODEMIRROR_CONFIG" nil org-re-reveal-klipse-codemirror newline)
  105. (:reveal-default-frag-style "REVEAL_DEFAULT_FRAG_STYLE" nil org-re-reveal-default-frag-style t)
  106. (:reveal-default-slide-background "REVEAL_DEFAULT_SLIDE_BACKGROUND" nil nil t)
  107. (:reveal-default-slide-background-position "REVEAL_DEFAULT_SLIDE_BACKGROUND_POSITION" nil nil t)
  108. (:reveal-default-slide-background-repeat "REVEAL_DEFAULT_SLIDE_BACKGROUND_REPEAT" nil nil t)
  109. (:reveal-default-slide-background-size "REVEAL_DEFAULT_SLIDE_BACKGROUND_SIZE" nil nil t)
  110. (:reveal-default-slide-background-transition "REVEAL_DEFAULT_SLIDE_BACKGROUND_TRANSITION" nil nil t)
  111. (:reveal-external-plugins "REVEAL_EXTERNAL_PLUGINS" nil org-re-reveal-external-plugins t)
  112. (:reveal-extra-attr "REVEAL_EXTRA_ATTR" nil org-re-reveal-extra-attr nil)
  113. (:reveal-extra-css "REVEAL_EXTRA_CSS" nil org-re-reveal-extra-css newline)
  114. (:reveal-extra-js "REVEAL_EXTRA_JS" nil org-re-reveal-extra-js nil)
  115. (:reveal-extra-options "REVEAL_EXTRA_OPTIONS" nil org-re-reveal-extra-options t)
  116. (:reveal-extra-scripts "REVEAL_EXTRA_SCRIPTS" nil org-re-reveal-extra-scripts nil)
  117. (:reveal-head-preamble "REVEAL_HEAD_PREAMBLE" nil org-re-reveal-head-preamble newline)
  118. (:reveal-highlight-css "REVEAL_HIGHLIGHT_CSS" nil org-re-reveal-highlight-css nil)
  119. (:reveal-highlight-url "REVEAL_HIGHLIGHT_URL" nil org-re-reveal-highlight-url nil)
  120. (:reveal-hlevel "REVEAL_HLEVEL" nil nil t)
  121. (:reveal-init-script "REVEAL_INIT_SCRIPT" nil org-re-reveal-init-script space)
  122. (:reveal-klipse-css-url "REVEAL_KLIPSE_CSS_URL" nil org-re-reveal-klipse-css t)
  123. (:reveal-klipse-extra-config "REVEAL_KLIPSE_EXTRA_CONFIG" nil org-re-reveal-klipse-extra-config newline)
  124. (:reveal-klipse-js-url "REVEAL_KLIPSE_JS_URL" nil org-re-reveal-klipse-js t)
  125. (:reveal-klipse-setup "REVEAL_KLIPSE_SETUP" nil org-re-reveal-klipse-setup t)
  126. (:reveal-margin "REVEAL_MARGIN" nil org-re-reveal-margin t)
  127. (:reveal-mathjax-url "REVEAL_MATHJAX_URL" nil org-re-reveal-mathjax-url t)
  128. (:reveal-max-scale "REVEAL_MAX_SCALE" nil org-re-reveal-max-scale t)
  129. (:reveal-min-scale "REVEAL_MIN_SCALE" nil org-re-reveal-min-scale t)
  130. (:reveal-miscinfo "REVEAL_MISCINFO" nil nil t)
  131. (:reveal-multiplex-id "REVEAL_MULTIPLEX_ID" nil org-re-reveal-multiplex-id nil)
  132. (:reveal-multiplex-secret "REVEAL_MULTIPLEX_SECRET" nil org-re-reveal-multiplex-secret nil)
  133. (:reveal-multiplex-socketio-url "REVEAL_MULTIPLEX_SOCKETIO_URL" nil org-re-reveal-multiplex-socketio-url nil)
  134. (:reveal-multiplex-url "REVEAL_MULTIPLEX_URL" nil org-re-reveal-multiplex-url nil)
  135. (:reveal-plugins "REVEAL_PLUGINS" nil org-re-reveal-plugins t)
  136. (:reveal-postamble "REVEAL_POSTAMBLE" nil org-re-reveal-postamble t)
  137. (:reveal-preamble "REVEAL_PREAMBLE" nil org-re-reveal-preamble t)
  138. (:reveal-root "REVEAL_ROOT" nil org-re-reveal-root t)
  139. (:reveal-script-files "REVEAL_SCRIPT_FILES" nil org-re-reveal-script-files t)
  140. (:reveal-slide-footer "REVEAL_SLIDE_FOOTER" nil org-re-reveal-slide-footer t)
  141. (:reveal-slide-header "REVEAL_SLIDE_HEADER" nil org-re-reveal-slide-header t)
  142. (:reveal-speed "REVEAL_SPEED" nil org-re-reveal-transition-speed t)
  143. (:reveal-talk-qr-code "REVEAL_TALK_QR_CODE" nil nil t)
  144. (:reveal-talk-url "REVEAL_TALK_URL" nil nil t)
  145. (:reveal-theme "REVEAL_THEME" nil org-re-reveal-theme t)
  146. (:reveal-title-slide "REVEAL_TITLE_SLIDE" nil org-re-reveal-title-slide newline)
  147. (:reveal-title-slide-background "REVEAL_TITLE_SLIDE_BACKGROUND" nil nil t)
  148. (:reveal-title-slide-background-position "REVEAL_TITLE_SLIDE_BACKGROUND_POSITION" nil nil t)
  149. (:reveal-title-slide-background-repeat "REVEAL_TITLE_SLIDE_BACKGROUND_REPEAT" nil nil t)
  150. (:reveal-title-slide-background-size "REVEAL_TITLE_SLIDE_BACKGROUND_SIZE" nil nil t)
  151. (:reveal-title-slide-background-transition "REVEAL_TITLE_SLIDE_BACKGROUND_TRANSITION" nil nil t)
  152. (:reveal-title-slide-state "REVEAL_TITLE_SLIDE_STATE" nil nil t)
  153. (:reveal-title-slide-timing "REVEAL_TITLE_SLIDE_TIMING" nil nil t)
  154. (:reveal-toc-slide-class "REVEAL_TOC_SLIDE_CLASS" nil nil t)
  155. (:reveal-toc-slide-state "REVEAL_TOC_SLIDE_STATE" nil nil t)
  156. (:reveal-toc-slide-title "REVEAL_TOC_SLIDE_TITLE" nil org-re-reveal-toc-slide-title t)
  157. (:reveal-trans "REVEAL_TRANS" nil org-re-reveal-transition t))
  158. :translate-alist
  159. '((headline . org-re-reveal-headline)
  160. (inner-template . org-re-reveal-inner-template)
  161. (item . org-re-reveal-item)
  162. (keyword . org-re-reveal-keyword)
  163. (link . org-re-reveal-link)
  164. (latex-environment . org-re-reveal-latex-environment)
  165. (latex-fragment . (lambda (frag contents info)
  166. (setq info (plist-put info :reveal-mathjax t))
  167. (org-html-latex-fragment frag contents info)))
  168. (plain-list . org-re-reveal-plain-list)
  169. (quote-block . org-re-reveal-quote-block)
  170. (section . org-re-reveal-section)
  171. (src-block . org-re-reveal-src-block)
  172. (special-block . org-re-reveal-special-block)
  173. (template . org-re-reveal-template))
  174. :filters-alist '((:filter-parse-tree . org-re-reveal-filter-parse-tree))))
  175. (defun org-re-reveal-define-menu (symbol value)
  176. "Define back-end with (new) key bindings.
  177. SYMBOL must be `org-re-reveal-keys' and VALUE its new value."
  178. (let ((standard (eval (car (get symbol 'standard-value)))))
  179. (cl-assert
  180. (eq symbol 'org-re-reveal-keys) nil
  181. (format "Symbol in org-re-reveal-define-menu unexpected: %s" symbol))
  182. (cl-assert
  183. (= (length standard) (length value))
  184. (format "Value for org-re-reveal-keys must have length %s (same as standard), not %s"
  185. (length standard) (length value)))
  186. (set-default symbol value)
  187. (org-re-reveal-define-backend)))
  188. (defgroup org-export-re-reveal nil
  189. "Options for exporting Org files to reveal.js HTML pressentations."
  190. :tag "Org Export Reveal"
  191. :group 'org-export)
  192. (defcustom org-re-reveal-keys '(?v ?v ?b ?s)
  193. "Define keys for export with org-re-reveal.
  194. This list must contain four characters: The first one triggers export
  195. with org-re-reveal (after \\<org-mode-map> \\[org-export-dispatch]).
  196. The remaining three charaters each invoke a different export variant.
  197. One of those characters must be typed after the first one; the
  198. variants are, in sequence: Export to file, export to file followed by
  199. browsing that file, subtree export to file."
  200. :group 'org-export-re-reveal
  201. :type '(list (character :tag "Key to trigger export with org-re-reveal")
  202. (character :tag "Key for export to file")
  203. (character :tag "Key to browse file after export")
  204. (character :tag "Key for subtree export to file"))
  205. :set #'org-re-reveal-define-menu)
  206. (defcustom org-re-reveal-root "./reveal.js"
  207. "Specify root directory of reveal.js containing js/reveal.js."
  208. :group 'org-export-re-reveal
  209. :type '(radio (const :tag "Online at https://revealjs.com" "https://revealjs.com")
  210. (string :tag "Other directory path")))
  211. (defcustom org-re-reveal-script-files '("lib/js/head.min.js" "js/reveal.js")
  212. "Specify files to initialize reveal.js.
  213. Note that file names here are relative under `org-re-reveal-root'.
  214. On 2018-10-04, head.min.js was removed on the dev branch of reveal.js.
  215. If you are using a version including that removal, customize this variable
  216. to remove the first file name."
  217. :group 'org-export-re-reveal
  218. :type '(repeat string))
  219. (defcustom org-re-reveal-hlevel 1
  220. "Specify minimum level of headings for grouping into vertical slides."
  221. :group 'org-export-re-reveal
  222. :type 'integer)
  223. (defun org-re-reveal--get-hlevel (info)
  224. "Get HLevel value safely for INFO.
  225. If option \"REVEAL_HLEVEL\" is set, retrieve integer value from it,
  226. else get value from custom variable `org-re-reveal-hlevel'."
  227. (let ((hlevel-str (plist-get info :reveal-hlevel)))
  228. (if hlevel-str (string-to-number hlevel-str)
  229. org-re-reveal-hlevel)))
  230. (defcustom org-re-reveal-title-slide 'auto
  231. "If nil or empty string, do not insert a title slide.
  232. Otherwise (`auto' or non-empty string), insert title slide.
  233. When `auto', generate automatic title slide.
  234. When set to a string, use this string as format string for the title
  235. slide, where the following escaping elements are allowed:
  236. %t for the title.
  237. %s for the subtitle.
  238. %a for the author's name.
  239. %e for the author's email.
  240. %d for the date.
  241. %A for the author's academic title (set with #+REVEAL_ACADEMIC_TITLE).
  242. %q for the name of a file to a QR code (set with #+REVEAL_TALK_QR_CODE).
  243. %u for the URL of the presentation (set with #+REVEAL_TALK_URL).
  244. %m for misc information (set with #+REVEAL_MISCINFO).
  245. %% for a literal %.
  246. Alternatively, the string can also be the name of a file with the title
  247. slide's HTML code (containing the above escape sequences)."
  248. :group 'org-export-re-reveal
  249. :type '(choice (const :tag "No title slide" nil)
  250. (const :tag "Auto title slide" 'auto)
  251. (string :tag "Custom title slide")))
  252. (defcustom org-re-reveal-transition "convex"
  253. "Reveal transistion style."
  254. :group 'org-export-re-reveal
  255. :type '(radio (const "none")
  256. (const "fade")
  257. (const "slide")
  258. (const "convex")
  259. (const "concave")
  260. (const "zoom")
  261. (string :tag "Other transition")))
  262. (defcustom org-re-reveal-transition-speed "default"
  263. "Reveal transistion speed."
  264. :group 'org-export-re-reveal
  265. :type '(radio (const "default")
  266. (const "fast")
  267. (const "slow")
  268. (string :tag "Other transition speed")))
  269. (defcustom org-re-reveal-theme "black"
  270. "Reveal theme.
  271. Note that most themes load fonts from remote servers, which (a)
  272. obviously limits offline use of presentations and (b) is not privacy
  273. friendly. See URL `https://github.com/hakimel/reveal.js/issues/2491'
  274. and URL `https://github.com/google/fonts/issues/1495'."
  275. :group 'org-export-re-reveal
  276. :type '(radio (const "beige")
  277. (const "black")
  278. (const "blood")
  279. (const "league")
  280. (const "moon")
  281. (const "night")
  282. (const "serif")
  283. (const "simple")
  284. (const "sky")
  285. (const "solarized")
  286. (const "white")
  287. (string :tag "Other theme"))
  288. :package-version '(org-re-reveal . "2.8.1"))
  289. (defcustom org-re-reveal-extra-js ""
  290. "URL to extra JS file.
  291. If you use this variable, please take the time to report your current
  292. usage at URL `https://gitlab.com/oer/org-re-reveal/issues/31'."
  293. :group 'org-export-re-reveal
  294. :type 'string)
  295. (defcustom org-re-reveal-extra-scripts nil
  296. "List of extra scripts.
  297. Each list element can be the filename or URL of a JavaScript file or an
  298. entire HTML script element.
  299. If relative filenames are used, they must be relative to the presentation's
  300. HTML file."
  301. :group 'org-export-re-reveal
  302. :type '(repeat string)
  303. :package-version '(org-re-reveal . "2.10.0"))
  304. (make-obsolete-variable 'org-re-reveal-extra-js
  305. 'org-re-reveal-extra-scripts "org-re-reveal 2.9.0")
  306. (defcustom org-re-reveal-extra-attr nil
  307. "Global Reveal Extra Attrs for all slides."
  308. :group 'org-export-re-reveal
  309. :type '(choice
  310. string
  311. (const nil)))
  312. (defcustom org-re-reveal-extra-css ""
  313. "URL to extra css file."
  314. :group 'org-export-re-reveal
  315. :type 'string)
  316. (defcustom org-re-reveal-multiplex-id ""
  317. "The ID to use for multiplexing.
  318. E.g., per README of reveal.js 3.8.0, generate id and secrete by visiting
  319. URL `https://reveal-js-multiplex-ccjbegmaii.now.sh/'.
  320. To enable multiplex, see `org-re-reveal-plugins'."
  321. :group 'org-export-re-reveal
  322. :type 'string)
  323. (defcustom org-re-reveal-multiplex-secret ""
  324. "The secret to use for the master presentation.
  325. E.g., per README of reveal.js 3.8.0, generate id and secrete by visiting
  326. URL `https://reveal-js-multiplex-ccjbegmaii.now.sh/'.
  327. To enable multiplex, see `org-re-reveal-plugins'."
  328. :group 'org-export-re-reveal
  329. :type 'string)
  330. (defcustom org-re-reveal-multiplex-url
  331. "https://reveal-js-multiplex-ccjbegmaii.now.sh"
  332. "The url of the socketio server.
  333. To enable multiplex, see `org-re-reveal-plugins'."
  334. :group 'org-export-re-reveal
  335. :type 'string
  336. :package-version '(org-re-reveal . "2.1.0"))
  337. (defcustom org-re-reveal-multiplex-socketio-url
  338. "https://cdn.socket.io/socket.io-1.3.5.js"
  339. "The url of the socketio.js library.
  340. To enable multiplex, see `org-re-reveal-plugins'."
  341. :group 'org-export-re-reveal
  342. :type 'string
  343. :package-version '(org-re-reveal . "2.1.0"))
  344. (defcustom org-re-reveal-client-multiplex-filter nil
  345. "If non-nil, a regular expression to filter multiplex client publication.
  346. When using `org-re-reveal-publish-to-reveal-client', by default all Org
  347. files are also published as multiplex client files (which roughly
  348. doubles the amount of time necessary for publication). If you have got
  349. a mix of Org files that use multiplexing and that do not, set to this
  350. variable to a regular expression matching files for which a multiplex
  351. client file should be generated."
  352. :group 'org-export-re-reveal
  353. :type '(choice
  354. regexp
  355. (const nil))
  356. :package-version '(org-re-reveal . "2.12.0"))
  357. (defcustom org-re-reveal-control t
  358. "Reveal control applet."
  359. :group 'org-export-re-reveal
  360. :type 'boolean)
  361. (defcustom org-re-reveal-progress t
  362. "Reveal progress applet."
  363. :group 'org-export-re-reveal
  364. :type 'boolean)
  365. (defcustom org-re-reveal-history nil
  366. "Reveal history applet."
  367. :group 'org-export-re-reveal
  368. :type 'boolean)
  369. (defcustom org-re-reveal-center t
  370. "Reveal center applet."
  371. :group 'org-export-re-reveal
  372. :type 'boolean)
  373. (defcustom org-re-reveal-rolling-links nil
  374. "Reveal use rolling links."
  375. :group 'org-export-re-reveal
  376. :type 'boolean)
  377. (defcustom org-re-reveal-slide-number "c"
  378. "Reveal showing slide numbers."
  379. :group 'org-export-re-reveal
  380. :type '(radio (const :tag "horizontal . vertical slide number" "h.v")
  381. (const :tag "horizontal / vertical slide number" "h/v")
  382. (const :tag "flattened slide number" "c")
  383. (const :tag "flattened slide number / total slides" "c/t")
  384. (string :tag "Other slide number format")))
  385. (defcustom org-re-reveal-keyboard t
  386. "Reveal use keyboard navigation."
  387. :group 'org-export-re-reveal
  388. :type 'boolean)
  389. (defcustom org-re-reveal-mousewheel nil
  390. "Reveal use mousewheel navigation."
  391. :group 'org-export-re-reveal
  392. :type 'boolean)
  393. (defcustom org-re-reveal-fragmentinurl nil
  394. "Reveal use fragmentInURL setting."
  395. :group 'org-export-re-reveal
  396. :type 'boolean)
  397. (defcustom org-re-reveal-hashonebasedindex nil
  398. "Reveal use hashOneBasedIndex setting."
  399. :group 'org-export-re-reveal
  400. :type 'boolean)
  401. (defcustom org-re-reveal-pdfseparatefragments t
  402. "Reveal disable pdfSeparateFragments setting."
  403. :group 'org-export-re-reveal
  404. :type 'boolean)
  405. (defcustom org-re-reveal-defaulttiming nil
  406. "If non-nil, use defaultTiming for speaker notes view.
  407. For indivual timing of specific slides, use \"REVEAL_TITLE_SLIDE_TIMING\" for
  408. the title slide, and assign data-timing attributes to other headlines/slides."
  409. :group 'org-export-re-reveal
  410. :type '(choice integer (const nil)))
  411. (defcustom org-re-reveal-overview t
  412. "Reveal show overview."
  413. :group 'org-export-re-reveal
  414. :type 'boolean)
  415. (defcustom org-re-reveal-subtree-with-title-slide nil
  416. "If t, export title slide also for subtree exports."
  417. :group 'org-export-re-reveal
  418. :type 'boolean)
  419. (defcustom org-re-reveal-width nil
  420. "Slide width as positive integer (pixels) or string (percentage) or nil."
  421. :group 'org-export-re-reveal
  422. :type '(choice integer string (const nil))
  423. :package-version '(org-re-reveal . "1.1.4"))
  424. (defcustom org-re-reveal-height nil
  425. "Slide height as positive integer (pixels) or string (percentage) or nil."
  426. :group 'org-export-re-reveal
  427. :type '(choice integer string (const nil))
  428. :package-version '(org-re-reveal . "1.1.4"))
  429. (defcustom org-re-reveal-margin "-1"
  430. "Slide margin (in a string)."
  431. :group 'org-export-re-reveal
  432. :type 'string)
  433. (defcustom org-re-reveal-min-scale "-1"
  434. "Minimum bound for scaling slide (in a string)."
  435. :group 'org-export-re-reveal
  436. :type 'string)
  437. (defcustom org-re-reveal-max-scale "-1"
  438. "Maximum bound for scaling slide (in a string)."
  439. :group 'org-export-re-reveal
  440. :type 'string)
  441. (defcustom org-re-reveal-extra-options nil
  442. "Extra options to be passed to Reveal.initialize().
  443. Useful to specify options without keyword in org-re-reveal, e.g.,
  444. \"controlsTutorial: false, controlsLayout: 'edges'\".
  445. Individual options are separated by comma.
  446. For the current list of reveal.js options, see URL
  447. `https://github.com/hakimel/reveal.js/#configuration.'"
  448. :group 'org-export-re-reveal
  449. :type '(choice string (const nil)))
  450. (defcustom org-re-reveal-mathjax-url
  451. "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_HTMLorMML"
  452. "Default MathJax URL."
  453. :group 'org-export-re-reveal
  454. :type 'string)
  455. (defcustom org-re-reveal-preamble nil
  456. "Preamble contents."
  457. :group 'org-export-re-reveal
  458. :type '(choice (const nil) string))
  459. (defcustom org-re-reveal-head-preamble nil
  460. "Preamble contents for head part."
  461. :group 'org-export-re-reveal
  462. :type '(choice (const nil) string))
  463. (defcustom org-re-reveal-postamble nil
  464. "Postamble contents."
  465. :group 'org-export-re-reveal
  466. :type '(choice (const nil) string))
  467. (defcustom org-re-reveal-body-attrs nil
  468. "Attribute string to assign to body element.
  469. By default, no attributes are assigned."
  470. :group 'org-export-re-reveal
  471. :type '(choice (const nil) string))
  472. (defcustom org-re-reveal-slide-header nil
  473. "HTML content used as Reveal.js slide header."
  474. :group 'org-export-re-reveal
  475. :type '(choice (const nil) string))
  476. (defcustom org-re-reveal-slide-header-html "<div class=\"slide-header\">%s</div>\n"
  477. "HTML format string to construct slide footer."
  478. :group 'org-export-re-reveal
  479. :type 'string)
  480. (defcustom org-re-reveal-global-header nil
  481. "If non nil, display slide header also on title and toc slide.
  482. Header is defined by `org-re-reveal-slide-header'."
  483. :group 'org-export-re-reveal
  484. :type 'boolean)
  485. (defcustom org-re-reveal-global-footer nil
  486. "If non nil, display slide footer also on title and toc slide.
  487. Footer is defined by `org-re-reveal-slide-footer'."
  488. :group 'org-export-re-reveal
  489. :type 'boolean)
  490. (defcustom org-re-reveal-toc-footer nil
  491. "If non nil, display slide footer also on toc slide.
  492. Footer is defined by `org-re-reveal-slide-footer'."
  493. :group 'org-export-re-reveal
  494. :type 'boolean)
  495. (defcustom org-re-reveal-slide-footer nil
  496. "Specify HTML content used as Reveal.js slide footer."
  497. :group 'org-export-re-reveal
  498. :type '(choice (const nil) string))
  499. (defcustom org-re-reveal-slide-footer-html "<div class=\"slide-footer\">%s</div>\n"
  500. "HTML format string to construct slide footer.
  501. Must constain exactly one %-sequence \"%s\"."
  502. :group 'org-export-re-reveal
  503. :type 'string)
  504. (defcustom org-re-reveal-toc-slide-title "Table of Contents"
  505. "String to display as title of toc slide."
  506. :group 'org-export-re-reveal
  507. :type 'string)
  508. (defcustom org-re-reveal-default-frag-style nil
  509. "Default fragment style."
  510. :group 'org-export-re-reveal
  511. :type '(choice (const nil) string))
  512. (defcustom org-re-reveal-plugins
  513. '(markdown notes search zoom)
  514. "Default builtin plugins.
  515. By default, variables related to multiplex are hidden.
  516. Include 'multiplex in this variable to enable it.
  517. This variable, like any other variable, can be overridden
  518. in the org buffer comments as follows:
  519. #+REVEAL_PLUGINS: (markdown zoom notes multiplex)"
  520. :group 'org-export-re-reveal
  521. :type '(set
  522. (const markdown)
  523. (const highlight)
  524. (const zoom)
  525. (const notes)
  526. (const search)
  527. (const multiplex)
  528. (const :tag "classList (absent from modern reveal.js)" classList)
  529. (const :tag "remotes (absent from modern reveal.js)" remotes))
  530. :package-version '(org-re-reveal . "1.1.11"))
  531. (defcustom org-re-reveal-external-plugins nil
  532. "Additional third-party plugins to load with reveal.js.
  533. This is either an alist or a filename.
  534. In case of an alist, each entry should contain a name and an expression
  535. of the following form:
  536. \"{src: '%srelative/path/from/reveal/root', async:true/false,
  537. condition: jscallbackfunction(){}}\"
  538. In case of a file, its lines must be expressions of the above form.
  539. Note that some plugins have dependencies such as jquery; these must be
  540. included here as well, BEFORE the plugins that depend on them."
  541. :group 'org-export-re-reveal
  542. :type '(choice alist file))
  543. (defcustom org-re-reveal-single-file nil
  544. "Export presentation into one single HTML file.
  545. That file embeds JS scripts and pictures."
  546. :group 'org-export-re-reveal
  547. :type 'boolean)
  548. (defcustom org-re-reveal-inter-presentation-links nil
  549. "If non nil, try to convert links between presentations."
  550. :group 'org-export-re-reveal
  551. :type 'boolean)
  552. (defcustom org-re-reveal-init-script nil
  553. "Custom script to be passed to Reveal.initialize."
  554. :group 'org-export-re-reveal
  555. :type '(choice (const nil) string))
  556. (defcustom org-re-reveal-highlight-css "%r/lib/css/zenburn.css"
  557. "Hightlight.js CSS file."
  558. :group 'org-export-re-reveal
  559. :type 'string)
  560. (defcustom org-re-reveal-highlight-url nil
  561. "Location of Hightlight.js.
  562. If nil (default), the local plugin file is used."
  563. :group 'org-export-re-reveal
  564. :type '(choice (const nil) string))
  565. (defcustom org-re-reveal-note-key-char "n"
  566. "If not nil, register key for Org structure completion for speaker notes.
  567. When `<' followed by the key character are
  568. typed and then the completion key is pressed, which is usually
  569. `TAB', \"#+BEGIN_NOTES\" and \"#+END_NOTES\" is inserted (maybe in
  570. lower-case). See \"Readme.org\" how to make this work with Org version
  571. 9.2 or later.
  572. The default value is \"n\". Set the variable to nil to disable
  573. registering the completion."
  574. :group 'org-export-re-reveal
  575. :type '(choice (const nil) string))
  576. (defcustom org-re-reveal-no-htmlize-src nil
  577. "For syntax highlighting with org-re-reveal, three options exist:
  578. 1. Use reveal.js plugin highlight for syntax highlighting with highlight.js.
  579. This applies to all source code blocks.
  580. 2. If plugin highlight is not enabled, by default the library htmlize
  581. is used.
  582. 3. Do not use highlight and customize this variable to t.
  583. This disables syntax highlighting but you can activate htmlize for
  584. individual source code blocks with attributes:
  585. \"#+ATTR_REVEAL: :htmlize t\""
  586. :group 'org-export-re-reveal
  587. :type 'boolean)
  588. (defcustom org-re-reveal-klipsify-src nil
  589. "Set to non-nil to enable live code execution with klipse.
  590. See test-cases/test-klipsify.org in the source repository for examples.
  591. To export a source code block without klipse, use the following:
  592. \"#+ATTR_REVEAL: :no-klipsify t\""
  593. :group 'org-export-re-reveal
  594. :type 'boolean)
  595. (defcustom org-re-reveal-klipse-css "https://storage.googleapis.com/app.klipse.tech/css/codemirror.css"
  596. "Location of the codemirror css file for use with klipse."
  597. :group 'org-export-re-reveal
  598. :type 'string)
  599. (defcustom org-re-reveal-klipse-extra-css "<style>
  600. /* Position computations of klipse get confused by reveal.js's scaling.
  601. Hence, scaling should be disabled with this code. Fix height of code area
  602. with scrollbar (use overflow instead of overflow-y to restore CodeMirror
  603. setting afterwards): */
  604. .reveal section pre { max-height: 70vh; height: auto; overflow: auto; }
  605. /* Reset some reveal.js and oer-reveal settings: */
  606. .reveal section pre .CodeMirror pre { font-size: 2em; box-shadow: none; width: auto; padding: 0.4em; display: block; overflow: visible; }
  607. /* Enlarge cursor: */
  608. .CodeMirror-cursor { border-left: 3px solid black; }
  609. </style>\n"
  610. "CSS string to ensure compatibility between klipse and reveal.js."
  611. :group 'org-export-re-reveal
  612. :type 'string
  613. :package-version '(org-re-reveal . "2.0.1"))
  614. (defcustom org-re-reveal-klipse-codemirror nil
  615. "If not nil, a string to pass as CodeMirror options to \"klipse_setting\"."
  616. :group 'org-export-re-reveal
  617. :type '(choice (const nil) string))
  618. (defcustom org-re-reveal-klipse-js
  619. "https://storage.googleapis.com/app.klipse.tech/plugin/js/klipse_plugin.js"
  620. "Location of the klipse js source code.
  621. The minified version may not work, see URL
  622. `https://github.com/viebel/klipse/issues/334'."
  623. :group 'org-export-re-reveal
  624. :type 'string
  625. :package-version '(org-re-reveal . "1.1.11"))
  626. (defcustom org-re-reveal-klipse-setup
  627. '(("clojure" "selector" "language-klipse")
  628. ("html" "selector_eval_html" "language-klipse-html")
  629. ("javascript" "selector_eval_js" "language-klipse-javascript")
  630. ("js" "selector_eval_js" "language-klipse-js")
  631. ("php" "selector_eval_php" "language-klipse-php")
  632. ("python" "selector_eval_python_client" "language-klipse-python")
  633. ("ruby" "selector_eval_ruby" "language-klipse-ruby")
  634. ("scheme" "selector_eval_scheme" "language-klipse-scheme")
  635. ("sql" "selector_sql" "language-klipse-sql"))
  636. "Supported klipse languages with selectors.
  637. This is a list of triples (language selectorname selectorvalue).
  638. Each language needs to be the language of an Org source block.
  639. For existing names of klipse selectors, see URL
  640. `https://github.com/viebel/klipse/blob/master/README.md#page-level-configuration'.
  641. If additional languages work for you, maybe you could report that in issue #23
  642. at URL `https://gitlab.com/oer/org-re-reveal/issues/23'?"
  643. :group 'org-export-re-reveal
  644. :type '(repeat
  645. (list
  646. (string :tag "Language")
  647. (string :tag "Selector name")
  648. (string :tag "CSS class")))
  649. :package-version '(org-re-reveal . "1.1.11"))
  650. (defvar org-re-reveal-klipse-languages
  651. (mapcar #'car org-re-reveal-klipse-setup)
  652. "List of languages supported by org-re-reveal.")
  653. (defcustom org-re-reveal-klipse-extra-config nil
  654. "If not nil, extra JavaScript string to execute for klipse initialization.
  655. E.g., window.klipse_settings.editor_type = \"html\"; for SQL."
  656. :group 'org-export-re-reveal
  657. :type '(choice (const nil) string))
  658. (defcustom org-re-reveal-generate-custom-ids t
  659. "If t, generate CUSTOM_IDs for headings that don't have one.
  660. Set to nil to revert to old behavior, where HTML section elements have
  661. content hashes as \"id\" attributes, which change when slide contents
  662. change. With the default of t, generate CUSTOM_ID for headlines
  663. missing such a property, by using the value of the headline's number.
  664. This results in more stable URLs when working on presentations and
  665. reloading slides. You may want to set \"#+OPTIONS: reveal_history:t\"
  666. to see the section identifiers as URL fragments in the address bar,
  667. and you should not disable section numbering (for unnumbered
  668. headlines, hash IDs are used unless a CUSTOM_ID is present).
  669. For CSS code to hide section numbers if necessary, see
  670. URL `https://github.com/yjwen/org-reveal/pull/284'."
  671. :group 'org-export-re-reveal
  672. :type 'boolean
  673. :package-version '(org-re-reveal . "1.1.3"))
  674. (defvar org-re-reveal--slide-id-prefix "slide-"
  675. "Prefix to use in ID attributes of slide elements.")
  676. (defvar org-re-reveal--href-fragment-prefix
  677. (concat "/" org-re-reveal--slide-id-prefix)
  678. "Prefix to use when linking to specific slides.
  679. The default uses a slash between hash sign and slide ID,
  680. which leads to broken links that are not understood outside reveal.js.
  681. See there: https://github.com/hakimel/reveal.js/issues/2276")
  682. (defun org-re-reveal--if-format (fmt val)
  683. "Apply `format' to FMT and VAL if VAL is a non-empty string.
  684. Otherwise, return empty string."
  685. (if (and (stringp val) (> (length val) 0)) (format fmt val) ""))
  686. (defun org-re-reveal--frag-style (frag info)
  687. "Return fragment string according to FRAG and the default fragment style.
  688. FRAG is the fragment style set on element, INFO is a plist
  689. holding contextual information."
  690. (cond
  691. ((string= frag t)
  692. (let ((default-frag-style (plist-get info :reveal-default-frag-style)))
  693. (if default-frag-style (format "fragment %s" default-frag-style)
  694. "fragment")))
  695. (t (format "fragment %s" frag))))
  696. (defun org-re-reveal--frag-class (frag info)
  697. "Return proper HTML string description of fragment style.
  698. FRAG is the fragment style set on element, INFO is a plist
  699. holding contextual information."
  700. (and frag
  701. (format " class=\"%s\"" (org-re-reveal--frag-style frag info))))
  702. (defun org-re-reveal--frag-index (index)
  703. "Return attribute string for fragment INDEX if set."
  704. (and index
  705. (format " data-fragment-index=\"%s\"" index)))
  706. (defun org-re-reveal-special-block (special-block contents info)
  707. "Transcode a SPECIAL-BLOCK element from Org to Reveal.
  708. CONTENTS holds the contents of the block. INFO is a plist
  709. holding contextual information.
  710. If the block type is 'NOTES' (case-insensitive), transcode the block
  711. into a Reveal.js slide note. Otherwise, export the block as by the HTML
  712. exporter."
  713. (let ((block-type (org-element-property :type special-block)))
  714. (if (string= (downcase block-type) "notes")
  715. (format "<aside class=\"notes\">\n%s\n</aside>\n" contents)
  716. (org-html-special-block special-block contents info))))
  717. (defun org-re-reveal--add-class (elem value)
  718. "Add VALUE as \"class\" attribute in HTML header element ELEM.
  719. Do nothing if \"class\" attribute is already present."
  720. (let ((match (string-match "\\`<h[1-9][^>]+>" elem)))
  721. (unless match (error "Element no headline: %s" elem))
  722. (let ((tag (match-string 0 elem)))
  723. (if (string-match "class" tag)
  724. elem
  725. (replace-regexp-in-string "\\`\\(<h[1-9][^>]+\\)>"
  726. (format "\\1 class=\"%s\">" value)
  727. elem)))))
  728. (defun org-re-reveal--fix-html-headline (headline contents info)
  729. "Convert HEADLINE with CONTENTS and INFO to HTML.
  730. Call `org-html-headline' to generate initial HTML, remove surrounding
  731. \"div\" tags, and add class attribute to h-element if
  732. \":HTML_HEADLINE_CLASS\" property is present.
  733. Adding a class attribute in ox-reveal.el is a hack which is only
  734. necessary until that functionality has arrived in ox-html.el:
  735. https://lists.gnu.org/archive/html/emacs-orgmode/2018-12/msg00016.html
  736. As that patch has been accepted, the property is called
  737. \":HTML_HEADLINE_CLASS\". Otherwise, \":REVEAL_HEADLINE_CLASS\" would
  738. have been appropriate..."
  739. (let* ((class (org-element-property :HTML_HEADLINE_CLASS headline))
  740. (html (org-html-headline headline contents info))
  741. (nodiv
  742. (if (string-prefix-p "<div" html)
  743. ;; Remove the first <div> and the last </div> tags from html
  744. (concat "<"
  745. (mapconcat 'identity
  746. (butlast (cdr (split-string html "<" t)))
  747. "<"))
  748. ;; Return the HTML content unchanged
  749. html)))
  750. (if class
  751. (org-re-reveal--add-class nodiv class)
  752. nodiv)))
  753. (defun org-re-reveal--section-attrs (headline info)
  754. "Compute attributes for section element of HEADLINE with INFO.
  755. Return empty string or one starting with a space character."
  756. (let* ((default-slide-background (plist-get info :reveal-default-slide-background))
  757. (default-slide-background-size (plist-get info :reveal-default-slide-background-size))
  758. (default-slide-background-position (plist-get info :reveal-default-slide-background-position))
  759. (default-slide-background-repeat (plist-get info :reveal-default-slide-background-repeat))
  760. (default-slide-background-transition (plist-get info :reveal-default-slide-background-transition))
  761. (attrs (org-html--make-attribute-string
  762. `(:data-transition ,(org-element-property :REVEAL_DATA_TRANSITION headline)
  763. :data-state ,(org-element-property :REVEAL_DATA_STATE headline)
  764. :data-background ,(or (org-element-property :REVEAL_BACKGROUND headline)
  765. default-slide-background)
  766. :data-background-size ,(or (org-element-property :REVEAL_BACKGROUND_SIZE headline)
  767. default-slide-background-size)
  768. :data-background-position ,(or (org-element-property :REVEAL_BACKGROUND_POSITION headline)
  769. default-slide-background-position)
  770. :data-background-repeat ,(or (org-element-property :REVEAL_BACKGROUND_REPEAT headline)
  771. default-slide-background-repeat)
  772. :data-background-transition ,(or (org-element-property :REVEAL_BACKGROUND_TRANS headline)
  773. default-slide-background-transition)))))
  774. (if (> (length attrs) 0) (format " %s" attrs) "")))
  775. ;; Copied from org-html-headline and modified to embed org-re-reveal
  776. ;; specific attributes.
  777. (defun org-re-reveal-headline (headline contents info)
  778. "Transcode a HEADLINE element from Org to HTML.
  779. CONTENTS holds the contents of the headline. INFO is a plist
  780. holding contextual information."
  781. (unless (org-element-property :footnote-section-p headline)
  782. (if (or (org-export-low-level-p headline info)
  783. (org-element-property :NOSLIDE headline))
  784. ;; This is a deep sub-tree: export it as in ox-html.
  785. (org-html-headline headline contents info)
  786. ;; Standard headline. Export it as a slide
  787. (let* ((level (org-export-get-relative-level headline info))
  788. (preferred-id (or (org-element-property :CUSTOM_ID headline)
  789. (and (fboundp 'org-export-get-reference)
  790. (org-export-get-reference headline info))
  791. (org-element-property :ID headline)))
  792. (hlevel (org-re-reveal--get-hlevel info))
  793. (header (plist-get info :reveal-slide-header))
  794. (header-div (if header (format org-re-reveal-slide-header-html header) ""))
  795. (footer (plist-get info :reveal-slide-footer))
  796. (footer-div (if footer (format org-re-reveal-slide-footer-html footer) ""))
  797. (first-sibling (org-export-first-sibling-p headline info))
  798. (attrs (org-re-reveal--section-attrs headline info))
  799. (extra-attrs (or (org-element-property :REVEAL_EXTRA_ATTR headline)
  800. (plist-get info :reveal-extra-attr)))
  801. (slide-section-tag (format "<section id=\"%s\"%s%s>\n"
  802. (format "%s%s" org-re-reveal--slide-id-prefix preferred-id)
  803. attrs
  804. (if extra-attrs (format " %s" extra-attrs) "")))
  805. (ret (concat
  806. (if (or (/= level 1) (not first-sibling))
  807. ;; Not the first heading. Close previous slide.
  808. (concat
  809. ;; Slide footer if any.
  810. footer-div
  811. ;; Close previous slide.
  812. "</section>\n"
  813. (if (<= level hlevel)
  814. ;; Close previous vertical slide group.
  815. "</section>\n")))
  816. (if (<= level hlevel)
  817. ;; Add an extra "<section>" to group following slides
  818. ;; into vertical slide group. Transition override
  819. ;; attributes are attached at this level, too.
  820. (let ((attrs
  821. (org-html--make-attribute-string
  822. `(:data-transition ,(org-element-property :REVEAL_DATA_TRANSITION headline)))))
  823. (if (string= attrs "")
  824. "<section>\n"
  825. (format "<section %s>\n" attrs))))
  826. ;; Start a new slide.
  827. slide-section-tag
  828. ;; Slide header if any.
  829. header-div
  830. ;; The HTML content of the headline
  831. (org-re-reveal--fix-html-headline headline contents info)
  832. (if (and (= level 1)
  833. (org-export-last-sibling-p headline info))
  834. ;; Last head 1. Close all slides.
  835. (concat
  836. ;; Slide footer if any
  837. footer-div
  838. "</section>\n</section>\n")))))
  839. ret))))
  840. (defun org-re-reveal--read-list (thing)
  841. "Return THING if it is a list.
  842. Otherwise, `read' THING and return value if it is a list.
  843. Otherwise, raise an error."
  844. (if (listp thing)
  845. thing
  846. (let ((lthing (read thing)))
  847. (if (listp lthing)
  848. lthing
  849. (error "Expected a list, but got: %s" thing)))))
  850. (defun org-re-reveal--parse-listoption (info option)
  851. "Parse and return OPTION in INFO.
  852. That value for OPTION may be a list or a string representing a list."
  853. (org-re-reveal--read-list (plist-get info option)))
  854. (defun org-re-reveal--read-file (file)
  855. "Return the content of FILE."
  856. (with-temp-buffer
  857. (insert-file-contents-literally file)
  858. (buffer-string)))
  859. (defun org-re-reveal--file-url-to-path (url)
  860. "Convert URL that points to local files to file path."
  861. (replace-regexp-in-string
  862. (if (string-equal system-type "windows-nt") "^file:///" "^file://")
  863. "" url))
  864. (defun org-re-reveal--css-label (in-single-file file-name style-id)
  865. "Generate HTML code to include CSS file FILE-NAME.
  866. If IN-SINGLE-FILE is t, the content of FILE-NAME is embedded;
  867. otherwise, a `<link>' label is generated."
  868. (when (and file-name (not (string= file-name "")))
  869. (if in-single-file
  870. ;; Single-file
  871. (let ((local-file-name (org-re-reveal--file-url-to-path file-name)))
  872. (if (file-readable-p local-file-name)
  873. (concat "<style type=\"text/css\">\n"
  874. (org-re-reveal--read-file local-file-name)
  875. "\n</style>\n")
  876. ;; But file is not readable.
  877. (error "Cannot read %s" file-name)))
  878. ;; Not in-single-file
  879. (concat "<link rel=\"stylesheet\" href=\"" file-name "\""
  880. (if style-id (format " id=\"%s\"" style-id))
  881. "/>\n"))))
  882. (defun org-re-reveal--klipsify-header (info)
  883. "Return code (CSS and JavaScript) to activate klipse when indicated by INFO."
  884. (if (plist-get info :reveal-klipsify-src)
  885. (concat (format "<link rel=\"stylesheet\" href=\"%s\"/>\n"
  886. (plist-get info :reveal-klipse-css-url))
  887. org-re-reveal-klipse-extra-css
  888. (format "<script>
  889. window.klipse_settings = {
  890. %s%s
  891. };\n"
  892. (org-re-reveal--if-format
  893. "%s,\n" (plist-get info :reveal-codemirror-config))
  894. (mapconcat (lambda (elem)
  895. (format " %s: '.%s'"
  896. (nth 1 elem) (nth 2 elem)))
  897. (org-re-reveal--parse-listoption
  898. info :reveal-klipse-setup)
  899. ",\n"))
  900. (org-re-reveal--if-format
  901. " %s\n" (plist-get info :reveal-klipse-extra-config))
  902. "</script>\n")
  903. ""))
  904. (defun org-re-reveal--klipsify-script (info)
  905. "Return script element for klipse when indicated by INFO."
  906. (if (plist-get info :reveal-klipsify-src)
  907. (format "<script src=\"%s\"></script>
  908. <script>
  909. /* Recompute layout upon changes by klipse. Code fragment from
  910. asciidoctor-revealjs-klipse by Timothy Pratley under GPLv3:
  911. https://github.com/timothypratley/asciidoctor-revealjs-klipse/blob/master/docs/docinfo-footer.html */
  912. Reveal.addEventListener( 'slidechanged', function( event ) {
  913. window.dispatchEvent( new Event('resize') );
  914. } );
  915. </script>\n" (plist-get info :reveal-klipse-js-url))
  916. ""))
  917. (defun org-re-reveal-stylesheets (info)
  918. "Return HTML code for reveal stylesheets using INFO and `org-re-reveal-root'."
  919. (let* ((root-path (file-name-as-directory (plist-get info :reveal-root)))
  920. (reveal-css (concat root-path "css/reveal.css"))
  921. (theme (plist-get info :reveal-theme))
  922. (theme-css (concat root-path "css/theme/" theme ".css"))
  923. (extra-css (plist-get info :reveal-extra-css))
  924. (in-single-file (plist-get info :reveal-single-file)))
  925. (concat
  926. ;; Default embedded style sheets
  927. "<style type=\"text/css\">
  928. .underline { text-decoration: underline; }
  929. </style>
  930. "
  931. ;; stylesheets
  932. (mapconcat (lambda (elem) (org-re-reveal--css-label
  933. in-single-file (car elem) (cdr elem)))
  934. (append (list (cons reveal-css nil)
  935. (cons theme-css "theme"))
  936. (mapcar (lambda (a) (cons a nil))
  937. (cl-delete-duplicates
  938. (split-string extra-css "\n" t)
  939. :test #'equal)))
  940. "\n")
  941. ;; Include CSS for highlight.js if necessary
  942. (if (org-re-reveal--using-highlight.js info)
  943. (format "<link rel=\"stylesheet\" href=\"%s\"/>\n"
  944. (format-spec (plist-get info :reveal-highlight-css)
  945. `((?r . ,(directory-file-name root-path)))))
  946. "")
  947. ;; Include CSS for klipse if necessary
  948. (org-re-reveal--klipsify-header info)
  949. ;; print-pdf
  950. (if in-single-file ""
  951. (format "\n<!-- If the query includes 'print-pdf', include the PDF print sheet -->
  952. <script>
  953. if( window.location.search.match( /print-pdf/gi ) ) {
  954. var link = document.createElement( 'link' );
  955. link.rel = 'stylesheet';
  956. link.type = 'text/css';
  957. link.href = '%scss/print/pdf.css';
  958. document.getElementsByTagName( 'head' )[0].appendChild( link );
  959. }
  960. </script>
  961. "
  962. root-path)))))
  963. (defun org-re-reveal-mathjax-scripts (info)
  964. "Return HTML code for declaring MathJax scripts for INFO."
  965. (if (plist-get info :reveal-mathjax)
  966. ;; MathJax enabled.
  967. (format "<script type=\"text/javascript\" src=\"%s\"></script>\n"
  968. (plist-get info :reveal-mathjax-url))))
  969. (defun org-re-reveal--read-file-as-string (filename)
  970. "If FILENAME exists as file, return its contents as string.
  971. Otherwise, return nil."
  972. (when (and (stringp filename)
  973. (file-readable-p filename)
  974. (not (file-directory-p filename)))
  975. (with-temp-buffer
  976. (insert-file-contents-literally filename)
  977. (buffer-string))))
  978. (defun org-re-reveal--external-plugins-maybe-from-file (info)
  979. "Create list of plugin dependencies from INFO.
  980. In INFO, `:reveal-external-plugins' can be a list or a filename.
  981. If it is a filename, split lines to produce a list."
  982. (let* ((external-plugins (plist-get info :reveal-external-plugins))
  983. (file-contents (org-re-reveal--read-file-as-string external-plugins)))
  984. (if file-contents
  985. (mapcar (lambda (line) (cons 'dummy line))
  986. (split-string (string-trim file-contents) "\n"))
  987. (org-re-reveal--read-list external-plugins))))
  988. (defun org-re-reveal--external-plugin-init (info root-path)
  989. "Build initialization strings for plugins of INFO under ROOT-PATH.
  990. Parameter INFO determines plugins and their initializations
  991. based on `org-re-reveal-external-plugins'."
  992. (let ((plugins (org-re-reveal--external-plugins-maybe-from-file info)))
  993. (cl-loop for (nil . value) in plugins
  994. collect (format value root-path))))
  995. (defvar org-re-reveal-client-multiplex nil
  996. "Used to cause generation of client html file for multiplex.")
  997. (defun org-re-reveal-scripts--libraries (info)
  998. "Internal function to generate script tags with INFO.
  999. This includes reveal.js libraries in `org-re-reveal-script-files' under
  1000. `org-re-reveal-root', and libraries in `org-re-reveal-extra-scripts'."
  1001. (let* ((root-path (file-name-as-directory (plist-get info :reveal-root)))
  1002. (script-files (org-re-reveal--parse-listoption
  1003. info :reveal-script-files))
  1004. (root-libs (mapcar (lambda (file) (concat root-path file))
  1005. script-files))
  1006. (extra-scripts (org-re-reveal--parse-listoption
  1007. info :reveal-extra-scripts))
  1008. ;; Treat extra scripts not starting with <script> as filenames.
  1009. (extra-script-files
  1010. (cl-remove-if (lambda (s) (string-prefix-p "<script>" s))
  1011. extra-scripts))
  1012. ;; Treat extra scripts starting with <script> as elements.
  1013. (extra-script-elements
  1014. (cl-remove-if-not (lambda (s) (string-prefix-p "<script>" s))
  1015. extra-scripts))
  1016. (in-single-file (plist-get info :reveal-single-file)))
  1017. (concat
  1018. (if in-single-file
  1019. (let* ((local-root-path (org-re-reveal--file-url-to-path root-path))
  1020. (local-libs (append (mapcar (lambda (file)
  1021. (concat local-root-path file))
  1022. script-files)
  1023. extra-script-files))
  1024. (local-libs-exist-p (cl-every #'file-readable-p local-libs)))
  1025. (if local-libs-exist-p
  1026. ;; Embed contents of files.
  1027. (mapconcat (lambda (file)
  1028. (format "<script>\n%s\n</script>\n"
  1029. (org-re-reveal--read-file file)))
  1030. local-libs "")
  1031. (error
  1032. (concat "Cannot read "
  1033. (mapconcat 'identity
  1034. (cl-remove-if #'file-readable-p local-libs)
  1035. ", ")))))
  1036. ;; Embed script files with src.
  1037. (mapconcat (lambda (file)
  1038. (concat "<script src=\"" file "\"></script>\n"))
  1039. (append root-libs extra-script-files) ""))
  1040. ;; Embed script tags.
  1041. (mapconcat 'identity extra-script-elements "\n")
  1042. (if extra-script-elements "\n" ""))))
  1043. (defun org-re-reveal-scripts--reveal-options (info)
  1044. "Internal function for `org-re-reveal-scripts' with INFO."
  1045. (format "
  1046. controls: %s,
  1047. progress: %s,
  1048. history: %s,
  1049. center: %s,
  1050. slideNumber: %s,
  1051. rollingLinks: %s,
  1052. keyboard: %s,
  1053. mouseWheel: %s,
  1054. fragmentInURL: %s,
  1055. hashOneBasedIndex: %s,
  1056. pdfSeparateFragments: %s,
  1057. %s
  1058. overview: %s,
  1059. "
  1060. (if (plist-get info :reveal-control) "true" "false")
  1061. (if (plist-get info :reveal-progress) "true" "false")
  1062. (if (plist-get info :reveal-history) "true" "false")
  1063. (if (plist-get info :reveal-center) "true" "false")
  1064. (let ((slide-number (plist-get info :reveal-slide-number)))
  1065. (if slide-number (format "'%s'" slide-number)
  1066. "false"))
  1067. (if (plist-get info :reveal-rolling-links) "true" "false")
  1068. (if (plist-get info :reveal-keyboard) "true" "false")
  1069. (if (plist-get info :reveal-mousewheel) "true" "false")
  1070. (if (plist-get info :reveal-fragmentinurl) "true" "false")
  1071. (if (plist-get info :reveal-hashonebasedindex) "true" "false")
  1072. (if (plist-get info :reveal-pdfseparatefragments) "true" "false")
  1073. (let ((timing (plist-get info :reveal-defaulttiming)))
  1074. (if timing (format "defaultTiming: %s," timing)
  1075. ""))
  1076. (if (plist-get info :reveal-overview) "true" "false")))
  1077. (defun org-re-reveal--to-string (option)
  1078. "Return OPTION as string.
  1079. If OPTION is an integer > 0, return as string.
  1080. If OPTION is a string, embed in quotation marks.
  1081. If OPTION is nil, return nil (not the empty string).
  1082. Otherwise, raise error."
  1083. (cond ((and (integerp option) (> option 0)) (format "%d" option))
  1084. ((stringp option) (format "\"%s\"" option))
  1085. ((eq option nil) nil)
  1086. (t (error "Option »%s« must be string, positive integer, or nil; not %s"
  1087. option (type-of option)))))
  1088. (defun org-re-reveal-scripts--main-configures (info)
  1089. "Internal function for `org-re-reveal-scripts' with INFO."
  1090. (concat
  1091. ;; slide width
  1092. (let ((width (plist-get info :reveal-width)))
  1093. (org-re-reveal--if-format "width: %s,\n"
  1094. (org-re-reveal--to-string width)))
  1095. ;; slide height
  1096. (let ((height (plist-get info :reveal-height)))
  1097. (org-re-reveal--if-format "height: %s,\n"
  1098. (org-re-reveal--to-string height)))
  1099. ;; slide margin
  1100. (let ((margin (string-to-number (plist-get info :reveal-margin))))
  1101. (if (>= margin 0) (format "margin: %.2f,\n" margin) ""))
  1102. ;; slide minimum scaling factor
  1103. (let ((min-scale (string-to-number (plist-get info :reveal-min-scale))))
  1104. (if (> min-scale 0) (format "minScale: %.2f,\n" min-scale) ""))
  1105. ;; slide maximux scaling factor
  1106. (let ((max-scale (string-to-number (plist-get info :reveal-max-scale))))
  1107. (if (> max-scale 0) (format "maxScale: %.2f,\n" max-scale) ""))
  1108. ;; thems and transitions
  1109. (format "
  1110. theme: Reveal.getQueryHash().theme, // available themes are in /css/theme
  1111. transition: Reveal.getQueryHash().transition || '%s', // see README of reveal.js for options
  1112. transitionSpeed: '%s',\n"
  1113. (plist-get info :reveal-trans)
  1114. (plist-get info :reveal-speed))
  1115. (let ((options (plist-get info :reveal-extra-options)))
  1116. (org-re-reveal--if-format "%s,\n" options))))
  1117. (defun org-re-reveal-scripts--multiplex (info)
  1118. "Internal function for `org-re-reveal-scripts' with INFO."
  1119. (let ((enabled-builtin-plugins
  1120. (org-re-reveal--parse-listoption info :reveal-plugins)))
  1121. (when (memq 'multiplex enabled-builtin-plugins)
  1122. (format
  1123. "multiplex: {
  1124. secret: %s, // null if client
  1125. id: '%s', // id, obtained from socket.io server
  1126. url: '%s' // Location of socket.io server
  1127. },\n"
  1128. (if (eq org-re-reveal-client-multiplex nil)
  1129. (format "'%s'" (plist-get info :reveal-multiplex-secret))
  1130. (format "null"))
  1131. (plist-get info :reveal-multiplex-id)
  1132. (plist-get info :reveal-multiplex-url)))))
  1133. (defun org-re-reveal-scripts--dependencies (info)
  1134. "Internal function for `org-re-reveal-scripts' with INFO."
  1135. (let* ((root-path (file-name-as-directory (plist-get info :reveal-root)))
  1136. (in-single-file (plist-get info :reveal-single-file))
  1137. (enabled-builtin-plugins (org-re-reveal--parse-listoption
  1138. info :reveal-plugins)))
  1139. ;; optional JS library heading
  1140. (if in-single-file ""
  1141. (concat
  1142. "
  1143. // Optional libraries used to extend reveal.js
  1144. dependencies: [
  1145. "
  1146. ;; JS libraries
  1147. (let* ((highlight-url (plist-get info :reveal-highlight-url))
  1148. (builtins
  1149. `(classList ,(format " { src: '%slib/js/classList.js', condition: function() { return !document.body.classList; } }" root-path)
  1150. markdown ,(format " { src: '%splugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
  1151. { src: '%splugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }" root-path root-path)
  1152. highlight ,(if highlight-url
  1153. (format " { src: '%s', async: true, callback: function() { hljs.initHighlightingOnLoad(); } }" highlight-url)
  1154. (format " { src: '%splugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } }" root-path))
  1155. zoom ,(format " { src: '%splugin/zoom-js/zoom.js', async: true, condition: function() { return !!document.body.classList; } }" root-path)
  1156. notes ,(format " { src: '%splugin/notes/notes.js', async: true, condition: function() { return !!document.body.classList; } }" root-path)
  1157. search ,(format " { src: '%splugin/search/search.js', async: true, condition: function() { return !!document.body.classList; } }" root-path)
  1158. remotes ,(format " { src: '%splugin/remotes/remotes.js', async: true, condition: function() { return !!document.body.classList; } }" root-path)
  1159. multiplex ,(format " { src: '%s', async: true },\n%s"
  1160. (plist-get info :reveal-multiplex-socketio-url)
  1161. ;; following ensures that either client.js or master.js is included depending on defvar org-re-reveal-client-multiplex value state
  1162. (if (not org-re-reveal-client-multiplex)
  1163. (progn
  1164. (if (not (string= "" (plist-get info :reveal-multiplex-secret)))
  1165. (setq org-re-reveal-client-multiplex t))
  1166. (format " { src: '%splugin/multiplex/master.js', async: true }" root-path))
  1167. (format " { src: '%splugin/multiplex/client.js', async: true }" root-path)))))
  1168. (builtin-codes
  1169. (mapcar (lambda (p) (plist-get builtins p)) enabled-builtin-plugins))
  1170. (external-plugins
  1171. (org-re-reveal--external-plugin-init info root-path))
  1172. (all-plugins (if external-plugins (append external-plugins builtin-codes) builtin-codes))
  1173. (extra-codes (plist-get info :reveal-extra-js))
  1174. (total-codes
  1175. (if (string= "" extra-codes)
  1176. all-plugins
  1177. (append (list extra-codes) all-plugins))))
  1178. (mapconcat 'identity total-codes ",\n"))
  1179. "]\n\n"))))
  1180. (defun org-re-reveal-scripts--init-script (info)
  1181. "Internal function for `org-re-reveal-scripts' with INFO."
  1182. (let ((init-script (plist-get info :reveal-init-script))
  1183. (in-single-file (plist-get info :reveal-single-file)))
  1184. (if (and (stringp init-script) (> (length init-script) 0))
  1185. (concat (if in-single-file "" ",") init-script)
  1186. "")))
  1187. (defun org-re-reveal-scripts (info)
  1188. "Return necessary scripts to initialize reveal.js.
  1189. Use INFO and custom variable `org-re-reveal-root'."
  1190. (concat
  1191. ;; Libraries in script tags, including reveal.js itself.
  1192. (org-re-reveal-scripts--libraries info)
  1193. ;; Create <script> tag for Reveal.initialize(...).
  1194. "<script>
  1195. // Full list of configuration options available here:
  1196. // https://github.com/hakimel/reveal.js#configuration
  1197. Reveal.initialize({
  1198. "
  1199. ;; plugin configures/frags
  1200. (org-re-reveal-scripts--reveal-options info)
  1201. ;; reveal.js main configures
  1202. (org-re-reveal-scripts--main-configures info)
  1203. ;; multiplexing - depends on defvar 'org-re-reveal-client-multiplex'
  1204. (org-re-reveal-scripts--multiplex info)
  1205. ;; load dependency js
  1206. (org-re-reveal-scripts--dependencies info)
  1207. ;; init-script
  1208. (org-re-reveal-scripts--init-script info)
  1209. ;; end of <script> tag
  1210. "});\n</script>\n"))
  1211. (defun org-re-reveal-toc (depth info)
  1212. "Build a slide of table of contents with DEPTH and INFO."
  1213. (let ((toc (org-html-toc depth info)))
  1214. (org-re-reveal-toc-1 toc info)))
  1215. (defun org-re-reveal-toc-1 (toc info)
  1216. "Build table of contents with TOC and INFO."
  1217. (when toc
  1218. (let* ((toc-slide-with-header (plist-get info :reveal-slide-global-header))
  1219. (toc-slide-with-footer (or
  1220. (plist-get info :reveal-slide-global-footer)
  1221. (plist-get info :reveal-slide-toc-footer)))
  1222. (toc-slide-state (plist-get info :reveal-toc-slide-state))
  1223. (toc-slide-class (plist-get info :reveal-toc-slide-class))
  1224. (toc-slide-title (plist-get info :reveal-toc-slide-title))
  1225. (toc (replace-regexp-in-string
  1226. "<a href=\"#"
  1227. (concat "<a href=\"#" org-re-reveal--href-fragment-prefix) toc))
  1228. (toc (replace-regexp-in-string
  1229. (org-html--translate "Table of Contents" info)
  1230. toc-slide-title toc)))
  1231. (concat "<section id=\"table-of-contents-section\""
  1232. (when toc-slide-state
  1233. (format " data-state=\"%s\"" toc-slide-state))
  1234. ">\n"
  1235. (when toc-slide-with-header
  1236. (let ((header (plist-get info :reveal-slide-header)))
  1237. (when header (format org-re-reveal-slide-header-html header))))
  1238. (if toc-slide-class
  1239. (replace-regexp-in-string
  1240. "<h\\([1-3]\\)>"
  1241. (format "<h\\1 class=\"%s\">" toc-slide-class)
  1242. toc)
  1243. toc)
  1244. (when toc-slide-with-footer
  1245. (let ((footer (plist-get info :reveal-slide-footer)))
  1246. (when footer (format org-re-reveal-slide-footer-html footer))))
  1247. "</section>\n"))))
  1248. (defun org-re-reveal-inner-template (contents info)
  1249. "Return body of document string after HTML conversion.
  1250. CONTENTS is the transcoded contents string. INFO is a plist
  1251. holding export options."
  1252. (concat
  1253. ;; Table of contents.
  1254. (let ((depth (plist-get info :with-toc)))
  1255. (when (and depth
  1256. (not (plist-get info :reveal-subtree)))
  1257. (org-re-reveal-toc depth info)))
  1258. ;; Document contents.
  1259. contents))
  1260. (defun org-re-reveal-parse-keyword-value (value footer keyword info)
  1261. "According to VALUE of KEYWORD and INFO, return HTML tags to split slides.
  1262. Currently, only the keyword \"split\" is implemented, and VALUE must
  1263. start with \"split\". Any following text is inserted literally into
  1264. the section tag.
  1265. The possibly empty FOOTER is inserted at the end of the slide."
  1266. (cl-assert (string-prefix-p "split" value) nil
  1267. (format "Unknown REVEAL keyword. Expected \"split\", got: %s"
  1268. value))
  1269. (let* ((headline (org-export-get-parent-headline keyword))
  1270. (split-attrs (substring value 5)) ; Everything after "split"
  1271. (real-attrs (if (< 0 (length split-attrs))
  1272. split-attrs
  1273. (org-re-reveal--section-attrs headline info))))
  1274. (format "%s</section>\n<section%s>"
  1275. footer real-attrs)))
  1276. ;; Copied from org-html-format-list-item. Overwrite HTML class
  1277. ;; attribute when there is attr_html attributes.
  1278. (defun org-re-reveal-format-list-item (contents type checkbox attributes info
  1279. &optional term-counter-id
  1280. headline)
  1281. "Format a list item into HTML based on INFO.
  1282. Item has CONTENTS, TYPE, may be a CHECKBOX, have ATTRIBUTES, and may have
  1283. TERM-COUNTER-ID and HEADLINE."
  1284. (let ((attr-html (cond (attributes (format " %s" (org-html--make-attribute-string attributes)))
  1285. (checkbox (format " class=\"%s\"" (symbol-name checkbox)))
  1286. (t "")))
  1287. (checkbox (concat (org-html-checkbox checkbox info)
  1288. (and checkbox " ")))
  1289. (br (org-html-close-tag "br" nil info)))
  1290. (concat
  1291. (cl-case type
  1292. (ordered
  1293. (let* ((counter term-counter-id)
  1294. (extra (if counter (format " value=\"%s\"" counter) "")))
  1295. (concat
  1296. (format "<li%s%s>" attr-html extra)
  1297. (when headline (concat headline br)))))
  1298. (unordered
  1299. (let* ((id term-counter-id)
  1300. (extra (if id (format " id=\"%s\"" id) "")))
  1301. (concat
  1302. (format "<li%s%s>" attr-html extra)
  1303. (when headline (concat headline br)))))
  1304. (descriptive
  1305. (let* ((term term-counter-id))
  1306. (setq term (or term "(no term)"))
  1307. ;; Check-boxes in descriptive lists are associated to tag.
  1308. (concat (format "<dt%s>%s</dt>"
  1309. attr-html (concat checkbox term))
  1310. (format "<dd%s>" attr-html)))))
  1311. (unless (eq type 'descriptive) checkbox)
  1312. (and contents (org-trim contents))
  1313. (cl-case type
  1314. (ordered "</li>")
  1315. (unordered "</li>")
  1316. (descriptive "</dd>")))))
  1317. ;; Copied from org-html-item, changed to call
  1318. ;; org-re-reveal-format-list-item.
  1319. (defun org-re-reveal-item (item contents info)
  1320. "Transcode an ITEM element from Org to Reveal.
  1321. CONTENTS holds the contents of the item. INFO is a plist holding
  1322. contextual information."
  1323. (let* ((plain-list (org-export-get-parent item))
  1324. (type (org-element-property :type plain-list))
  1325. (counter (org-element-property :counter item))
  1326. (attributes (org-export-read-attribute :attr_html item))
  1327. (checkbox (org-element-property :checkbox item))
  1328. (tag (let ((tag (org-element-property :tag item)))
  1329. (and tag (org-export-data tag info)))))
  1330. (org-re-reveal-format-list-item
  1331. contents type checkbox attributes info (or tag counter))))
  1332. (defun org-re-reveal-keyword (keyword contents info)
  1333. "Transcode a KEYWORD element from Org to Reveal.
  1334. May change custom variables as SIDE EFFECT.
  1335. CONTENTS is nil. INFO is a plist holding contextual information."
  1336. (let* ((key (org-element-property :key keyword))
  1337. (value (org-element-property :value keyword))
  1338. (footer (plist-get info :reveal-slide-footer))
  1339. (footer-div (if footer
  1340. (format org-re-reveal-slide-footer-html footer) "")))
  1341. (cl-case (intern key)
  1342. (REVEAL (org-re-reveal-parse-keyword-value value footer-div keyword info))
  1343. (REVEAL_HTML value)
  1344. (HTML value)
  1345. ;; Handling of TOC at arbitrary position is a hack.
  1346. ;; We end the previous section by inserting a closing section tag,
  1347. ;; which will *break* the presentation if other tags are still open.
  1348. ;; To avoid unbalanced tags, remove the TOC's closing tag.
  1349. ;; If slide footers are used, insert it before closing the section.
  1350. ;; In any case, if footers are used, the one of the closed section
  1351. ;; is sufficient, and the one contained in the TOC needs to be removed.
  1352. (TOC (message "Please use #+REVEAL_TOC instead of #+TOC. See Readme.")
  1353. (sit-for 2)
  1354. (concat footer-div
  1355. "</section>\n"
  1356. (replace-regexp-in-string
  1357. (format "</section>\\|%s"
  1358. (format org-re-reveal-slide-footer-html ".*"))
  1359. ""
  1360. (org-re-reveal-toc-1
  1361. (org-html-keyword keyword contents info) info))))
  1362. (REVEAL_TOC
  1363. ;; Following code stiched together with snippets from
  1364. ;; org-html-keyword and org-html-toc.
  1365. (when (string-match "\\<headlines\\>" value)
  1366. (let* ((depth (and (string-match "\\<[0-9]+\\>" value)
  1367. (string-to-number (match-string 0 value))))
  1368. (toc-entries
  1369. (mapcar (lambda (headline)
  1370. (cons (org-html--format-toc-headline headline info)
  1371. (org-export-get-relative-level headline info)))
  1372. (org-export-collect-headlines info depth))))
  1373. (when toc-entries
  1374. (let ((toc (concat "<div id=\"text-table-of-contents\">"
  1375. (org-html--toc-text toc-entries)
  1376. "</div>\n")))
  1377. ;; Use link format of reveal.js.
  1378. (replace-regexp-in-string
  1379. "<a href=\"#"
  1380. (concat "<a href=\"#" org-re-reveal--href-fragment-prefix)
  1381. toc)))))))))
  1382. (defun org-re-reveal-embedded-svg (path)
  1383. "Embed the SVG content at PATH into Reveal HTML."
  1384. (with-temp-buffer
  1385. (insert-file-contents-literally path)
  1386. (let ((start (re-search-forward "<[ \t\n]*svg[ \t\n]"))
  1387. (end (re-search-forward "<[ \t\n]*/svg[ \t\n]*>")))
  1388. (concat "<svg " (buffer-substring-no-properties start end)))))
  1389. (defun org-re-reveal--format-image-data-uri (link path info)
  1390. "Generate the data URI for the image referenced by LINK at PATH with INFO."
  1391. (let* ((ext (downcase (file-name-extension path))))
  1392. (if (string= ext "svg")
  1393. (org-re-reveal-embedded-svg path)
  1394. (org-html-close-tag
  1395. "img"
  1396. (org-html--make-attribute-string
  1397. (org-combine-plists
  1398. (list :src
  1399. (concat
  1400. "data:image/"
  1401. ;; Image type
  1402. ext
  1403. ";base64,"
  1404. ;; Base64 content
  1405. (with-temp-buffer
  1406. (insert-file-contents-literally path)
  1407. (base64-encode-region 1 (point-max))
  1408. (buffer-string))))
  1409. ;; Get attribute list from parent element
  1410. ;; Copied from ox-html.el
  1411. (let* ((parent (org-export-get-parent-element link))
  1412. (link (let ((container (org-export-get-parent link)))
  1413. (if (and (eq (org-element-type container) 'link)
  1414. (org-html-inline-image-p link info))
  1415. container
  1416. link))))
  1417. (and (eq (org-element-map parent 'link 'identity info t) link)
  1418. (org-export-read-attribute :attr_html parent)))))
  1419. info))))
  1420. (defun org-re-reveal--maybe-replace-in-link (link allow-inter-link)
  1421. "Replace hash sign in LINK, affected by ALLOW-INTER-LINK.
  1422. If ALLOW-INTER-LINK is nil, only replace hash signs if URL in LINK starts
  1423. with it. Otherwise, also replace if the URL does not contain a hostname;
  1424. such links are assumed to point into other presentations."
  1425. (if (and allow-inter-link
  1426. (string-match "<a href=\"\\([^\"]*\\)\"" link))
  1427. (let* ((url (match-string 1 link))
  1428. (obj (url-generic-parse-url url))
  1429. (host (url-host obj)))
  1430. (if host
  1431. link
  1432. (replace-regexp-in-string
  1433. "<a href=\"\\([^#]*\\)#"
  1434. (concat "<a href=\"\\1#" org-re-reveal--href-fragment-prefix)
  1435. link)))
  1436. (replace-regexp-in-string
  1437. "<a href=\"#"
  1438. (concat "<a href=\"#" org-re-reveal--href-fragment-prefix)
  1439. link)))
  1440. (defun org-re-reveal--internal-link-class (link info)
  1441. "Check if LINK is internal, given INFO, and maybe assign class.
  1442. The direction of the link is assigned as class attribute to the link
  1443. and to its parent via \"attr_html\":
  1444. If link points backward (to previous content), class \"backwardlink\"
  1445. is assigned, else \"forwardlink\".
  1446. Assigning the class to \"attr_html\" of parent is based on a hack in
  1447. `org-html-link', while use of \"attr_html\" of the link itself
  1448. requires a version of org-mode as of 2018-12-08 or newer."
  1449. (let ((target (or (ignore-errors (org-export-resolve-id-link link info))
  1450. (ignore-errors (org-export-resolve-fuzzy-link link info)))))
  1451. (when target
  1452. (let* ((lbegin (org-element-property :begin link))
  1453. (tbegin (org-element-property :begin target))
  1454. (direction (if (< tbegin lbegin)
  1455. "backwardlink"
  1456. "forwardlink"))
  1457. (parent (org-export-get-parent-element link))
  1458. (attrs (org-combine-plists
  1459. (org-export-read-attribute :attr_html parent)
  1460. (org-export-read-attribute :attr_html link)))
  1461. (class (plist-get attrs :class))
  1462. (newclass (if class (concat direction " " class) direction))
  1463. (newattrs (mapconcat (lambda (elem) (format "%s" elem))
  1464. (plist-put attrs :class newclass)
  1465. " ")))
  1466. (org-element-put-property parent :attr_html (list newattrs))
  1467. (org-element-put-property link :attr_html (list newattrs))))))
  1468. (defun org-re-reveal-link (link desc info)
  1469. "Transcode a LINK object with DESC and INFO from Org to Reveal.
  1470. The result is identical to ox-html expect for image links.
  1471. When `org-re-reveal-single-file' is t,
  1472. the result is the Data URI of the referenced image."
  1473. (let* ((want-embed-image (and (plist-get info :reveal-single-file)
  1474. (plist-get info :html-inline-images)
  1475. (string= "file" (org-element-property :type link))
  1476. (org-export-inline-image-p
  1477. link (plist-get info :html-inline-image-rules))))
  1478. (allow-inter-link (plist-get info :reveal-inter-presentation-links))
  1479. (raw-path (org-element-property :path link))
  1480. (clean-path (org-re-reveal--file-url-to-path raw-path))
  1481. (can-embed-image (and want-embed-image
  1482. (file-readable-p clean-path))))
  1483. (if can-embed-image
  1484. (org-re-reveal--format-image-data-uri link clean-path info)
  1485. (if want-embed-image
  1486. (error "Cannot embed image %s" raw-path)
  1487. (org-re-reveal--internal-link-class link info)
  1488. (org-re-reveal--maybe-replace-in-link (org-html-link link desc info)
  1489. allow-inter-link)))))
  1490. (defun org-re-reveal-latex-environment (latex-env contents info)
  1491. "Transcode a LaTeX environment from Org to Reveal.
  1492. LATEX-ENV is the Org element. CONTENTS is the contents of the environment.
  1493. INFO is a plist holding contextual information."
  1494. (setq info (plist-put info :reveal-mathjax t))
  1495. (let ((attrs (org-export-read-attribute :attr_html latex-env)))
  1496. (format "<div%s>\n%s\n</div>\n"
  1497. (if attrs (concat " " (org-html--make-attribute-string attrs)) "")
  1498. (org-html-latex-environment latex-env contents info))))
  1499. (defun org-re-reveal-plain-list (plain-list contents info)
  1500. "Transcode a PLAIN-LIST element from Org to Reveal.
  1501. CONTENTS is the contents of the list. INFO is a plist holding
  1502. contextual information.
  1503. Extract and set `attr_html' to plain-list tag attributes."
  1504. (ignore info) ; Silence byte compiler
  1505. (let ((tag (cl-case (org-element-property :type plain-list)
  1506. (ordered "ol")
  1507. (unordered "ul")
  1508. (descriptive "dl")))
  1509. (attrs (org-export-read-attribute :attr_html plain-list)))
  1510. (format "%s<%s%s>\n%s\n</%s>%s"
  1511. (if (string= org-html-checkbox-type 'html) "<form>" "")
  1512. tag
  1513. (if attrs (concat " " (org-html--make-attribute-string attrs)) "")
  1514. contents
  1515. tag
  1516. (if (string= org-html-checkbox-type 'html) "</form>" ""))))
  1517. (defun org-re-reveal-format-spec (info)
  1518. "Return format specification with INFO.
  1519. Formatting extends `org-html-format-spec' as follows:
  1520. misc information and academic title."
  1521. (append (org-html-format-spec info)
  1522. `((?A . ,(org-export-data
  1523. (plist-get info :reveal-academic-title) info))
  1524. (?m . ,(org-export-data
  1525. (plist-get info :reveal-miscinfo) info))
  1526. (?q . ,(url-encode-url
  1527. (org-export-data
  1528. (plist-get info :reveal-talk-qr-code) info)))
  1529. (?u . ,(url-encode-url
  1530. (org-export-data
  1531. (plist-get info :reveal-talk-url) info))))))
  1532. (defun org-re-reveal--build-pre-postamble (type info)
  1533. "Depending on TYPE, return preamble or postamble for INFO as string, or nil."
  1534. (let ((section (plist-get info (intern (format ":reveal-%s" type))))
  1535. (spec (org-re-reveal-format-spec info)))
  1536. (when section
  1537. (let ((section-contents
  1538. (if (functionp (intern section)) (funcall (intern section) info)
  1539. ;; else section is a string.
  1540. (format-spec section spec))))
  1541. (when (org-string-nw-p section-contents)
  1542. (org-element-normalize-string section-contents))))))
  1543. (defun org-re-reveal-section (section contents info)
  1544. "Transcode a SECTION element from Org to Reveal.
  1545. CONTENTS holds the contents of the section. INFO is a plist
  1546. holding contextual information."
  1547. ;; Just return the contents. No "<div>" tags.
  1548. (ignore section info) ; Silence byte compiler
  1549. contents)
  1550. (defun org-re-reveal--using-highlight.js (info)
  1551. "Check with INFO whether highlight.js plugin is enabled."
  1552. (let ((reveal-plugins (condition-case nil
  1553. (car (read-from-string (plist-get info :reveal-plugins)))
  1554. (end-of-file nil)
  1555. (wrong-type-argument nil))))
  1556. (memq 'highlight (or (and reveal-plugins (listp reveal-plugins) reveal-plugins)
  1557. org-re-reveal-plugins))))
  1558. (defun org-re-reveal--buffer-substring-html-escape (start end)
  1559. "Convert buffer substring characters from plain text to HTML equivalent.
  1560. START and END are character positions as used by `buffer-substring'.
  1561. Conversion is done by escaping special HTML chars."
  1562. (org-html-encode-plain-text (buffer-substring start end)))
  1563. (defun org-re-reveal-src-block (src-block contents info)
  1564. "Transcode a SRC-BLOCK element from Org to Reveal.
  1565. INFO is a plist holding contextual information. CONTENTS is unused."
  1566. (ignore contents) ; Silence byte compiler
  1567. (if (org-export-read-attribute :attr_html src-block :textarea)
  1568. (org-html--textarea-block src-block)
  1569. (let* ((use-highlight (org-re-reveal--using-highlight.js info))
  1570. (use-htmlize (or (not org-re-reveal-no-htmlize-src)
  1571. (org-export-read-attribute
  1572. :attr_reveal src-block :htmlize)))
  1573. (lang (org-element-property :language src-block))
  1574. (caption (org-export-get-caption src-block))
  1575. (code (if (and (not use-highlight) use-htmlize)
  1576. (org-html-format-code src-block info)
  1577. (cl-letf (((symbol-function
  1578. 'org-html-htmlize-region-for-paste)
  1579. #'org-re-reveal--buffer-substring-html-escape))
  1580. (org-html-format-code src-block info))))
  1581. (frag (org-export-read-attribute :attr_reveal src-block :frag))
  1582. (findex (org-export-read-attribute :attr_reveal src-block :frag_idx))
  1583. (code-attribs (or (org-export-read-attribute
  1584. :attr_reveal src-block :code_attribs) ""))
  1585. (label (let ((lbl (org-element-property :name src-block)))
  1586. (if (not lbl) ""
  1587. (format " id=\"%s\"" lbl))))
  1588. (klipse-setup (org-re-reveal--parse-listoption
  1589. info :reveal-klipse-setup))
  1590. (klipsify (and (member lang (mapcar #'car klipse-setup))
  1591. (plist-get info :reveal-klipsify-src)
  1592. (not (org-export-read-attribute
  1593. :attr_reveal src-block :no-klipsify)))))
  1594. (if (not lang)
  1595. (format "<pre %s%s>\n%s</pre>"
  1596. (or (org-re-reveal--frag-class frag info) " class=\"example\"")
  1597. label
  1598. code)
  1599. (if klipsify
  1600. (let* ((triple (assoc lang klipse-setup))
  1601. (selectorclass (nth 2 triple)))
  1602. (concat
  1603. "<pre><code class=\"" selectorclass "\" " code-attribs ">\n"
  1604. (if (string= lang "html")
  1605. (replace-regexp-in-string
  1606. "'" "&#39;"
  1607. (replace-regexp-in-string
  1608. "<" "&lt;"
  1609. (replace-regexp-in-string
  1610. ">" "&gt;"
  1611. (replace-regexp-in-string
  1612. "&" "&amp;"
  1613. (cl-letf (((symbol-function
  1614. 'org-html-htmlize-region-for-paste)
  1615. #'buffer-substring))
  1616. (org-html-format-code src-block info))))))
  1617. (replace-regexp-in-string "'" "&#39;" code))
  1618. "</code></pre>\n"))
  1619. (format
  1620. "<div class=\"org-src-container\">\n%s%s\n</div>"
  1621. (if (not caption) ""
  1622. (format "<label class=\"org-src-name\">%s</label>"
  1623. (org-export-data caption info)))
  1624. (if use-highlight
  1625. (format "\n<pre%s%s><code class=\"%s %s\" %s>%s</code></pre>"
  1626. (or (org-re-reveal--frag-class frag info) "")
  1627. (or (org-re-reveal--frag-index findex) "")
  1628. label lang code-attribs code)
  1629. (format "\n<pre %s%s%s>%s</pre>"
  1630. (or (org-re-reveal--frag-class frag info)
  1631. (format " class=\"src src-%s\"" lang))
  1632. (or (org-re-reveal--frag-index findex) "")
  1633. label code))))))))
  1634. (defun org-re-reveal-quote-block (quote-block contents info)
  1635. "Transcode a QUOTE-BLOCK element from Org to Reveal.
  1636. CONTENTS holds the contents of the block INFO is a plist holding
  1637. contextual information."
  1638. (format "<blockquote%s>\n%s</blockquote>"
  1639. (let ((frag (org-re-reveal--frag-class
  1640. (org-export-read-attribute
  1641. :attr_reveal quote-block :frag) info)))
  1642. (if frag
  1643. (concat " " frag)
  1644. ""))
  1645. contents))
  1646. (defun org-re-reveal--auto-title-slide-template (info)
  1647. "Generate the automatic title slide template with INFO."
  1648. (let* ((spec (org-re-reveal-format-spec info))
  1649. (title (org-export-data (plist-get info :title) info))
  1650. (author (cdr (assq ?a spec)))
  1651. (email (cdr (assq ?e spec)))
  1652. (date (cdr (assq ?d spec))))
  1653. (concat
  1654. (when (and (plist-get info :with-title)
  1655. (org-string-nw-p title))
  1656. (concat "<h1 class=\"title\">" title "</h1>"))
  1657. (when (and (plist-get info :with-author)
  1658. (org-string-nw-p author))
  1659. (concat "<h2 class=\"author\">" author "</h2>"))
  1660. (when (and (plist-get info :with-email)
  1661. (org-string-nw-p email))
  1662. (concat "<h2 class=\"email\">" email "</h2>"))
  1663. (when (and (plist-get info :with-date)
  1664. (org-string-nw-p date))
  1665. (concat "<h2 class=\"date\">" date "</h2>"))
  1666. (when (plist-get info :time-stamp-file)
  1667. (concat "<p class=\"date\">"
  1668. (org-html--translate "Created" info)
  1669. ": "
  1670. (format-time-string
  1671. (plist-get info :html-metadata-timestamp-format))
  1672. "</p>")))))
  1673. (defun org-re-reveal-template (contents info)
  1674. "Return complete document string after HTML conversion.
  1675. CONTENTS is the transcoded contents string.
  1676. INFO is a plist holding export options."
  1677. (concat
  1678. (format "<!DOCTYPE html>\n<html%s>\n<head>\n"
  1679. (org-re-reveal--if-format " lang=\"%s\"" (plist-get info :language)))
  1680. "<meta charset=\"utf-8\"/>\n"
  1681. (org-re-reveal--if-format "<title>%s</title>\n"
  1682. (org-export-data (plist-get info :title) info))
  1683. (org-re-reveal--if-format "<meta name=\"author\" content=\"%s\"/>\n"
  1684. (org-element-interpret-data (plist-get info :author)))
  1685. (org-re-reveal--if-format "<meta name=\"description\" content=\"%s\"/>\n"
  1686. (plist-get info :description))
  1687. (org-re-reveal--if-format "<meta name=\"keywords\" content=\"%s\"/>\n"
  1688. (plist-get info :keywords))
  1689. (org-re-reveal-stylesheets info)
  1690. (org-re-reveal-mathjax-scripts info)
  1691. (org-re-reveal--build-pre-postamble 'head-preamble info)
  1692. (org-element-normalize-string (plist-get info :html-head))
  1693. (org-element-normalize-string (plist-get info :html-head-extra))
  1694. "</head>\n<body"
  1695. (org-re-reveal--if-format " %s" org-re-reveal-body-attrs)
  1696. ">\n"
  1697. (org-re-reveal--build-pre-postamble 'preamble info)
  1698. "<div class=\"reveal\">
  1699. <div class=\"slides\">\n"
  1700. ;; Title slides
  1701. (let ((title-slide (plist-get info :reveal-title-slide)))
  1702. (when (and (or (eq 'auto title-slide)
  1703. (and (stringp title-slide) (< 0 (length title-slide))))
  1704. (or (not (plist-get info :reveal-subtree))
  1705. (plist-get info :reveal-subtree-with-title-slide)))
  1706. (let ((title-slide-background (plist-get info :reveal-title-slide-background))
  1707. (title-slide-background-size (plist-get info :reveal-title-slide-background-size))
  1708. (title-slide-background-position (plist-get info :reveal-title-slide-background-position))
  1709. (title-slide-background-repeat (plist-get info :reveal-title-slide-background-repeat))
  1710. (title-slide-background-transition (plist-get info :reveal-title-slide-background-transition))
  1711. (title-slide-state (plist-get info :reveal-title-slide-state))
  1712. (title-slide-timing (plist-get info :reveal-title-slide-timing))
  1713. (title-slide-with-header (plist-get info :reveal-slide-global-header))
  1714. (title-slide-with-footer (plist-get info :reveal-slide-global-footer)))
  1715. (concat "<section id=\"sec-title-slide\""
  1716. (when title-slide-background
  1717. (concat " data-background=\"" title-slide-background "\""))
  1718. (when title-slide-background-size
  1719. (concat " data-background-size=\"" title-slide-background-size "\""))
  1720. (when title-slide-background-position
  1721. (concat " data-background-position=\"" title-slide-background-position "\""))
  1722. (when title-slide-background-repeat
  1723. (concat " data-background-repeat=\"" title-slide-background-repeat "\""))
  1724. (when title-slide-background-transition
  1725. (concat " data-background-transition=\"" title-slide-background-transition "\""))
  1726. (when title-slide-state
  1727. (concat " data-state=\"" title-slide-state "\""))
  1728. (when title-slide-timing
  1729. (concat " data-timing=\"" title-slide-timing "\""))
  1730. ">\n"
  1731. (when title-slide-with-header
  1732. (let ((header (plist-get info :reveal-slide-header)))
  1733. (when header (format org-re-reveal-slide-header-html header))))
  1734. (cond ((eq title-slide nil) nil)
  1735. ((stringp title-slide)
  1736. (let* ((file-contents
  1737. (org-re-reveal--read-file-as-string title-slide))
  1738. (title-string (or file-contents title-slide)))
  1739. (format-spec title-string
  1740. (org-re-reveal-format-spec info))))
  1741. ((eq title-slide 'auto) (org-re-reveal--auto-title-slide-template info)))
  1742. "\n"
  1743. (when title-slide-with-footer
  1744. (let ((footer (plist-get info :reveal-slide-footer)))
  1745. (when footer (format org-re-reveal-slide-footer-html footer))))
  1746. "</section>\n"))))
  1747. contents
  1748. "</div>
  1749. </div>\n"
  1750. (org-re-reveal--build-pre-postamble 'postamble info)
  1751. (org-re-reveal-scripts info)
  1752. (org-re-reveal--klipsify-script info)
  1753. "</body>
  1754. </html>\n"))
  1755. (defun org-re-reveal-filter-parse-tree (tree backend info)
  1756. "Do filtering before parsing TREE.
  1757. TREE is the parse tree being exported. BACKEND is the export
  1758. back-end used. INFO is a plist-used as a communication channel.
  1759. BACKEND must be (or be derived from) `re-reveal'.
  1760. Modify the TREE in two ways:
  1761. First, map each `attr_reveal' attribute to corresponding
  1762. `attr_html' attributes.
  1763. Second, if `org-re-reveal-generate-custom-ids' is t (or option
  1764. \"reveal_generate_ids\" is t), generate \"CUSTOM_ID\" values for
  1765. section headings that do not have one already."
  1766. (cl-assert (org-export-derived-backend-p backend 're-reveal) nil
  1767. (format "Function org-re-reveal-filter-parse-tree called on unexpected backend: %s" backend))
  1768. (let ((default-frag-style (plist-get info :reveal-default-frag-style)))
  1769. (org-element-map tree (remq 'item org-element-all-elements)
  1770. (lambda (elem) (org-re-reveal-append-frag elem default-frag-style))))
  1771. (when (plist-get info :reveal-generate-ids)
  1772. (let ((numbering (org-export--collect-headline-numbering tree info)))
  1773. (dolist (pair numbering nil)
  1774. (let ((headline (car pair))
  1775. (number (cdr pair)))
  1776. (when (org-export-numbered-headline-p headline info)
  1777. (let ((section-number (mapconcat #'number-to-string number "-")))
  1778. (when (and (> (length section-number) 0)
  1779. (not (org-element-property :CUSTOM_ID headline)))
  1780. (org-element-put-property headline :CUSTOM_ID section-number))))))))
  1781. ;; Return the updated tree.
  1782. tree)
  1783. (defun org-re-reveal--update-attr-html (elem frag default-style
  1784. &optional frag-index frag-audio)
  1785. "Update ELEM's attr_html attribute with reveal's fragment attributes.
  1786. FRAG is the fragment style, a DEFAULT-STYLE may be used;
  1787. optional FRAG-INDEX and FRAG-AUDIO may indicate fragment positions
  1788. and audio files."
  1789. (let ((attr-html (org-element-property :attr_html elem)))
  1790. (when (and frag (not (string= frag "none")))
  1791. (push (if (string= frag t)
  1792. (if default-style (format ":class fragment %s" default-style)
  1793. ":class fragment")
  1794. (format ":class fragment %s" frag))
  1795. attr-html)
  1796. (when frag-index
  1797. ;; Index positions should be numbers or the minus sign.
  1798. (cl-assert (or (integerp frag-index)
  1799. (eq frag-index '-)
  1800. (and (not (listp frag-index))
  1801. (not (char-equal
  1802. (string-to-char frag-index) ?\())))
  1803. nil "Index cannot be a list: %s" frag-index)
  1804. (push (format ":data-fragment-index %s" frag-index) attr-html))
  1805. (when (and frag-audio (not (string= frag-audio "none")))
  1806. (push (format ":data-audio-src %s" frag-audio) attr-html)))
  1807. (org-element-put-property elem :attr_html attr-html)))
  1808. (defun org-re-reveal-append-frag (elem default-style)
  1809. "Append transformed fragment from ELEM with DEFAULT-STYLE.
  1810. Read fragment from ELEM and append transformed fragment attribute to ELEM's
  1811. attr_html plist."
  1812. (let ((frag (org-export-read-attribute :attr_reveal elem :frag))
  1813. (frag-index (org-export-read-attribute :attr_reveal elem :frag_idx))
  1814. (frag-audio (org-export-read-attribute :attr_reveal elem :audio)))
  1815. (when frag
  1816. (if (and (string= (org-element-type elem) 'plain-list)
  1817. (char-equal (string-to-char frag) ?\())
  1818. (let* ((items (org-element-contents elem))
  1819. (frag-list (car (read-from-string frag)))
  1820. (frag-list (if default-style
  1821. (mapcar (lambda (s)
  1822. "Replace t with default-style"
  1823. (if (string= s t) default-style
  1824. s))
  1825. frag-list)
  1826. frag-list))
  1827. (itemno (length items))
  1828. (style-list (make-list itemno default-style))
  1829. ;; Make sure that we have enough fragments. Duplicate the
  1830. ;; last element of frag-list so that frag-list and items
  1831. ;; have the same length.
  1832. (last-frag (car (last frag-list)))
  1833. (tail-list (make-list
  1834. (- itemno (length frag-list)) last-frag))
  1835. (frag-list (append frag-list tail-list))
  1836. ;; Concerning index positions and audio files, check later
  1837. ;; that their number is OK.
  1838. (frag-index (if frag-index
  1839. (car (read-from-string frag-index))
  1840. (make-list itemno nil)))
  1841. (frag-audio (when frag-audio
  1842. (car (read-from-string frag-audio)))))
  1843. ;; As we are looking at fragments in lists, we make sure
  1844. ;; that other specs are lists of proper length.
  1845. (cl-assert (listp frag-index) t
  1846. "Must use list for index positions, not: %s")
  1847. (when frag-index
  1848. (cl-assert (= (length frag-index) itemno) nil
  1849. "Use one index per item! %s has %d, need %d"
  1850. frag-index (length frag-index) (length items)))
  1851. (cl-assert (listp frag-audio) t
  1852. "Must use list for audio files! %s")
  1853. (when frag-audio
  1854. (cl-assert (= (length frag-audio) itemno) nil
  1855. "Use one audio file per item! %s has %d, need %d"
  1856. frag-audio (length frag-audio) itemno))
  1857. (if frag-audio
  1858. (cl-mapcar 'org-re-reveal--update-attr-html
  1859. items frag-list style-list frag-index frag-audio)
  1860. (cl-mapcar 'org-re-reveal--update-attr-html
  1861. items frag-list style-list frag-index)))
  1862. (org-re-reveal--update-attr-html
  1863. elem frag default-style frag-index frag-audio))
  1864. elem)))
  1865. (defun org-re-reveal-export-to-html
  1866. (&optional async subtreep visible-only body-only ext-plist backend)
  1867. "Export current buffer to a reveal.js HTML file.
  1868. Optional ASYNC, SUBTREEP, VISIBLE-ONLY, BODY-ONLY, EXT-PLIST are passed
  1869. to `org-export-to-file'.
  1870. Optional BACKEND must be `re-reveal' or a backend derived from it."
  1871. (interactive)
  1872. (let* ((backend (or backend 're-reveal))
  1873. (extension (concat "." org-html-extension))
  1874. (file (org-export-output-file-name extension subtreep))
  1875. (clientfile (org-export-output-file-name (concat "_client" extension) subtreep))
  1876. (org-html-container-element "div"))
  1877. (setq org-re-reveal-client-multiplex nil)
  1878. (org-export-to-file backend file
  1879. async subtreep visible-only body-only ext-plist)
  1880. ;; Export the client HTML file if org-re-reveal-client-multiplex is set true
  1881. ;; by previous call to org-export-to-file
  1882. (if org-re-reveal-client-multiplex
  1883. (org-export-to-file backend clientfile
  1884. async subtreep visible-only body-only ext-plist))
  1885. file))
  1886. (defun org-re-reveal-export-to-html-and-browse
  1887. (&optional async subtreep visible-only body-only ext-plist)
  1888. "Export current buffer to a reveal.js and browse HTML file.
  1889. Optional ASYNC, SUBTREEP, VISIBLE-ONLY, BODY-ONLY, EXT-PLIST are passed
  1890. to `org-re-reveal-export-to-html'."
  1891. (interactive)
  1892. (browse-url-of-file
  1893. (expand-file-name
  1894. (org-re-reveal-export-to-html
  1895. async subtreep visible-only body-only ext-plist))))
  1896. (defun org-re-reveal-export-current-subtree
  1897. (&optional async subtreep visible-only body-only ext-plist)
  1898. "Export current subtree to a Reveal.js HTML file.
  1899. Optional ASYNC, SUBTREEP, VISIBLE-ONLY, BODY-ONLY, EXT-PLIST are passed
  1900. to `org-re-reveal-export-to-html'."
  1901. (interactive)
  1902. (org-narrow-to-subtree)
  1903. (let ((ret (org-re-reveal-export-to-html
  1904. async subtreep visible-only body-only
  1905. (plist-put ext-plist :reveal-subtree t))))
  1906. (widen)
  1907. ret))
  1908. ;;;###autoload
  1909. (defun org-re-reveal-publish-to-reveal
  1910. (plist filename pub-dir &optional backend)
  1911. "Publish an Org file to HTML.
  1912. FILENAME is the filename of the Org file to be published. PLIST
  1913. is the property list for the given project. PUB-DIR is the
  1914. publishing directory. Optional BACKEND may specify a derived export
  1915. backend.
  1916. Return output file name."
  1917. (let ((org-re-reveal-client-multiplex nil))
  1918. (org-publish-org-to
  1919. (or backend 're-reveal) filename ".html" plist pub-dir)))
  1920. ;;;###autoload
  1921. (defun org-re-reveal-publish-to-reveal-client
  1922. (plist filename pub-dir &optional backend)
  1923. "Publish an Org file to HTML as multiplex client.
  1924. FILENAME is the filename of the Org file to be published. PLIST
  1925. is the property list for the given project. PUB-DIR is the
  1926. publishing directory. Optional BACKEND may specify a derived export
  1927. backend.
  1928. If `org-re-reveal-client-multiplex-filter' is non-nil, use it as regular
  1929. expression to only publish FILENAME if it matches this regular expression.
  1930. Return output file name."
  1931. (if (or (not org-re-reveal-client-multiplex-filter)
  1932. (string-match org-re-reveal-client-multiplex-filter filename))
  1933. (let ((org-re-reveal-client-multiplex t))
  1934. (org-publish-org-to
  1935. (or backend 're-reveal) filename "_client.html" plist pub-dir))
  1936. (message "File '%s' not published (not matched by '%s')."
  1937. filename org-re-reveal-client-multiplex-filter)
  1938. nil)
  1939. :package-version '(org-re-reveal . "2.12.0"))
  1940. ;; Register auto-completion for speaker notes.
  1941. (when org-re-reveal-note-key-char
  1942. (add-to-list 'org-structure-template-alist
  1943. (if (version< org-version "9.2")
  1944. (list org-re-reveal-note-key-char "#+BEGIN_NOTES\n\?\n#+END_NOTES")
  1945. (cons org-re-reveal-note-key-char "notes"))))
  1946. ;;; Extract version string.
  1947. ;;;###autoload
  1948. (defun org-re-reveal-version ()
  1949. "Display version string for org-re-reveal from Lisp file."
  1950. (interactive)
  1951. (let ((lisp-file
  1952. (concat (file-name-sans-extension (locate-library "org-re-reveal"))
  1953. ".el")))
  1954. (with-temp-buffer
  1955. (insert-file-contents lisp-file)
  1956. (goto-char (point-min))
  1957. (re-search-forward "^;; Version: \\([0-9.]+\\)$")
  1958. (message "org-re-reveal version %s" (match-string 1)))))
  1959. (provide 'org-re-reveal)
  1960. ;;; org-re-reveal.el ends here