react-reader

repository·main·Indexed 21 days ago

https://github.com/gerhardsletten/react-reader

A React wrapper for ePubJS that provides an easy way to embed ePub readers into web applications using an iframe-based approach. It includes the high-level ReactReader component for UI features like Table of Contents, search, and swipe gestures, as well as the lower-level EpubView component for granular control over rendering, text selection, and rendition options.

Tokens
3.5K
Snippets
12
Records
16
Agent score
73%

What's inside react-reader

  1. Configure scrolled epub-view with epubOptions

    main

    To display a scrolled view instead of paginated pages, pass the appropriate manager and flow options via epubOptions.

    Note: Using mismatched combinations may cause rendering issues.

    • Flow: auto (default), paginated (left-to-right), or scrolled.
    • Manager: default (for auto/paginated) or continuous (for scrolled).

    Recommended pairing for scrolling: flow: 'scrolled' with manager: 'continuous'.

  2. Perform searches within the ePub

    main

    You can trigger a search within the book by passing a searchQuery string to the ReactReader component. The component will scan the book's spine and return results via the onSearchResults callback.

    Each result in the array contains:

    • cfi: The Content Fragment Identifier (CFI) used to locate the specific position in the book.
    • excerpt: A string containing the text surrounding the match, based on the contextLength prop.

    Note: The search is performed asynchronously by loading each chapter in the spine.

    <ReactReader
      url="/book.epub"
      searchQuery="chapter one"
      contextLength={20}
      onSearchResults={(results) => {
        console.log("Found results:", results);
        // results = [{ cfi: '...', excerpt: '...' }, ...]
      }}
    />
  3. Basic usage of ReactReader

    main

    To implement a basic reader, you must provide a url to the ePub file, a location state to track progress, and a locationChanged callback to update that state. Ensure the parent container has a defined height (e.g., 100vh).

    import React, { useState } from 'react'
    import { ReactReader } from 'react-reader'
    
    export const App = () => {
      const [location, setLocation] = useState<string | number>(0)
      return (
        <div style={{ height: '100vh' }}>
          <ReactReader
            url="https://react-reader.metabits.no/files/alice.epub"
            location={location}
            locationChanged={(epubcfi: string) => setLocation(epubcfi)}
          />
        </div>
      )
    }
  4. Fix invalid ePub files by overriding DOMParser

    main

    If you encounter invalid ePub files (e.g., containing broken <title/> tags that cause blank pages), you can override the global window.DOMParser to sanitize the markup before parsing:

    const DOMParser = window.DOMParser
    
    class OwnParser {
      parseFromString(markup, mime) {
        if (markup.indexOf('<title/>') !== -1) {
          markup = markup.replace('<title/>', '');
        }
        return new DOMParser().parseFromString(markup, mime)
      }
    }
    
    window.DOMParser = OwnParser
  5. Enable links and scripts in epubjs iframe

    main

    By default, the iframe is sandboxed. To allow links to open or JavaScript to run within the ePub content, pass allowPopups and allowScriptedContent in epubOptions:

    <ReactReader
      url={localFile}
      epubOptions={{
        allowPopups: true,
        allowScriptedContent: true,
      }}
    />
    <ReactReader
      url={localFile}
      epubOptions={{
        allowPopups: true, // Adds `allow-popups` to sandbox-attribute
        allowScriptedContent: true, // Adds `allow-scripts` to sandbox-attribute
      }}
    />
  6. Handle missing mime-types using epubInitOptions

    main

    If your server returns incorrect mime-types or the file lacks a .epub extension, use epubInitOptions to force the correct reading mode:

    <ReactReader
      url="/my-epub-service"
      epubInitOptions={{
        openAs: 'epub',
      }}
    />
    import React from 'react'
    import { ReactReader } from 'react-reader'
    
    const App = () => {
      return (
        <div style={{ height: '100vh' }}>
          <ReactReader
            url="/my-epub-service"
            epubInitOptions={{
              openAs: 'epub',
            }}
          />
        </div>
      )
    }
  7. EpubView props reference

    main

    The following props are passed down to the inner EpubView (the iframe-view from EpubJS):

    • url [string, required]: URL to the ePub file. If hosted on another domain, ensure CORS is configured. The file must be publicly available as EpubJS fetches it via HTTP.
    • loadingView [element]: Custom element to show while loading.
    • location [string, number, null]: Set or update the ePub location.
    • locationChanged [func]: Callback receiving the current location. Called on page changes and initial render.
    • tocChanged [func]: Callback receiving an array of chapters once the book is parsed.
    • epubInitOptions [object]: Custom properties for the epub.js init function.
    • epubOptions [object]: Custom properties for the epub rendition (see epub.js documentation).
    • getRendition [func]: Callback providing access to the epubjs-rendition object once rendered.
    • isRTL [boolean]: Support for Right-to-Left reading direction.
  8. ReactReader props reference

    main

    The ReactReader component accepts the following props:

    • title [string]: The title of the book, displayed above the reading-canvas.
    • showToc [boolean]: Whether to show the table of contents / toc-nav.
    • readerStyles [object]: Override the default styles for the ReactReader component.
    • epubViewStyles [object]: Override the default styles for the inner EpubView.
    • swipeable [boolean, default false]: Enable swiping left/right using react-swipeable. Warning: This disables interacting with iframe content like text selection.
  9. Use the ReactReader component

    main

    The ReactReader component is the primary entry point for embedding an ePub reader into a React application. It wraps an EpubView and provides high-level features like Table of Contents (ToC) management, swipe gestures, and search functionality. It accepts props inherited from IEpubViewProps along with additional configuration for the reader UI.

    import { ReactReader } from 'react-reader';
    
    function MyReader() {
      return (
        <ReactReader
          url="/path/to/book.epub"
          title="My Book"
          locationChanged={(epub, location) => {
            console.log(location);
          }}
        />
      );
    }
  10. Handle text selection events

    main

    You can intercept text selection within the ePub by providing a handleTextSelected function to the EpubView component. This is useful for implementing highlighting, note-taking, or dictionary lookups.

    The callback receives two arguments:

    1. cfiRange: A string representing the CFI (Canonical Fragment Identifier) range of the selected text.
    2. contents: The epubjs Contents object associated with the selection.
    <EpubView
      url="/path/to/book.epub"
      location={location}
      locationChanged={locationChanged}
      handleTextSelected={(cfiRange, contents) => {
        console.log('Selected CFI:', cfiRange);
        console.log('Contents:', contents);
      }}
    />