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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@soulehshaikh99/ghostscript-wasm

v0.1.0

Published

Ghostscript (pdfwrite) compiled to WASM

Readme

@soulehshaikh99/ghostscript-wasm · NPM Version License: AGPL-3.0

Ghostscript 10.08.0 compiled to WebAssembly, built with only the pdfwrite device. Runs in the browser, in Web Workers and in Node.js.

Made for PDF to PDF/A conversion (PDF/A-1b, 2b, 3b) entirely client side, but any pdfwrite job works (rewrite, downsample, convert colors, ...).

What's inside

| Component | Version | | --- | --- | | Ghostscript | 10.08.0 (release tarball, SHA-256 pinned in Dockerfile) | | Emscripten (emsdk) | 6.0.13 | | Bundled libs | zlib, libpng, libjpeg, lcms2mt, FreeType, OpenJPEG, jbig2dec (from the Ghostscript tarball) | | Devices | pdfwrite only | | Fonts | URW base35 (the standard 35 PostScript fonts) | | ICC profiles | Ghostscript's iccprofiles/ (incl. srgb.icc) |

Fonts, init files, CMaps and ICC profiles are compiled into the binary's %rom% filesystem, so no extra files are fetched at runtime. The CJK fallback font (DroidSansFallback.ttf) is left out to save 3.9 MB: PDFs that use non-embedded CJK fonts may render with substitutes.

Size: gs.wasm is about 16 MB (about 9 MB gzipped).

Installation

npm install @soulehshaikh99/ghostscript-wasm

Quick start (Node.js)

const createGs = require("@soulehshaikh99/ghostscript-wasm");
const fs = require("fs");

const gs = await createGs({ print: console.log, printErr: console.error });
gs.FS.writeFile("/in.pdf", fs.readFileSync("in.pdf"));
const code = gs.callMain([
  "-dSAFER", "-dBATCH", "-dNOPAUSE", "-sDEVICE=pdfwrite",
  "-sOutputFile=/out.pdf", "/in.pdf",
]);
if (code === 0) fs.writeFileSync("out.pdf", gs.FS.readFile("/out.pdf"));

callMain returns gs's exit code (it never calls process.exit) and can be called again on the same instance.

PDF/A

PDF/A needs an OutputIntent. Write a definition file that points at the sRGB profile in %rom%, and pass it before the input:

/ICCProfile (%rom%iccprofiles/srgb.icc) def
[/_objdef {icc_PDFA} /type /stream /OBJ pdfmark
[{icc_PDFA} << /N 3 >> /PUT pdfmark
[{icc_PDFA} ICCProfile (r) file /PUT pdfmark
[/_objdef {OutputIntent_PDFA} /type /dict /OBJ pdfmark
[{OutputIntent_PDFA} <<
  /Type /OutputIntent /S /GTS_PDFA1
  /DestOutputProfile {icc_PDFA}
  /OutputConditionIdentifier (sRGB IEC61966-2.1)
  /Info (sRGB IEC61966-2.1)
  /RegistryName (http://www.color.org)
>> /PUT pdfmark
[{Catalog} << /OutputIntents [ {OutputIntent_PDFA} ] >> /PUT pdfmark
gs.FS.writeFile("/PDFA_def.ps", pdfaDef);
gs.callMain([
  "-dSAFER", "-dBATCH", "-dNOPAUSE", "-sDEVICE=pdfwrite",
  "-dPDFA=2",                      // 1, 2 or 3
  "-dPDFACompatibilityPolicy=1",   // drop what PDF/A forbids, keep the file compliant
  "-sColorConversionStrategy=RGB",
  "-sOutputFile=/out.pdf", "/PDFA_def.ps", "/in.pdf",
]);

Patched for PDF/A (patches/pdfa-actions.patch): with -dPDFA, actions PDF/A forbids (JavaScript, Launch, Sound, Movie, ResetForm, ImportData, Hide, SetOCGState, Rendition, Trans, GoTo3DView, ...) are removed from the document, links and outlines, with a **** Warning: <type> action not permitted in PDF/A, removed. line each; annotations lose their additional actions (/AA). Upstream gs copies these through and the output fails PDF/A validation.

PDFACompatibilityPolicy: 0 keeps forbidden features (output claims PDF/A but is not compliant), 1 drops them with a warning each, 2 aborts. Ghostscript produces conformance level b only.

Browser / Web Worker

import createGs from "@soulehshaikh99/ghostscript-wasm";
import wasmUrl from "@soulehshaikh99/ghostscript-wasm/dist/gs.wasm?url"; // Vite

const gs = await createGs({ locateFile: () => wasmUrl, print, printErr });

Run it in a Web Worker: a conversion blocks the thread it runs on. Large inputs can be mounted with WORKERFS instead of copied into memory.

Options

createGs(options) accepts locateFile, print, printErr, thisProgram (default gs), preRun, wasmBinary and instantiateWasm. The instance exposes callMain, FS, NODEFS, WORKERFS and ENV. Types: dist/gs.d.ts.

Building from source

Requires Docker.

docker build -t soulehshaikh99/ghostscript-wasm .
docker compose up   # copies dist/ out of the image, runs npm ci && npm test

Or copy dist out by hand: docker create the image, then docker cp <id>:/opt/gs/. dist.

To update Ghostscript, change GS_VERSION, GS_TAG and GS_SHA256 in the Dockerfile. build.sh configures gs for Emscripten (native gcc builds the aux tools), applies patches/*.patch and links bin/gs.js + bin/gs.wasm.

License

Ghostscript is © Artifex Software, Inc. and licensed under the GNU AGPL v3 (see also LICENSE-ghostscript). This package, its build scripts and JS glue are distributed under the same license. If you ship it in a network service, you must offer the corresponding source. A commercial license is available from Artifex.