You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

mupdf-webviewer

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mupdf-webviewer

The web viewer SDK using mupdf.js

0.5.0
latest
npmnpm
Version published
Weekly downloads
94
-34.72%
Maintainers
1
Weekly downloads
 
Created
Source

MuPDF WebViewer

A customizable PDF Viewer Component for the Web.

MuPDF WebViewer is an easy to use drop-in UI component for web pages which allows for in-context PDF viewing.

Get Started with Examples

  • MuPDF WebViewer React sample
  • MuPDF WebViewer Angular sample

Installation

npm install mupdf-webviewer

Documentation

Usage

Note: A trial license key is required to use MuPDF WebViewer. For local development and testing, please generate a license key for "localhost" domain. Visit MuPDF WebViewer to obtain your trial license.

Copy the library assets

cp -r node_modules/mupdf-webviewer/lib/* {YOUR_LIBRARY_PATH}/

If you want to use the library in a web application, you need to copy the library assets to your web application.

Create DOM Element for Viewer

<div id="viewer"></div>

You need to prepare DOM element with id viewer in your html. Initialization function must be called after the DOM element is created.

Initialize Viewer

import { initMuPDFWebViewer } from 'mupdf-webviewer'

initMuPDFWebViewer('#viewer', 'sample.pdf', {
  libraryPath: 'YOUR_LIBRARY_PATH',
  licenseKey: 'YOUR_LICENSE_KEY',
})
  .then(mupdf => {
    /* API */
    mupdf.toast.show({ type: 'success', content: 'Opened' });
  })
  .catch(err => {
    /* Error handling */
  });

TypeScript Definition

export function initMuPDFWebViewer(
  selector: string,
  docURL: string,
  options?: {
    licenseKey: string; 
    libraryPath?: string;
    filename?: string;
    standalone?: boolean;
    withoutLoader?: boolean;
  }
): Promise<MuPDFWebViewer>;

Reference Variables

MuPDF WebViewer provides reference variables for API calls.

[Example]

mupdf.refs.icon.SHARE

Saving Documents

MuPDF WebViewer provides two primary methods for saving documents:

1. Save as Binary

mupdf.document.export()
  .then(buffer => {
    const blob = new Blob([ buffer ], { type: 'application/pdf' });
    const objUrl = URL.createObjectURL(blob);
    window.open(objUrl);
    /* or anything you want */
});

2. Save as File (Download)

mupdf.document.download();

3. Saving Annotations Separately

For sharing annotations without the full document:

// Get annotations only
async function getAnnotationsAsJSON() {
  const annotations = await mupdf.annotation.get();
  return JSON.stringify(annotations);
}

// Save annotations to local storage
async function saveAnnotationsLocally() {
  const annotations = await mupdf.annotation.get();
  localStorage.setItem('pdfAnnotations', JSON.stringify(annotations));
  mupdf.toast.show({
    type: 'success',
    content: 'Annotations saved locally'
  });
}

// Load annotations from local storage
async function loadLocalAnnotations() {
  const savedAnnotations = JSON.parse(localStorage.getItem('pdfAnnotations') ?? '{ "annotations": [] }');
  if (savedAnnotations?.annotations.length > 0) {
    await mupdf.annotation.add(savedAnnotations);
    mupdf.toast.show({
      type: 'notification',
      content: 'Annotations loaded'
    });
  }
}

Customizing the Viewer

1. Display/Hide UI

You can display/hide the UI of the viewer using viewer.setViewVisibility() function. For example, if you want to hide the toolbar, you can do the following:

mupdf.viewer.setViewVisibility({
  view: mupdf.refs.visibility.view.TOOLBAR,
  visibility: false,
});

2. Add Buttons to Toolbar

You can add buttons to the toolbar using viewer.addButton() function. For example, if you want to add a button to the toolbar to enter fullscreen, you can do the following:

mupdf.viewer.addButton({
  buttons: [
    {
      position: 'TOOLBAR.LEFT_SECTION.FIRST',
      icon: mupdf.refs.icon.ENTER_FULLSCREEN,
      label: 'Enter fullscreen',
      onclick: () => {
        document.body.requestFullscreen();
      },
    },
  ],
});

3. Add Context Menu

You can add context menu to the viewer using viewer.addContextMenu() function. For example, if you want to add a context menu to the viewer to rotate the page clockwise, you can do the following:

