Initial version.

This commit is contained in:
yjwen 2013-04-28 15:45:05 +08:00
parent c02b65c2e5
commit 238fa41446
4 changed files with 666 additions and 0 deletions

233
Readme.org Normal file
View File

@ -0,0 +1,233 @@
#+Title: Introduction to Org-Reveal
#+Author: Yujie Wen
#+Email: yjwen.ty@gmail.com
#+OPTIONS: reveal_center:nil
#+REVEAL_TRANS: cube
#+REVEAL_THEME: moon
#+REVEAL_HLEVEL: 2
* Reveal.js and Org-Reveal
- *Reveal.js* is a tool for creating good look HTML presentations,
authored by Hakim El Hattab. \\
For an example of reveal.js presentation, click [[http://lab.hakim.se/reveal-js/#/][here]].
- *Org-Reveal* exports your Org documents to reveal.js
presentations.\\
So you can create beautiful presentations with 3D effects from
simple but powerful org contents.
* Requirements and Installation
- Reveal.js.
- Latest org-mode.
- ox-reveal.el.
- And, of course, emacs.
** Obtain Reveal.js
Download Reveal.js packages from [[https://github.com/hakimel/reveal.js/][here]].
Extract reveal.js folders from the downloaded zip file.
** Obtain org-mode
*Note*: Org-reveal relies on the LATEST org-mode export frame work.
Pre-packaged org-mode may be out-of-date.
If not sure, use the freshest development codes from git repository.
#+BEGIN_SRC sh
$ git clone git://orgmode.org/org-mode.git
#+END_SRC
Follow the [[http://orgmode.org/worg/dev/org-build-system.html][online instruction]] to build and install Org-mode.
** TODO Obtain Org-reveal
Obtain latest Org-reveal from github.
Copy =ox-reveal.el= to the Org-mode install directory.
Add the following statement to your =.emacs= file.
#+BEGIN_SRC lisp
(require 'ox-reveal)
#+END_SRC
* Configuration
** Set the location of Reveal.js
Org-reveal must know where reveal.js is before exporting Org
contents.
Default location is =./reveal.js=, relative to the Org file.
Change variable =org-reveal-root= 's value will change the location
globally. For example, add the following statement to your .emacs
file:
#+BEGIN_SRC lisp
(setq org-reveal-root "d:/reveal.js")
#+END_SRC
By setting option =REVEAL_ROOT=, the location is only affected
within the Org file.
#+BEGIN_SRC org
,#+REVEAL_ROOT: d:/reveal.js
#+END_SRC
** First Try
Modifications to =.emacs= will take effect at next time Emacs
starts up.
To wake-up Org-reveal now, type "M-x load-library", then type
"ox-reveal".
Now you can export this manual into Reveal.js presentation by
typing "C-c C-e R R".
Open the generated "Readme.html" in your browser and enjoy the
cool slides.
** The HLevel
Org-reveal maps each heading and its contents to one Reveal.js
slides. Since Reveal.js arrange slides into a 2-dimentional matrix,
Org-reveal use *HLevel* value to decide map headings to hozirontal
or vertical slides.
* Headings of level less or equal to HLevel are mapped to hozirontal
slides.
* Headings of deeper levels are mapped to vertical slides.
HLevel's default value is 1, means only level 1 headings are arranged
horizontally, deeper headings are mapped to vertical slides below its
parent level 1 heading.
*** HLevel's Affects on Slides Layout
Assume we have a simple Org file as below:
#+BEGIN_SRC org
,* H1
,* H2
,** H2.1
,*** H2.1.1
,* H3
#+END_SRC
If HLevel is 1, the default value, headings H2.1 and H2.1.1 will
be mapping to vertical slides below the slides of heading H2.
[[./images/hlevel.png]]
If HLevel is changed to 2, slide of heading H2.1 will be changed
to the main hozirontal queue, and slide of heading H2.1.1 will be
a vertical slide below it.
[[./images/hlevel2.png]]
*** Configure HLevel's Value
* Change variable =org-reveal-hlevel='s value to set HLevel globally.\\
For example, add the following statement to your =.emacs= file.
#+BEGIN_SRC lisp
(setq org-reveal-hlevel 2)
#+END_SRC
* Setting Org files local HLevel to option =REVEAL_HLEVEL=.
#+BEGIN_SRC org
,#+REVEAL_HLEVEL 2
#+END_SRC
** Select Theme and Transition
Themes and transitions are set globally throughout the whole file by
setting options =REVEAL_THEME= and =REVEAL_TRANS=.
For example, check the heading parting of this documents.
Available themes can be find in "css/theme/" in the reveal.js directory.
Available transitions are: default|cube|page|concave|zoom|linear|fade|none.
** Fragmented Contents
Make contents fragmented, show up one-by-one, by setting option =ATTR_REVEAL= with
property ":frag frag-style", as illustrated below.
#+ATTR_REVEAL: :frag roll-in
Paragraphs can be fragmented.
#+ATTR_REVEAL: :frag roll-in
Items can be fragmented, too.
Availabe fragment styles are:
#+ATTR_REVEAL: :frag grow
* grow
#+ATTR_REVEAL: :frag shrink
* shrink
#+ATTR_REVEAL: :frag roll-in
* roll-in
#+ATTR_REVEAL: :frag fade-out
* fade-out
#+ATTR_REVEAL: :frag highlight-red
* highlight-red
#+ATTR_REVEAL: :frag highlight-green
* highlight-green
#+ATTR_REVEAL: :frag highlight-blue
* highlight-blue
** Data State
:PROPERTIES:
:reveal_data_state: alert
:END:
Set property =reveal_data_state= to headings to change this slide's
style, as illustrated above.
** Plug-ins
Reveal.js provides several plug-in functions.
- reveal-control : Show/hide browse control pad.
- reveal-progress : Show/hide progress bar.
- reveal-history : Enable/disable slide history track.
- reveal-center : Enable/disable slide centering.
*** Configure Plug-ins
Each plug-ins can be set on/off by adding =#+OPTIONS= tags or
settinng custom variables.
- =#+OPTIONS= tags:\\
=reveal_control=, =reveal_progress=, =reveal_history=,
=reveal_center=
- Custom variables:\\
=org-reveal-control=, =org-reveal-progress=,
=org-reveal-history=, =org-reveal-center=
** Source Codes
Org-reveal use Org-Babel to highlight source codes.
Codes copied from [[http://www.haskell.org/haskellwiki/The_Fibonacci_sequence][Haskell Wiki]].
#+BEGIN_SRC haskell
fibs = 0 : 1 : next fibs
where next (a : t@(b:_)) = (a+b) : next t
#+END_SRC
If you saw odd indentation, please set variable =org-html-indent=
to nil and export again.
* Thanks
Courtesy to:
#+ATTR_REVEAL: :frag roll-in
the powerfull Org-mode,
#+ATTR_REVEAL: :frag roll-in
and the impressive Reveal.js

BIN
images/hlevel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
images/hlevel2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

433
ox-reveal.el Normal file
View File

@ -0,0 +1,433 @@
;; ox-reveal --- reveal.js Presentation Back-End for Org Export Engine
;; Copyright (C) 2013 Yujie Wen
;; Author: Yujie Wen <yjwen.ty at gmail dot com>
;; Keywords: outlines, hypermedia, slideshow, presentation
;; This file is not part of GNU Emacs.
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;; Please see "Readme.org" for detail introductions.
(require 'ox-html)
(eval-when-compile (require 'cl))
(org-export-define-derived-backend reveal html
:menu-entry
(?R "Export to reveal.js HTML Presentation"
((?R "To file" org-reveal-export-to-html)))
:options-alist
((:reveal-control nil "reveal_control" org-reveal-control t)
(:reveal-progress nil "reveal_progress" org-reveal-progress t)
(:reveal-history nil "reveal_history" org-reveal-history t)
(:reveal-center nil "reveal_center" org-reveal-center t)
(:reveal-root "REVEAL_ROOT" nil org-reveal-root t)
(:reveal-trans "REVEAL_TRANS" nil org-reveal-transition t)
(:reveal-theme "REVEAL_THEME" nil org-reveal-theme t)
(:reveal-hlevel "REVEAL_HLEVEL" nil nil t)
)
:translate-alist
((headline . org-reveal-headline)
(inner-template . org-reveal-inner-template)
(item . org-reveal-item)
(paragraph . org-reveal-paragraph)
(template . org-reveal-template)))
(defcustom org-reveal-root "./reveal.js"
"The root directory of reveal.js packages. It is the directory
within which js/reveal.min.js is."
:group 'org-export-reveal)
(defcustom org-reveal-hlevel 1
"The minimum level of headings that should be grouped into
vertical slides."
:group 'org-export-reveal
:type 'integer)
(defun org-reveal--get-hlevel (info)
"Get HLevel value safely.
If option \"REVEAL_HLEVEL\" is set, retrieve integer value from it,
else get value from custom variable `org-reveal-hlevel'."
(let ((hlevel-str (plist-get info :reveal-hlevel)))
(if hlevel-str (string-to-int hlevel-str)
org-reveal-hlevel)))
(defcustom org-reveal-title-slide-template
"<h1>%t</h1>
<h2>%a</h2>
<h2>%e</h2>
<h2>%d</h2>"
"Format template to specify title page slide.
See `org-html-postamble-format' for the valid elements which
can be include."
:group 'org-export-reveal
:type 'string)
(defcustom org-reveal-transition
"default"
"Reveal transistion style."
:group 'org-export-reveal
:type 'string)
(defcustom org-reveal-theme
"default"
"Reveal theme."
:group 'org-export-reveal
:type 'string)
(defcustom org-reveal-control t
"Reveal control applet."
:group 'org-export-reveal
:type 'string)
(defcustom org-reveal-progress t
"Reveal progress applit."
:group 'org-export-reveal
:type 'boolean)
(defcustom org-reveal-history t
"Reveal history applit."
:group 'org-export-reveal
:type 'boolean)
(defcustom org-reveal-center t
"Reveal center applit."
:group 'org-export-reveal
:type 'boolean)
(defun if-format (fmt val)
(if val (format fmt val) ""))
(defun org-reveal-headline (headline contents info)
"Transcode a HEADLINE element from Org to HTML.
CONTENTS holds the contents of the headline. INFO is a plist
holding contextual information."
;; First call org-html-headline to get the formatted HTML contents.
;; Then add enclosing <section> tags to mark slides.
(setq contents (or contents ""))
(let* ((numberedp (org-export-numbered-headline-p headline info))
(level (org-export-get-relative-level headline info))
(text (org-export-data (org-element-property :title headline) info))
(todo (and (plist-get info :with-todo-keywords)
(let ((todo (org-element-property :todo-keyword headline)))
(and todo (org-export-data todo info)))))
(todo-type (and todo (org-element-property :todo-type headline)))
(tags (and (plist-get info :with-tags)
(org-export-get-tags headline info)))
(priority (and (plist-get info :with-priority)
(org-element-property :priority headline)))
(section-number (and (org-export-numbered-headline-p headline info)
(mapconcat 'number-to-string
(org-export-get-headline-number
headline info) ".")))
;; Create the headline text.
(full-text (org-html-format-headline--wrap headline info)))
(cond
;; Case 1: This is a footnote section: ignore it.
((org-element-property :footnote-section-p headline) nil)
;; Case 2. This is a deep sub-tree: export it as a list item.
;; Also export as items headlines for which no section
;; format has been found.
((org-export-low-level-p headline info)
;; Build the real contents of the sub-tree.
(let* ((type (if numberedp 'ordered 'unordered))
(itemized-body (org-reveal-format-list-item
contents type nil nil 'none full-text)))
(concat
(and (org-export-first-sibling-p headline info)
(org-html-begin-plain-list type))
itemized-body
(and (org-export-last-sibling-p headline info)
(org-html-end-plain-list type)))))
;; Case 3. Standard headline. Export it as a section.
(t
(let* ((section-number (mapconcat 'number-to-string
(org-export-get-headline-number
headline info) "-"))
(ids (remove 'nil
(list (org-element-property :CUSTOM_ID headline)
(concat "sec-" section-number)
(org-element-property :ID headline))))
(extra-ids (cdr ids))
(level1 (+ level (1- org-html-toplevel-hlevel)))
(hlevel (org-reveal--get-hlevel info))
(first-content (car (org-element-contents headline))))
(concat
(if (or (/= level 1)
(not (org-export-first-sibling-p headline info)))
;; Stop previous slide.
"</section>\n")
(if (eq level hlevel)
;; Add an extra "<section>" to group following slides
;; into vertical ones.
"<section>\n")
;; Start a new slide.
(format "<section%s>\n"
(if-format " data-state=\"%s\"" (org-element-property :REVEAL_DATA_STATE headline)))
;; The HTML content of this headline.
(format "\n<h%d%s>%s%s</h%d>\n"
level1
(if-format " class=\"fragment %s\""
(org-element-property :REVEAL-FRAG headline))
(mapconcat
(lambda (x)
(let ((id (org-export-solidify-link-text
(if (org-uuidgen-p x) (concat "ID-" x)
x))))
(org-html--anchor id)))
extra-ids "")
full-text
level1)
;; When there is no section, pretend there is an empty
;; one to get the correct <div class="outline- ...>
;; which is needed by `org-info.js'.
(if (not (eq (org-element-type first-content) 'section))
(concat (org-html-section first-content "" info)
contents)
contents)
(if (= level hlevel)
;; Add an extra "</section>" to stop vertical slide
;; grouping.
"</section>\n")
(if (and (= level 1)
(org-export-last-sibling-p headline info))
;; Last head 1. Stop all slides.
"</section>")))))))
(defgroup org-export-reveal nil
"Options for exporting Orgmode files to reveal.js HTML pressentations."
:tag "Org Export reveal")
(defun org-reveal--append-path (dir-name path-name)
"Append `path-name' to the end of `dir-name' to form a legal path name."
(concat (file-name-as-directory dir-name) path-name))
(defun org-reveal--append-pathes (dir-name pathes)
"Append all the path names in `pathes' to the end of `dir-name'
to form a legal path name."
(if pathes
(org-reveal--append-pathes
(org-reveal--append-path dir-name (car pathes))
(cdr pathes))
dir-name))
(defun org-reveal-stylesheets (info)
"Return the HTML contents for decalaring reveal stylesheets
using custom variable `org-reveal-root'."
(let* ((root-path (plist-get info :reveal-root))
(css-dir-name (org-reveal--append-path root-path "css"))
(min-css-file-name (org-reveal--append-path css-dir-name "reveal.min.css"))
(theme-file (format "%s.css" (plist-get info :reveal-theme)))
(theme-path (org-reveal--append-path css-dir-name "theme"))
(theme-full (org-reveal--append-path theme-path theme-file)))
(format "<link rel=\"stylesheet\" href=\"%s\">
<link rel=\"stylesheet\" href=\"%s\" id=\"theme\">"
min-css-file-name theme-full)))
(defun org-reveal-scripts (info)
"Return the necessary scripts for initializing reveal.js using
custom variable `org-reveal-root'."
(let* ((root-path (plist-get info :reveal-root))
(root-dir-name (file-name-as-directory root-path))
(lib-dir-name (org-reveal--append-path root-path "lib"))
(lib-js-dir-name (org-reveal--append-path lib-dir-name "js"))
(plugin-dir-name (org-reveal--append-path root-path "plugin"))
(markdown-dir-name (org-reveal--append-path plugin-dir-name "markdown")))
(concat
(format "<script src=\"%s\"></script>\n<script src=\"%s\"></script>\n"
(org-reveal--append-path lib-js-dir-name "head.min.js")
(org-reveal--append-pathes root-path '("js" "reveal.min.js")))
"<script>\n"
(format "
// Full list of configuration options available here:
// https://github.com/hakimel/reveal.js#configuration
Reveal.initialize({
controls: %s,
progress: %s,
history: %s,
center: %s,
theme: Reveal.getQueryHash().theme, // available themes are in /css/theme
transition: Reveal.getQueryHash().transition || '%s', // default/cube/page/concave/zoom/linear/fade/none\n"
(if (plist-get info :reveal-control) "true" "false")
(if (plist-get info :reveal-progress) "true" "false")
(if (plist-get info :reveal-history) "true" "false")
(if (plist-get info :reveal-center) "true" "false")
(plist-get info :reveal-trans))
(format "
// Optional libraries used to extend on reveal.js
dependencies: [
{ src: '%s', condition: function() { return !document.body.classList; } },
{ src: '%s', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: '%s', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: '%s', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
{ src: '%s', async: true, condition: function() { return !!document.body.classList; } },
{ src: '%s', async: true, condition: function() { return !!document.body.classList; } }
// { src: '%s', async: true, condition: function() { return !!document.body.classList; } }
// { src: '%s', async: true, condition: function() { return !!document.body.classList; } }
]
});\n"
(org-reveal--append-path lib-js-dir-name "classList.js")
(org-reveal--append-path markdown-dir-name "showdown.js")
(org-reveal--append-path markdown-dir-name "markdown.js")
(org-reveal--append-pathes plugin-dir-name '("highlight" "highlight.js"))
(org-reveal--append-pathes plugin-dir-name '("zoom-js" "zoom.js"))
(org-reveal--append-pathes plugin-dir-name '("notes" "notes.js"))
(org-reveal--append-pathes plugin-dir-name '("search" "search.js"))
(org-reveal--append-pathes plugin-dir-name '("remotes" "remotes.js")))
"</script>\n")))
(defun org-reveal-toc (depth info)
"Build a slide of table of contents."
(concat
"<section>\n"
(org-html-toc depth info)
"</section>\n"))
(defun org-reveal-inner-template (contents info)
"Return body of document string after HTML conversion.
CONTENTS is the transcoded contents string. INFO is a plist
holding export options."
(concat
;; Table of contents.
(let ((depth (plist-get info :with-toc)))
(when depth (org-reveal-toc depth info)))
;; Document contents.
contents))
(defun org-reveal-format-list-item
(content type checkbox &optional term-counter-id frag headline)
"Format a list item into Reveal.js HTML."
(let ((checkbox (concat (org-html-checkbox checkbox) (and checkbox " "))))
(concat
(case type
(ordered
(concat
"<li"
(if-format " value=\"%s\"" counter)
(if-format " class=\"fragment %s\"" frag)
">"
(if headline (concat headline "<br/>"))))
(unordered
(concat
"<li"
(if-format " class=\"fragment %s\"" frag)
">"
(if headline (concat headline "<br/>"))))
(descriptive
(concat
"<dt"
(if-format " class=\"fragment %s\"" frag)
">"
(concat checkbox (or term-counter-id "(no term)"))
"</dt><dd>")))
(unless (eq type 'descriptive) checkbox)
contents
(case type
(ordered "</li>")
(unordered "</li>")
(descriptive "</dd>")))))
(defun org-reveal--headline-property (property blob)
"Get property from BLOB's parent headline and return."
(let ((headline (if (eq (org-element-type blob) 'headline) blob
(org-export-get-parent-headline blob))))
(org-element-property property headline)))
(defun org-reveal--get-frag (info)
"Get Reveal fragment settings from context."
(let ((frag (plist-get info :reveal-frag)))
(if (eq frag "none") nil frag)))
(defun org-reveal-item (item contents info)
"Transcode an ITEM element from Org to Reveal.
CONTENTS holds the contents of the item. INFO is aplist holding
contextual information."
(let* ((plain-list (org-export-get-parent item))
(type (org-element-property :type plain-list))
(counter (org-element-property :counter item))
(checkbox (org-element-property :checkbox item))
(tag (let ((tag (org-element-property :tag item)))
(and tag (org-export-data tag info))))
(frag (org-export-read-attribute :attr_reveal plain-list :frag)))
(org-reveal-format-list-item
contents type checkbox (or tag counter) frag)))
(defun org-reveal-paragraph (paragraph contents info)
"Transcode a PARAGRAPH element from Org to Reveal HTML.
CONTENTS is the contents of the paragraph, as a string. INFO is
the plist used as a communication channel."
(let ((parent (org-export-get-parent paragraph)))
(cond
((and (eq (org-element-type parent) 'item)
(= (org-element-property :begin paragraph)
(org-element-property :contents-begin parent)))
;; leading paragraph in a list item have no tags
contents)
((org-html-standalone-image-p paragraph info)
;; standalone image
contents)
(t (format "<p%s>\n%s</p>"
(if-format " class=\"fragment %s\""
(org-export-read-attribute :attr_reveal paragraph :frag))
contents)))))
(defun org-reveal-template (contents info)
"Return complete document string after HTML conversion.
contents is the transcoded contents string.
info is a plist holding export options."
(concat
(format "<!doctype html>\n<html%s>\n<head>\n"
(if-format " lang=\"%s\"" (plist-get info :language)))
(if-format "<title>%s</title>\n" (plist-get info :title))
(if-format "<meta name=\"author\" content=\"%s\"/>\n" (plist-get info :author))
(if-format "<meta name=\"description\" content=\"%s\"/>\n" (plist-get info :description))
(if-format "<meta name=\"keywords\" content=\"%s\"/>\n" (plist-get info :keywords))
(org-reveal-stylesheets info)
"</head>
<body>
<div class=\"reveal\">
<div class=\"slides\">
<section>
"
(format-spec org-reveal-title-slide-template (org-html-format-spec info))
"</section>\n"
contents
"</div>
</div>\n"
(org-reveal-scripts info)
"</body>
</html>\n"))
(defun org-reveal-export-to-html
(&optional async subtreep visible-only body-only ext-plist)
"Export current buffer to a reveal.js HTML file."
(interactive)
(let* ((extension (concat "." org-html-extension))
(file (org-export-output-file-name extension subtreep)))
(org-export-to-file
'reveal file subtreep visible-only body-only ext-plist)))
(provide 'ox-reveal)