| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559 | ;;; 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 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 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)(eval-when-compile (require 'cl))(org-export-define-derived-backend deck html  :menu-entry  (?d "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-postamble nil "html-postamble" nil t)   (:html-preamble nil "html-preamble" nil t)   (:html-head-include-default-style "HTML_INCLUDE_DEFAULT_STYLE" nil nil)   (:html-head-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))  :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 '("./deck.js")  "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 inin 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/TYPEdirectories 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 andtransitions (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 appropriatefiles (scripts and/or stylesheets) to include in the generatedhtml. 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 aliteral 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 theDECK_TRANSITION property.If this value contains a path component (\"/\"), it is used as aliteral 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, extensionsand 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)))))         (cons          (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))    (if (not (string-match-p "^[[:space:]]*$" theme))	(add-to-list 'sheets		     (if (file-name-directory theme) theme		       (format "%sthemes/style/%s" prefix theme))))    (if (not (string-match-p "^[[:space:]]*$" transition))	(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-deck-inner-template (contents info)  "Return body of document string after HTML conversion.CONTENTS is the transcoded contents string.  INFO is a plistholding export options."  (concat contents "\n"))(defun org-deck-headline (headline contents info)  (let ((org-html-toplevel-hlevel 2)        (class (or (org-element-property :HTML_CONTAINER_CLASS headline) ""))        (level (org-export-get-relative-level headline info)))    (when (and (= 1 level) (not (string-match-p "\\<slide\\>" class)))      (org-element-put-property headline :HTML_CONTAINER_CLASS (concat class " slide")))    (org-html-headline 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 holdingcontextual information.If the containing headline has the property :slide, thenthe \"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 plistholding 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-head 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 itsnarrowed part.If a region is active, export that region.A non-nil optional argument ASYNC means the process should happenasynchronously.  The resulting buffer should be accessiblethrough the `org-export-stack' interface.When optional argument SUBTREEP is non-nil, export the sub-treeat point, extracting information from the headline propertiesfirst.When optional argument VISIBLE-ONLY is non-nil, don't exportcontents of hidden elements.When optional argument BODY-ONLY is non-nil, only write codebetween \"<body>\" and \"</body>\" tags.EXT-PLIST, when provided, is a property list with externalparameters overriding Org default settings, but still inferior tofile-local settings.Export is done in a buffer named \"*Org deck.js Export*\", whichwill 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 itsnarrowed part.If a region is active, export that region.A non-nil optional argument ASYNC means the process should happenasynchronously.  The resulting file should be accessible throughthe `org-export-stack' interface.When optional argument SUBTREEP is non-nil, export the sub-treeat point, extracting information from the headline propertiesfirst.When optional argument VISIBLE-ONLY is non-nil, don't exportcontents of hidden elements.When optional argument BODY-ONLY is non-nil, only write codebetween \"<body>\" and \"</body>\" tags.EXT-PLIST, when provided, is a property list with externalparameters overriding Org default settings, but still inferior tofile-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.  PLISTis the property list for the given project.  PUB-DIR is thepublishing directory. Returns output file name."  (org-publish-org-to 'deck filename ".html" plist pub-dir))(provide 'ox-deck)
 |