{"_id":"@fastgpt-sdk/anydoc","name":"@fastgpt-sdk/anydoc","dist-tags":{"latest":"0.2.5"},"versions":{"0.2.5":{"name":"@fastgpt-sdk/anydoc","version":"0.2.5","description":"Convert documents (doc, docx, odt, rtf, epub, pdf, presentations, spreadsheets, csv) to GitHub-Flavored Markdown","license":"MIT","homepage":"https://github.com/c121914yu/anydoc#readme","repository":{"type":"git","url":"git+https://github.com/c121914yu/anydoc.git","directory":"node"},"bugs":{"url":"https://github.com/c121914yu/anydoc/issues"},"keywords":["markdown","docx","pdf","pptx","xlsx","epub","converter","document"],"main":"anydoc.js","types":"anydoc.d.ts","bin":{"anydoc":"cli.js"},"engines":{"node":">= 20"},"napi":{"binaryName":"anydoc","packageName":"@fastgpt-sdk/anydoc","dtsHeaderFile":"dts-header.d.ts","targets":["x86_64-apple-darwin","aarch64-apple-darwin","x86_64-unknown-linux-gnu","aarch64-unknown-linux-gnu","x86_64-unknown-linux-musl","aarch64-unknown-linux-musl","x86_64-pc-windows-msvc"]},"scripts":{"artifacts":"napi artifacts","build":"napi build --platform --release","build:debug":"napi build --platform","prepublishOnly":"napi prepublish -t npm --no-gh-release","test":"node --test","version":"napi version"},"devDependencies":{"@napi-rs/cli":"^3.8.2"},"optionalDependencies":{"@fastgpt-sdk/anydoc-darwin-x64":"0.2.5","@fastgpt-sdk/anydoc-darwin-arm64":"0.2.5","@fastgpt-sdk/anydoc-linux-x64-gnu":"0.2.5","@fastgpt-sdk/anydoc-linux-arm64-gnu":"0.2.5","@fastgpt-sdk/anydoc-linux-x64-musl":"0.2.5","@fastgpt-sdk/anydoc-linux-arm64-musl":"0.2.5","@fastgpt-sdk/anydoc-win32-x64-msvc":"0.2.5"},"gitHead":"434b5648f4c0e0d54790f4cd62c805221574d52d","_id":"@fastgpt-sdk/anydoc@0.2.5","_nodeVersion":"25.2.1","_npmVersion":"11.6.2","dist":{"integrity":"sha512-veXj6Jv0NgsAVE2QTxdb1hM99PExildb1ZyzxfEoamLGXGUZSM6cG1E50jCOKT04Ch8YGsIBBX9Mv5yVv3ZMWA==","shasum":"26474dd5ddf427d946e6cf248925636577d3ab47","tarball":"https://registry.npmjs.org/@fastgpt-sdk/anydoc/-/anydoc-0.2.5.tgz","fileCount":7,"unpackedSize":60965,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIADl2AAf5DwXX5fgw93QnL3+ISWGt/OKPI8I0jv9RqxqAiEAhu+n2EEoQiwnQD0UxTFYWJSbePUEL9yWt+BKou3mDAc="}]},"_npmUser":{"name":"archer-jinlong","email":"c121914yjl@gmail.com"},"directories":{},"maintainers":[{"name":"dighuang","email":"dighuang27@gmail.com"},{"name":"whoeverimf5","email":"whoeverimf5@gmail.com"},{"name":"archer-jinlong","email":"c121914yjl@gmail.com"},{"name":"finley_ge","email":"atlasgj@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/anydoc_0.2.5_1788066112900_0.1438394656589983"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-30T05:01:52.731Z","0.2.5":"2026-08-30T05:01:53.080Z","modified":"2026-08-30T05:01:53.322Z"},"maintainers":[{"name":"dighuang","email":"dighuang27@gmail.com"},{"name":"whoeverimf5","email":"whoeverimf5@gmail.com"},{"name":"archer-jinlong","email":"c121914yjl@gmail.com"},{"name":"finley_ge","email":"atlasgj@gmail.com"}],"description":"Convert documents (doc, docx, odt, rtf, epub, pdf, presentations, spreadsheets, csv) to GitHub-Flavored Markdown","homepage":"https://github.com/c121914yu/anydoc#readme","keywords":["markdown","docx","pdf","pptx","xlsx","epub","converter","document"],"repository":{"type":"git","url":"git+https://github.com/c121914yu/anydoc.git","directory":"node"},"bugs":{"url":"https://github.com/c121914yu/anydoc/issues"},"license":"MIT","readme":"# @fastgpt-sdk/anydoc\n\n[![npm](https://img.shields.io/npm/v/@fastgpt-sdk/anydoc.svg)](https://www.npmjs.com/package/@fastgpt-sdk/anydoc)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/firecrawl/anydoc/blob/main/LICENSE)\n\nConvert Word, PowerPoint, Excel, OpenDocument, RTF, EPUB, CSV, and PDF files into clean GitHub-Flavored Markdown. Node.js bindings for the [anydoc](https://github.com/firecrawl/anydoc) Rust crate, built by [Firecrawl](https://firecrawl.dev). Also available as a hosted API through [Firecrawl Parse](https://firecrawl.dev/parse), which adds our OCR models for the scanned pages anydoc can't read on its own.\n\nEvery format parses into one shared document model and renders through a single Markdown serializer, so headings, tables, lists, and footnotes come out the same no matter which format goes in. Conversion runs on the libuv thread pool and never blocks the event loop. TypeScript types ship with the package.\n\n```bash\nnpm install @fastgpt-sdk/anydoc\n```\n\n## Supported formats\n\n| Format           | Extensions                                                 |\n| ---------------- | ---------------------------------------------------------- |\n| Word             | `.doc`, `.docx`, `.docm`                                   |\n| PowerPoint       | `.ppt`, `.pps`, `.pot`, `.pptx`, `.pptm`, `.ppsx`, `.ppsm` |\n| Excel            | `.xls`, `.xlsx`, `.xlsm`, `.xlsb`                          |\n| OpenDocument     | `.odt`, `.ods`, `.odp`                                     |\n| Rich Text Format | `.rtf`                                                     |\n| EPUB             | `.epub`                                                    |\n| CSV              | `.csv`                                                     |\n| PDF              | `.pdf`                                                     |\n\n## CLI\n\nThe package ships an `anydoc` command, so `npx` converts a document with no install:\n\n```bash\nnpx @fastgpt-sdk/anydoc report.docx               # Markdown to stdout\nnpx @fastgpt-sdk/anydoc slides.pptx -o slides.md  # or to a file\nnpx @fastgpt-sdk/anydoc - --format csv < data.csv # read stdin\nnpx @fastgpt-sdk/anydoc scan.pdf --ocr hosted     # scanned pages via Firecrawl Parse\n```\n\nMarkdown goes to stdout, errors to stderr, and `anydoc --help` covers the rest.\n\n## Usage\n\n```js\nimport { toDocument, toMarkdown, toMarkdownBytes } from '@fastgpt-sdk/anydoc';\n\n// From a file path:\nconst markdown = await toMarkdown('report.docx');\n\n// From bytes, with the format detected from the content:\nconst fromBytes = await toMarkdownBytes(bytes);\n\n// Or name it, which signature-less formats (CSV) need:\nconst fromCsv = await toMarkdownBytes(bytes, 'csv');\n\n// Preserve embedded images and their positions in the Markdown:\nconst { markdown, assets } = await toMarkdownBytes(bytes, 'doc', {\n  embeddedImageMode: 'reference',\n  maxImageBytes: 32 * 1024 * 1024,\n  maxImageTotalBytes: 128 * 1024 * 1024,\n});\n// markdown contains ![alt](asset:0); assets contains { id: 0, mediaType, data, ... }.\n\n// Or stop at the document model, which also carries embedded assets:\nconst document = await toDocument(bytes);\n```\n\n## Scanned pages\n\nanydoc converts locally and does not do OCR, so a PDF with scanned or image-only pages rejects with `needsOcr`. Opt in with `ocr: 'hosted'` to send that document to [Firecrawl Parse](https://firecrawl.dev/parse). No signup needed. Set `apiKey` or `FIRECRAWL_API_KEY` for higher limits.\n\n```js\nconst markdown = await toMarkdown('scan.pdf', { ocr: 'hosted' });\n```\n\nOn the CLI, `anydoc scan.pdf --ocr hosted`.\n\n## Errors\n\nA conversion rejects only when no complete Markdown could come out of the file. The rejection is an `Error` whose `code` names what went wrong:\n\n```js\ntry {\n  return await toMarkdown(path);\n} catch (error) {\n  // No document comes out of these, so record the file and take the next one.\n  if (error.code === 'encrypted' || error.code === 'unsupported') {\n    unconverted.push({ path, reason: error.code });\n    return null;\n  }\n  throw error;\n}\n```\n\n| `code`          | Meaning                                                             |\n| --------------- | ------------------------------------------------------------------- |\n| `unsupported`   | Unknown format, or one that cannot be converted                     |\n| `needsOcr`      | Scanned or image-only pages of a PDF, listed in `pages`             |\n| `malformed`     | Structurally unusable: no meaningful content could be extracted     |\n| `encrypted`     | Encrypted or password-protected                                     |\n| `resourceLimit` | Crossed a fixed safety limit (decompression, nesting, node count)   |\n| `missingPart`   | A part required for any meaningful output is absent                 |\n| `io`            | The file could not be read, from `toMarkdown` only                  |\n| `hosted`        | `ocr: 'hosted'` could not get the document through Firecrawl Parse  |\n\n`error.message` carries the detail, naming the package part at fault where the format identifies one. TypeScript gets the union as `ConvertErrorCode`.\n\n## Format detection\n\nThe format is read from the file content, using the marker its specification designates: the PDF header, the RTF open group, OLE stream names, the ZIP package mimetype and content types. CSV has no such marker, so detection returns `null` for it and the extension, or an explicit format, names it instead.\n\n```js\nformatFromBytes(bytes); // 'docx', or null when nothing matches\nformatFromExtension('.pptm'); // 'pptx'\nformatFromPath('report.odt'); // 'odt'\n```\n\n## Images and embedded objects\n\nBy default, an embedded image renders as its alt text while the bytes stay on `document.assets`. Pass `embeddedImageMode: 'reference'` to `toMarkdown` or `toMarkdownBytes` to receive `{ markdown, assets }`: the Markdown contains `asset:<id>` image URLs and `assets` contains the corresponding `image/*` bytes. `maxImageBytes` and `maxImageTotalBytes` cap one image and all images respectively; both default to 128 MiB and reject with `resourceLimit` when crossed. Non-image embedded objects keep the default alt-text behavior. Images that carry an external URL always render as ordinary Markdown images.\n\nFull behavior notes and benchmarks live in the [repository README](https://github.com/firecrawl/anydoc#readme).\n\n## License\n\n[MIT](https://github.com/firecrawl/anydoc/blob/main/LICENSE)\n","readmeFilename":"README.md","_rev":"1-783d7af8e1ab2fd456c66bb2da63eacc"}