npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

xyz-pdf-snippet

v1.0.3

Published

Offline-capable PDF viewer with CSS styles included - Built on EmbedPDF

Readme

xyz-pdf-snippet

编译自embyed-pdf-viewer,官方提供的cdn无法离线使用,打了个包,把wasm加了进去

npm version License: MIT GitHub

A complete, offline-capable PDF viewer built on EmbedPDF. Perfect for applications that need robust PDF viewing without relying on external CDNs.

✨ Features

  • 📄 Full PDF Support - Render any PDF document with high fidelity
  • 🔍 Search - Find text within PDFs
  • 📝 Annotations - Add notes, highlights, and comments
  • 🔄 Rotate & Zoom - Full control over document viewing
  • 📱 Responsive - Works on desktop and mobile devices
  • 🖨️ Print - Print documents directly from the viewer
  • 💾 Download - Export PDFs with or without annotations
  • 🎨 Customizable - Theming and UI customization options
  • 🚀 WebAssembly Powered - Fast rendering using PDFium
  • 📦 Offline First - No CDN dependencies, all assets bundled

📦 Installation

npm install xyz-pdf-snippet

or

yarn add xyz-pdf-snippet

or

pnpm add xyz-pdf-snippet

🚀 Quick Start

Basic Usage

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>PDF Viewer</title>
</head>
<body>
  <div id="pdf-viewer" style="height: 600px"></div>

  <script type="module">
    import EmbedPDF from 'xyz-pdf-snippet';
 
    const viewer = EmbedPDF.init({
      type: 'container',
      target: document.getElementById('pdf-viewer'),
      src: './your-document.pdf'
    });

    // Optional: Listen to events
    viewer.on('documentLoaded', () => {
      console.log('PDF loaded successfully!');
    });
  </script>
</body>
</html>

With Module Bundler (Webpack, Vite, etc.)

import EmbedPDF from 'xyz-pdf-snippet';

const viewer = EmbedPDF.init({
  type: 'container',
  target: document.getElementById('pdf-viewer'),
  src: '/path/to/document.pdf'
});

React Example

import { useEffect, useRef } from 'react';
import EmbedPDF from 'xyz-pdf-snippet';

function PDFViewer({ pdfUrl }) {
  const viewerRef = useRef(null);

  useEffect(() => {
    const viewer = EmbedPDF.init({
      type: 'container',
      target: viewerRef.current,
      src: pdfUrl
    });

    return () => {
      // Cleanup if needed
    };
  }, [pdfUrl]);

  return <div ref={viewerRef} style={{ height: '600px' }} />;
}

Vue Example

<template>
  <div ref="viewerRef" style="height: 600px"></div>
</template>

<script setup>
import { ref, onMounted } from 'vue';
import EmbedPDF from 'xyz-pdf-snippet';

const props = defineProps({
  pdfUrl: String
});

const viewerRef = ref(null);

onMounted(() => {
  EmbedPDF.init({
    type: 'container',
    target: viewerRef.value,
    src: props.pdfUrl
  });
});
</script>

⚙️ Configuration Options

const viewer = EmbedPDF.init({
  // Required
  type: 'container',              // 'container' or 'inline'
  target: HTMLElement,            // DOM element to mount viewer
  src: string,                    // PDF file path or URL
  
  // Optional
  initialPage: 1,                 // Starting page number
  zoom: 1.0,                      // Initial zoom level (0.5 - 3.0)
  enableAnnotations: true,        // Enable annotation tools
  enableSearch: true,             // Enable text search
  enablePrint: true,              // Enable printing
  enableDownload: true,           // Enable download button
  enableFullscreen: true,         // Enable fullscreen mode
  theme: 'light',                 // 'light' or 'dark'
  toolbar: true,                  // Show/hide toolbar
  sidebar: true                   // Show/hide sidebar
});

📡 API Reference

Methods

// Navigation
viewer.goToPage(pageNumber: number): void
viewer.nextPage(): void
viewer.previousPage(): void
viewer.getPageCount(): number
viewer.getCurrentPage(): number

// Zoom
viewer.zoomIn(): void
viewer.zoomOut(): void
viewer.setZoom(level: number): void
viewer.fitToWidth(): void
viewer.fitToPage(): void

// Rotation
viewer.rotate(degrees: number): void  // 90, 180, 270, etc.

