files-to-markdown
v0.1.1
Published
Convert uploaded files (PDF, Word, Excel, HTML, CSV, images) to Markdown to cut LLM token usage. Node-native, no Python.
Maintainers
Readme
files-to-markdown
Convert uploaded files — PDF, Word, Excel, CSV, HTML, JSON, text, and images — into clean Markdown so you can feed text to an LLM instead of raw files. That cuts token usage dramatically (and lets you cache the markdown, e.g. in S3, so repeat turns never re-upload the file).
Node-native. No Python, no markitdown runtime, no extra service.
Install
npm install files-to-markdown
# Optional — only if you need .xlsx/.xls Excel support:
npm install xlsxExcel uses SheetJS (
xlsx), kept as an optional peer dependency because its npm build carries an unfixed advisory. Everything else (PDF, Word, CSV, HTML, JSON, text, images) works without it.
Usage
import { fileToMarkdown } from 'files-to-markdown';
// PDF / Word / Excel / CSV / HTML / JSON / text — auto-detected:
const { markdown, kind, truncated } = await fileToMarkdown({
buffer, // Buffer of the uploaded file
filename: 'report.pdf', // or pass mimeType
maxChars: 200_000, // optional safety cap
});Images need a vision function
The library is model-agnostic: images are turned into markdown by your OCR / vision call (Gemini, Claude, Tesseract — your choice). Without it, image inputs throw, so the token-free types still work on their own.
import { fileToMarkdown, VisionInput } from 'files-to-markdown';
async function geminiOcr({ buffer, mimeType }: VisionInput): Promise<string> {
// call your vision model, return markdown (e.g. transcribed text / a table)
return '# Invoice\n\n| Item | Qty | Price |\n| --- | --- | --- |\n| Pen | 2 | 20 |';
}
const { markdown } = await fileToMarkdown({
buffer,
mimeType: 'image/png',
vision: geminiOcr,
});Suggested flow (token-saving)
- On upload,
fileToMarkdown(...)→ markdown. - Store the markdown in S3 (keyed by file hash).
- On every chat turn, pass the markdown text to the model — never the raw file again.
API
function fileToMarkdown(input: ConvertInput): Promise<ConvertResult>;
function detectKind(input: { mimeType?: string; filename?: string }): ConvertKind;
interface ConvertInput {
buffer: Buffer;
filename?: string;
mimeType?: string;
vision?: (input: VisionInput) => Promise<string>; // images only
maxChars?: number;
}
interface ConvertResult {
markdown: string;
kind: 'pdf' | 'docx' | 'xlsx' | 'csv' | 'html' | 'image' | 'json' | 'text';
bytes: number;
truncated: boolean;
}License
MIT