mupdf.viewer.addContextMenu({
  menus: [
    {
      type: 'MENU',
      position: 'FIRST',
      icon: mupdf.refs.icon.ROTATE_CLOCKWISE,
      label: 'Rotate Clockwise',
      onclick: () => {
        mupdf.viewer.rotateClockwise();
      },
    },
  ],
});

4. Define Document Panel

You can define document panel using viewer.setDocumentPanel() function. For example, if you want to define document panel to show the bookmark panel, you can do the following:

mupdf.viewer.defineDocumentPanel({
  items: [
    {
      label: 'TOC',
      icon: mupdf.refs.icon.BOOKMARK,
      onclick: () => {
        mupdf.viewer.togglePanel({
          type: mupdf.refs.panel.open.BOOKMARK,
        });
      },
    },
  ],
});

5. Define Annotation Selection Menu

You can define annotation selection menu using viewer.defineAnnotSelectMenu() function. For example, if you want to define annotation selection menu when selecting a highlight annotation, you can do the following:

mupdf.viewer.defineAnnotSelectMenu({
  html: `
    <h1>This is a highlight</h1>
  `,
  tool: mupdf.refs.annotation.tool.HIGHLIGHT,
});

Event System

TypeScript Definition

public addEventListener<T extends keyof EventDataMap>(
  type: T, 
  callback: (event: { type: T; data: EventDataMap[T] }) => void
): void;

Event Types

event: {
  type: {
    SCALE_CHANGE: EventType.SCALE_CHANGE,
    ANNOTATION_TOOL_CHANGE: EventType.ANNOTATION_TOOL_CHANGE,
    CURRENT_PAGE_INDEX_CHANGE: EventType.CURRENT_PAGE_INDEX_CHANGE,
    DOCUMENT_DOWNLOAD: EventType.DOCUMENT_DOWNLOAD,
    SIDE_VIEW_OPEN: EventType.SIDE_VIEW_OPEN,
    SIDE_VIEW_CLOSE: EventType.SIDE_VIEW_CLOSE,
    KEYDOWN: EventType.KEYDOWN,
    KEYUP: EventType.KEYUP,
    SCROLL_POSITION_CHANGE: EventType.SCROLL_POSITION_CHANGE,
    CURRENT_READING_PAGE_CHANGE: EventType.CURRENT_READING_PAGE_CHANGE,
    MOUSEDOWN: EventType.MOUSEDOWN,
    MOUSEUP: EventType.MOUSEUP,
    POINTERDOWN: EventType.POINTERDOWN,
    POINTERUP: EventType.POINTERUP,
    ANNOTATION_CREATE: EventType.ANNOTATION_CREATE,
    ANNOTATION_MODIFY: EventType.ANNOTATION_MODIFY,
    ANNOTATION_REMOVE: EventType.ANNOTATION_REMOVE,
    REDACTION_CREATE: EventType.REDACTION_CREATE,
    REDACTION_MODIFY: EventType.REDACTION_MODIFY,
    REDACTION_REMOVE: EventType.REDACTION_REMOVE,
    CUSTOM_CONTEXT_MENU_EXECUTE: EventType.CUSTOM_CONTEXT_MENU_EXECUTE,
    TEXT_SEARCH_START: EventType.TEXT_SEARCH_START,
    ACTION_HISTORY_CHANGE: EventType.ACTION_HISTORY_CHANGE,
    ANNOTATION_SELECTION_CHANGE: EventType.ANNOTATION_SELECTION_CHANGE,
  }
}
mupdf.addEventListener(mupdf.refs.event.type.KEYDOWN, (event) => {
  if (event.data.event.ctrlKey && event.data.event.key === 's') {
    mupdf.document.download();
  }
});

API

Document API

document.download(config?: { fileName?: string; includeAnnotations?: boolean })

Downloads the PDF file.

  • fileName (optional): Name of the file to download
  • includeAnnotations (optional; default: true): Whether to include annotations

document.getPages(config?: { pageRange?: string })

Gets PDF page information.

  • pageRange (optional; default: 'all'): Page index range (e.g., "1-5, 7, 9-12", "all")

Returns:

