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

bare-x-to-pdf

v0.4.0

Published

Convert Word, PowerPoint, Excel and OpenDocument files to PDF for Bare: a Rust engine on Typst

Readme

bare-x-to-pdf

Convert office documents to PDF for Bare. A native addon with a Rust engine that lays pages out with Typst.

x is every format it reads into a PDF today:

| Family | Extensions | | ------------------------- | ---------------------------------- | | Word | .docx, .docm, .dotx, .dotm | | Word 97–2003 | .doc, .dot | | Excel | .xlsx, .xlsm, .xltx, .xltm | | Excel 97–2003 | .xls, .xlt | | PowerPoint | .pptx | | OpenDocument Text | .odt, .ott, .fodt | | OpenDocument Spreadsheet | .ods, .ots, .fods | | OpenDocument Presentation | .odp, .otp, .fodp | | Markdown | .md, .markdown |

The from name for each is the extension without its dot, and PDF is the only output. Markdown is CommonMark plus GitHub tables, task lists and strikethrough. Legacy PowerPoint (.ppt), .pptm, .potx, .ppsx, Rich Text and HTML are not read.

Install

npm install bare-x-to-pdf

The native prebuild is an optional dependency per platform (bare-x-to-pdf-<platform>-<arch>), so an install downloads only the package for its own platform, about 17 MB packed and 42 MB unpacked, plus the main package with the fonts and sources, about 4 MB packed. Prebuilds exist for android (arm, arm64, x64), darwin (arm64, x64), ios (arm64 and the arm64 and x64 simulators), linux (arm64, x64) and win32 (x64); other hosts build from a checkout with the Bare toolchain, CMake 4 and Rust.

To bundle for a different platform, ask npm for that prebuild as well:

npm install --os=android --cpu=arm64
npm install --os=ios --cpu=arm64

Usage

const converter = require('bare-x-to-pdf')

const pdf = await converter.convert(docxBytes, { to: 'pdf' })

Input is a Uint8Array or ArrayBuffer and the result is a Buffer. convert() runs on the libuv thread pool and does not block the JavaScript thread; convertSync() runs on the calling thread.

API

const pdf = await convert(input, options)

Convert input off the JavaScript thread and resolve with a Buffer. The input is copied, so it may be changed or transferred once the call returns. Invalid options and conversion errors reject the promise.

  • options.to — target format, 'pdf'. Required.
  • options.from — source format; sniffed from the bytes when omitted. Markdown has no signature to sniff, so pass from: 'md' for it. Markdown images load only from data: URIs, since the input is bytes with no directory to resolve relative paths against.
  • options.fontsDir — a directory of fonts to use instead of the bundled set.

const pdf = convertSync(input, options)

Convert input on the calling thread and return a Buffer. Takes the same options as convert().

detect(input)

Sniff the format from the bytes and return 'docx', 'pptx', 'xlsx', 'doc', 'xls', 'odt', 'ods', 'odp', 'fodt', 'fods', 'fodp' or null. Templates and macro-enabled files report their base format (a .dotx is 'docx', an .ots is 'ods'), which converts the same way. Markdown is plain text and always returns null.

supports(from, to)

Return whether the from → to conversion is supported.

conversions()

Return every supported pair as { from, to }.

FONTS_DIR

Path to the bundled fonts directory.

Limits

Documents are often untrusted, so the engine caps what a small file can make it allocate or lay out. A document past a hard limit is rejected with an error. One past a soft limit still converts, with the value clamped.

Rejected:

  • An archive part larger than 128 MB uncompressed.
  • XML nested more than 512 elements deep.
  • A spreadsheet that would print more than 30,000 cells.

Clamped:

  • Table spans: 1–1,000 columns.
  • Text columns: 1–64.
  • Pages: 72–14,400 pt on each side, with margins scaled to fit.
  • Lengths: NaN and infinity become 0; any other length is held within ±1,000,000 pt.
  • List counters: above 32,767, letter and Roman labels fall back to decimal.
  • Charts: up to 100,000 points per series (in .xls, 32,000 per series and 256,000 per chart).
  • Formulas: nesting depth up to 256.
  • Images: more than 50 megapixels, or ones that cannot be decoded, are drawn as blank space.
  • Tables nested more than 12 deep: the inner tables are flattened into paragraphs.

Spreadsheet pages with no content are not printed, as in LibreOffice Calc.

Development

The platform packages in npm/ are npm workspaces, and each declares its own os and cpu so that installs download only one. In a checkout, install with npm install --force so npm links all of them, then build the host prebuild with npm run prebuild and run npm test. The fidelity benchmark in bench/ has its own dependencies: cd bench && npm install.

Releases

.github/workflows/publish.yml runs when a v* tag is pushed. Tag the commit whose package.json has that version, after running npm run packages to bring the platform packages to it. The workflow builds every platform, publishes the platform packages and then the main package through npm trusted publishing, and creates a GitHub release. A tag newer than npm's current latest publishes as latest; an older one as release-<major>.<minor>.

License

Apache-2.0. Typst, pulldown-cmark and the other Rust dependencies are Apache-2.0 or MIT. Liberation, Carlito and Caladea are under the SIL Open Font License (see fonts/); OpenSymbol comes from LibreOffice.