# officeParser reads and writes every office format through one AST

> officeParser is a strictly typed Node.js and browser library that parses docx, pptx, xlsx, odt, odp, ods, pdf, rtf, csv, markdown, html, epub and LaTeX into one abstract syntax tree, and generates DOCX, ODT, LaTeX, Markdown, HTML, CSV, RTF, PDF, EPUB, plain text and RAG chunks from it. It is MIT licensed, it wants Node 22.13 or newer, and the v8 line is a large rewrite rather than an incremental release.

**harshankur/officeParser** — A robust, strictly-typed Node.js and Browser library for parsing office files into a rich Abstract Syntax Tree (AST) and generating high-fidelity output in multiple formats.  Parses: docx · pptx · xlsx · odt · odp · ods · pdf · rtf · csv · md · html. Generates: Markdown · HTML · CSV · RTF · PDF · Plain Text · RAG Chunks

- Repository: https://github.com/harshankur/officeParser
- Website: http://officeparser.harshankur.com/
- Stars: 562 · Forks: 56
- Language: Rich Text Format
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/harshankur-officeparser

## One tree, and the formats that feed it

officeParser is a Node.js and browser library for parsing office files into an abstract syntax tree and generating high-fidelity output in multiple formats. The parsing side covers a lot of ground: docx, pptx and xlsx from the Office Open XML family, odt, odp, ods and odg from OpenDocument, then pdf, rtf, csv, markdown and html, and in v8 also epub and tex, with LaTeX understood as including Overleaf project zips.

The generation side is equally broad: DOCX, ODT, LaTeX, Markdown, HTML, CSV, RTF, PDF, EPUB, plain text and RAG chunks.

Having one tree in the middle is the point. A converter that goes from docx to markdown loses everything that markdown cannot express, and a converter written per format pair multiplies quickly. Here a document is parsed once into a structure, and each generator reads that structure, so the number of pairs stops being the cost.

The package is typed throughout, with a types entry point and separate browser and slim browser bundles in the exports map. The manifest declares sideEffects as false, so bundlers can tree shake it, and the engines field requires node >=22.13.0.

The project is MIT licensed, and the release line is active: v8.2.0 on 2026-10-20, v8.1.1 on 2026-10-05 and v8.1.0 on 2026-09-29, with the last push on the same day as the newest tag.

## The v8 PDF rewrite, which is the headline

The v8 release rebuilt PDF text extraction, and the documentation is specific about what that means.

PDF is no longer treated as a page of flat lines. Tagged PDFs now yield real heading nodes with correct levels, table, row and cell nodes, list nodes, footnote and endnote note nodes, and one paragraph node per paragraph. Untagged PDFs recover the same structure geometrically. Multi-column and float-beside-text pages are read in the correct order through a recursive XY-cut, broken and glued words are fixed from inter-fragment spacing, super and subscripts and hyphenated line breaks are rejoined, rotated text is recovered, and internal links resolve to the target section.

Two default behaviours are worth knowing before you rely on them. The to('text') output is now layout faithful by default, rendering each page as a spatial grid so columns and tables line up like the source, and per-run colour and highlight extraction is on by default, which you turn off with pdfParserConfig.extractTextColor set to false. Every node also carries page geometry in a bounds field.

For anyone who has fought a PDF text extractor, the list reads like a summary of the things that usually go wrong, and having them handled is the single biggest practical reason to look at this library.

## Encrypted files, and a native PDF engine

Two features in v8 change what you can hand the library.

The first is password-protected documents. Encrypted PDF, the OOXML formats and the ODF formats open through one unified password or onPassword option, applied across parsing, conversion and templating. One option for all of those is the right design, since a caller handling a document pipeline should not have to know which internal parser is behind each format.

The second is native generation. There is native DOCX and ODT generation, and a native PDF engine selected with pdfConfig.engine set to native, built on pdf-lib, which produces real PDF bytes with no headless browser, in Node and in the browser alike. That last part is the significant one. The usual way to make a PDF from a document in a Node service is to drive a headless browser, which means shipping Chromium, managing its memory and its sandbox, and accepting the latency. Producing PDF bytes directly removes an entire class of deployment problem.

There is also template and mail-merge support through OfficeTemplate.render, which fills a DOCX template's placeholders, handles conditional and loop constructs, can produce one table row per item, formats values with Word-style pictures, and works for a single document or a batch.

## LaTeX parses and generates, in both directions

The v8.1 release added LaTeX in both directions, and it is the feature that pushes the format list past office documents into the research and publishing world.

On the parsing side, .tex files and Overleaf project zips parse into the same AST as every other format, with sections, lists, tables including merged cells, figures, math, footnotes, citations, cross-references, user macros and beamer slides all represented. The consequence is that LaTeX converts to DOCX, ODT, HTML, Markdown and the rest through the same path as everything else.

On the generation side, to('tex') turns any parsed document into LaTeX source. The documentation states that the result compiles unmodified with pdfLaTeX, XeLaTeX, LuaLaTeX, upLaTeX, pLaTeX and latex, with the last three through dvipdfmx, and that presentations are included as beamer frames. Images are carried inside the one .tex file, or as separate files in a zip in bundle mode.

Compiling unmodified is the claim that matters, because a LaTeX generator that emits source needing fixes is not a converter. And the fact that a beamer presentation can be generated from the same tree that produced a DOCX means the tree models a document rather than a page.

## The API shape: parse, then ast.to()

The library surface is organised around a parse step and a generate step, and the documentation walks through the variants.

