javascript - epub book doesn't display using Epub.js and Electron, but no errors in console log - Stack Overflow

admin2025-04-18  2

I am doing this work for my college project and I'm stuck. I am not getting any errors in my console log, but nothing is being displayed.

I have checked that the epub file itself is fine, which it is, since it can be displayed in a regular HTML file.

This is my code:

html:

<!DOCTYPE html>
<html lang="en">
    <head>
        <link rel="stylesheet" href="style.css">
        <meta charset="UTF-8">
        <meta
        http-equiv="Content-Security-Policy"
        content="default-src 'self' 'unsafe-inline' blob: data: filesystem:; script-src 'self' ; object-src 'self'"
        />    
        <title></title>
        <script src=".min.js"></script>
    </head>
    <body>
        <div id="content">
            <!-- Library Section -->
            <div id="library">
                <h3>Your Book Library</h3>
                <button id="openBookButton">Add Book</button>
            </div>
    
            <!-- Book Display Section -->
            <div id="bookContainer"></div>
            <button id="prevPageButton">Previous Page</button>
            <button id="nextPageButton">Next Page</button>
        </div>
    </body>
    <script src="./renderer.js"></script>
</html>

style for the bookContainer:

#bookContainer {
    width: 100%;
    height: 600px;
    overflow-y: auto;
    border: 1px solid red;
    background-color: #f0f0f0;
}

main.js:

const { app, BrowserWindow, ipcMain, dialog } = require('electron/main')
const path = require('node:path')
const fs = require('fs')

let win

const createWindow = () => {
  win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      nodeIntegration: false,
      contextIsolation: true,
      sandbox: false
    }
  })

  win.loadFile('index.html')
}

ipcMain.handle('select-epub-file', async () => {
  const result = await dialog.showOpenDialog({
      filters: [
          { name: 'EPUB Files', extensions: ['epub'] }
      ],
      properties: ['openFile']
  })

  if (!result.canceled) {
      const filePath = result.filePaths[0]
      console.log('File selected in main process:', filePath);
      const fileName = path.basename(filePath)
      const destPath = path.join(app.getPath('userData'), 'books', fileName)

      // Ensure the books directory exists
      if (!fs.existsSync(path.dirname(destPath))) {
          fs.mkdirSync(path.dirname(destPath), { recursive: true })
      }

      // Copy the EPUB file to the app's persistent data folder
      fs.copyFileSync(filePath, destPath)

      return destPath
  }
  return null
})

ipcMain.handle('load-epub-file', (event, filePath) => {
  if (filePath) {
    console.log('Loading EPUB file from renderer process:', filePath);
    return filePath;
  }
  return null;
})

app.whenReady().then(() => {
  createWindow()

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow()
    }
  })
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

preload.js:

const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('api', {
    loadEpub: () => ipcRenderer.invoke('select-epub-file'),
})

renderer.js:

const openBookButton = document.getElementById('openBookButton')


openBookButton.addEventListener('click', () => {
    console.log('Button clicked, opening file dialog...')
    window.api.loadEpub().then((filePath) => {
        console.log('Selected EPUB file path:', filePath)
        if (filePath) {
            console.log('File selected:', filePath)
            initializeEPUB(filePath)
        }
    }).catch((error) => {
        console.error('Error loading EPUB:', error)
    });
});

function loadEPUB(filePath) {
    try {
        console.log('Loading EPUB file:', filePath);
        const book = ePub(filePath);
        console.log('EPUB initialized:', book);

        // Check if book's spine is loaded
        book.loaded.spine.then((spine) => {
            console.log('Spine loaded:', spine);
            console.log('Spine items:', spine.items); // Log the spine items
        }).catch((err) => {
            console.error('Error loading spine:', err);
        });

        return book; // Return the initialized book
    } catch (error) {
        console.error('Error initializing EPUB:', error);
        return null;
    }
}

function renderBook(book) {
    try {
        console.log('Rendering the book...');
        const rendition = book.renderTo('bookContainer', {
            method: 'viewport',
            width: '100%',
            height: '600px',
        });
        console.log('Rendition created:', rendition);
        return rendition; // Return the rendition
    } catch (error) {
        console.error('Error rendering the book:', error);
        return null;
    }
}

async function initializeEPUB(filePath) {
    const book = loadEPUB(filePath);
    if (!book) {
        console.error('Failed to load EPUB.');
        return;
    } else {
        console.log('EPUB loaded:', book);
    }

    const rendition = renderBook(book);
    if (!rendition) {
        console.error('Failed to render EPUB.');
        return;
    } else {
        console.log('Rendition created:', rendition);
    }

    // Wait for the spine to load before calling display
    try {
        await book.loaded.spine;  // Ensure spine is loaded before rendering
        console.log('Spine loaded successfully.');

        // Try to display the book
        await rendition.display(); // Wait for the rendering to be completed
        console.log('Book rendered successfully.');
        //setupNavigation(rendition); // Setup navigation after the book is displayed
    } catch (error) {
        console.error('Error rendering book:', error);
    }
}
转载请注明原文地址:http://anycun.com/QandA/1744915022a89421.html