// Search
viewer.search(text: string): void
viewer.clearSearch(): void

// Download & Print
viewer.download(filename?: string): void
viewer.print(): void

// Fullscreen
viewer.enterFullscreen(): void
viewer.exitFullscreen(): void

Events

// Document events
viewer.on('documentLoaded', () => {
  console.log('Document loaded');
});

viewer.on('documentError', (error) => {
  console.error('Failed to load document:', error);
});

// Page events
viewer.on('pageChange', (pageNumber) => {
  console.log('Current page:', pageNumber);
});

// Zoom events
viewer.on('zoomChange', (zoomLevel) => {
  console.log('Zoom level:', zoomLevel);
});

// Annotation events
viewer.on('annotationAdded', (annotation) => {
  console.log('Annotation added:', annotation);
});

viewer.on('annotationUpdated', (annotation) => {
  console.log('Annotation updated:', annotation);
});

viewer.on('annotationDeleted', (annotationId) => {
  console.log('Annotation deleted:', annotationId);
});

// Remove event listener
const handler = (page) => console.log(page);
viewer.on('pageChange', handler);
viewer.off('pageChange', handler);

🌐 Server Configuration

Important: Cross-Origin Headers

This package uses WebAssembly and SharedArrayBuffer, which require specific HTTP headers:

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

Nginx Configuration

location / {
    add_header Cross-Origin-Opener-Policy "same-origin" always;
    add_header Cross-Origin-Embedder-Policy "require-corp" always;
}

Apache Configuration

<IfModule mod_headers.c>
    Header set Cross-Origin-Opener-Policy "same-origin"
    Header set Cross-Origin-Embedder-Policy "require-corp"
</IfModule>

Vite Configuration

// vite.config.js
export default {
  server: {
    headers: {
      'Cross-Origin-Opener-Policy': 'same-origin',
      'Cross-Origin-Embedder-Policy': 'require-corp',
    },
  },
};

Webpack Dev Server

// webpack.config.js
module.exports = {
  devServer: {
    headers: {
      'Cross-Origin-Opener-Policy': 'same-origin',
      'Cross-Origin-Embedder-Policy': 'require-corp',
    },
  },
};

Next.js Configuration

// next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: '/:path*',
        headers: [
          {
            key: 'Cross-Origin-Opener-Policy',
            value: 'same-origin',
          },
          {
            key: 'Cross-Origin-Embedder-Policy',
            value: 'require-corp',
          },
        ],
      },
    ];
  },
};

📦 What's Included

  • embedpdf.js - Main entry point (ESM module)
  • embedpdf-5926cb22.js - Core library (~495 KB)
  • worker-engine-de49cddb.js - PDF rendering engine (~574 KB)
  • direct-engine-9996aac8.js - Direct rendering fallback (~248 KB)
  • hammer-e1aXHboh-6cda5c0f.js - Touch gesture support (~20 KB)
  • pdfium.wasm - PDF rendering core (~3.7 MB)
  • TypeScript definitions included

Total size: ~5 MB (gzip recommended for production)

🔧 Troubleshooting

PDF fails to load

  1. Check browser console for CORS errors
  2. Verify server headers are set correctly
  3. Ensure PDF path is correct
  4. Check browser compatibility

Module not found errors

Make sure your bundler can handle ES modules and WASM files. For Webpack, you may need:

module.exports = {
  module: {
    rules: [
      {
        test: /\.wasm$/,
        type: 'asset/resource',
      },
    ],
  },
};

Performance issues

  1. Enable gzip/brotli compression on your server
  2. Use CDN for static assets
  3. Consider lazy loading for large PDFs
  4. Reduce initial zoom level for better initial render

🌍 Browser Support

  • Chrome 89+
  • Firefox 89+
  • Safari 15.2+
  • Edge 89+

Requires support for:

  • ES Modules
  • WebAssembly
  • SharedArrayBuffer
  • Web Workers

📄 License

MIT License - see LICENSE file for details

🙏 Acknowledgments

Built on top of EmbedPDF - an amazing open-source PDF viewer.

🤝 Contributing

Issues and pull requests are welcome! Please feel free to contribute to the GitHub repository.

📞 Support

If you encounter any issues or have questions:

  • Open an issue on GitHub Issues
  • Check existing issues for solutions
  • Review the documentation

Made with ❤️ by DBeidachazi