iammuttaqi/laravel-anydoc

Convert Word, PowerPoint, Excel, OpenDocument, RTF, EPUB, CSV, and PDF documents to clean GitHub-Flavored Markdown in Laravel, powered by Firecrawl anydoc.

Maintainers

Package info

github.com/iammuttaqi/laravel-anydoc

pkg:composer/iammuttaqi/laravel-anydoc

Transparency log

Statistics

Installs: 5

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.2 2026-08-05 20:49 UTC

This package is auto-updated.

Last update: 2026-08-05 20:49:55 UTC


README

Packagist Version Packagist Downloads License Tests Quality

Convert Word, PowerPoint, Excel, OpenDocument, RTF, EPUB, CSV, and PDF documents to clean GitHub-Flavored Markdown in Laravel — powered by Firecrawl anydoc, the Rust library that converts office documents to LLM-ready Markdown in single-digit milliseconds.

There is no PHP binding for anydoc, so this package drives its CLI through Symfony Process. The CLI ships as the npm package @firecrawl/anydoc; npx downloads the prebuilt binary on first use and caches it, so there is nothing else to install beyond Node.js.

Requirements

  • PHP 8.1+
  • Laravel 10, 11, 12 or 13
  • Node.js 20+ (with npx on PATH)

Installation

composer require iammuttaqi/laravel-anydoc

Optionally publish the config file:

php artisan vendor:publish --tag=anydoc-config

For a permanent install of the CLI (instead of going through npx on every call), run:

php artisan anydoc:install

Usage

use Muttaqi\Anydoc\Facades\Anydoc;
use Muttaqi\Anydoc\Support\Format;

// From a file path:
$markdown = Anydoc::toMarkdown('/path/to/report.docx');

// From an uploaded file:
$markdown = Anydoc::toMarkdown($request->file('document'));

// From bytes, with the format detected from the content:
$markdown = Anydoc::toMarkdownBytes($bytes);

// Or name it, which signature-less formats (CSV) need:
$markdown = Anydoc::toMarkdownBytes($bytes, Format::Csv);

// Format detection:
Anydoc::formatFromPath('report.odt');      // Format::Odt
Anydoc::formatFromExtension('.pptm');      // Format::Pptx
Anydoc::formatFromBytes($bytes);           // Format::Docx, or null

Or via dependency injection:

use Muttaqi\Anydoc\Anydoc;

class DocumentController
{
    public function show(Anydoc $anydoc, string $id)
    {
        return $anydoc->toMarkdown('/path/to/'.$id.'.pptx');
    }
}

Supported formats

Format Extensions
Word .doc, .docx, .docm
PowerPoint .ppt, .pps, .pot, .pptx, .pptm, .ppsx, .ppsm
Excel .xls, .xlsx, .xlsm, .xlsb
OpenDocument .odt, .ods, .odp
Rich Text .rtf
EPUB .epub
CSV .csv
PDF .pdf

The format is detected from the file content, not the extension, so mislabeled files still convert correctly. CSV has no content marker — pass it explicitly (or rely on the file extension).

Artisan commands

# Convert a single document
php artisan anydoc:convert report.docx
php artisan anydoc:convert slides.pptx --output=slides.md
php artisan anydoc:convert data.csv --format=csv --output=data.md

# Install the anydoc CLI globally
php artisan anydoc:install

Errors

A conversion only fails when no meaningful Markdown could come out of the file. Each failure is thrown as a typed exception, mirroring anydoc's own error variants:

Exception Meaning
UnsupportedException Unknown format, or one that cannot be converted (an image-only PDF)
MalformedException Structurally unusable document
EncryptedException Encrypted or password-protected
ResourceLimitException Crossed a fixed safety limit
MissingPartException A part required for meaningful output is absent
InvalidUsageException The CLI was invoked with bad arguments (should not happen)
ConversionException Any other conversion failure
BinaryNotFoundException Node/npx/the anydoc binary is not installed
AnydocException Base class for all of the above
use Muttaqi\Anydoc\Exceptions\AnydocException;
use Muttaqi\Anydoc\Exceptions\EncryptedException;
use Muttaqi\Anydoc\Exceptions\UnsupportedException;

try {
    $markdown = Anydoc::toMarkdown($file);
} catch (EncryptedException|UnsupportedException $e) {
    // No document comes out of these — record the file and move on.
    report($e);
}

Configuration

Publish the config and adjust config/anydoc.php:

Variable Default Description
ANYDOC_USE_NPX true Use npx -y @firecrawl/anydoc instead of a fixed binary
ANYDOC_BINARY anydoc Binary to call when ANYDOC_USE_NPX=false
ANYDOC_NPX_PACKAGE @firecrawl/anydoc npm package providing the CLI
ANYDOC_TIMEOUT 60 Max seconds per conversion (seconds)
ANYDOC_TEMP_DIR sys_get_temp_dir() Where temporary input files are written

Windows

Symfony Process resolves npx through the shell-less PATH lookup, which can miss npx.cmd. If that happens, install the CLI and point the package at the full path:

npm install -g @firecrawl/anydoc
ANYDOC_USE_NPX=false
ANYDOC_BINARY=C:\path\to\npx.cmd

Notes

  • Embedded images render as their alt text (Markdown cannot embed bytes); the raw bytes stay available on anydoc's document model, which the CLI does not expose.
  • Scanned/image-only PDFs need OCR, which anydoc does not do — they fail as UnsupportedException. Firecrawl's hosted Parse API handles those (see firecrawl/firecrawl-sdk).
  • Conversions are synchronous and spawn a short-lived process. For batch pipelines, queue the work.

Testing

composer test

Unit tests always run. Integration tests convert real documents and auto-skip when the anydoc CLI is unavailable.

License

MIT