{
  pages: {
    pageIndex: number;
    read: boolean;
    isVisible: boolean;
    bbox: {
      width: number;
      height: number;
      x: number;
      y: number;
    }
  }[]
}

document.getPageCount()

Gets the total number of pages in the PDF.

Returns:

{ pageCount: number }

document.open(config: { url: string; filename: string })

Opens a PDF document.

document.close()

Closes the currently opened PDF document.

document.print(config: { pageRange: string })

Prints the PDF.

  • pageRange (required): Page index range to print (e.g., "1-5, 7, 9-12", "all")

Returns:

{ status: 'PRINTED' | 'CANCELLED' }

document.rotatePage(config: { pageRange: string; degree: 0 | 90 | 180 | 270 | 360 })

Rotates pages.

  • pageRange (required): Page index range to rotate (e.g., "1-5, 7, 9-12", "all")
  • degree (required): Rotation angle (0, 90, 180, 270, 360)

document.getText(config?: { pageRange?: string })

Extracts text from the PDF.

  • pageRange (optional; default: 'all'): Page index range to extract text from (e.g., "1-5, 7, 9-12", "all")

Returns:

{
  pageIndex: number;
  text: string;
}[]

document.export(config?: { includeAnnotations?: boolean })

Exports the PDF.

  • includeAnnotations (optional; default: true): Whether to include annotations

Returns: PDF data in Uint8Array format

Viewer API

viewer.toggleDialog(config: { dialogType: refs.dialog.type; visibility?: boolean })

Shows or hides a dialog.

  • dialogType (required): Dialog type (refs.dialog.type: 'PRINT' | 'SEARCH_TOOL')
  • visibility (optional): Whether to show or hide

viewer.getScale()

Gets the current zoom scale.

Returns:

{ scale: number }

viewer.setScale(config: { scale: number })

Sets the zoom scale.

  • scale (required): Zoom scale value

viewer.zoomIn(config?: { increment: number })

Zooms in.

  • increment (required): Zoom increment value

viewer.zoomOut(config?: { decrement: number })

Zooms out.

  • decrement (required): Zoom decrement value

viewer.getCurrentPageIndex()

Gets the current page index.

Returns:

{ currentPageIndex: number }

viewer.getRotation()

Gets the current rotation angle.

Returns:

{ degree: 0 | 90 | 180 | 270 }

viewer.setRotation(config: { degree: 0 | 90 | 180 | 270 | 360 })

Sets the rotation angle.

  • degree (required): Rotation angle (0, 90, 180, 270, 360)

viewer.rotateClockwise()

Rotates clockwise.

viewer.rotateCounterClockwise()

Rotates counter-clockwise.

viewer.setViewMode(config: { viewMode: refs.viewMode; })

Sets the view mode.

  • viewMode (required): View mode (refs.viewMode: 'SINGLE' | 'SINGLE_SCROLL' | 'DOUBLE' | 'DOUBLE_SCROLL')

viewer.fitTo(config: { to: refs.fit.to })

Sets page fitting.

  • to (required): Fit mode (refs.fit.to: 'WIDTH' | 'HEIGHT' | 'PAGE' | 'READ')

viewer.scrollTo(config: { type: refs.scroll.type; value: number; centerPoint?: { x: number; y: number }; select?: boolean; name?: string; pageIndex?: number })

Scrolls to a specific position.

{
  type: 'PAGE';
  value: number;
  centerPoint?: { x: number; y: number };
}
| {
  type: 'ANNOTATION';
  value: number;
  select?: boolean;
}
| {
  type: 'ANNOTATION';
  name: string;
  pageIndex: number;
  select?: boolean;
}
  • type (required): Scroll type (refs.scroll.type: 'PAGE' | 'ANNOTATION')
  • value (required): Scroll value ('PAGE': Page index, 'ANNOTATION': Annotation oid)
  • 'PAGE': centerPoint (optional): Center point of the page
  • 'ANNOTATION': select (optional): Whether to select the annotation
  • 'ANNOTATION': name (optional): Annotation name
  • 'ANNOTATION': pageIndex (optional): Page index

viewer.scrollToNextPage()

Scrolls to the next page.

viewer.scrollToPreviousPage()

Scrolls to the previous page.

viewer.selectAnnotationTool(config: AnnotationTool | AnnotationStampTool)