There is an async and await API and a callback API kept for backward compatibility, and the input can be a file buffer, an ArrayBuffer or a Blob, which is what makes the same code work in Node and in a browser. The central call is ast.to(), which generates output from the AST, and to('text') is the specific case for plain text extraction.

There is a one-step API called OfficeConverter, and a separate OfficeTemplate entry point for the mail-merge and document generation work described earlier.

The configuration surface is where the library is most demanding. There is an OfficeParserConfig, a shared GeneratorConfig, and then a per-generator configuration for HTML, Markdown, PDF, DOCX, ODT, LaTeX, CSV and plain text. On top of that there is an onNode callback for advanced node manipulation, a styleMap for semantic style mapping, metadataOverrides, an OfficeConverterConfig, and a ChunkingConfig for the RAG chunking path. The parser options the visualizer exposes are ignoreNotes, ocr and newlineDelimiter.

That is a large surface, and it is documented in detail, but it also means there is a lot to configure before the output is right. A RAG chunker needs its chunk size and overlap set, and a document generator needs its style mapping decided.

## RAG chunks and OCR scheduling

Two features are aimed squarely at retrieval pipelines rather than at document conversion.

The first is native RAG chunking, with its own ChunkingConfig, and it appears in the generation list as an output format alongside the document formats. Chunks derived from the same AST that produced the documents mean a chunker does not have to re-parse the source file, and the chunk boundaries follow the document's own structure rather than a fixed character count.

The second is OCR, with its own scheduler and resource management, referenced in the table of contents and with an ocr option in the parser config. Scanned documents need OCR, and OCR is the expensive part of a document pipeline, so the fact that it has a scheduler rather than being bolted on suggests it is meant to run within a budget.

There is also a live interactive AST visualizer and documentation, hosted on GitHub Pages, where you can upload any office file in your browser, inspect the hierarchical node tree with its metadata and raw content, tweak configuration options and preview generated output in real time. The visualizer exists to identify exactly how nodes are interpreted, which is the debugging task you would otherwise do by writing print statements.

The primary language of the repository is listed as Rich Text Format, which is a reflection of the format that is both parsed and generated rather than of the implementation language, which is TypeScript.

## Install, and what the project asks you to read before using it

Installation is one command:

```bash
npm i officeparser
```

The note beside it is a hard requirement: Node.js 22.13 or newer. The engines field in the manifest says the same, node >=22.13.0, so the floor is enforced by the package manager as well as documented.

The repository is more than a src directory. Alongside it there is a CHANGELOG that the v8 notes point to for the complete list including breaking changes, a SECURITY.md, a SUPPORT.md, a CODE_OF_CONDUCT.md, a CONTRIBUTING guide, a funding.json, a .husky directory, an eslint config, a tsconfig, a build_browser.js, a scripts directory, a test directory, a docs directory and a blog directory. The build script is itself a pipeline, running version syncing, site syncing, the TypeScript compile, an ESM wrapper generation, browser type bundling, the browser build and a blog build.

Two sections in the table of contents deserve a reader's attention before you rely on the library on untrusted input: Known Limitations and Security and Trust Boundary. A library that parses zip containers, executes macros-adjacent document structures, runs OCR and calls out to LaTeX toolchains is a parser of untrusted input, and the presence of a dedicated security section suggests the maintainers think about it that way.

The homepage is officeparser.harshankur.com, and the release cadence suggests an active project: three releases in the last three weeks of the visible history.

## Conclusion

Adopt officeParser if your pipeline has to read documents that arrive in whatever format a customer sends, or has to emit the same document as DOCX, PDF, Markdown and RAG chunks without maintaining a converter per format. Do not adopt it if you only handle one simple format, since the AST and the configuration surface are a lot of machinery for that, and read the Known Limitations and Security and Trust Boundary sections before you point it at untrusted files. Before you upgrade, check three things: the Node requirement, since the package declares node >=22.13.0, the changelog, because the v8 release rebuilt PDF extraction and the documentation points to it for breaking changes, and the PDF behaviour you depend on, since text output is now layout faithful by default and per-run colour extraction is on by default.

## FAQ

### Which file formats can officeParser read and write?

It parses docx, pptx, xlsx, odt, odp, ods, odg, pdf, rtf, csv, md, html, epub and tex, including Overleaf project zips, and generates DOCX, ODT, LaTeX, Markdown, HTML, CSV, RTF, PDF, EPUB, plain text and RAG chunks from the same AST.

### What Node.js version does officeParser need?

Node.js 22.13 or newer. The install notes state the requirement and the package manifest declares engines node >=22.13.0, so the floor is also enforced by the package manager.

### How does officeParser handle password-protected documents?

Encrypted PDF, the OOXML formats and the ODF formats open through one unified password or onPassword option, applied across parsing, conversion and templating.

### Can officeParser generate a PDF without a headless browser?

Yes. The native PDF engine is selected with pdfConfig.engine set to native, is built on pdf-lib, and produces real PDF bytes in Node and in the browser. The v8 release also added native DOCX and ODT generation.

### Does officeParser support LaTeX?

In both directions since v8.1. .tex files and Overleaf project zips parse into the same AST as other formats, and to('tex') generates source that compiles unmodified with pdfLaTeX, XeLaTeX, LuaLaTeX, upLaTeX, pLaTeX and latex, with presentations as beamer frames.

## Sources

- [harshankur/officeParser on GitHub](https://github.com/harshankur/officeParser)
- [License: MIT](https://github.com/harshankur/officeParser/blob/master/LICENSE)
- [Project website](http://officeparser.harshankur.com/)
- [README](https://github.com/harshankur/officeParser/blob/master/README.md)
- [Releases](https://github.com/harshankur/officeParser/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/harshankur-officeparser
