javascripthtmlepubepub.js

How do I display in HTML the cover of an epub book using epub.js?


I'm using EPUB.js and Vue to render an Epub. I want to display the cover images of several epub books so users can click one to then see the whole book.

There's no documentation on how to do this, but there are several methods that indicate that this should be possible.

First off, there's Book.coverUrl() method.

Note that I'm setting an img src property equal to bookCoverSrc in the Vue template. Setting this.bookCoverSrc will automatically update the src of the img tag and cause an image to display (if the src is valid / resolves).

this.book = new Epub(this.epubUrl, {});
this.book.ready.then(() => {
  this.book.coverUrl().then((url) => {
    this.bookCoverSrc = url;
  });
})

The above doesn't work. url is undefined.

Weirdly, there appears to be a cover property directly on book. So, I try:

this.book = new Epub(this.epubUrl, {});
this.book.ready.then(() => {
  this.coverSrc = this.book.cover;
});

this.book.cover resolves to OEBPS/@public@vhost@g@gutenberg@html@files@49010@49010-h@images@cover.jpg, so at least locally when I set it to a src results in a request to http://localhost:8080/OEBPS/@public@vhost@g@gutenberg@html@files@49010@49010-h@images@cover.jpg, which 200s but returns no content. Probably a quirk of webpack-dev-server to 200 on that, but if I page through sources in Chrome dev tools I also don't see any indicate that such a URL should resolve.

So, docs not helping. I googled and found this github question from 2015. Their code is like

$("#cover").attr("src", Book.store.urlCache[Book.cover]);

Interesting, nothing in the docks about Book.store.urlCache. As expected, urlCache is undefined, though book.store exists. I don't see anything on there that can help me display a cover image though.

Using epub.js, how can I display a cover image of an Epub file? Note that simply rendering the first "page" of the Epub file (which is usually the cover image) doesn't solve my problem, as I'd like to list a couple epub files' cover images.

Note also that I believe the epub files I'm using do have cover images. The files are Aesop's Fables and Irish Wonders.

EDIT: It's possible I need to use Book.load on the url provided by book.cover first. I did so and tried to console.log it, but it's a massive blog of weirdly encoded text that looks something like:

����

So I think it's an image straight up, and I need to find a way to get that onto the Document somehow?

EDIT2: that big blobby blob is type: string, and I can't atob() or btoa() it.

EDIT3: Just fetching the url provided by this.book.cover returns my index.html, default behavior for webpack-dev-server when it doesn't know what else to do.

EDIT4: Below is the code for book.coverUrl from epub.js

    key: "coverUrl",
    value: function coverUrl() {
        var _this9 = this;

        var retrieved = this.loaded.cover.then(function (url) {
            if (_this9.archived) {
                // return this.archive.createUrl(this.cover);
                return _this9.resources.get(_this9.cover);
            } else {
                return _this9.cover;
            }
        });

        return retrieved;
    }

If I use this.archive.createUrl(this.cover) instead of this.resources.get, I actually get a functional URL, that looks like blob:http://localhost:8080/9a3447b7-5cc8-4cfd-8608-d963910cb5f5. I'll try getting that out into src and see what happens.


Solution

  • The reason this was happening to me was because the functioning line of code in the coverUrl function was commented out in the source library epub.js, and a non-functioning line of code was written instead.

    So, I had to copy down the entire library, uncomment the good code and delete the bad. Now the function works as it should.

    To do so, clone down the entire epub.js project. Copy over the dependencies in that project's package.json to your own. Then, take the src, lib, and libs folders and copy them somewhere into your project. Find a way to disable eslint for the location you put these folders into because the project uses TAB characters for spacing which caused my terminal to hang due to ESLINT exploding.

    npm install so you have your and epub.js dependencies in your node_modules.

    Open book.js. Uncomment line 661 which looks like

          return this.archive.createUrl(this.cover);
    

    and comment out line 662 which looks like

          // return this.resources.get(this.cover);
    

    Now you can display an image by setting an img tag's src attribute to the URL returned by book.coverUrl().

    this.book = new Epub(this.epubUrl, {});
    this.book.ready.then(() => {
      this.book.coverUrl().then((url) => {
        this.bookCoverSrc = url;
      });
    })