Selects an annotation tool.

  • tool (required): Annotation tool (refs.annotation.tool: 'HIGHLIGHT' | 'STRIKE' | 'UNDERLINE' | ...)

viewer.toggleAnnotationTool(config: AnnotationTool | AnnotationStampTool)

Toggles an annotation tool.

  • tool (required): Annotation tool (refs.annotation.tool: 'HIGHLIGHT' | 'STRIKE' | 'UNDERLINE' | ...)

viewer.openSideView(config: { type: refs.panel.open })

Opens a side view.

  • type (required): Side view type (refs.panel.open: 'THUMBNAIL' | 'BOOKMARK' | 'ANNOTATION' | 'REDACTION' | 'ANNOTATION_PROPERTY' | 'TEXT_SEARCH')

viewer.closeSideView(config: { type: refs.panel.close })

Closes a side view.

  • type (required): Side view type (refs.panel.close: 'LEFT' | 'RIGHT')

viewer.togglePanel(config: { type: refs.panel.open })

Toggles a panel.

  • type (required): Panel type (refs.panel.open: 'THUMBNAIL' | 'BOOKMARK' | 'ANNOTATION' | 'REDACTION' | 'ANNOTATION_PROPERTY' | 'TEXT_SEARCH')

viewer.highlight(config: { rects: Array<{ color: string; pageIndex: number; opacity?: number; rect: { top: number; left: number; bottom: number; right: number } }> })

viewer.highlight(config: { keywords: Array<{ keyword: string; color: string; opacity?: number; caseSensitive?: boolean; useRegex?: boolean }> })

Highlights text.

  • rects (required): Array of highlight area information
    • color (required): Highlight color
    • pageIndex (required): Page index
    • opacity (optional): Highlight opacity
    • rect (required): Highlight area (top > bottom, right > left)
  • keywords (required): Array of keyword information
    • keyword (required): Keyword to highlight
    • color (required): Highlight color
    • opacity (optional; default: 0.5): Highlight opacity
    • caseSensitive (optional; default: true): Whether to be case sensitive
    • useRegex (optional; default: false): Whether to use regular expressions

Example:

mupdf.viewer.highlight({ rects: [ { color: '#FF0000', pageIndex: 0, rect: { left: 100, top: 200, right: 200, bottom: 100 } } ] });
mupdf.viewer.highlight({ keywords: [ { keyword: 'keyword', color: '#FF0000' } ] });

Returns:

{
  rects: { id: number }[]
}

viewer.unhighlight(config: { rects: { id: number }[] })

Removes highlights.

  • rects (required): Array of highlight areas to remove

viewer.searchText(config: { keyword: string; caseSensitive?: boolean; useRegex?: boolean; emitEvent?: boolean })

Searches for text in the viewer right panel.

  • keyword (required): Search keyword
  • caseSensitive (optional): Whether to be case sensitive
  • useRegex (optional): Whether to use regular expressions
  • emitEvent (optional): Whether to emit events

viewer.setViewVisibility(config: { view: refs.visibility.view; visibility: boolean })

Sets view visibility.

  • view (required): View type (refs.visibility.view: 'TOOLBAR' | 'FLOATING_NAV' | 'SIDE_VIEW' | 'CONTEXT_MENU' | 'INDICATOR' | ...)
  • visibility (required): Whether to show or hide

viewer.addButton(config: { buttons: Array<{ position: 'TOOLBAR.LEFT_SECTION.FIRST' | 'TOOLBAR.LEFT_SECTION.LAST'; icon: refs.icon; label: string; onclick: Function }> })

Adds a button to the toolbar.

  • buttons (required): Array of button information
    • position (required): Button position
    • icon (required): Button icon (refs.icon: 'SHARE' | 'PENCIL' | 'MAIL' | ...)
    • label (required): Button label
    • onclick (required): Click handler

viewer.addContextMenu(config: { menus: Array<{ type: 'MENU'; position: 'FIRST' | 'LAST'; icon?: refs.icon; label?: string; onclick?: Function }> })

Adds a context menu.

  • menus (required): Array of menu information
    • type (required): Menu type
    • position (required): Menu position
    • icon (optional): Menu icon (refs.icon: 'SHARE' | 'PENCIL' | 'MAIL' | ...)
    • label (optional): Menu label
    • onclick (optional): Click handler

