Pollen, ePUB export: how to do it?

Hello. I’ve made a web book using Pollen, and I would like to know what would be the best/simplest course of action to get an ePUB version of it.

The current project structure is the following:

  • assets/
    • some-file.pdf
  • images/
    • image-1.png
    • image-1.webp
  • pollen/
    • [contains racket+pollen functions]
  • styles/
    • body.css (generated)
    • body.css.pp
    • structure.css (generated)
    • structure.css.pp
    • font/
      • font-1.woff2
      • font-2.woff2
  • index.ptree
  • name-of-chapter-1.poly.pm
  • name-of-chapter-1.html (generated)
  • name-of-chapter-2.poly.pm
  • name-of-chapter-2.html (generated)
  • name-of-chapter-3.poly.pm
  • name-of-chapter-3.html (generated)
  • pollen.rkt
  • template.html.p

And when the time comes for a web release, I simply perform —after a review via raco pollen start— a raco pollen render; after which I put the generated HTML files and the other necessary files to the web server.

For a web project, the structure and workflow makes sense. But for ePUB, each chapter must translate first to XHTML, then assembled into the final package. And the same goes for the styles (the ePUB will have dedicated stylesheets), fonts and images; the assets must be discarded from the ePUB though.

I’ve tried to break down this project: GitHub - otherjoel/perfect-edition-pollen: A Pollen port of @robinsloan’s “Perfect Edition” ebook template. While educational on concepts about the ePUB structure, I found it a little too difficult to decipher (and the build doesn’t work either, failing to reach the end of the process, which doesn’t help). And this project is based on a single source file, while my current project has 1 source for each chapter.

So what are the steps I would have to follow to get an ePUB export?

(If you’re curious about my web book, simply search my name on a search engine, and it’s only a few links after that; it’s free and adfree to read, but in french, though.)

Small update, current thoughts on the steps:

  • Step 1: create the XHTML template dedicated for the EPUB(3) source render.
  • Step 2: review the 4th tutorial (8 Fourth tutorial: multiple output targets) which contains info about file handling.
  • Step 3: start with something like book.epub.pp, which I will use for rendering the EPUB file like this: raco pollen render book.epub.
  • Step 4: from the book.epub.pp, load a specific index ptree for the EPUB export (because not the same as the HTML export one).
  • Step 5: render each XHTML file from the source files into a temporary directory.
  • Step 6: create / infer the other metadata files required by the EPUB format into the temporary directory.
  • Step 7: zip the files, load the zip file content, delete the temporary directory.
  • Step 8: output the file content into the book.epub.

I have a problem with the renderer.

It loops over the first item forever:

$ raco pollen render livre.epub
pollen: rendering livre.epub
pollen: rendering /livre.epub.pp
pollen: transitively loading /index_epub.ptree
pollen: transitively loading /petit-déjeuner.poly.pm
pollen: rendering /petit-déjeuner.poly.pm as epubxhtml
pollen: rendering /petit-déjeuner.poly.pm as epubxhtml
pollen: rendering /petit-déjeuner.poly.pm as epubxhtml
pollen: rendering /petit-déjeuner.poly.pm as epubxhtml

I’ve tried render-pagenodes and render with the complete path of a single item. Any idea?

I can work around the issue by loading the (->html doc) directly. By doing this, I will not rely on the render functions anymore, and building the template with strings in the rkt file.

The current code is like this (the render which has been commented is the one creating the infinite loop):

;; Creates the XHTML files for EPUB from the source files.
(define (create-text-files)
  ; Text files build directory.
  (make-directory* text-dir)

  ; Pagetree containing the XHTML files.
  ; This pagetree must contain only source files for the XHTML target.
  (define page-tree (get-pagetree "index_epub_text.ptree"))
  (define page-list (pagetree->list page-tree))

  ; Tell Pollen we want the epubxhtml target.
  (parameterize ([current-poly-target 'epubxhtml])
                ; Create all the XHTML files.
                (for-each (lambda (page-item)
                                  ; Todo: insert into the template.
                                  ; try with (define (render source-path [maybe-template-path #f] [maybe-output-path #f])
                                  ; coming from pollen/render
                                  ; start test
                                  ;(render (path->complete-path (symbol->string page-item))
                                  ;        (path->complete-path "template.epubxhtml")
                                  ;        (path-replace-extension (path->complete-path (symbol->string page-item)) ".xhtmls"))
                                  ; end test
                                  (display-to-file (->html (get-doc page-item))
                                                   (build-path text-dir
                                                               ; We need to replace the ".epubxhtml" extension by ".xhtml".
                                                               (path-replace-extension (symbol->string page-item) ".xhtml"))
                                                   #:exists 'replace))

It’s me again. :slight_smile:

I just wanted to say I could create an EPUB!

Regarding the issue in the previous message, I just didn’t use the (render) function.

The only thing I’m not entirely satisfied with is the fact that I have some cache issues when juggling between my different outputs (web and epub for instance). What I have done is using the POLLEN environment variable to perform a switch during the processes to prevent (or not) the EPUB creation which happens everytime my epub.rkt entrypoint file is required. It’s ugly, but it works. :laughing:

Thanks again, Matthew and the contributors, for sharing Pollen with the world. I’ve been using it for a year. It’s quite addicting. :slight_smile: Take care of yourselves. :+1:

Congratulations on getting one step closer to enlightenment.