@bandf/babel
v1.2.1
Published
Document-to-markdown utility package. Turns PDF, images, EPUB, Office/OpenDocument files, structured data, HTML, plain text, markdown, and URLs into clean Markdown.
Downloads
492
Maintainers
Readme
@bandf/babel
Document-to-markdown converter for turning common document formats into clean Markdown.
@bandf/babel converts PDF, raster images, EPUB, Office/OpenDocument files,
structured data, HTML, plain text, Markdown, and http(s) URLs into normalized
Markdown plus source metadata. One function in, clean Markdown out.
Requires Node.js 24 or newer.
import { convert } from '@bandf/babel';
const result = await convert({ filePath: './paper.pdf' });
const markdown = result.markdown;
// → '# Title\n\nbody prose...\n\n## Section\n\n...'Library API
convert({ filePath, langs })— the main export. Document file → conversion result withmarkdown, source fields, MIME type, and conversion metadata. Used to bring foreign formats into Markdown.validate({ markdown })— takes a markdown string and returns cleaned, validated GFM with unsafe raw markup and unwanted text artifacts removed.convert()runs every result through it.createBabel(config)— builds a configured converter instance. Use this when you want instance-level defaults for deterministic conversion options.
import { convert, validate, createBabel } from '@bandf/babel';
const clean = await validate({ markdown: someUntrustedMarkdown });Markdown Contract
babel's output contract is clean GitHub Flavored Markdown with useful document structure preserved. Every conversion produces:
- ATX headings (
#,##…) — stable section boundaries for downstream consumers. - Pipe-format tables — kept together as one block, cells preserved.
- GFM structure — links, images, blockquotes, fenced code, and tables survive when the source format exposes them.
- Normalized prose — homoglyphs transliterated, smart punctuation and invisible characters stripped, no raw HTML tag residue.
A convert() call either returns a result whose markdown field is valid
markdown or throws. validate() returns valid markdown or throws.
API
Functions
| Function | Returns | Description |
|---|---|---|
| convert(options) (@bandf/babel) | Promise<BabelConversionResult> | Zero-config document → { markdown, sourceUri, sourceType, mimeType, extension, meta }. |
| createBabel(config) (@bandf/babel) | BabelInstance | Builds a configured instance with convert, validate, and supported-format lists. |
| validate({ markdown }) (@bandf/babel) | Promise<string> | Markdown string → cleaned + validated markdown. |
Constants
These are named JavaScript exports from @bandf/babel, not environment
variables or configuration settings:
| Exported constant | Type | Description |
|---|---|---|
| supportedExtensions | string[] | All recognized local-file extensions. |
| supportedImageExtensions | string[] | OCR-capable image extensions: .png, .gif, .jpg, .jpeg, .webp. |
import {
supportedExtensions,
supportedImageExtensions
} from '@bandf/babel';The original uppercase names remain as compatibility aliases for existing 1.x consumers, but new code should use the camelCase exports above.
convert(options)
filePath is required. Every other option is optional and may be supplied to
the top-level convert() function or to babel.convert() on a configured
instance.
| Option | Type | Default | Description |
|---|---|---|---|
| filePath | string | — | Local file path or an http:// / https:// URL. |
| transliterateHomoglyphs | boolean | true | Maps common Unicode homoglyphs to stable ASCII equivalents during cleanup. |
| langs | string \| string[] | ocr.langs, then ['eng'] | OCR language shorthand for PDF and image conversion. Strings may use + or ,, such as 'eng+fra'. Takes precedence over ocr.langs. |
| ocr.langs | string \| string[] | ['eng'] | Language codes used for PDF and image OCR. |
| ocr.tessdataPath | string | Bundled data directory | Optional directory override for OCR language files. Leave unset for English; eng.traineddata ships with the package and is used automatically. Set this only when supplying other <lang>.traineddata files. |
| url.timeoutMs | number | 30000 | Positive URL-fetch timeout in milliseconds. |
| url.maxBytes | number | 26214400 (25 MiB) | Positive maximum response-body size for URL conversion. |
| url.maxRedirects | number | 2 | Positive maximum number of redirects followed during URL conversion. |
| url.lookup | BabelUrlLookup | System DNS lookup | Advanced async DNS resolver override used when checking remote addresses. |
The ocr options apply only to PDFs and raster images. The url options apply
only when filePath is an HTTP(S) URL. Per-call options override defaults from
createBabel().
The UI's --max-upload-size flag does not apply to this API. Local paths have
no general configurable file-size limit, although available memory, underlying
runtime constraints, and format-specific safety checks still apply. URL response
size is controlled separately with url.maxBytes.
const result = await convert({
filePath: 'https://example.com/article',
url: {
timeoutMs: 15_000,
maxBytes: 50 * 1024 * 1024,
maxRedirects: 2
}
});validate(options)
| Option | Type | Default | Description |
|---|---|---|---|
| markdown | string | — | Required Markdown string to clean and validate. |
| sourceUri | string | '(string)' | Source label included in validation error messages. |
| transliterateHomoglyphs | boolean | true | Enables or disables homoglyph transliteration. |
Supported formats
| Format | Conversion behavior |
|---|---|
| .txt / .text | UTF-8 text cleanup, then markdown-normalized + validated |
| .md / .markdown | read as markdown, then markdown-normalized + validated |
| .html / .htm | Main article content, structure, and links → GFM markdown |
| .docx | Headings, paragraphs, lists, links, and tables → GFM markdown |
| .csv / .tsv | Rows and columns → GFM table |
| .json | JSON parse/validate → fenced json block |
| .yaml / .yml | YAML parse/validate → fenced yaml block |
| .xml | XML parse/validate → fenced xml block |
| .xlsx | Visible cell values → one GFM table per worksheet |
| .ods | Visible cell values → one GFM table per sheet |
| .pptx | Slide text, speaker notes, and image alt text → markdown |
| .odt | Headings, paragraphs, lists, and tables → GFM markdown |
| .rtf | Text and basic document structure → markdown |
| .pdf | Embedded text extraction with OCR when needed |
| .png / .gif / .jpg / .jpeg / .webp | Image OCR → markdown |
| .epub | EPUB 2/3 chapters in reading order → GFM markdown |
| http(s) URL | Safety-checked conversion of HTML, Markdown, plain text, or JSON |
Spreadsheet conversion extracts visible values only. It does not evaluate formulas, render charts, or OCR images embedded inside Office/OpenDocument containers. PPTX conversion extracts slide text, speaker notes, and image alt text; embedded media stays out of scope unless it is already exposed as text.
URL conversion blocks common private/internal targets, checks resolved addresses before fetching, rechecks every redirect, and enforces redirect and response-size limits. Hosted multi-tenant deployments should still isolate network access when accepting user-provided URLs.
All listed formats work after a normal npm install; no format-specific packages
need to be installed separately. English OCR requires no configuration:
eng.traineddata ships with the package and is used automatically. For other
OCR languages, set ocr.tessdataPath to a directory containing each requested
<lang>.traineddata file:
const { markdown, meta } = await convert({
filePath: './scan.pdf',
ocr: {
langs: ['fra'],
tessdataPath: './ocr-data'
}
});Configured instances
Use createBabel(config) when you want an instance with shared conversion
defaults:
| Config option | Type | Default | Description |
|---|---|---|---|
| transliterateHomoglyphs | boolean | true | Default for calls to babel.convert(). |
| ocr | BabelOcrConfig | { langs: ['eng'] } | Shared langs and tessdataPath defaults for PDF/image OCR. |
| url | BabelUrlConfig | See convert() defaults | Shared timeoutMs, maxBytes, maxRedirects, and lookup defaults for URL conversion. |
import { createBabel } from '@bandf/babel';
const babel = createBabel({
transliterateHomoglyphs: false,
ocr: {
langs: ['eng'],
tessdataPath: './tessdata'
},
url: {
timeoutMs: 15_000,
maxBytes: 50 * 1024 * 1024,
maxRedirects: 2
}
});
const result = await babel.convert({ filePath: './paper.pdf' });
console.log(result.markdown, result.meta);Options passed to babel.convert() override these instance defaults.
babel.validate() takes the standalone validate() options shown above and
does not inherit conversion defaults from createBabel().
Browser UI
Launch the local document-testing UI directly from the npm package:
npx @bandf/babel [options]The server opens the UI in your default browser automatically. Upload a document and inspect the raw Markdown next to the rendered preview. Stop the server with Ctrl+C.
| Flag | Default | Description |
|---|---|---|
| --port <number> | 0 | Listening port from 0 to 65535. Port 0 asks the operating system for an available port. |
| --max-upload-size <size> | 1.5gb | Maximum HTTP upload body. Accepts bytes or kb, kib, mb, mib, gb, and gib, including decimal values such as 1.5gb. |
| --max-upload-bytes <size> | 1.5gb | Alias for --max-upload-size; raw byte counts are accepted. |
| --no-open | — | Start the server without opening a browser. |
| --open | Enabled | Explicitly enable automatic browser opening. |
Value flags accept either --flag=value or --flag value. Options may be
combined:
npx @bandf/babel --port=3187 --max-upload-size=2gb --no-openThe server always binds to 127.0.0.1 and prints the resulting URL. It is only
intended for local use. The upload-size flags control the UI's HTTP request body;
they do not limit files passed directly to the public convert() API.
License
AGPL-3.0-or-later. See LICENSE.