viewer.defineDocumentPanel(config: { items: Array<{ label: string; onclick: Function; icon?: refs.icon }> })

Defines document panel at the left side of the viewer toolbar.

  • items (required): Array of menu item information
    • label (required): Menu label
    • onclick (required): Click handler
    • icon (optional): Menu icon (refs.icon: 'SHARE' | 'PENCIL' | 'MAIL' | ...)

viewer.defineAnnotSelectMenu(config: { html: string; style?: string; script?: string; tool?: refs.annotation.tool})

Defines a menu when selecting an annotation.

  • html (required): HTML content of the menu
  • style (optional): CSS content of the menu
  • script (optional): JavaScript content of the menu
  • tool (optional): Annotation tool that the menu is displayed for (refs.annotation.tool: 'HIGHLIGHT' | 'STRIKE' | 'UNDERLINE' | ...)

NOTE: When using style or script, please consider the following:

  • Style: CSS selectors will apply to all matching elements within the viewer scope.
  • Script: JavaScript code will be executed in the viewer's context with the following limitations:
    • External resources cannot be accessed
    • Variables declared will be in global scope

viewer.setBackgroundColor(config: { color: string })

Sets the background color.

  • color (required): Background color hex code (e.g., '#000000')

viewer.setPageBorderColor(config: { color: string })

Sets the page border color.

  • color (required): Border color hex code (e.g., '#000000')

viewer.setColor(config: { mainColor: string; subColor: string })

Sets main and sub colors.

  • mainColor (required): Main color hex code (e.g., '#000000')
  • subColor (required): Sub color hex code (e.g., '#000000')

viewer.setTheme(config: { type: refs.theme })

Sets the theme.

  • type (required): Theme type (refs.theme: 'LIGHT_MODE' | 'DARK_MODE' | 'SYSTEM_SYNCHRONIZATION')

viewer.setLanguage(config: { key: refs.language })

Sets the language.

  • key (required): Language key (refs.language: 'ko' | 'en' | 'ja')

viewer.getSize()

Gets the viewer size.

Returns:

{ width: number; height: number }

viewer.setLogo(config: { url: string })

Sets the brand logo (maximum size: 100x24px).

It displays the logo in the top center of the viewer.

  • url (required): Logo URL

Watermark API

watermark.create(config: { watermarks: Array<TextWatermark | ImageWatermark> })

Creates watermarks.

  • watermarks (required): Array of text or image watermarks

Text API

text.search(config: { keyword: string; caseSensitive?: boolean; useRegex?: boolean; pageRange?: string })

Searches for text in code.

  • keyword (required): Search keyword
  • caseSensitive (optional): Whether to be case sensitive
  • useRegex (optional): Whether to use regular expressions
  • pageRange (optional): Page index range to search (e.g., "1-5, 7, 9-12", "all")

Returns:

{
  results: {
    words: {
      prefix: string;
      keyword: string;
      suffix: string;
      rects: {
        top: number;
        left: number;
        bottom: number;
        right: number;
      }[];
    }[];
  }[];
}

text.getSelected()

Gets selected text.

Returns:

{
  text: string;
}

Annotation API

annotation.remove(config: { annotations: Array<{ name: string; pageIndex: number } | { oid: number; pageIndex: number }>; emitEvent?: boolean })

Removes annotations.

  • annotations (required): Array of annotation information to remove
  • emitEvent (optional): Whether to emit events

annotation.get(config?: { pageIndex: number })

Gets annotations.

  • pageIndex (optional): Page index
  • Returns: Array of annotations

annotation.add(config: { annotations: Annotation[]; emitEvent?: boolean })

Adds annotations.

  • annotations (required): Array of annotations to add
  • emitEvent (optional): Whether to emit events
  • Returns: Array of added annotations

annotation.undo()

Undoes annotation operations.

  • Returns: Success status

annotation.redo()

Redoes undone annotation operations.

  • Returns: Success status

Toast API

toast.show(config: { type: 'success' | 'fail' | 'notification'; content: string; header?: string; timeout?: number })

Shows a toast message.

  • type (required): Toast type ('success' | 'fail' | 'notification')
  • content (required): Toast content
  • header (optional): Toast header
  • timeout (optional): Display duration in milliseconds

Keywords

MuPDF

FAQs

Package last updated on 17 Jul 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts