commit 01792e1e08c0d743fa666677d69c32078b30cb2a
parent 2fec34774de420b966bb36d70db5853a09e004a5
Author: Lukas Henkel <lh@entf.net>
Date: Fri, 12 May 2023 19:06:26 +0200
Install ox-epub
Diffstat:
4 files changed, 729 insertions(+), 1 deletion(-)
diff --git a/elpa/ox-epub-0.3/ox-epub-autoloads.el b/elpa/ox-epub-0.3/ox-epub-autoloads.el
@@ -0,0 +1,37 @@
+;;; ox-epub-autoloads.el --- automatically extracted autoloads (do not edit) -*- lexical-binding: t -*-
+;; Generated by the `loaddefs-generate' function.
+
+;; This file is part of GNU Emacs.
+
+;;; Code:
+
+(add-to-list 'load-path (or (and load-file-name (file-name-directory load-file-name)) (car load-path)))
+
+
+
+;;; Generated autoloads from ox-epub.el
+
+(autoload 'org-epub-export-to-epub "ox-epub" "\
+Export the current buffer to an EPUB file.
+
+ASYNC defines wether this process should run in the background,
+SUBTREEP supports narrowing of the document, VISIBLE-ONLY allows
+you to export only visible parts of the document, EXT-PLIST is
+the property list for the export process.
+
+(fn &optional ASYNC SUBTREEP VISIBLE-ONLY EXT-PLIST)" t)
+(register-definition-prefixes "ox-epub" '("org-epub-"))
+
+;;; End of scraped data
+
+(provide 'ox-epub-autoloads)
+
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; no-native-compile: t
+;; coding: utf-8-emacs-unix
+;; End:
+
+;;; ox-epub-autoloads.el ends here
diff --git a/elpa/ox-epub-0.3/ox-epub-pkg.el b/elpa/ox-epub-0.3/ox-epub-pkg.el
@@ -0,0 +1,2 @@
+;;; Generated package description from ox-epub.el -*- no-byte-compile: t -*-
+(define-package "ox-epub" "0.3" "Export org mode projects to EPUB" '((emacs "24.3") (org "9")) :commit "3d958203e169cbfb2204c43cb4c5543befec0b9d" :authors '(("Mark Meyer" . "mark@ofosos.org")) :maintainers '(("Mark Meyer" . "mark@ofosos.org")) :maintainer '("Mark Meyer" . "mark@ofosos.org") :keywords '("hypermedia") :url "http://github.com/ofosos/org-epub")
diff --git a/elpa/ox-epub-0.3/ox-epub.el b/elpa/ox-epub-0.3/ox-epub.el
@@ -0,0 +1,689 @@
+;;; ox-epub.el --- Export org mode projects to EPUB -*- lexical-binding: t; -*-
+
+;; Copyright (c) 2017 - Mark Meyer
+
+;; Author: Mark Meyer <mark@ofosos.org>
+;; Maintainer: Mark Meyer <mark@ofosos.org>
+
+;; URL: http://github.com/ofosos/org-epub
+;; Package-Version: 0.3
+;; Package-Commit: 3d958203e169cbfb2204c43cb4c5543befec0b9d
+;; Keywords: hypermedia
+
+;; Version: 0.1.0
+
+;; Package-Requires: ((emacs "24.3") (org "9"))
+
+;; 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 is an addition to the standard org-mode exporters. The package
+;; extends the (X)HTML exporter to produce EPUB files. It eliminates
+;; all inline CSS and JavaScript to accomplish this. This exporter
+;; will also tie the XHTML DTD to XHTML 1.1, a concrete DTD specifier
+;; that was not supported by ox-html previously.
+
+;; The main part is the generation of the table of contents in machine
+;; readable form, as well as the spine, which defines the order in
+;; which files are presented. A lesser part is the inclusion of
+;; various metadata properties, among them authorship and rights.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'ox-publish)
+(require 'ox-html)
+(require 'org-element)
+
+(org-export-define-derived-backend 'epub 'html
+ :options-alist
+ '((:epub-uid "UID" nil nil t)
+ (:epub-subject "Subject" nil nil t)
+ (:epub-description "Description" nil nil t)
+ (:epub-publisher "Publisher" nil nil t)
+ (:epub-rights "License" nil nil t)
+ (:epub-style "EPUBSTYLE" nil nil t)
+ (:epub-cover "EPUBCOVER" nil nil t)
+ (:html-doctype "HTML_DOCTYPE" nil "xhtml" t))
+
+ :translate-alist
+ '((template . org-epub-template)
+ (link . org-epub-link)
+ (latex-environment . org-epub--latex-environment)
+ (latex-fragment . org-epub--latex-fragment))
+ :menu-entry
+ '(?E "Export to Epub"
+ ((?e "As Epub file" org-epub-export-to-epub)
+ (?O "As Epub file and open"
+ (lambda (a s v b)
+ (if a (org-epub-export-to-epub t s v)
+ (org-open-file (org-epub-export-to-epub nil s v) 'system)))))))
+
+(defvar org-epub-zip-dir nil
+ "The temporary directory to export to")
+
+(defvar org-epub-style-default "
+ .title { text-align: center;
+ margin-bottom: .2em; }
+ .subtitle { text-align: center;
+ font-size: medium;
+ font-weight: bold;
+ margin-top:0; }
+ .todo { font-family: monospace; color: red; }
+ .done { font-family: monospace; color: green; }
+ .priority { font-family: monospace; color: orange; }
+ .tag { background-color: #eee; font-family: monospace;
+ padding: 2px; font-size: 80%; font-weight: normal; }
+ .timestamp { color: #bebebe; }
+ .timestamp-kwd { color: #5f9ea0; }
+ .org-right { margin-left: auto; margin-right: 0px; text-align: right; }
+ .org-left { margin-left: 0px; margin-right: auto; text-align: left; }
+ .org-center { margin-left: auto; margin-right: auto; text-align: center; }
+ .underline { text-decoration: underline; }
+ #postamble p, #preamble p { font-size: 90%; margin: .2em; }
+ p.verse { margin-left: 3%; }
+ pre {
+ border: 1px solid #ccc;
+ box-shadow: 3px 3px 3px #eee;
+ padding: 8pt;
+ font-family: monospace;
+ overflow: auto;
+ margin: 1.2em;
+ }
+ pre.src {
+ position: relative;
+ overflow: visible;
+ padding-top: 1.2em;
+ }
+
+ table { border-collapse:collapse; }
+ caption.t-above { caption-side: top; }
+ caption.t-bottom { caption-side: bottom; }
+ td, th { vertical-align:top; }
+ th.org-right { text-align: center; }
+ th.org-left { text-align: center; }
+ th.org-center { text-align: center; }
+ td.org-right { text-align: right; }
+ td.org-left { text-align: left; }
+ td.org-center { text-align: center; }
+ dt { font-weight: bold; }
+ .footpara { display: inline; }
+ .footdef { margin-bottom: 1em; }
+ .figure { padding: 1em; }
+ .figure p { text-align: center; }
+ .inlinetask {
+ padding: 10px;
+ border: 2px solid gray;
+ margin: 10px;
+ background: #ffffcc;
+ }
+ #org-div-home-and-up
+ { text-align: right; font-size: 70%; white-space: nowrap; }
+ textarea { overflow-x: auto; }
+ .linenr { font-size: smaller }
+ .code-highlighted { background-color: #ffff00; }
+ .org-info-js_info-navigation { border-style: none; }
+ #org-info-js_console-label
+ { font-size: 10px; font-weight: bold; white-space: nowrap; }
+ .org-info-js_search-highlight
+ { background-color: #ffff00; color: #000000; font-weight: bold; }
+ .org-svg { width: 90%; }
+
+"
+ "Default style declarations for org epub")
+
+(defvar org-epub-zip-command "zip"
+ "Command to call to create zip files.")
+
+(defvar org-epub-zip-no-compress (list "-Xu0")
+ "Zip command option list to pass for no compression.")
+
+(defvar org-epub-zip-compress (list "-Xu9")
+ "Zip command option list to pass for compression.")
+
+(defvar org-epub-metadata nil
+ "EPUB export metadata")
+
+(defvar org-epub-headlines nil
+ "EPUB headlines")
+
+(defvar org-epub-style-counter 0
+ "EPUB style counter")
+
+;; manifest mechanism
+
+(defvar org-epub-manifest nil
+ "EPUB export manifest")
+
+(defun org-epub-manifest-entry (id filename type mimetype &optional source)
+ "Create a manifest entry with the given ID, FILENAME, TYPE, MIMETYPE and optional SOUCE.
+
+FILENAME should be the new name in the epub container. TYPE
+should be one of `'html', `'stylesheet', `'coverimg', `'cover' or
+`'img'. If SOURCE is given the file name by SOUCE will be copied
+to FILENAME at the end of the export process. "
+ (list :id id :filename filename :type type :mimetype mimetype :source source))
+
+(defun org-epub-cover-p (manifest-entry)
+ "Determine if MANIFEST-ENTRY is of type cover."
+ (eq (plist-get manifest-entry :type) 'cover))
+
+(defun org-epub-coverimg-p (manifest-entry)
+ "Determine if MANIFEST-ENTRY is of type cover image."
+ (eq (plist-get manifest-entry :type) 'coverimg))
+
+(defun org-epub-style-p (manifest-entry)
+ "Determine if MANIFEST-ENTRY is of type stylesheet."
+ (eq (plist-get manifest-entry :type) 'stylesheet))
+
+(defun org-epub-manifest-needcopy (manifest-entry)
+ "Determine if MANIFEST-ENTRY needs to be copied.
+
+If it needs to be copied return a pair (sourcefile . targetfile)."
+ (if (plist-get manifest-entry :source)
+ (cons (plist-get manifest-entry :source)
+ (plist-get manifest-entry :filename))
+ nil))
+
+(defun org-epub-manifest-all (pred)
+ "Return all manifest entries for which PRED is true."
+ (cl-remove-if-not pred org-epub-manifest))
+
+(cl-defun org-epub-manifest-first (pred)
+ "Return the first manifest entry for which PRED is true."
+ (let ((val))
+ (dolist (el org-epub-manifest val)
+ (when (funcall pred el)
+ (cl-return-from org-epub-manifest-first el)))))
+
+;; core
+
+;;; Latex Environment - stolen from ox-html
+
+(defun org-epub--latex-environment (latex-environment _contents info)
+ "Transcode a LATEX-ENVIRONMENT element from Org to HTML.
+CONTENTS is nil. INFO is a plist holding contextual information."
+ (let ((processing-type (plist-get info :with-latex))
+ (latex-frag (org-remove-indentation
+ (org-element-property :value latex-environment)))
+ (attributes (org-export-read-attribute :attr_html latex-environment)))
+ (cond
+ ((assq processing-type org-preview-latex-process-alist)
+ (let ((formula-link
+ (org-html-format-latex latex-frag processing-type info)))
+ (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link))
+ ;; Do not provide a caption or a name to be consistent with
+ ;; `mathjax' handling.
+ (org-html--wrap-image
+ (org-html--format-image
+ (let* ((path (match-string 1 formula-link))
+ (ref (org-export-get-reference latex-environment info))
+ (mime (file-name-extension path))
+ (name (concat "img-" ref "." mime)))
+ (message "Formatting Latex environment: %s" name)
+ (push (org-epub-manifest-entry ref name 'img (concat "image/" mime) path) org-epub-manifest)
+ name) attributes info) info))))
+ (t latex-frag))))
+
+;;;; Latex Fragment - stolen from ox-html
+
+(defun org-epub--latex-fragment (latex-fragment _contents info)
+ "Transcode a LATEX-FRAGMENT object from Org to HTML.
+CONTENTS is nil. INFO is a plist holding contextual information."
+ (let ((latex-frag (org-element-property :value latex-fragment))
+ (processing-type (plist-get info :with-latex)))
+ (cond
+ ((assq processing-type org-preview-latex-process-alist)
+ (let ((formula-link
+ (org-html-format-latex latex-frag processing-type info)))
+ (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link))
+ (let* ((path (match-string 1 formula-link))
+ (ref (org-export-get-reference latex-fragment info))
+ (mime (file-name-extension path))
+ (name (concat "img-" ref "." mime)))
+ (message "Formatting Latex fragement: %s" name)
+ (push (org-epub-manifest-entry ref name 'img (concat "image/" mime) path) org-epub-manifest)
+ (org-html--format-image name nil info)))))
+ (t latex-frag))))
+
+
+(defun org-epub-link (link desc info)
+ "Return the HTML required for a link descriped by LINK, DESC, and INFO.
+
+See org-html-link for more info."
+ (when (and (not desc) (org-export-inline-image-p link (plist-get info :html-inline-image-rules)))
+ (let* ((path (org-element-property :path link))
+ (ref (org-export-get-reference link info))
+ (mime (file-name-extension path))
+ (name (concat "img-" ref "." mime)))
+ (push (org-epub-manifest-entry ref name 'img (concat "image/" mime) path) org-epub-manifest)
+ (org-element-put-property link :path name)))
+ (org-html-link link desc info))
+
+(defun org-epub-meta-put (symbols info)
+ "Put SYMBOLS taken from INFO into the org-epub metadata cache."
+ (mapc
+ #'(lambda (sym)
+ (let ((data (plist-get info sym)))
+ (setq org-epub-metadata
+ (plist-put org-epub-metadata sym
+ (if (listp data)
+ (org-export-data data info)
+ data)))))
+ symbols))
+
+(defun org-epub-template (contents info)
+ "Return complete document string after HTML conversion.
+CONTENTS is the transcoded contents string. INFO is a plist
+holding export options."
+ (org-epub-meta-put '(:epub-uid :title :language :epub-subject :epub-description :author
+ :epub-publisher :date :epub-rights :html-head-include-default-style :epub-cover :epub-style) info)
+ (setq org-epub-metadata (plist-put org-epub-metadata :epub-toc-depth 2))
+ ;; maybe set toc-depth "2" to some dynamic value
+ (setq org-epub-headlines
+ (mapcar (lambda (headline)
+ (list
+ (org-element-property :raw-value headline)
+ (org-element-property :level headline)
+ (org-export-get-reference headline info)))
+ (org-export-collect-headlines info 2)))
+ (let ((styles (split-string (or (plist-get org-epub-metadata :epub-style) " "))))
+ (mapc #'(lambda (style)
+ (let* ((stylenum (cl-incf org-epub-style-counter))
+ (stylename (concat "style-" (format "%d" stylenum)))
+ (stylefile (concat stylename ".css")))
+ (push (org-epub-manifest-entry stylename stylefile 'stylesheet "text/css" style) org-epub-manifest)))
+ styles))
+ (concat
+ (when (and (not (org-html-html5-p info)) (org-html-xhtml-p info))
+ (let* ((xml-declaration (plist-get info :html-xml-declaration))
+ (decl (or (and (stringp xml-declaration) xml-declaration)
+ (cdr (assoc (plist-get info :html-extension)
+ xml-declaration))
+ (cdr (assoc "html" xml-declaration))
+ "")))
+ (when (not (or (not decl) (string= "" decl)))
+ (format "%s\n"
+ (format decl
+ (or (and org-html-coding-system
+ (fboundp 'coding-system-get)
+ (coding-system-get org-html-coding-system 'mime-charset))
+ "iso-8859-1"))))))
+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">"
+ "\n"
+ (concat "<html"
+ (format
+ " xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"%s\" xml:lang=\"%s\""
+ (plist-get info :language) (plist-get info :language))
+ ">\n")
+
+ "<head>\n"
+ (org-html--build-meta-info info)
+ (when (plist-get info :html-head-include-default-style)
+ "<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\"/>\n")
+ (when (plist-get info :epub-style)
+ (mapconcat
+ #'(lambda (entry)
+ (concat "<link rel=\"stylesheet\" type=\"text/css\" href=\"" (plist-get entry :filename) "\"/>\n"))
+ (org-epub-manifest-all #'org-epub-style-p) "\n"))
+ "</head>\n"
+ "<body>\n"
+ ;; Preamble.
+ (org-html--build-pre/postamble 'preamble info)
+ ;; Document contents.
+ ; (let ((div (assq 'content (plist-get info :html-divs))))
+ ; (format "<%s id=\"%s\">\n" (nth 1 div) (nth 2 div)))
+ "<div id=\"content\">"
+ ;; Document title.
+ (when (plist-get info :with-title)
+ (let ((ftitle (plist-get info :title))
+ (subtitle (plist-get info :subtitle)))
+ (when ftitle
+ (message (org-export-data ftitle info))
+ (format
+ "<h1 class=\"title\">%s</h1>%s\n"
+ (org-export-data ftitle info)
+ (if subtitle
+ (format
+ "<p class=\"subtitle\">%s</p>\n"
+ (org-export-data subtitle info))
+ "")))))
+ contents
+ "</div>"
+ ; (format "</%s>\n" (nth 1 (assq 'content (plist-get info :html-divs))))
+ ;; Postamble.
+ (org-html--build-pre/postamble 'postamble info)
+ ;; Closing document.
+ "</body>\n</html>"))
+
+;; see ox-odt
+
+(defmacro org-epub--export-wrapper (outfile &rest body)
+ "Export an Epub with BODY generating the main html file and OUTFILE as target file."
+ `(let* ((outfile ,outfile)
+ (org-epub-manifest nil)
+ (org-epub-metadata nil)
+ (org-epub-style-counter 0)
+ (out-file-type (file-name-extension outfile))
+ (org-epub-zip-dir (file-name-as-directory
+ (make-temp-file (format "%s-" out-file-type) t)))
+ (body ,@body))
+ (condition-case err
+ (progn
+ (when (plist-get org-epub-metadata :html-head-include-default-style)
+ (with-current-buffer (find-file (concat org-epub-zip-dir "style.css"))
+ (insert org-epub-style-default)
+ (save-buffer 0)
+ (kill-buffer)
+ (push (org-epub-manifest-entry "default-style" "style.css" 'stylesheet "text/css") org-epub-manifest)))
+ (when (org-string-nw-p (plist-get org-epub-metadata :epub-cover))
+ (let* ((cover-path (plist-get org-epub-metadata :epub-cover))
+ (cover-type (file-name-extension cover-path))
+ (cover-img (create-image (expand-file-name cover-path)))
+ (cover-width (car (image-size cover-img t)))
+ (cover-height (cdr (image-size cover-img t)))
+ (cover-name (concat "cover." cover-type)))
+ (with-current-buffer (find-file (concat org-epub-zip-dir "cover.html"))
+ (erase-buffer)
+ (insert
+ (org-epub-template-cover cover-name cover-width cover-height))
+ (save-buffer 0)
+ (kill-buffer)
+ (let ((men (org-epub-manifest-entry "cover" "cover.html" 'cover "application/xhtml+xml")))
+ (push men org-epub-manifest))
+ (let ((men (org-epub-manifest-entry "cover-image" cover-name 'coverimg (concat "image/" cover-type) cover-path)))
+ (push men org-epub-manifest)))))
+ (unless (file-directory-p (expand-file-name "META-INF" org-epub-zip-dir))
+ (make-directory (file-name-as-directory (expand-file-name "META-INF" org-epub-zip-dir))))
+ (with-current-buffer (find-file (expand-file-name "META-INF/container.xml" org-epub-zip-dir))
+ (erase-buffer)
+ (insert (org-epub-template-container))
+ (save-buffer 0)
+ (kill-buffer))
+ (with-current-buffer (find-file (concat org-epub-zip-dir "mimetype"))
+ (erase-buffer)
+ (insert (org-epub-template-mimetype))
+ (save-buffer 0)
+ (kill-buffer))
+ (with-current-buffer (find-file (concat org-epub-zip-dir "body.html"))
+ (erase-buffer)
+ (insert body)
+ (save-buffer 0)
+ (kill-buffer)
+ (nconc org-epub-manifest (list (org-epub-manifest-entry "body-html" "body.html" 'html "application/xhtml+xml"))))
+ (with-current-buffer (find-file (concat org-epub-zip-dir "toc.ncx"))
+ (erase-buffer)
+ (insert
+ (org-epub-template-toc-ncx
+ (plist-get org-epub-metadata :epub-uid)
+ (plist-get org-epub-metadata :epub-toc-depth)
+ (plist-get org-epub-metadata :title)
+ (org-epub-generate-toc-single org-epub-headlines "body.html")))
+ (save-buffer 0)
+ (kill-buffer))
+ (with-current-buffer (find-file (concat org-epub-zip-dir "content.opf"))
+ (erase-buffer)
+ (insert (org-epub-template-content-opf
+ org-epub-metadata
+ (org-epub-gen-manifest org-epub-manifest)
+ (org-epub-gen-spine '(("body-html" . "body.html")))))
+ (save-buffer 0)
+ (kill-buffer))
+ (org-epub-zip-it-up outfile org-epub-manifest org-epub-zip-dir)
+ (delete-directory org-epub-zip-dir t)
+ (message (with-output-to-string (print org-epub-manifest)))
+ (message "Generated %s" outfile)
+ (expand-file-name outfile))
+ (error (delete-directory org-epub-zip-dir t)
+ (message "ox-epub eport error: %s" err)))))
+
+;;compare org-export-options-alist
+;;;###autoload
+(defun org-epub-export-to-epub (&optional async subtreep visible-only ext-plist)
+ "Export the current buffer to an EPUB file.
+
+ASYNC defines wether this process should run in the background,
+SUBTREEP supports narrowing of the document, VISIBLE-ONLY allows
+you to export only visible parts of the document, EXT-PLIST is
+the property list for the export process."
+ (interactive)
+ (let* ((outfile (org-export-output-file-name ".epub" subtreep)))
+ (message "Output to:")
+ (message outfile)
+ (if async
+ (org-export-async-start (lambda (f) (org-export-add-to-stack f 'odt))
+ (org-epub--export-wrapper
+ outfile
+ (org-export-as 'epub subtreep visible-only nil ext-plist)))
+ (org-epub--export-wrapper
+ outfile
+ (org-export-as 'epub subtreep visible-only nil ext-plist)))))
+
+(defun org-epub-template-toc-ncx (uid toc-depth title toc-nav)
+ "Create the toc.ncx file.
+
+UID is the uid/url of the file. TOC-DEPTH is the depth of the toc
+that should be shown to the readers. TITLE is the title of the
+ebook and TOC-NAV being the raw contents enclosed in navMap."
+ (concat
+ "<?xml version=\"1.0\"?>
+<!DOCTYPE ncx PUBLIC \"-//NISO//DTD ncx 2005-1//EN\"
+ \"http://www.daisy.org/z3986/2005/ncx-2005-1.dtd\">
+
+<ncx xmlns=\"http://www.daisy.org/z3986/2005/ncx/\" version=\"2005-1\">
+
+ <head>
+ <meta name=\"dtb:uid\" content=\""
+ uid
+ "\"/>
+ <meta name=\"dtb:depth\" content=\""
+ (format "%d" toc-depth)
+ "\"/>
+ <meta name=\"dtb:totalPageCount\" content=\"0\"/>
+ <meta name=\"dtb:maxPageNumber\" content=\"0\"/>
+ </head>
+
+ <docTitle>
+ <text>"
+ title
+ "</text>
+ </docTitle>
+
+ <navMap>"
+ toc-nav
+ "</navMap>
+</ncx>"))
+
+(defun org-epub-template-content-opf (meta manifest spine)
+ "Create the content.opf file.
+
+META is a metadata PLIST.
+
+The following arguments are XML strings: MANIFEST is the content
+inside the manifest tags, this should include all user generated
+html files but not things like the cover page, SPINE is an XML
+string with the list of html files in reading order."
+ (concat
+ "<?xml version=\"1.0\"?>
+
+<package xmlns=\"http://www.idpf.org/2007/opf\" unique-identifier=\"dcidid\"
+ version=\"2.0\">
+
+ <metadata xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
+ xmlns:dcterms=\"http://purl.org/dc/terms/\"
+ xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
+ xmlns:opf=\"http://www.idpf.org/2007/opf\">
+ <dc:title>" (plist-get meta :title) "</dc:title>
+ <dc:language xsi:type=\"dcterms:RFC3066\">" (plist-get meta :language) "</dc:language>
+ <dc:identifier id=\"dcidid\" opf:scheme=\"URI\">"
+ (plist-get meta :epub-uid)
+ "</dc:identifier>
+ <dc:subject>" (plist-get meta :epub-subject)
+ "</dc:subject>
+ <dc:description>" (plist-get meta :epub-description)
+
+ "</dc:description>
+ <dc:creator>" (plist-get meta :author) "</dc:creator>
+ <dc:publisher>" (plist-get meta :epub-publisher) "</dc:publisher>
+ <dc:date xsi:type=\"dcterms:W3CDTF\">" (plist-get meta :date) "</dc:date>
+ <dc:rights>" (plist-get meta :epub-rights) "</dc:rights>"
+ (let ((cimg (org-epub-manifest-first #'org-epub-coverimg-p)))
+ (when cimg
+ (concat "<meta name=\"cover\" content=\"" (plist-get cimg :id) "\"/>")))
+ "
+ </metadata>
+
+ <manifest>\n
+ <item id=\"ncx\" href=\"toc.ncx\"
+ media-type=\"application/x-dtbncx+xml\" />"
+
+ manifest
+
+ "</manifest>
+
+ <spine toc=\"ncx\">"
+ (let ((chtml (org-epub-manifest-first #'org-epub-cover-p)))
+ (when chtml
+ (concat "<itemref idref=\"" (plist-get chtml :id) "\" linear=\"no\" />")))
+
+ spine
+
+ "</spine>
+
+ <guide>"
+ (let ((chtml (org-epub-manifest-first #'org-epub-cover-p)))
+ (when chtml
+ (concat " <reference type=\"cover\" href=\"" (plist-get chtml :filename) "\" />")))
+ "
+ </guide>
+
+</package>"))
+
+(defun org-epub-gen-manifest (files)
+ "Generate the manifest XML string.
+
+FILES is the list of files to be included in the manifest xml string."
+ (mapconcat
+ (lambda (file)
+ (concat "<item id=\"" (plist-get file :id) "\" href=\"" (plist-get file :filename) "\"
+ media-type=\"" (plist-get file :mimetype) "\" />\n"))
+ files ""))
+
+(defun org-epub-gen-spine (files)
+ "Generate the spine XML string.
+
+FILES is the list of files to be included in the spine, these
+must be in reading order."
+ (mapconcat
+ (lambda (file)
+ (concat "<itemref idref=\"" (car file) "\" />\n"))
+ files ""))
+
+(defun org-epub-template-container ()
+ "Generate the container.xml file, the root of any EPUB."
+ "<?xml version=\"1.0\"?>
+<container version=\"1.0\" xmlns=\"urn:oasis:names:tc:opendocument:xmlns:container\">
+ <rootfiles>
+ <rootfile full-path=\"content.opf\"
+ media-type=\"application/oebps-package+xml\"/>
+ </rootfiles>
+</container>")
+
+(defun org-epub-template-cover (cover-file width height)
+ "Generate a HTML template for the cover page.
+
+COVER-FILE is the filename of a jpeg file, while WIDTH and HEIGHT are
+properties of the image."
+ (concat "<?xml version=\"1.0\" encoding=\"utf-8\"?>
+ <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">
+
+ <html xmlns=\"http://www.w3.org/1999/xhtml\">
+ <head>
+ <title></title>
+ </head>
+
+ <body>
+ <svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"
+ width=\"100%\" height=\"100%\" viewBox=\"0 0 573 800\" preserveAspectRatio=\"xMidYMid meet\">
+ <image xlink:href=\"" cover-file "\" height=\"" (format "%d" height) "\" width=\"" (format "%d" width) "\" />
+ </svg>
+ </body>
+ </html>"))
+
+(defun org-epub-template-mimetype ()
+ "Generate the mimetype file for the epub."
+ "application/epub+zip")
+
+(defun org-epub-zip-it-up (epub-file files target-dir)
+ "Create the .epub file by zipping up the contents.
+
+EPUB-FILE is the target filename, FILES is the list of source
+files to process, while TARGET-DIR is the directory where
+exported HTML files live. This function will copy any files into
+their proper place."
+ (mapc #'(lambda (entry)
+ (let ((copy (org-epub-manifest-needcopy entry)))
+ (when copy
+ (copy-file (car copy) (concat target-dir (cdr copy)) t))))
+ files)
+ (let ((default-directory target-dir)
+ (meta-files '("META-INF/container.xml" "content.opf" "toc.ncx")))
+ (apply 'call-process
+ (append (list org-epub-zip-command nil '(:file "zip.log") nil)
+ org-epub-zip-no-compress
+ (list epub-file
+ "mimetype")))
+ (apply 'call-process org-epub-zip-command nil '(:file "zip.log") nil
+ (append org-epub-zip-compress
+ (list epub-file)
+ (append meta-files (mapcar #'(lambda (el) (plist-get el :filename)) files)))))
+ (copy-file (concat target-dir epub-file) default-directory t))
+
+(defun org-epub-generate-toc-single (headlines filename)
+ "Generate a single file TOC.
+
+HEADLINES is a list containing the abbreviated headline
+information. The name of the target file is given by FILENAME."
+ (let ((toc-id 0)
+ (current-level 0))
+ (with-output-to-string
+ (mapc
+ (lambda (headline)
+ (let* ((title (nth 0 headline))
+ (level (nth 1 headline))
+ (ref (nth 2 headline)))
+ (cl-incf toc-id)
+ (cond
+ ((< current-level level)
+ (cl-incf current-level))
+ ((> current-level level)
+ (princ "</navPoint>")
+ (while (> current-level level)
+ (cl-decf current-level)
+ (princ "</navPoint>")))
+ ((eq current-level level)
+ (princ "</navPoint>")))
+ (princ
+ (concat (format "<navPoint class=\"h%d\" id=\"%s-%d\">\n" current-level filename toc-id)
+ (format "<navLabel><text>%s</text></navLabel>\n" (org-html-encode-plain-text title))
+ (format "<content src=\"%s#%s\"/>" filename ref)))))
+ headlines)
+ (while (> current-level 0)
+ (princ "</navPoint>")
+ (cl-decf current-level)))))
+
+(provide 'ox-epub)
+
+;;; ox-epub.el ends here
diff --git a/init.el b/init.el
@@ -347,7 +347,7 @@
("melpa-stable" . "https://stable.melpa.org/packages/")
("melpa" . "https://melpa.org/packages/")))
'(package-selected-packages
- '(ob-powershell powershell web-mode lexic editorconfig forge elfeed-tube-mpv elfeed-tube cider restclient-jq graphviz-dot-mode consult-eglot jq-mode multiple-cursors ob-restclient restclient vterm deadgrep helpful pdf-tools paredit-menu paredit corfu sly eglot aggressive-indent project nov nhexl-mode elfeed magit yaml-mode json-mode lua-mode go-mode geiser-guile geiser org-roam org-contrib org ace-window expand-region consult marginalia uuidgen request diminish which-key))
+ '(ox-epub ob-powershell powershell web-mode lexic editorconfig forge elfeed-tube-mpv elfeed-tube cider restclient-jq graphviz-dot-mode consult-eglot jq-mode multiple-cursors ob-restclient restclient vterm deadgrep helpful pdf-tools paredit-menu paredit corfu sly eglot aggressive-indent project nov nhexl-mode elfeed magit yaml-mode json-mode lua-mode go-mode geiser-guile geiser org-roam org-contrib org ace-window expand-region consult marginalia uuidgen request diminish which-key))
'(pcomplete-ignore-case t t)
'(pixel-scroll-precision-mode t)
'(read-buffer-completion-ignore-case t)