diff options
author | Bastien Guerry <bzg@altern.org> | 2013-02-20 16:32:54 +0100 |
---|---|---|
committer | Bastien Guerry <bzg@altern.org> | 2013-02-20 16:32:54 +0100 |
commit | 177fd6501a1d56ad9941fc32c6bf9b1bf7504906 (patch) | |
tree | 7a63d9fbed307fab930fee3a7de30db2bf9a6e07 | |
parent | f35e82641c02e4b406801f76060ffbf5617abfb6 (diff) | |
download | org-mode-177fd6501a1d56ad9941fc32c6bf9b1bf7504906.tar.gz |
contrib/: Add ox-deck.el and ox-s5.el by Rick Frankel
Thanks to Rick Frankel for these contributions!
-rw-r--r-- | contrib/lisp/ox-deck.el | 564 | ||||
-rw-r--r-- | contrib/lisp/ox-s5.el | 384 |
2 files changed, 948 insertions, 0 deletions
diff --git a/contrib/lisp/ox-deck.el b/contrib/lisp/ox-deck.el new file mode 100644 index 0000000..c07d250 --- /dev/null +++ b/contrib/lisp/ox-deck.el @@ -0,0 +1,564 @@ +;;; ox-deck.el --- deck.js Presentation Back-End for Org Export Engine + +;; Copyright (C) 2013 Rick Frankel + +;; Author: Rick Frankel <emacs at rickster dot com> +;; Keywords: outlines, hypermedia, slideshow + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. + +;;; Commentary: + +;; This library implements a deck.js presentation back-end for the Org +;; generic exporter. + +;; Installation +;; ------------- +;; Get a copy of deck.js from http://imakewebthings.com/deck.js/ or +;; the gitub repository at https://github.com/imakewebthings/deck.js. +;; +;; Add the path to the extracted code to the variable +;; `org-deck-directories' There are a number of customization in the +;; org-export-deck group, most of which can be overrriden with buffer +;; local customization (starting with DECK_.) + +;; See ox.el and ox-html.el for more details on how this exporter +;; works (it is derived from ox-html.) + +(require 'ox-html) + +(org-export-define-derived-backend deck html + :menu-entry + (?s "Export to deck.js HTML Presentation" + ((?H "To temporary buffer" org-deck-export-as-html) + (?h "To file" org-deck-export-to-html) + (?o "To file and open" + (lambda (a s v b) + (if a (org-deck-export-to-html t s v b) + (org-open-file (org-deck-export-to-html nil s v b))))))) + :options-alist + ((:html-link-home "HTML_LINK_HOME" nil nil) + (:html-link-up "HTML_LINK_UP" nil nil) + (:html-mathjax "HTML_MATHJAX" nil "" space) + (:html-postamble nil "html-postamble" nil t) + (:html-preamble nil "html-preamble" nil t) + (:html-style-extra "HTML_STYLE" nil org-html-style-extra newline) + (:html-style-include-default "HTML_INCLUDE_DEFAULT" nil nil) + (:html-style-include-scripts "HTML_INCLUDE_SCRIPTS" nil nil) + (:deck-base-url "DECK_BASE_URL" nil org-deck-base-url) + (:deck-theme "DECK_THEME" nil org-deck-theme) + (:deck-transition "DECK_TRANSITION" nil org-deck-transition) + (:deck-include-extensions "DECK_INCLUDE_EXTENSIONS" nil + org-deck-include-extensions split) + (:deck-exclude-extensions "DECK_EXCLUDE_EXTENSIONS" nil + org-deck-exclude-extensions split) + (:deck-directories "DECK_DIRECTORIES" nil + org-deck-directories split)) + :translate-alist + ((headline . org-deck-headline) + (inner-template . org-deck-inner-template) + (item . org-deck-item) + (template . org-deck-template))) + +(defgroup org-export-deck nil + "Options for exporting Org mode files to deck.js HTML Presentations." + :tag "Org Export DECK" + :group 'org-export-html) + +(defcustom org-deck-directories nil + "Directories to search for deck.js components (jquery, +modernizr; core, extensions and themes directories.)" + :group 'org-export-deck + :type '(repeat (string :tag "Directory"))) + +(defun org-deck--cleanup-components (components) + (remove-duplicates + (car (remove 'nil components)) + :test (lambda (x y) + (string= (file-name-nondirectory x) + (file-name-nondirectory y))))) + +(defun org-deck--find-extensions () + "Returns a unique list of all extensions found in +in the extensions directories under `org-deck-directories'" + (org-deck--cleanup-components + (mapcar ; extensions under existing dirs + (lambda (dir) + (when (file-directory-p dir) (directory-files dir t "^[^.]"))) + (mapcar ; possible extension directories + (lambda (x) (expand-file-name "extensions" x)) + org-deck-directories)))) + +(defun org-deck--find-css (type) + "Return a unique list of all the css stylesheets in the themes/TYPE +directories under `org-deck-directories'." + (org-deck--cleanup-components + (mapcar + (lambda (dir) + (let ((css-dir (expand-file-name + (concat (file-name-as-directory "themes") type) dir))) + (when (file-directory-p css-dir) + (directory-files css-dir t "\\.css$")))) + org-deck-directories))) + +(defun org-deck-list-components () + "List all available deck extensions, styles and +transitions (with full paths) to a temporary buffer." + (interactive) + (let ((outbuf (get-buffer-create "*deck.js Extensions*"))) + (with-current-buffer outbuf + (erase-buffer) + (insert "Extensions\n----------\n") + (insert (mapconcat 'identity (org-deck--find-extensions) "\n")) + (insert "\n\nStyles\n------\n") + (insert (mapconcat 'identity (org-deck--find-css "style") "\n")) + (insert "\n\nTransitions\n----------\n") + (insert (mapconcat 'identity (org-deck--find-css "transition") "\n"))) + (switch-to-buffer-other-window outbuf))) + +(defcustom org-deck-include-extensions nil + "If non-nil, list of extensions to include instead of all available. +Can be overriden or set with the DECK_INCLUDE_EXTENSIONS property. +During output generation, the extensions found by +`org-deck--find-extensions' are searched for the appropriate +files (scripts and/or stylesheets) to include in the generated +html. The href/src attributes are created relative to `org-deck-base-url'." + :group 'org-export-deck + :type '(repeat (string :tag "Extension"))) + +(defcustom org-deck-exclude-extensions nil + "If non-nil, list of extensions to exclude. +Can be overriden or set with the DECK_EXCLUDE_EXTENSIONS property." + :group 'org-export-deck + :type '(repeat (string :tag "Extension"))) + +(defcustom org-deck-theme "swiss.css" + "deck.js theme. Can be overriden with the DECK_THEME property. +If this value contains a path component (\"/\"), it is used as a +literal path (url). Otherwise it is prepended with +`org-deck-base-url'/themes/style/." + :group 'org-export-deck + :type 'string) + +(defcustom org-deck-transition "fade.css" + "deck.js transition theme. Can be overriden with the +DECK_TRANSITION property. +If this value contains a path component (\"/\"), it is used as a +literal path (url). Otherwise it is prepended with +`org-deck-base-url'/themes/transition/." + :group 'org-export-deck + :type 'string) + +(defcustom org-deck-base-url "deck.js" + "Url prefix to deck.js base directory containing the core, extensions +and themes directories. +Can be overriden with the DECK_BASE_URL property." + :group 'org-export-deck + :type 'string) + +(defcustom org-deck-footer-template +"<h1>%author - %title</h1>" + "Format template to specify footer div. +Completed using `org-fill-template'. +Optional keys include %author, %email, %file, %title and %date. +This is included in a <footer> section." + :group 'org-export-deck + :type 'string) + +(defcustom org-deck-header-template "" + "Format template to specify page. Completed using `org-fill-template'. +Optional keys include %author, %email, %file, %title and %date. +This is included in a <header> section." + :group 'org-export-deck + :type 'string) + +(defcustom org-deck-title-page-style + "<style type='text/css'> + header, footer { left: 5px; width: 100% } + header { position: absolute; top: 10px; } + #title-slide h1 { + position: static; padding: 0; + margin-top: 10%; + -webkit-transform: none; + -moz-transform: none; + -ms-transform: none; + -o-transform: none; + transform: none; + } + #title-slide h2 { + text-align: center; + border:none; + padding: 0; + margin: 0; + } +</style>" + "CSS styles to use for title page" + :group 'org-export-deck + :type 'string) + +(defcustom org-deck-title-page-template + "<div class='slide' id='title-slide'> +<h1>%title</h1> +<h2>%author</h2> +<h2>%email</h2> +<h2>%date</h2> +</div>" + "Format template to specify title page div. +Completed using `org-fill-template'. +Optional keys include %author, %email, %file, %title and %date. +Note that the wrapper div must include the class \"slide\"." + :group 'org-export-deck + :type 'string) + +(defcustom org-deck-toc-style + "<style type='text/css'> + header, footer { left: 5px; width: 100% } + header { position: absolute; top: 10px; } + #table-of-contents h1 { + position: static; padding: 0; + margin-top: 10%; + -webkit-transform: none; + -moz-transform: none; + -ms-transform: none; + -o-transform: none; + Transform: none; + } + #title-slide h2 { + text-align: center; + border:none; + padding: 0; + margin: 0; + } +</style>" + "CSS styles to use for title page" + :group 'org-export-deck + :type 'string) + +(defun org-deck-toc (depth info) + (concat + "<div id=\"table-of-contents\" class=\"slide\">\n" + (format "<h2>%s</h2>\n" + (org-html--translate "Table of Contents" info)) + (org-html-toc-text + (mapcar + (lambda (headline) + (let* ((class (org-element-property :html-container-class headline)) + (section-number + (when + (and (not (org-export-low-level-p headline info)) + (org-export-numbered-headline-p headline info)) + (concat + (mapconcat + 'number-to-string + (org-export-get-headline-number headline info) ".") ". "))) + (title + (concat + section-number + (replace-regexp-in-string ; remove any links in headline... + "</?a[^>]*>" "" + (org-export-data + (org-element-property :title headline) info))))) + (list + (if (and class (string-match-p "\\<slide\\>" class)) + (format + "<a href='#outline-container-%s'>%s</a>" + (or (org-element-property :custom-id headline) + (mapconcat + 'number-to-string + (org-export-get-headline-number headline info) "-")) + title) + title) + (org-export-get-relative-level headline info)))) + (org-export-collect-headlines info depth))) + "</div>\n" )) + +(defun org-deck--get-packages (info) + (let ((prefix (concat (plist-get info :deck-base-url) "/")) + (theme (plist-get info :deck-theme)) + (transition (plist-get info :deck-transition)) + (include (plist-get info :deck-include-extensions)) + (exclude (plist-get info :deck-exclude-extensions)) + (scripts '()) (sheets '()) (snippets '())) + (add-to-list 'scripts (concat prefix "jquery-1.7.2.min.js")) + (add-to-list 'scripts (concat prefix "core/deck.core.js")) + (add-to-list 'scripts (concat prefix "modernizr.custom.js")) + (add-to-list 'sheets (concat prefix "core/deck.core.css")) + (mapc + (lambda (extdir) + (let* ((name (file-name-nondirectory extdir)) + (dir (file-name-as-directory extdir)) + (path (concat prefix "extensions/" name "/")) + (base (format "deck.%s." name))) + (when (and (or (eq nil include) (member name include)) + (not (member name exclude))) + (when (file-exists-p (concat dir base "js")) + (add-to-list 'scripts (concat path base "js"))) + (when (file-exists-p (concat dir base "css")) + (add-to-list 'sheets (concat path base "css"))) + (when (file-exists-p (concat dir base "html")) + (add-to-list 'snippets (concat dir base "html")))))) + (org-deck--find-extensions)) + (add-to-list 'sheets + (if (file-name-directory theme) theme + (format "%sthemes/style/%s" prefix theme))) + (add-to-list + 'sheets + (if (file-name-directory transition) transition + (format "%sthemes/transition/%s" prefix transition))) + (list :scripts (nreverse scripts) :sheets (nreverse sheets) + :snippets snippets))) + +(defun org-html-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-deck-toc depth info))) + ;; Document contents. + contents + "\n")) + +(defun org-deck-headline (headline contents info) + (let ((org-html-toplevel-hlevel 2)) + (org-html-headline + (if (= 1 (+ (org-element-property :level headline) + (plist-get info :headline-offset))) + (org-element-put-property headline :html-container-class "slide") + headline) contents info))) + +(defun org-deck-item (item contents info) + "Transcode an ITEM element from Org to HTML. +CONTENTS holds the contents of the item. INFO is a plist holding +contextual information. +If the containing headline has the property :slide, then +the \"slide\" class will be added to the to the list element, + which will make the list into a \"build\"." + (let ((text (org-html-item item contents info))) + (if (org-export-get-node-property :step item t) + (replace-regexp-in-string "^<li>" "<li class='slide'>" text) + text))) + +(defun org-deck-template-alist (info) + (list + `("title" . ,(car (plist-get info :title))) + `("author" . ,(car (plist-get info :author))) + `("email" . ,(plist-get info :email)) + `("date" . ,(nth 0 (plist-get info :date))) + `("file" . ,(plist-get info :input-file)))) + +(defun org-deck-template (contents info) + "Return complete document string after HTML conversion. +CONTENTS is the transcoded contents string. INFO is a plist +holding export options." + (let ((pkg-info (org-deck--get-packages info))) + (mapconcat + 'identity + (list + "<!DOCTYPE html>" + (let ((lang (plist-get info :language))) + (mapconcat + (lambda (x) + (apply + 'format + "<!--%s <html class='no-js %s' lang='%s'> %s<![endif]-->" + x)) + (list `("[if lt IE 7]>" "ie6" ,lang "") + `("[if IE 7]>" "ie7" ,lang "") + `("[if IE 8]>" "ie8" ,lang "") + `("[if gt IE 8]><!-->" "" ,lang "<!--")) "\n")) + "<head>" + (org-deck--build-meta-info info) + (mapconcat + (lambda (sheet) + (format + "<link rel='stylesheet' href='%s' type='text/css' />" sheet)) + (plist-get pkg-info :sheets) "\n") + "<style type='text/css'>" + "#table-of-contents a {color: inherit;}" + "#table-of-contents ul {margin-bottom: 0;}" + (when (plist-get info :section-numbers) + "#table-of-contents ul li {list-style-type: none;}") + "</style>" + "" + (mapconcat + (lambda (script) + (format + "<script src='%s' type='text/javascript'></script>" script)) + (plist-get pkg-info :scripts) "\n") + (org-html--build-mathjax-config info) + "<script type='text/javascript'>" + " $(document).ready(function () { $.deck('.slide'); });" + "</script>" + (org-html--build-style info) + org-deck-title-page-style + "</head>" + "<body>" + "<header class='deck-status'>" + (org-fill-template + org-deck-header-template (org-deck-template-alist info)) + "</header>" + "<div class='deck-container'>" + ;; title page + (org-fill-template + org-deck-title-page-template (org-deck-template-alist info)) + ;; toc page + (let ((depth (plist-get info :with-toc))) + (when depth (org-deck-toc depth info))) + contents + (mapconcat + (lambda (snippet) + (with-temp-buffer (insert-file-contents snippet) + (buffer-string))) + (plist-get pkg-info :snippets) "\n") + "<footer class='deck-status'>" + (org-fill-template + org-deck-footer-template (org-deck-template-alist info)) + "</footer>" + "</div>" + "</body>" + "</html>\n") "\n"))) + +(defun org-deck--build-meta-info (info) + "Return meta tags for exported document. +INFO is a plist used as a communication channel." + (let* ((title (org-export-data (plist-get info :title) info)) + (author (and (plist-get info :with-author) + (let ((auth (plist-get info :author))) + (and auth (org-export-data auth info))))) + (date (and (plist-get info :with-date) + (let ((date (plist-get info :date))) + (and date (org-export-data date info))))) + (description (plist-get info :description)) + (keywords (plist-get info :keywords))) + (mapconcat + 'identity + (list + (format "<title>%s</title>" title) + (format "<meta charset='%s' />" + (or (and org-html-coding-system + (fboundp 'coding-system-get) + (coding-system-get + org-html-coding-system 'mime-charset)) + "iso-8859-1")) + (mapconcat + (lambda (attr) + (when (< 0 (length (car attr))) + (format "<meta name='%s' content='%s'/>\n" + (nth 1 attr) (car attr)))) + (list '("Org-mode" "generator") + `(,author "author") + `(,description "description") + `(,keywords "keywords")) "")) "\n"))) +(defun org-deck-export-as-html + (&optional async subtreep visible-only body-only ext-plist) + "Export current buffer to an HTML buffer. + +If narrowing is active in the current buffer, only export its +narrowed part. + +If a region is active, export that region. + +A non-nil optional argument ASYNC means the process should happen +asynchronously. The resulting buffer should be accessible +through the `org-export-stack' interface. + +When optional argument SUBTREEP is non-nil, export the sub-tree +at point, extracting information from the headline properties +first. + +When optional argument VISIBLE-ONLY is non-nil, don't export +contents of hidden elements. + +When optional argument BODY-ONLY is non-nil, only write code +between \"<body>\" and \"</body>\" tags. + +EXT-PLIST, when provided, is a property list with external +parameters overriding Org default settings, but still inferior to +file-local settings. + +Export is done in a buffer named \"*Org deck.js Export*\", which +will be displayed when `org-export-show-temporary-export-buffer' +is non-nil." + (interactive) + (if async + (org-export-async-start + (lambda (output) + (with-current-buffer (get-buffer-create "*Org deck.js Export*") + (erase-buffer) + (insert output) + (goto-char (point-min)) + (nxml-mode) + (org-export-add-to-stack (current-buffer) 'deck))) + `(org-export-as 'deck ,subtreep ,visible-only ,body-only ',ext-plist)) + (let ((outbuf (org-export-to-buffer + 'deck "*Org deck.js Export*" + subtreep visible-only body-only ext-plist))) + ;; Set major mode. + (with-current-buffer outbuf (nxml-mode)) + (when org-export-show-temporary-export-buffer + (switch-to-buffer-other-window outbuf))))) + +(defun org-deck-export-to-html + (&optional async subtreep visible-only body-only ext-plist) + "Export current buffer to a deck.js HTML file. + +If narrowing is active in the current buffer, only export its +narrowed part. + +If a region is active, export that region. + +A non-nil optional argument ASYNC means the process should happen +asynchronously. The resulting file should be accessible through +the `org-export-stack' interface. + +When optional argument SUBTREEP is non-nil, export the sub-tree +at point, extracting information from the headline properties +first. + +When optional argument VISIBLE-ONLY is non-nil, don't export +contents of hidden elements. + +When optional argument BODY-ONLY is non-nil, only write code +between \"<body>\" and \"</body>\" tags. + +EXT-PLIST, when provided, is a property list with external +parameters overriding Org default settings, but still inferior to +file-local settings. + +Return output file's name." + (interactive) + (let* ((extension (concat "." org-html-extension)) + (file (org-export-output-file-name extension subtreep)) + (org-export-coding-system org-html-coding-system)) + (if async + (org-export-async-start + (lambda (f) (org-export-add-to-stack f 'deck)) + (let ((org-export-coding-system org-html-coding-system)) + `(expand-file-name + (org-export-to-file + 'deck ,file ,subtreep ,visible-only ,body-only ',ext-plist)))) + (let ((org-export-coding-system org-html-coding-system)) + (org-export-to-file + 'deck file subtreep visible-only body-only ext-plist))))) + +(defun org-deck-publish-to-html (plist filename pub-dir) + "Publish an org file to deck.js HTML Presentation. +FILENAME is the filename of the Org file to be published. PLIST +is the property list for the given project. PUB-DIR is the +publishing directory. Returns output file name." + (org-publish-org-to 'deck filename ".html" plist pub-dir)) + +(provide 'ox-deck) diff --git a/contrib/lisp/ox-s5.el b/contrib/lisp/ox-s5.el new file mode 100644 index 0000000..39f41ef --- /dev/null +++ b/contrib/lisp/ox-s5.el @@ -0,0 +1,384 @@ +;;; ox-s5.el --- S5 Presentation Back-End for Org Export Engine + +;; Copyright (C) 2011-2013 Rick Frankel + +;; Author: Rick Frankel <emacs at rickster dot com> +;; Keywords: outlines, hypermedia, S5, wp + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. + +;;; Commentary: + +;; This library implements an S5 Presentation back-end for the Org +;; generic exporter. + +;; Installation +;; ------------ +;; Get the s5 scripts from +;; http://meyerweb.com/eric/tools/s5/ +;; (Note that the default s5 version is set for using the alpha, 1.2a2. +;; Copy the ui dir to somewhere reachable from your published presentation +;; The default (`org-s5-ui-url') is set to "ui" (e.g., in the +;; same directory as the html file). + +;; Usage +;; ----- +;; Follow the general instructions at the above website. To generate +;; incremental builds, you can set the HTML_CONTAINER_CLASS on an +;; object to "incremental" to make it build. If you want an outline to +;; build, set the` INCREMENTAL property on the parent headline. + +;; To test it, run: +;; +;; M-x org-s5-export-as-html +;; +;; in an Org mode buffer. See ox.el and ox-html.el for more details +;; on how this exporter works. + +(require 'ox-html) + +(org-export-define-derived-backend s5 html + :menu-entry + (?s "Export to S5 HTML Presentation" + ((?H "To temporary buffer" org-s5-export-as-html) + (?h "To file" org-s5-export-to-html) + (?o "To file and open" + (lambda (a s v b) + (if a (org-s5-export-to-html t s v b) + (org-open-file (org-s5-export-to-html nil s v b))))))) + :options-alist + ((:html-link-home "HTML_LINK_HOME" nil nil) + (:html-link-up "HTML_LINK_UP" nil nil) + (:html-mathjax "HTML_MATHJAX" nil "" space) + (:html-postamble nil "html-postamble" nil t) + (:html-preamble nil "html-preamble" nil t) + (:html-style-extra "HTML_STYLE" nil org-html-style-extra newline) + (:html-style-include-default "HTML_INCLUDE_DEFAULT" nil nil) + (:html-style-include-scripts "HTML_INCLUDE_SCRIPTS" nil nil) + (:s5-version "S5_VERSION" nil org-s5-version) + (:s5-theme-file "S5_THEME_FILE" nil org-s5-theme-file) + (:s5-ui-url "S5_UI_URL" nil org-s5-ui-url)) + :translate-alist + ((headline . org-s5-headline) + (plain-list . org-s5-plain-list) + (template . org-s5-template))) + +(defgroup org-export-s5 nil + "Options for exporting Org mode files to S5 HTML Presentations." + :tag "Org Export S5" + :group 'org-export-html) + +(defcustom org-s5-version "1.2a2" + "Version of s5 being used (for version metadata.) Defaults to +s5 v2 alpha 2. +Can be overridden with S5_VERSION." + :group 'org-export-s5 + :type 'string) + +(defcustom org-s5-theme-file nil +"Url to S5 theme (slides.css) file. Can be overriden with the +S5_THEME_FILE property. If nil, defaults to +`org-s5-ui-url'/default/slides.css. If it starts with anything but +\"http\" or \"/\", it is used as-is. Otherwise the link in generated +relative to `org-s5-ui-url'. +The links for all other required stylesheets and scripts will be +generated relative to `org-s5-ui-url'/default." + :group 'org-export-s5 + :type 'string) + +(defcustom org-s5-ui-url "ui" + "Base url to directory containing S5 \"default\" subdirectory +and the \"s5-notes.html\" file. +Can be overriden with the S5_UI_URL property." + :group 'org-export-s5 + :type 'string) + +(defcustom org-s5-default-view 'slideshow + "Setting for \"defaultView\" meta info." + :group 'org-export-s5 + :type '(choice (const slideshow) (const outline))) + +(defcustom org-s5-control-visibility 'hidden + "Setting for \"controlVis\" meta info." + :group 'org-export-s5 + :type '(choice (const hidden) (const visibile))) + +(defcustom org-s5-footer-template + "<div id=\"footer\"> +<h1>%author - %title</h1> +</div>" + "Format template to specify footer div. Completed using +`org-fill-template'. +Optional keys include %author, %email, %file, %title and %date. +Note that the div id must be \"footer\"." + :group 'org-export-s5 + :type 'string) + +(defcustom org-s5-header-template "<div id=\"header\"></div>" + "Format template to specify footer div. Completed using +`org-fill-template'. +Optional keys include %author, %email, %file, %title and %date. +Note that the div id must be \"header\"." + :group 'org-export-s5 + :type 'string) + +(defcustom org-s5-title-page-template + "<div class=\"slide title-page\"> +<h1>%title</h1> +<h1>%author</h1> +<h1>%email</h1> +<h1>%date</h1> +</div>" + "Format template to specify title page div. Completed using +`org-fill-template'. +Optional keys include %author, %email, %file, %title and %date. +Note that the wrapper div must include the class \"slide\"." + :group 'org-export-s5 + :type 'string) + + +(defun org-s5-toc (depth info) + (let* ((headlines (org-export-collect-headlines info depth)) + (toc-entries + (loop for headline in headlines collect + (list (org-html-format-headline--wrap + headline info 'org-html-format-toc-headline) + (org-export-get-relative-level headline info))))) + (when toc-entries + (concat + "<div id=\"table-of-contents\" class=\"slide\">\n" + (format "<h1>%s</h1>\n" + (org-html--translate "Table of Contents" info)) + "<div id=\"text-table-of-contents\">" + (org-html-toc-text toc-entries) + "</div>\n" + "</div>\n")))) + +(defun org-s5--build-style (info) + (let* ((dir (plist-get info :s5-ui-url)) + (theme (or (plist-get info :s5-theme-file) "default/slides.css"))) + (mapconcat + 'identity + (list + "<!-- style sheet links -->" + (mapconcat + (lambda (list) + (format + (concat + "<link rel='stylesheet' href='%s/default/%s' type='text/css'" + " media='%s' id='%s' />") + dir (nth 0 list) (nth 1 list) (nth 2 list))) + (list + '("outline.css" "screen" "outlineStyle") + '("print.css" "print" "slidePrint") + '("opera.css" "projection" "operaFix")) "\n") + (format (concat + "<link rel='stylesheet' href='%s' type='text/css'" + " media='screen' id='slideProj' />") + (if (string-match-p "^\\(http\\|/\\)" theme) theme + (concat dir "/" theme))) + "<!-- S5 JS -->" + (concat + "<script src='" dir + "/default/slides.js' type='text/javascript'></script>")) "\n"))) + +(defun org-s5--build-meta-info (info) + (concat + (org-html--build-meta-info info) + (format "<meta name=\"version\" content=\"S5 %s\" />" + (plist-get info :s5-version)) + "<meta name='defaultView' content='slideshow' />\n" + "<meta name='controlVis' content='hidden' />")) + +(defun org-s5-headline (headline contents info) + (let ((org-html-toplevel-hlevel 1)) + (org-html-headline + (if (= 1 (+ (org-element-property :level headline) + (plist-get info :headline-offset))) + (org-element-put-property + headline :html-container-class + (mapconcat 'identity + (list + (org-element-property + :html-container-class headline) + "slide") " ")) + headline) contents info))) + +(defun org-s5-plain-list (plain-list contents info) + "Transcode a PLAIN-LIST element from Org to HTML. +CONTENTS is the contents of the list. INFO is a plist holding +contextual information. +If a containing headline has the property :incremental, +then the \"incremental\" class will be added to the to the list, +which will make the list into a \"build\"." + (let* ((type (org-element-property :type plain-list)) + (tag (case type + (ordered "ol") + (unordered "ul") + (descriptive "dl")))) + (format "%s\n%s%s" + (format + "<%s class='org-%s%s'>" tag tag + (if (org-export-get-node-property :incremental plain-list t) + " incremental" "")) + contents (org-html-end-plain-list type)))) + +(defun org-s5-template-alist (info) + `( + ("title" . ,(car (plist-get info :title))) + ("author" . ,(car (plist-get info :author))) + ("email" . ,(plist-get info :email)) + ("date" . ,(substring (nth 0 (plist-get info :date)) 0 10)) + ("file" . ,(plist-get info :input-file)))) + +(defun org-s5-template (contents info) + "Return complete document string after HTML conversion. +CONTENTS is the transcoded contents string. INFO is a plist +holding export options." + (mapconcat + 'identity + (list + "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" + \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">" + (format "<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"%s\" xml:lang=\"%s\">" + (plist-get info :language) (plist-get info :language)) + "<head>" + (org-s5--build-meta-info info) + (org-s5--build-style info) + (org-html--build-style info) + (org-html--build-mathjax-config info) + "</head>" + "<body>" + "<div class=\"layout\">" + "<div id=\"controls\"><!-- no edit --></div>" + "<div id=\"currentSlide\"><!-- no edit --></div>" + (org-fill-template + org-s5-header-template (org-s5-template-alist info)) + (org-fill-template + org-s5-footer-template (org-s5-template-alist info)) + "</div>" + (format "<div id=\"%s\" class=\"presentation\">" (nth 1 org-html-divs)) + ;; title page + (org-fill-template + org-s5-title-page-template (org-s5-template-alist info)) + (let ((depth (plist-get info :with-toc))) + (when depth (org-s5-toc depth info))) + contents + "</div>" + "</body>" + "</html>\n") "\n")) + +(defun org-s5-export-as-html + (&optional async subtreep visible-only body-only ext-plist) + "Export current buffer to an HTML buffer. + +If narrowing is active in the current buffer, only export its +narrowed part. + +If a region is active, export that region. + +A non-nil optional argument ASYNC means the process should happen +asynchronously. The resulting buffer should be accessible +through the `org-export-stack' interface. + +When optional argument SUBTREEP is non-nil, export the sub-tree +at point, extracting information from the headline properties +first. + +When optional argument VISIBLE-ONLY is non-nil, don't export +contents of hidden elements. + +When optional argument BODY-ONLY is non-nil, only write code +between \"<body>\" and \"</body>\" tags. + +EXT-PLIST, when provided, is a property list with external +parameters overriding Org default settings, but still inferior to +file-local settings. + +Export is done in a buffer named \"*Org S5 Export*\", which +will be displayed when `org-export-show-temporary-export-buffer' +is non-nil." + (interactive) + (if async + (org-export-async-start + (lambda (output) + (with-current-buffer (get-buffer-create "*Org S5 Export*") + (erase-buffer) + (insert output) + (goto-char (point-min)) + (nxml-mode) + (org-export-add-to-stack (current-buffer) 's5))) + `(org-export-as 's5 ,subtreep ,visible-only ,body-only ',ext-plist)) + (let ((outbuf (org-export-to-buffer + 's5 "*Org S5 Export*" + subtreep visible-only body-only ext-plist))) + ;; Set major mode. + (with-current-buffer outbuf (nxml-mode)) + (when org-export-show-temporary-export-buffer + (switch-to-buffer-other-window outbuf))))) + +(defun org-s5-export-to-html + (&optional async subtreep visible-only body-only ext-plist) + "Export current buffer to a S5 HTML file. + +If narrowing is active in the current buffer, only export its +narrowed part. + +If a region is active, export that region. + +A non-nil optional argument ASYNC means the process should happen +asynchronously. The resulting file should be accessible through +the `org-export-stack' interface. + +When optional argument SUBTREEP is non-nil, export the sub-tree +at point, extracting information from the headline properties +first. + +When optional argument VISIBLE-ONLY is non-nil, don't export +contents of hidden elements. + +When optional argument BODY-ONLY is non-nil, only write code +between \"<body>\" and \"</body>\" tags. + +EXT-PLIST, when provided, is a property list with external +parameters overriding Org default settings, but still inferior to +file-local settings. + +Return output file's name." + (interactive) + (let* ((extension (concat "." org-html-extension)) + (file (org-export-output-file-name extension subtreep)) + (org-export-coding-system org-html-coding-system)) + (if async + (org-export-async-start + (lambda (f) (org-export-add-to-stack f 's5)) + (let ((org-export-coding-system org-html-coding-system)) + `(expand-file-name + (org-export-to-file + 's5 ,file ,subtreep ,visible-only ,body-only ',ext-plist)))) + (let ((org-export-coding-system org-html-coding-system)) + (org-export-to-file + 's5 file subtreep visible-only body-only ext-plist))))) + +(defun org-s5-publish-to-html (plist filename pub-dir) + "Publish an org file to S5 HTML Presentation. + +FILENAME is the filename of the Org file to be published. PLIST +is the property list for the given project. PUB-DIR is the +publishing directory. + +Return output file name." + (org-publish-org-to 's5 filename ".html" plist pub-dir)) + +(provide 'ox-s5) |