Skip to content

Repository files navigation

docling-node-ts

Zero-dependency document-to-markdown conversion for Node.js.

npm versionnpm downloadslicensenode

Convert HTML, plain text, and markdown documents into clean, structure-preserving markdown suitable for RAG (Retrieval-Augmented Generation) pipelines, knowledge base construction, and LLM ingestion. Accepts string or Buffer input, auto-detects the format, routes to the appropriate converter, extracts metadata and image references, and returns a typed ConversionResult. No external services, no Python runtime, no network calls -- everything runs locally in Node.js.


Installation

npm install docling-node-ts

Requires Node.js 18 or later.

Quick Start

import{convert}from'docling-node-ts';// Convert HTML to markdownconstresult=convert('<h1>Quarterly Report</h1><p>Revenue grew <strong>15%</strong> year-over-year.</p>');console.log(result.markdown);// # Quarterly Report//// Revenue grew **15%** year-over-year.console.log(result.metadata);// { wordCount: 5, headingCount: 1, imageCount: 0, readingTimeMinutes: 1 }console.log(result.durationMs);// 2
// Convert a Buffer with auto-detectionimport{readFileSync}from'fs';constbuf=readFileSync('report.html');const{ markdown, metadata, images, warnings }=convert(buf);

Features

  • HTML to Markdown -- Converts headings (h1-h6), paragraphs, bold, italic, strikethrough, inline code, links, images, ordered and unordered lists (including nested), GFM pipe tables, fenced code blocks with language hints, blockquotes, horizontal rules, <figure>/<figcaption>, and <sup>/<sub> elements.
  • Plain Text to Markdown -- Detects setext-style headings (underlined with === or ---), ALL CAPS headings, unordered and ordered lists, and paragraph breaks. Normalizes list markers and line endings.
  • Markdown Normalization -- Cleans and normalizes existing markdown: collapses excessive blank lines, standardizes list markers to -, normalizes heading levels to eliminate gaps, fixes broken links with empty hrefs, and ensures consistent spacing around headings.
  • Format Auto-Detection -- Detects the input format automatically using file extension, magic bytes (for Buffer inputs), and content analysis (HTML tags, markdown patterns). Supports explicit format override via options.
  • Metadata Extraction -- Returns word count, heading count, image count, and estimated reading time. For HTML inputs, extracts title, author, and date from <title>, <meta>, and Open Graph tags.
  • Image Reference Extraction -- Collects all image references from HTML with their id, alt text, and src path. Can be disabled with extractImages: false.
  • Binary Format Guidance -- Detects PDF, DOCX, and PPTX inputs (via magic bytes or extension) and returns informative messages with suggested packages (pdfjs-dist, mammoth, jszip) and code examples. No binary parsers are bundled to keep the dependency tree at zero.
  • HTML Sanitization -- Strips <script>, <style>, <noscript>, <iframe>, <svg>, <canvas>, <nav>, <footer>, <header>, and <aside> elements. Decodes HTML entities including numeric and hex character references.
  • Zero Dependencies -- No runtime dependencies. Only devDependencies for building and testing.

API Reference

convert(input, options?)

The primary conversion function. Accepts a string or Buffer, auto-detects the format (or uses the explicit format from options), converts to markdown, and returns a ConversionResult.

functionconvert(input: string|Buffer,options?: ConvertOptions): ConversionResult;

Parameters:

ParameterTypeDescription
inputstring | BufferThe document content to convert
optionsConvertOptionsOptional conversion settings

Returns:ConversionResult

import{convert}from'docling-node-ts';constresult=convert('<table><thead><tr><th>Name</th><th>Age</th></tr></thead><tbody><tr><td>Alice</td><td>30</td></tr></tbody></table>');console.log(result.markdown);// | Name | Age |// | --- | --- |// | Alice | 30 |

convertHtml(html)

Convenience function that converts HTML to markdown. Equivalent to calling convert(html, { format: 'html' }).

functionconvertHtml(html: string): ConversionResult;
import{convertHtml}from'docling-node-ts';const{ markdown }=convertHtml('<ul><li>First</li><li>Second</li></ul>');// - First// - Second

convertMarkdown(md)

Cleans and normalizes existing markdown. Standardizes list markers, normalizes heading levels, collapses blank lines, removes broken links, and ensures consistent formatting. Equivalent to calling convert(md, { format: 'markdown' }).

functionconvertMarkdown(md: string): ConversionResult;
import{convertMarkdown}from'docling-node-ts';const{ markdown }=convertMarkdown('# Title\n\n\n\n\n#### Skipped Level\n\n* Item');// # Title//// ## Skipped Level//// - Item

convertText(text)

Converts plain text to markdown. Detects headings, lists, and paragraph structure. Equivalent to calling convert(text, { format: 'text' }).

functionconvertText(text: string): ConversionResult;
import{convertText}from'docling-node-ts';const{ markdown }=convertText('INTRODUCTION\n\nSome body text.\n\n1) First step\n2) Second step');// ## INTRODUCTION//// Some body text.//// 1. First step// 2. Second step

detectFormat(input, fileName?)

Detects the format of a document from its content or file name.

Detection priority:

  1. File extension from fileName (.pdf, .docx, .pptx, .html, .htm, .xhtml, .txt, .md, .markdown)
  2. Magic bytes for Buffer inputs (%PDF for PDF, PK\x03\x04 for ZIP-based Office formats)
  3. Content analysis (HTML tags, markdown patterns)
  4. Default: 'text'
functiondetectFormat(input: string|Buffer,fileName?: string): InputFormat;
import{detectFormat}from'docling-node-ts';detectFormat('','report.pdf');// 'pdf'detectFormat('<html><body>Hi</body></html>');// 'html'detectFormat('# Title\n\n## Section');// 'markdown'detectFormat('Just plain text.');// 'text'constpdfBuffer=Buffer.from('%PDF-1.4 ...');detectFormat(pdfBuffer);// 'pdf'

extractMetadata(markdown)

Extracts metadata from a markdown string. Computes word count, heading count, image count, and estimated reading time.

functionextractMetadata(markdown: string): Pick<DocumentMetadata,'wordCount'|'headingCount'|'imageCount'|'readingTimeMinutes'>;
import{extractMetadata}from'docling-node-ts';constmeta=extractMetadata('# Title\n\nSome **bold** text with ![img](photo.png).\n');// { wordCount: 4, headingCount: 1, imageCount: 1, readingTimeMinutes: 1 }

Word counting strips markdown syntax (headings, bold/italic, code blocks, image references, links, blockquotes, horizontal rules, table pipes, and HTML tags) before counting. Reading time is calculated at 200 words per minute, rounded up, with a minimum of 1 minute.

Types

ConversionResult

The return type of all conversion functions.

interfaceConversionResult{/** The converted markdown string */markdown: string;/** Extracted document metadata */metadata: DocumentMetadata;/** Image references found in the document */images: ImageReference[];/** Per-page content breakdown (for paginated formats) */pages: PageContent[];/** Warnings generated during conversion */warnings: string[];/** Conversion duration in milliseconds */durationMs: number;}

ConvertOptions

Options for the convert function.

interfaceConvertOptions{/** Explicitly specify the input format (skips auto-detection) */format?: InputFormat;/** Whether to extract image references (default: true) */extractImages?: boolean;/** Whether to preserve document structure like headings and lists (default: true) */preserveStructure?: boolean;/** Maximum number of pages to process (for paginated formats) */maxPages?: number;/** Whether to insert page break markers (default: false) */pageBreaks?: boolean;/** File name hint for format detection */fileName?: string;}

InputFormat

Supported input format identifiers.

typeInputFormat='html'|'markdown'|'text'|'pdf'|'docx'|'pptx';

DocumentMetadata

Metadata extracted from a converted document.

interfaceDocumentMetadata{title?: string;author?: string;date?: string;pageCount?: number;wordCount: number;headingCount: number;imageCount: number;readingTimeMinutes: number;}

ImageReference

A reference to an image found in the document.

interfaceImageReference{/** Unique identifier for the image (e.g., "img-1") */id: string;/** Alt text for the image */alt: string;/** Source URL or path of the image */src: string;/** Page number where the image was found (if applicable) */page?: number;}

PageContent

Content of a single page in a paginated document.

interfacePageContent{/** Page number (1-based) */pageNumber: number;/** Markdown content of the page */markdown: string;/** Headings found on this page */headings: string[];}

Configuration

Format Override

Skip auto-detection by specifying the format explicitly:

constresult=convert(content,{format: 'html'});

File Name Hint

Provide a file name for extension-based format detection:

constresult=convert(buffer,{fileName: 'report.html'});

Disable Image Extraction

Suppress image reference collection:

constresult=convert(html,{extractImages: false});console.log(result.images);// []

Strip All Formatting

Produce plain text output with no markdown syntax:

constresult=convert('# Heading\n\n**bold** and *italic*',{format: 'markdown',preserveStructure: false,});console.log(result.markdown);// Heading//// bold and italic

Error Handling

All conversion functions are synchronous and do not throw under normal operation. Errors and edge cases are communicated through the warnings array in the ConversionResult.

Binary Formats

When a binary format (PDF, DOCX, PPTX) is detected, the library does not throw. Instead, it returns a ConversionResult with an informative markdown message describing the detected format, suggested external packages, and example code:

constresult=convert(pdfBuffer);console.log(result.warnings);// [// 'Binary format "pdf" detected. Install a dedicated parser for full support.',// 'Suggested packages: `pdfjs-dist`, `pdf-parse`, `pdf2json`'// ]

Unexpected Formats

If the detected format does not match any known converter, the input is treated as plain text and a warning is added:

// result.warnings: ['Unexpected format: xyz. Treating as plain text.']

Empty or Whitespace Input

Empty strings and whitespace-only input produce minimal output without errors:

constresult=convert('');console.log(result.markdown);// '\n'console.log(result.metadata.wordCount);// 0

Advanced Usage

RAG Pipeline Integration

Use docling-node-ts as the first stage in a document ingestion pipeline. The output markdown is designed for downstream chunking and embedding:

import{convert}from'docling-node-ts';functioningestDocument(html: string){const{ markdown, metadata, images, warnings }=convert(html);if(warnings.length>0){console.warn('Conversion warnings:',warnings);}// Chunk the markdown for embedding (e.g., with chunk-smart)// const chunks = chunkMarkdown(markdown, { maxTokens: 512 });return{ markdown, metadata, images };}

Processing Buffers from File Uploads

import{convert}from'docling-node-ts';functionhandleUpload(buffer: Buffer,originalFileName: string){constresult=convert(buffer,{fileName: originalFileName});return{markdown: result.markdown,title: result.metadata.title,wordCount: result.metadata.wordCount,readingTime: result.metadata.readingTimeMinutes,imageCount: result.images.length,};}

HTML Metadata Extraction

When converting HTML, the library extracts metadata from <head> elements:

import{convert}from'docling-node-ts';consthtml=`<html><head> <title>Annual Report 2024</title> <meta name="author" content="Finance Team"> <meta name="date" content="2024-12-01"> <meta property="og:title" content="Annual Report"></head><body> <h1>Annual Report</h1> <p>Revenue increased by 20%.</p></body></html>`;constresult=convert(html);console.log(result.metadata.title);// 'Annual Report 2024'console.log(result.metadata.author);// 'Finance Team'console.log(result.metadata.date);// '2024-12-01'

Title extraction priority: <title> tag, then og:title. Author extraction checks both name="author" and property="article:author". Date extraction checks both name="date" and property="article:published_time".

Normalizing Imported Markdown

Clean up markdown from external sources that may have inconsistent formatting:

import{convertMarkdown}from'docling-node-ts';constmessy=`# Title#### Jumped Heading Level* Mixed+ List- MarkersClick [broken]() link.[Valid link](https://example.com)`;const{ markdown }=convertMarkdown(messy);// Heading levels normalized (#### becomes ##)// List markers standardized to -// Broken link text extracted without brackets// Excessive blank lines collapsed

HTML Table Conversion

Tables are converted to GitHub Flavored Markdown pipe tables with column normalization and pipe escaping:

import{convertHtml}from'docling-node-ts';consthtml=`<table> <thead> <tr><th>Product</th><th>Q1</th><th>Q2</th></tr> </thead> <tbody> <tr><td>Widget A</td><td>$1,200</td><td>$1,500</td></tr> <tr><td>Widget B</td><td>$800</td><td>$950</td></tr> </tbody></table>`;const{ markdown }=convertHtml(html);// | Product | Q1 | Q2 |// | --- | --- | --- |// | Widget A | $1,200 | $1,500 |// | Widget B | $800 | $950 |

Rows with fewer columns are padded with empty cells. Pipe characters (|) inside cell content are escaped as \|.

TypeScript

This package is written in TypeScript and ships type declarations (dist/index.d.ts) alongside the compiled JavaScript. All public types are exported from the package entry point:

importtype{ConversionResult,ConvertOptions,InputFormat,DocumentMetadata,ImageReference,PageContent,}from'docling-node-ts';

Compiled with strict: true, targeting ES2022 with CommonJS module output.

License

MIT

About

Convert documents to clean RAG-ready markdown in Node.js

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - SiluPanda/docling-node-ts: Convert documents to clean RAG-ready markdown in Node.js · GitHub
Skip to content

Repository files navigation

docling-node-ts

Zero-dependency document-to-markdown conversion for Node.js.

npm versionnpm downloadslicensenode

Convert HTML, plain text, and markdown documents into clean, structure-preserving markdown suitable for RAG (Retrieval-Augmented Generation) pipelines, knowledge base construction, and LLM ingestion. Accepts string or Buffer input, auto-detects the format, routes to the appropriate converter, extracts metadata and image references, and returns a typed ConversionResult. No external services, no Python runtime, no network calls -- everything runs locally in Node.js.


Installation

npm install docling-node-ts

Requires Node.js 18 or later.

Quick Start

import{convert}from'docling-node-ts';// Convert HTML to markdownconstresult=convert('<h1>Quarterly Report</h1><p>Revenue grew <strong>15%</strong> year-over-year.</p>');console.log(result.markdown);// # Quarterly Report//// Revenue grew **15%** year-over-year.console.log(result.metadata);// { wordCount: 5, headingCount: 1, imageCount: 0, readingTimeMinutes: 1 }console.log(result.durationMs);// 2
// Convert a Buffer with auto-detectionimport{readFileSync}from'fs';constbuf=readFileSync('report.html');const{ markdown, metadata, images, warnings }=convert(buf);

Features

  • HTML to Markdown -- Converts headings (h1-h6), paragraphs, bold, italic, strikethrough, inline code, links, images, ordered and unordered lists (including nested), GFM pipe tables, fenced code blocks with language hints, blockquotes, horizontal rules, <figure>/<figcaption>, and <sup>/<sub> elements.
  • Plain Text to Markdown -- Detects setext-style headings (underlined with === or ---), ALL CAPS headings, unordered and ordered lists, and paragraph breaks. Normalizes list markers and line endings.
  • Markdown Normalization -- Cleans and normalizes existing markdown: collapses excessive blank lines, standardizes list markers to -, normalizes heading levels to eliminate gaps, fixes broken links with empty hrefs, and ensures consistent spacing around headings.
  • Format Auto-Detection -- Detects the input format automatically using file extension, magic bytes (for Buffer inputs), and content analysis (HTML tags, markdown patterns). Supports explicit format override via options.
  • Metadata Extraction -- Returns word count, heading count, image count, and estimated reading time. For HTML inputs, extracts title, author, and date from <title>, <meta>, and Open Graph tags.
  • Image Reference Extraction -- Collects all image references from HTML with their id, alt text, and src path. Can be disabled with extractImages: false.
  • Binary Format Guidance -- Detects PDF, DOCX, and PPTX inputs (via magic bytes or extension) and returns informative messages with suggested packages (pdfjs-dist, mammoth, jszip) and code examples. No binary parsers are bundled to keep the dependency tree at zero.
  • HTML Sanitization -- Strips <script>, <style>, <noscript>, <iframe>, <svg>, <canvas>, <nav>, <footer>, <header>, and <aside> elements. Decodes HTML entities including numeric and hex character references.
  • Zero Dependencies -- No runtime dependencies. Only devDependencies for building and testing.

API Reference

convert(input, options?)

The primary conversion function. Accepts a string or Buffer, auto-detects the format (or uses the explicit format from options), converts to markdown, and returns a ConversionResult.

functionconvert(input: string|Buffer,options?: ConvertOptions): ConversionResult;

Parameters:

ParameterTypeDescription
inputstring | BufferThe document content to convert
optionsConvertOptionsOptional conversion settings

Returns:ConversionResult

import{convert}from'docling-node-ts';constresult=convert('<table><thead><tr><th>Name</th><th>Age</th></tr></thead><tbody><tr><td>Alice</td><td>30</td></tr></tbody></table>');console.log(result.markdown);// | Name | Age |// | --- | --- |// | Alice | 30 |

convertHtml(html)

Convenience function that converts HTML to markdown. Equivalent to calling convert(html, { format: 'html' }).

functionconvertHtml(html: string): ConversionResult;
import{convertHtml}from'docling-node-ts';const{ markdown }=convertHtml('<ul><li>First</li><li>Second</li></ul>');// - First// - Second

convertMarkdown(md)

Cleans and normalizes existing markdown. Standardizes list markers, normalizes heading levels, collapses blank lines, removes broken links, and ensures consistent formatting. Equivalent to calling convert(md, { format: 'markdown' }).

functionconvertMarkdown(md: string): ConversionResult;
import{convertMarkdown}from'docling-node-ts';const{ markdown }=convertMarkdown('# Title\n\n\n\n\n#### Skipped Level\n\n* Item');// # Title//// ## Skipped Level//// - Item

convertText(text)

Converts plain text to markdown. Detects headings, lists, and paragraph structure. Equivalent to calling convert(text, { format: 'text' }).

functionconvertText(text: string): ConversionResult;
import{convertText}from'docling-node-ts';const{ markdown }=convertText('INTRODUCTION\n\nSome body text.\n\n1) First step\n2) Second step');// ## INTRODUCTION//// Some body text.//// 1. First step// 2. Second step

detectFormat(input, fileName?)

Detects the format of a document from its content or file name.

Detection priority:

  1. File extension from fileName (.pdf, .docx, .pptx, .html, .htm, .xhtml, .txt, .md, .markdown)
  2. Magic bytes for Buffer inputs (%PDF for PDF, PK\x03\x04 for ZIP-based Office formats)
  3. Content analysis (HTML tags, markdown patterns)
  4. Default: 'text'
functiondetectFormat(input: string|Buffer,fileName?: string): InputFormat;
import{detectFormat}from'docling-node-ts';detectFormat('','report.pdf');// 'pdf'detectFormat('<html><body>Hi</body></html>');// 'html'detectFormat('# Title\n\n## Section');// 'markdown'detectFormat('Just plain text.');// 'text'constpdfBuffer=Buffer.from('%PDF-1.4 ...');detectFormat(pdfBuffer);// 'pdf'

extractMetadata(markdown)

Extracts metadata from a markdown string. Computes word count, heading count, image count, and estimated reading time.

functionextractMetadata(markdown: string): Pick<DocumentMetadata,'wordCount'|'headingCount'|'imageCount'|'readingTimeMinutes'>;
import{extractMetadata}from'docling-node-ts';constmeta=extractMetadata('# Title\n\nSome **bold** text with ![img](photo.png).\n');// { wordCount: 4, headingCount: 1, imageCount: 1, readingTimeMinutes: 1 }

Word counting strips markdown syntax (headings, bold/italic, code blocks, image references, links, blockquotes, horizontal rules, table pipes, and HTML tags) before counting. Reading time is calculated at 200 words per minute, rounded up, with a minimum of 1 minute.

Types

ConversionResult

The return type of all conversion functions.

interfaceConversionResult{/** The converted markdown string */markdown: string;/** Extracted document metadata */metadata: DocumentMetadata;/** Image references found in the document */images: ImageReference[];/** Per-page content breakdown (for paginated formats) */pages: PageContent[];/** Warnings generated during conversion */warnings: string[];/** Conversion duration in milliseconds */durationMs: number;}

ConvertOptions

Options for the convert function.

interfaceConvertOptions{/** Explicitly specify the input format (skips auto-detection) */format?: InputFormat;/** Whether to extract image references (default: true) */extractImages?: boolean;/** Whether to preserve document structure like headings and lists (default: true) */preserveStructure?: boolean;/** Maximum number of pages to process (for paginated formats) */maxPages?: number;/** Whether to insert page break markers (default: false) */pageBreaks?: boolean;/** File name hint for format detection */fileName?: string;}

InputFormat

Supported input format identifiers.

typeInputFormat='html'|'markdown'|'text'|'pdf'|'docx'|'pptx';

DocumentMetadata

Metadata extracted from a converted document.

interfaceDocumentMetadata{title?: string;author?: string;date?: string;pageCount?: number;wordCount: number;headingCount: number;imageCount: number;readingTimeMinutes: number;}

ImageReference

A reference to an image found in the document.

interfaceImageReference{/** Unique identifier for the image (e.g., "img-1") */id: string;/** Alt text for the image */alt: string;/** Source URL or path of the image */src: string;/** Page number where the image was found (if applicable) */page?: number;}

PageContent

Content of a single page in a paginated document.

interfacePageContent{/** Page number (1-based) */pageNumber: number;/** Markdown content of the page */markdown: string;/** Headings found on this page */headings: string[];}

Configuration

Format Override

Skip auto-detection by specifying the format explicitly:

constresult=convert(content,{format: 'html'});

File Name Hint

Provide a file name for extension-based format detection:

constresult=convert(buffer,{fileName: 'report.html'});

Disable Image Extraction

Suppress image reference collection:

constresult=convert(html,{extractImages: false});console.log(result.images);// []

Strip All Formatting

Produce plain text output with no markdown syntax:

constresult=convert('# Heading\n\n**bold** and *italic*',{format: 'markdown',preserveStructure: false,});console.log(result.markdown);// Heading//// bold and italic

Error Handling

All conversion functions are synchronous and do not throw under normal operation. Errors and edge cases are communicated through the warnings array in the ConversionResult.

Binary Formats

When a binary format (PDF, DOCX, PPTX) is detected, the library does not throw. Instead, it returns a ConversionResult with an informative markdown message describing the detected format, suggested external packages, and example code:

constresult=convert(pdfBuffer);console.log(result.warnings);// [// 'Binary format "pdf" detected. Install a dedicated parser for full support.',// 'Suggested packages: `pdfjs-dist`, `pdf-parse`, `pdf2json`'// ]

Unexpected Formats

If the detected format does not match any known converter, the input is treated as plain text and a warning is added:

// result.warnings: ['Unexpected format: xyz. Treating as plain text.']

Empty or Whitespace Input

Empty strings and whitespace-only input produce minimal output without errors:

constresult=convert('');console.log(result.markdown);// '\n'console.log(result.metadata.wordCount);// 0

Advanced Usage

RAG Pipeline Integration

Use docling-node-ts as the first stage in a document ingestion pipeline. The output markdown is designed for downstream chunking and embedding:

import{convert}from'docling-node-ts';functioningestDocument(html: string){const{ markdown, metadata, images, warnings }=convert(html);if(warnings.length>0){console.warn('Conversion warnings:',warnings);}// Chunk the markdown for embedding (e.g., with chunk-smart)// const chunks = chunkMarkdown(markdown, { maxTokens: 512 });return{ markdown, metadata, images };}

Processing Buffers from File Uploads

import{convert}from'docling-node-ts';functionhandleUpload(buffer: Buffer,originalFileName: string){constresult=convert(buffer,{fileName: originalFileName});return{markdown: result.markdown,title: result.metadata.title,wordCount: result.metadata.wordCount,readingTime: result.metadata.readingTimeMinutes,imageCount: result.images.length,};}

HTML Metadata Extraction

When converting HTML, the library extracts metadata from <head> elements:

import{convert}from'docling-node-ts';consthtml=`<html><head> <title>Annual Report 2024</title> <meta name="author" content="Finance Team"> <meta name="date" content="2024-12-01"> <meta property="og:title" content="Annual Report"></head><body> <h1>Annual Report</h1> <p>Revenue increased by 20%.</p></body></html>`;constresult=convert(html);console.log(result.metadata.title);// 'Annual Report 2024'console.log(result.metadata.author);// 'Finance Team'console.log(result.metadata.date);// '2024-12-01'

Title extraction priority: <title> tag, then og:title. Author extraction checks both name="author" and property="article:author". Date extraction checks both name="date" and property="article:published_time".

Normalizing Imported Markdown

Clean up markdown from external sources that may have inconsistent formatting:

import{convertMarkdown}from'docling-node-ts';constmessy=`# Title#### Jumped Heading Level* Mixed+ List- MarkersClick [broken]() link.[Valid link](https://example.com)`;const{ markdown }=convertMarkdown(messy);// Heading levels normalized (#### becomes ##)// List markers standardized to -// Broken link text extracted without brackets// Excessive blank lines collapsed

HTML Table Conversion

Tables are converted to GitHub Flavored Markdown pipe tables with column normalization and pipe escaping:

import{convertHtml}from'docling-node-ts';consthtml=`<table> <thead> <tr><th>Product</th><th>Q1</th><th>Q2</th></tr> </thead> <tbody> <tr><td>Widget A</td><td>$1,200</td><td>$1,500</td></tr> <tr><td>Widget B</td><td>$800</td><td>$950</td></tr> </tbody></table>`;const{ markdown }=convertHtml(html);// | Product | Q1 | Q2 |// | --- | --- | --- |// | Widget A | $1,200 | $1,500 |// | Widget B | $800 | $950 |

Rows with fewer columns are padded with empty cells. Pipe characters (|) inside cell content are escaped as \|.

TypeScript

This package is written in TypeScript and ships type declarations (dist/index.d.ts) alongside the compiled JavaScript. All public types are exported from the package entry point:

importtype{ConversionResult,ConvertOptions,InputFormat,DocumentMetadata,ImageReference,PageContent,}from'docling-node-ts';

Compiled with strict: true, targeting ES2022 with CommonJS module output.

License

MIT

About

Convert documents to clean RAG-ready markdown in Node.js

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - SiluPanda/docling-node-ts: Convert documents to clean RAG-ready markdown in Node.js · GitHub
Skip to content

Repository files navigation

docling-node-ts

Zero-dependency document-to-markdown conversion for Node.js.

npm versionnpm downloadslicensenode

Convert HTML, plain text, and markdown documents into clean, structure-preserving markdown suitable for RAG (Retrieval-Augmented Generation) pipelines, knowledge base construction, and LLM ingestion. Accepts string or Buffer input, auto-detects the format, routes to the appropriate converter, extracts metadata and image references, and returns a typed ConversionResult. No external services, no Python runtime, no network calls -- everything runs locally in Node.js.


Installation

npm install docling-node-ts

Requires Node.js 18 or later.

Quick Start

import{convert}from'docling-node-ts';// Convert HTML to markdownconstresult=convert('<h1>Quarterly Report</h1><p>Revenue grew <strong>15%</strong> year-over-year.</p>');console.log(result.markdown);// # Quarterly Report//// Revenue grew **15%** year-over-year.console.log(result.metadata);// { wordCount: 5, headingCount: 1, imageCount: 0, readingTimeMinutes: 1 }console.log(result.durationMs);// 2
// Convert a Buffer with auto-detectionimport{readFileSync}from'fs';constbuf=readFileSync('report.html');const{ markdown, metadata, images, warnings }=convert(buf);

Features

  • HTML to Markdown -- Converts headings (h1-h6), paragraphs, bold, italic, strikethrough, inline code, links, images, ordered and unordered lists (including nested), GFM pipe tables, fenced code blocks with language hints, blockquotes, horizontal rules, <figure>/<figcaption>, and <sup>/<sub> elements.
  • Plain Text to Markdown -- Detects setext-style headings (underlined with === or ---), ALL CAPS headings, unordered and ordered lists, and paragraph breaks. Normalizes list markers and line endings.
  • Markdown Normalization -- Cleans and normalizes existing markdown: collapses excessive blank lines, standardizes list markers to -, normalizes heading levels to eliminate gaps, fixes broken links with empty hrefs, and ensures consistent spacing around headings.
  • Format Auto-Detection -- Detects the input format automatically using file extension, magic bytes (for Buffer inputs), and content analysis (HTML tags, markdown patterns). Supports explicit format override via options.
  • Metadata Extraction -- Returns word count, heading count, image count, and estimated reading time. For HTML inputs, extracts title, author, and date from <title>, <meta>, and Open Graph tags.
  • Image Reference Extraction -- Collects all image references from HTML with their id, alt text, and src path. Can be disabled with extractImages: false.
  • Binary Format Guidance -- Detects PDF, DOCX, and PPTX inputs (via magic bytes or extension) and returns informative messages with suggested packages (pdfjs-dist, mammoth, jszip) and code examples. No binary parsers are bundled to keep the dependency tree at zero.
  • HTML Sanitization -- Strips <script>, <style>, <noscript>, <iframe>, <svg>, <canvas>, <nav>, <footer>, <header>, and <aside> elements. Decodes HTML entities including numeric and hex character references.
  • Zero Dependencies -- No runtime dependencies. Only devDependencies for building and testing.

API Reference

convert(input, options?)

The primary conversion function. Accepts a string or Buffer, auto-detects the format (or uses the explicit format from options), converts to markdown, and returns a ConversionResult.

functionconvert(input: string|Buffer,options?: ConvertOptions): ConversionResult;

Parameters:

ParameterTypeDescription
inputstring | BufferThe document content to convert
optionsConvertOptionsOptional conversion settings

Returns:ConversionResult

import{convert}from'docling-node-ts';constresult=convert('<table><thead><tr><th>Name</th><th>Age</th></tr></thead><tbody><tr><td>Alice</td><td>30</td></tr></tbody></table>');console.log(result.markdown);// | Name | Age |// | --- | --- |// | Alice | 30 |

convertHtml(html)

Convenience function that converts HTML to markdown. Equivalent to calling convert(html, { format: 'html' }).

functionconvertHtml(html: string): ConversionResult;
import{convertHtml}from'docling-node-ts';const{ markdown }=convertHtml('<ul><li>First</li><li>Second</li></ul>');// - First// - Second

convertMarkdown(md)

Cleans and normalizes existing markdown. Standardizes list markers, normalizes heading levels, collapses blank lines, removes broken links, and ensures consistent formatting. Equivalent to calling convert(md, { format: 'markdown' }).

functionconvertMarkdown(md: string): ConversionResult;
import{convertMarkdown}from'docling-node-ts';const{ markdown }=convertMarkdown('# Title\n\n\n\n\n#### Skipped Level\n\n* Item');// # Title//// ## Skipped Level//// - Item

convertText(text)

Converts plain text to markdown. Detects headings, lists, and paragraph structure. Equivalent to calling convert(text, { format: 'text' }).

functionconvertText(text: string): ConversionResult;
import{convertText}from'docling-node-ts';const{ markdown }=convertText('INTRODUCTION\n\nSome body text.\n\n1) First step\n2) Second step');// ## INTRODUCTION//// Some body text.//// 1. First step// 2. Second step

detectFormat(input, fileName?)

Detects the format of a document from its content or file name.

Detection priority:

  1. File extension from fileName (.pdf, .docx, .pptx, .html, .htm, .xhtml, .txt, .md, .markdown)
  2. Magic bytes for Buffer inputs (%PDF for PDF, PK\x03\x04 for ZIP-based Office formats)
  3. Content analysis (HTML tags, markdown patterns)
  4. Default: 'text'
functiondetectFormat(input: string|Buffer,fileName?: string): InputFormat;
import{detectFormat}from'docling-node-ts';detectFormat('','report.pdf');// 'pdf'detectFormat('<html><body>Hi</body></html>');// 'html'detectFormat('# Title\n\n## Section');// 'markdown'detectFormat('Just plain text.');// 'text'constpdfBuffer=Buffer.from('%PDF-1.4 ...');detectFormat(pdfBuffer);// 'pdf'

extractMetadata(markdown)

Extracts metadata from a markdown string. Computes word count, heading count, image count, and estimated reading time.

functionextractMetadata(markdown: string): Pick<DocumentMetadata,'wordCount'|'headingCount'|'imageCount'|'readingTimeMinutes'>;
import{extractMetadata}from'docling-node-ts';constmeta=extractMetadata('# Title\n\nSome **bold** text with ![img](photo.png).\n');// { wordCount: 4, headingCount: 1, imageCount: 1, readingTimeMinutes: 1 }

Word counting strips markdown syntax (headings, bold/italic, code blocks, image references, links, blockquotes, horizontal rules, table pipes, and HTML tags) before counting. Reading time is calculated at 200 words per minute, rounded up, with a minimum of 1 minute.

Types

ConversionResult

The return type of all conversion functions.

interfaceConversionResult{/** The converted markdown string */markdown: string;/** Extracted document metadata */metadata: DocumentMetadata;/** Image references found in the document */images: ImageReference[];/** Per-page content breakdown (for paginated formats) */pages: PageContent[];/** Warnings generated during conversion */warnings: string[];/** Conversion duration in milliseconds */durationMs: number;}

ConvertOptions

Options for the convert function.

interfaceConvertOptions{/** Explicitly specify the input format (skips auto-detection) */format?: InputFormat;/** Whether to extract image references (default: true) */extractImages?: boolean;/** Whether to preserve document structure like headings and lists (default: true) */preserveStructure?: boolean;/** Maximum number of pages to process (for paginated formats) */maxPages?: number;/** Whether to insert page break markers (default: false) */pageBreaks?: boolean;/** File name hint for format detection */fileName?: string;}

InputFormat

Supported input format identifiers.

typeInputFormat='html'|'markdown'|'text'|'pdf'|'docx'|'pptx';

DocumentMetadata

Metadata extracted from a converted document.

interfaceDocumentMetadata{title?: string;author?: string;date?: string;pageCount?: number;wordCount: number;headingCount: number;imageCount: number;readingTimeMinutes: number;}

ImageReference

A reference to an image found in the document.

interfaceImageReference{/** Unique identifier for the image (e.g., "img-1") */id: string;/** Alt text for the image */alt: string;/** Source URL or path of the image */src: string;/** Page number where the image was found (if applicable) */page?: number;}

PageContent

Content of a single page in a paginated document.

interfacePageContent{/** Page number (1-based) */pageNumber: number;/** Markdown content of the page */markdown: string;/** Headings found on this page */headings: string[];}

Configuration

Format Override

Skip auto-detection by specifying the format explicitly:

constresult=convert(content,{format: 'html'});

File Name Hint

Provide a file name for extension-based format detection:

constresult=convert(buffer,{fileName: 'report.html'});

Disable Image Extraction

Suppress image reference collection:

constresult=convert(html,{extractImages: false});console.log(result.images);// []

Strip All Formatting

Produce plain text output with no markdown syntax:

constresult=convert('# Heading\n\n**bold** and *italic*',{format: 'markdown',preserveStructure: false,});console.log(result.markdown);// Heading//// bold and italic

Error Handling

All conversion functions are synchronous and do not throw under normal operation. Errors and edge cases are communicated through the warnings array in the ConversionResult.

Binary Formats

When a binary format (PDF, DOCX, PPTX) is detected, the library does not throw. Instead, it returns a ConversionResult with an informative markdown message describing the detected format, suggested external packages, and example code:

constresult=convert(pdfBuffer);console.log(result.warnings);// [// 'Binary format "pdf" detected. Install a dedicated parser for full support.',// 'Suggested packages: `pdfjs-dist`, `pdf-parse`, `pdf2json`'// ]

Unexpected Formats

If the detected format does not match any known converter, the input is treated as plain text and a warning is added:

// result.warnings: ['Unexpected format: xyz. Treating as plain text.']

Empty or Whitespace Input

Empty strings and whitespace-only input produce minimal output without errors:

constresult=convert('');console.log(result.markdown);// '\n'console.log(result.metadata.wordCount);// 0

Advanced Usage

RAG Pipeline Integration

Use docling-node-ts as the first stage in a document ingestion pipeline. The output markdown is designed for downstream chunking and embedding:

import{convert}from'docling-node-ts';functioningestDocument(html: string){const{ markdown, metadata, images, warnings }=convert(html);if(warnings.length>0){console.warn('Conversion warnings:',warnings);}// Chunk the markdown for embedding (e.g., with chunk-smart)// const chunks = chunkMarkdown(markdown, { maxTokens: 512 });return{ markdown, metadata, images };}

Processing Buffers from File Uploads

import{convert}from'docling-node-ts';functionhandleUpload(buffer: Buffer,originalFileName: string){constresult=convert(buffer,{fileName: originalFileName});return{markdown: result.markdown,title: result.metadata.title,wordCount: result.metadata.wordCount,readingTime: result.metadata.readingTimeMinutes,imageCount: result.images.length,};}

HTML Metadata Extraction

When converting HTML, the library extracts metadata from <head> elements:

import{convert}from'docling-node-ts';consthtml=`<html><head> <title>Annual Report 2024</title> <meta name="author" content="Finance Team"> <meta name="date" content="2024-12-01"> <meta property="og:title" content="Annual Report"></head><body> <h1>Annual Report</h1> <p>Revenue increased by 20%.</p></body></html>`;constresult=convert(html);console.log(result.metadata.title);// 'Annual Report 2024'console.log(result.metadata.author);// 'Finance Team'console.log(result.metadata.date);// '2024-12-01'

Title extraction priority: <title> tag, then og:title. Author extraction checks both name="author" and property="article:author". Date extraction checks both name="date" and property="article:published_time".

Normalizing Imported Markdown

Clean up markdown from external sources that may have inconsistent formatting:

import{convertMarkdown}from'docling-node-ts';constmessy=`# Title#### Jumped Heading Level* Mixed+ List- MarkersClick [broken]() link.[Valid link](https://example.com)`;const{ markdown }=convertMarkdown(messy);// Heading levels normalized (#### becomes ##)// List markers standardized to -// Broken link text extracted without brackets// Excessive blank lines collapsed

HTML Table Conversion

Tables are converted to GitHub Flavored Markdown pipe tables with column normalization and pipe escaping:

import{convertHtml}from'docling-node-ts';consthtml=`<table> <thead> <tr><th>Product</th><th>Q1</th><th>Q2</th></tr> </thead> <tbody> <tr><td>Widget A</td><td>$1,200</td><td>$1,500</td></tr> <tr><td>Widget B</td><td>$800</td><td>$950</td></tr> </tbody></table>`;const{ markdown }=convertHtml(html);// | Product | Q1 | Q2 |// | --- | --- | --- |// | Widget A | $1,200 | $1,500 |// | Widget B | $800 | $950 |

Rows with fewer columns are padded with empty cells. Pipe characters (|) inside cell content are escaped as \|.

TypeScript

This package is written in TypeScript and ships type declarations (dist/index.d.ts) alongside the compiled JavaScript. All public types are exported from the package entry point:

importtype{ConversionResult,ConvertOptions,InputFormat,DocumentMetadata,ImageReference,PageContent,}from'docling-node-ts';

Compiled with strict: true, targeting ES2022 with CommonJS module output.

License

MIT

About

Convert documents to clean RAG-ready markdown in Node.js

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - SiluPanda/docling-node-ts: Convert documents to clean RAG-ready markdown in Node.js · GitHub
Skip to content

Repository files navigation

docling-node-ts

Zero-dependency document-to-markdown conversion for Node.js.

npm versionnpm downloadslicensenode

Convert HTML, plain text, and markdown documents into clean, structure-preserving markdown suitable for RAG (Retrieval-Augmented Generation) pipelines, knowledge base construction, and LLM ingestion. Accepts string or Buffer input, auto-detects the format, routes to the appropriate converter, extracts metadata and image references, and returns a typed ConversionResult. No external services, no Python runtime, no network calls -- everything runs locally in Node.js.


Installation

npm install docling-node-ts

Requires Node.js 18 or later.

Quick Start

import{convert}from'docling-node-ts';// Convert HTML to markdownconstresult=convert('<h1>Quarterly Report</h1><p>Revenue grew <strong>15%</strong> year-over-year.</p>');console.log(result.markdown);// # Quarterly Report//// Revenue grew **15%** year-over-year.console.log(result.metadata);// { wordCount: 5, headingCount: 1, imageCount: 0, readingTimeMinutes: 1 }console.log(result.durationMs);// 2
// Convert a Buffer with auto-detectionimport{readFileSync}from'fs';constbuf=readFileSync('report.html');const{ markdown, metadata, images, warnings }=convert(buf);

Features

  • HTML to Markdown -- Converts headings (h1-h6), paragraphs, bold, italic, strikethrough, inline code, links, images, ordered and unordered lists (including nested), GFM pipe tables, fenced code blocks with language hints, blockquotes, horizontal rules, <figure>/<figcaption>, and <sup>/<sub> elements.
  • Plain Text to Markdown -- Detects setext-style headings (underlined with === or ---), ALL CAPS headings, unordered and ordered lists, and paragraph breaks. Normalizes list markers and line endings.
  • Markdown Normalization -- Cleans and normalizes existing markdown: collapses excessive blank lines, standardizes list markers to -, normalizes heading levels to eliminate gaps, fixes broken links with empty hrefs, and ensures consistent spacing around headings.
  • Format Auto-Detection -- Detects the input format automatically using file extension, magic bytes (for Buffer inputs), and content analysis (HTML tags, markdown patterns). Supports explicit format override via options.
  • Metadata Extraction -- Returns word count, heading count, image count, and estimated reading time. For HTML inputs, extracts title, author, and date from <title>, <meta>, and Open Graph tags.
  • Image Reference Extraction -- Collects all image references from HTML with their id, alt text, and src path. Can be disabled with extractImages: false.
  • Binary Format Guidance -- Detects PDF, DOCX, and PPTX inputs (via magic bytes or extension) and returns informative messages with suggested packages (pdfjs-dist, mammoth, jszip) and code examples. No binary parsers are bundled to keep the dependency tree at zero.
  • HTML Sanitization -- Strips <script>, <style>, <noscript>, <iframe>, <svg>, <canvas>, <nav>, <footer>, <header>, and <aside> elements. Decodes HTML entities including numeric and hex character references.
  • Zero Dependencies -- No runtime dependencies. Only devDependencies for building and testing.

API Reference

convert(input, options?)

The primary conversion function. Accepts a string or Buffer, auto-detects the format (or uses the explicit format from options), converts to markdown, and returns a ConversionResult.

functionconvert(input: string|Buffer,options?: ConvertOptions): ConversionResult;

Parameters:

ParameterTypeDescription
inputstring | BufferThe document content to convert
optionsConvertOptionsOptional conversion settings

Returns:ConversionResult

import{convert}from'docling-node-ts';constresult=convert('<table><thead><tr><th>Name</th><th>Age</th></tr></thead><tbody><tr><td>Alice</td><td>30</td></tr></tbody></table>');console.log(result.markdown);// | Name | Age |// | --- | --- |// | Alice | 30 |

convertHtml(html)

Convenience function that converts HTML to markdown. Equivalent to calling convert(html, { format: 'html' }).

functionconvertHtml(html: string): ConversionResult;
import{convertHtml}from'docling-node-ts';const{ markdown }=convertHtml('<ul><li>First</li><li>Second</li></ul>');// - First// - Second

convertMarkdown(md)

Cleans and normalizes existing markdown. Standardizes list markers, normalizes heading levels, collapses blank lines, removes broken links, and ensures consistent formatting. Equivalent to calling convert(md, { format: 'markdown' }).

functionconvertMarkdown(md: string): ConversionResult;
import{convertMarkdown}from'docling-node-ts';const{ markdown }=convertMarkdown('# Title\n\n\n\n\n#### Skipped Level\n\n* Item');// # Title//// ## Skipped Level//// - Item

convertText(text)

Converts plain text to markdown. Detects headings, lists, and paragraph structure. Equivalent to calling convert(text, { format: 'text' }).

functionconvertText(text: string): ConversionResult;
import{convertText}from'docling-node-ts';const{ markdown }=convertText('INTRODUCTION\n\nSome body text.\n\n1) First step\n2) Second step');// ## INTRODUCTION//// Some body text.//// 1. First step// 2. Second step

detectFormat(input, fileName?)

Detects the format of a document from its content or file name.

Detection priority:

  1. File extension from fileName (.pdf, .docx, .pptx, .html, .htm, .xhtml, .txt, .md, .markdown)
  2. Magic bytes for Buffer inputs (%PDF for PDF, PK\x03\x04 for ZIP-based Office formats)
  3. Content analysis (HTML tags, markdown patterns)
  4. Default: 'text'
functiondetectFormat(input: string|Buffer,fileName?: string): InputFormat;
import{detectFormat}from'docling-node-ts';detectFormat('','report.pdf');// 'pdf'detectFormat('<html><body>Hi</body></html>');// 'html'detectFormat('# Title\n\n## Section');// 'markdown'detectFormat('Just plain text.');// 'text'constpdfBuffer=Buffer.from('%PDF-1.4 ...');detectFormat(pdfBuffer);// 'pdf'

extractMetadata(markdown)

Extracts metadata from a markdown string. Computes word count, heading count, image count, and estimated reading time.

functionextractMetadata(markdown: string): Pick<DocumentMetadata,'wordCount'|'headingCount'|'imageCount'|'readingTimeMinutes'>;
import{extractMetadata}from'docling-node-ts';constmeta=extractMetadata('# Title\n\nSome **bold** text with ![img](photo.png).\n');// { wordCount: 4, headingCount: 1, imageCount: 1, readingTimeMinutes: 1 }

Word counting strips markdown syntax (headings, bold/italic, code blocks, image references, links, blockquotes, horizontal rules, table pipes, and HTML tags) before counting. Reading time is calculated at 200 words per minute, rounded up, with a minimum of 1 minute.

Types

ConversionResult

The return type of all conversion functions.

interfaceConversionResult{/** The converted markdown string */markdown: string;/** Extracted document metadata */metadata: DocumentMetadata;/** Image references found in the document */images: ImageReference[];/** Per-page content breakdown (for paginated formats) */pages: PageContent[];/** Warnings generated during conversion */warnings: string[];/** Conversion duration in milliseconds */durationMs: number;}

ConvertOptions

Options for the convert function.

interfaceConvertOptions{/** Explicitly specify the input format (skips auto-detection) */format?: InputFormat;/** Whether to extract image references (default: true) */extractImages?: boolean;/** Whether to preserve document structure like headings and lists (default: true) */preserveStructure?: boolean;/** Maximum number of pages to process (for paginated formats) */maxPages?: number;/** Whether to insert page break markers (default: false) */pageBreaks?: boolean;/** File name hint for format detection */fileName?: string;}

InputFormat

Supported input format identifiers.

typeInputFormat='html'|'markdown'|'text'|'pdf'|'docx'|'pptx';

DocumentMetadata

Metadata extracted from a converted document.

interfaceDocumentMetadata{title?: string;author?: string;date?: string;pageCount?: number;wordCount: number;headingCount: number;imageCount: number;readingTimeMinutes: number;}

ImageReference

A reference to an image found in the document.

interfaceImageReference{/** Unique identifier for the image (e.g., "img-1") */id: string;/** Alt text for the image */alt: string;/** Source URL or path of the image */src: string;/** Page number where the image was found (if applicable) */page?: number;}

PageContent

Content of a single page in a paginated document.

interfacePageContent{/** Page number (1-based) */pageNumber: number;/** Markdown content of the page */markdown: string;/** Headings found on this page */headings: string[];}

Configuration

Format Override

Skip auto-detection by specifying the format explicitly:

constresult=convert(content,{format: 'html'});

File Name Hint

Provide a file name for extension-based format detection:

constresult=convert(buffer,{fileName: 'report.html'});

Disable Image Extraction

Suppress image reference collection:

constresult=convert(html,{extractImages: false});console.log(result.images);// []

Strip All Formatting

Produce plain text output with no markdown syntax:

constresult=convert('# Heading\n\n**bold** and *italic*',{format: 'markdown',preserveStructure: false,});console.log(result.markdown);// Heading//// bold and italic

Error Handling

All conversion functions are synchronous and do not throw under normal operation. Errors and edge cases are communicated through the warnings array in the ConversionResult.

Binary Formats

When a binary format (PDF, DOCX, PPTX) is detected, the library does not throw. Instead, it returns a ConversionResult with an informative markdown message describing the detected format, suggested external packages, and example code:

constresult=convert(pdfBuffer);console.log(result.warnings);// [// 'Binary format "pdf" detected. Install a dedicated parser for full support.',// 'Suggested packages: `pdfjs-dist`, `pdf-parse`, `pdf2json`'// ]

Unexpected Formats

If the detected format does not match any known converter, the input is treated as plain text and a warning is added:

// result.warnings: ['Unexpected format: xyz. Treating as plain text.']

Empty or Whitespace Input

Empty strings and whitespace-only input produce minimal output without errors:

constresult=convert('');console.log(result.markdown);// '\n'console.log(result.metadata.wordCount);// 0

Advanced Usage

RAG Pipeline Integration

Use docling-node-ts as the first stage in a document ingestion pipeline. The output markdown is designed for downstream chunking and embedding:

import{convert}from'docling-node-ts';functioningestDocument(html: string){const{ markdown, metadata, images, warnings }=convert(html);if(warnings.length>0){console.warn('Conversion warnings:',warnings);}// Chunk the markdown for embedding (e.g., with chunk-smart)// const chunks = chunkMarkdown(markdown, { maxTokens: 512 });return{ markdown, metadata, images };}

Processing Buffers from File Uploads

import{convert}from'docling-node-ts';functionhandleUpload(buffer: Buffer,originalFileName: string){constresult=convert(buffer,{fileName: originalFileName});return{markdown: result.markdown,title: result.metadata.title,wordCount: result.metadata.wordCount,readingTime: result.metadata.readingTimeMinutes,imageCount: result.images.length,};}

HTML Metadata Extraction

When converting HTML, the library extracts metadata from <head> elements:

import{convert}from'docling-node-ts';consthtml=`<html><head> <title>Annual Report 2024</title> <meta name="author" content="Finance Team"> <meta name="date" content="2024-12-01"> <meta property="og:title" content="Annual Report"></head><body> <h1>Annual Report</h1> <p>Revenue increased by 20%.</p></body></html>`;constresult=convert(html);console.log(result.metadata.title);// 'Annual Report 2024'console.log(result.metadata.author);// 'Finance Team'console.log(result.metadata.date);// '2024-12-01'

Title extraction priority: <title> tag, then og:title. Author extraction checks both name="author" and property="article:author". Date extraction checks both name="date" and property="article:published_time".

Normalizing Imported Markdown

Clean up markdown from external sources that may have inconsistent formatting:

import{convertMarkdown}from'docling-node-ts';constmessy=`# Title#### Jumped Heading Level* Mixed+ List- MarkersClick [broken]() link.[Valid link](https://example.com)`;const{ markdown }=convertMarkdown(messy);// Heading levels normalized (#### becomes ##)// List markers standardized to -// Broken link text extracted without brackets// Excessive blank lines collapsed

HTML Table Conversion

Tables are converted to GitHub Flavored Markdown pipe tables with column normalization and pipe escaping:

import{convertHtml}from'docling-node-ts';consthtml=`<table> <thead> <tr><th>Product</th><th>Q1</th><th>Q2</th></tr> </thead> <tbody> <tr><td>Widget A</td><td>$1,200</td><td>$1,500</td></tr> <tr><td>Widget B</td><td>$800</td><td>$950</td></tr> </tbody></table>`;const{ markdown }=convertHtml(html);// | Product | Q1 | Q2 |// | --- | --- | --- |// | Widget A | $1,200 | $1,500 |// | Widget B | $800 | $950 |

Rows with fewer columns are padded with empty cells. Pipe characters (|) inside cell content are escaped as \|.

TypeScript

This package is written in TypeScript and ships type declarations (dist/index.d.ts) alongside the compiled JavaScript. All public types are exported from the package entry point:

importtype{ConversionResult,ConvertOptions,InputFormat,DocumentMetadata,ImageReference,PageContent,}from'docling-node-ts';

Compiled with strict: true, targeting ES2022 with CommonJS module output.

License

MIT

About

Convert documents to clean RAG-ready markdown in Node.js

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - SiluPanda/docling-node-ts: Convert documents to clean RAG-ready markdown in Node.js · GitHub
Skip to content

Repository files navigation

docling-node-ts

Zero-dependency document-to-markdown conversion for Node.js.

npm versionnpm downloadslicensenode

Convert HTML, plain text, and markdown documents into clean, structure-preserving markdown suitable for RAG (Retrieval-Augmented Generation) pipelines, knowledge base construction, and LLM ingestion. Accepts string or Buffer input, auto-detects the format, routes to the appropriate converter, extracts metadata and image references, and returns a typed ConversionResult. No external services, no Python runtime, no network calls -- everything runs locally in Node.js.


Installation

npm install docling-node-ts

Requires Node.js 18 or later.

Quick Start

import{convert}from'docling-node-ts';// Convert HTML to markdownconstresult=convert('<h1>Quarterly Report</h1><p>Revenue grew <strong>15%</strong> year-over-year.</p>');console.log(result.markdown);// # Quarterly Report//// Revenue grew **15%** year-over-year.console.log(result.metadata);// { wordCount: 5, headingCount: 1, imageCount: 0, readingTimeMinutes: 1 }console.log(result.durationMs);// 2
// Convert a Buffer with auto-detectionimport{readFileSync}from'fs';constbuf=readFileSync('report.html');const{ markdown, metadata, images, warnings }=convert(buf);

Features

  • HTML to Markdown -- Converts headings (h1-h6), paragraphs, bold, italic, strikethrough, inline code, links, images, ordered and unordered lists (including nested), GFM pipe tables, fenced code blocks with language hints, blockquotes, horizontal rules, <figure>/<figcaption>, and <sup>/<sub> elements.
  • Plain Text to Markdown -- Detects setext-style headings (underlined with === or ---), ALL CAPS headings, unordered and ordered lists, and paragraph breaks. Normalizes list markers and line endings.
  • Markdown Normalization -- Cleans and normalizes existing markdown: collapses excessive blank lines, standardizes list markers to -, normalizes heading levels to eliminate gaps, fixes broken links with empty hrefs, and ensures consistent spacing around headings.
  • Format Auto-Detection -- Detects the input format automatically using file extension, magic bytes (for Buffer inputs), and content analysis (HTML tags, markdown patterns). Supports explicit format override via options.
  • Metadata Extraction -- Returns word count, heading count, image count, and estimated reading time. For HTML inputs, extracts title, author, and date from <title>, <meta>, and Open Graph tags.
  • Image Reference Extraction -- Collects all image references from HTML with their id, alt text, and src path. Can be disabled with extractImages: false.
  • Binary Format Guidance -- Detects PDF, DOCX, and PPTX inputs (via magic bytes or extension) and returns informative messages with suggested packages (pdfjs-dist, mammoth, jszip) and code examples. No binary parsers are bundled to keep the dependency tree at zero.
  • HTML Sanitization -- Strips <script>, <style>, <noscript>, <iframe>, <svg>, <canvas>, <nav>, <footer>, <header>, and <aside> elements. Decodes HTML entities including numeric and hex character references.
  • Zero Dependencies -- No runtime dependencies. Only devDependencies for building and testing.

API Reference

convert(input, options?)

The primary conversion function. Accepts a string or Buffer, auto-detects the format (or uses the explicit format from options), converts to markdown, and returns a ConversionResult.

functionconvert(input: string|Buffer,options?: ConvertOptions): ConversionResult;

Parameters:

ParameterTypeDescription
inputstring | BufferThe document content to convert
optionsConvertOptionsOptional conversion settings

Returns:ConversionResult

import{convert}from'docling-node-ts';constresult=convert('<table><thead><tr><th>Name</th><th>Age</th></tr></thead><tbody><tr><td>Alice</td><td>30</td></tr></tbody></table>');console.log(result.markdown);// | Name | Age |// | --- | --- |// | Alice | 30 |

convertHtml(html)

Convenience function that converts HTML to markdown. Equivalent to calling convert(html, { format: 'html' }).

functionconvertHtml(html: string): ConversionResult;
import{convertHtml}from'docling-node-ts';const{ markdown }=convertHtml('<ul><li>First</li><li>Second</li></ul>');// - First// - Second

convertMarkdown(md)

Cleans and normalizes existing markdown. Standardizes list markers, normalizes heading levels, collapses blank lines, removes broken links, and ensures consistent formatting. Equivalent to calling convert(md, { format: 'markdown' }).

functionconvertMarkdown(md: string): ConversionResult;
import{convertMarkdown}from'docling-node-ts';const{ markdown }=convertMarkdown('# Title\n\n\n\n\n#### Skipped Level\n\n* Item');// # Title//// ## Skipped Level//// - Item

convertText(text)

Converts plain text to markdown. Detects headings, lists, and paragraph structure. Equivalent to calling convert(text, { format: 'text' }).

functionconvertText(text: string): ConversionResult;
import{convertText}from'docling-node-ts';const{ markdown }=convertText('INTRODUCTION\n\nSome body text.\n\n1) First step\n2) Second step');// ## INTRODUCTION//// Some body text.//// 1. First step// 2. Second step

detectFormat(input, fileName?)

Detects the format of a document from its content or file name.

Detection priority:

  1. File extension from fileName (.pdf, .docx, .pptx, .html, .htm, .xhtml, .txt, .md, .markdown)
  2. Magic bytes for Buffer inputs (%PDF for PDF, PK\x03\x04 for ZIP-based Office formats)
  3. Content analysis (HTML tags, markdown patterns)
  4. Default: 'text'
functiondetectFormat(input: string|Buffer,fileName?: string): InputFormat;
import{detectFormat}from'docling-node-ts';detectFormat('','report.pdf');// 'pdf'detectFormat('<html><body>Hi</body></html>');// 'html'detectFormat('# Title\n\n## Section');// 'markdown'detectFormat('Just plain text.');// 'text'constpdfBuffer=Buffer.from('%PDF-1.4 ...');detectFormat(pdfBuffer);// 'pdf'

extractMetadata(markdown)

Extracts metadata from a markdown string. Computes word count, heading count, image count, and estimated reading time.

functionextractMetadata(markdown: string): Pick<DocumentMetadata,'wordCount'|'headingCount'|'imageCount'|'readingTimeMinutes'>;
import{extractMetadata}from'docling-node-ts';constmeta=extractMetadata('# Title\n\nSome **bold** text with ![img](photo.png).\n');// { wordCount: 4, headingCount: 1, imageCount: 1, readingTimeMinutes: 1 }

Word counting strips markdown syntax (headings, bold/italic, code blocks, image references, links, blockquotes, horizontal rules, table pipes, and HTML tags) before counting. Reading time is calculated at 200 words per minute, rounded up, with a minimum of 1 minute.

Types

ConversionResult

The return type of all conversion functions.

interfaceConversionResult{/** The converted markdown string */markdown: string;/** Extracted document metadata */metadata: DocumentMetadata;/** Image references found in the document */images: ImageReference[];/** Per-page content breakdown (for paginated formats) */pages: PageContent[];/** Warnings generated during conversion */warnings: string[];/** Conversion duration in milliseconds */durationMs: number;}

ConvertOptions

Options for the convert function.

interfaceConvertOptions{/** Explicitly specify the input format (skips auto-detection) */format?: InputFormat;/** Whether to extract image references (default: true) */extractImages?: boolean;/** Whether to preserve document structure like headings and lists (default: true) */preserveStructure?: boolean;/** Maximum number of pages to process (for paginated formats) */maxPages?: number;/** Whether to insert page break markers (default: false) */pageBreaks?: boolean;/** File name hint for format detection */fileName?: string;}

InputFormat

Supported input format identifiers.

typeInputFormat='html'|'markdown'|'text'|'pdf'|'docx'|'pptx';

DocumentMetadata

Metadata extracted from a converted document.

interfaceDocumentMetadata{title?: string;author?: string;date?: string;pageCount?: number;wordCount: number;headingCount: number;imageCount: number;readingTimeMinutes: number;}

ImageReference

A reference to an image found in the document.

interfaceImageReference{/** Unique identifier for the image (e.g., "img-1") */id: string;/** Alt text for the image */alt: string;/** Source URL or path of the image */src: string;/** Page number where the image was found (if applicable) */page?: number;}

PageContent

Content of a single page in a paginated document.

interfacePageContent{/** Page number (1-based) */pageNumber: number;/** Markdown content of the page */markdown: string;/** Headings found on this page */headings: string[];}

Configuration

Format Override

Skip auto-detection by specifying the format explicitly:

constresult=convert(content,{format: 'html'});

File Name Hint

Provide a file name for extension-based format detection:

constresult=convert(buffer,{fileName: 'report.html'});

Disable Image Extraction

Suppress image reference collection:

constresult=convert(html,{extractImages: false});console.log(result.images);// []

Strip All Formatting

Produce plain text output with no markdown syntax:

constresult=convert('# Heading\n\n**bold** and *italic*',{format: 'markdown',preserveStructure: false,});console.log(result.markdown);// Heading//// bold and italic

Error Handling

All conversion functions are synchronous and do not throw under normal operation. Errors and edge cases are communicated through the warnings array in the ConversionResult.

Binary Formats

When a binary format (PDF, DOCX, PPTX) is detected, the library does not throw. Instead, it returns a ConversionResult with an informative markdown message describing the detected format, suggested external packages, and example code:

constresult=convert(pdfBuffer);console.log(result.warnings);// [// 'Binary format "pdf" detected. Install a dedicated parser for full support.',// 'Suggested packages: `pdfjs-dist`, `pdf-parse`, `pdf2json`'// ]

Unexpected Formats

If the detected format does not match any known converter, the input is treated as plain text and a warning is added:

// result.warnings: ['Unexpected format: xyz. Treating as plain text.']

Empty or Whitespace Input

Empty strings and whitespace-only input produce minimal output without errors:

constresult=convert('');console.log(result.markdown);// '\n'console.log(result.metadata.wordCount);// 0

Advanced Usage

RAG Pipeline Integration

Use docling-node-ts as the first stage in a document ingestion pipeline. The output markdown is designed for downstream chunking and embedding:

import{convert}from'docling-node-ts';functioningestDocument(html: string){const{ markdown, metadata, images, warnings }=convert(html);if(warnings.length>0){console.warn('Conversion warnings:',warnings);}// Chunk the markdown for embedding (e.g., with chunk-smart)// const chunks = chunkMarkdown(markdown, { maxTokens: 512 });return{ markdown, metadata, images };}

Processing Buffers from File Uploads

import{convert}from'docling-node-ts';functionhandleUpload(buffer: Buffer,originalFileName: string){constresult=convert(buffer,{fileName: originalFileName});return{markdown: result.markdown,title: result.metadata.title,wordCount: result.metadata.wordCount,readingTime: result.metadata.readingTimeMinutes,imageCount: result.images.length,};}

HTML Metadata Extraction

When converting HTML, the library extracts metadata from <head> elements:

import{convert}from'docling-node-ts';consthtml=`<html><head> <title>Annual Report 2024</title> <meta name="author" content="Finance Team"> <meta name="date" content="2024-12-01"> <meta property="og:title" content="Annual Report"></head><body> <h1>Annual Report</h1> <p>Revenue increased by 20%.</p></body></html>`;constresult=convert(html);console.log(result.metadata.title);// 'Annual Report 2024'console.log(result.metadata.author);// 'Finance Team'console.log(result.metadata.date);// '2024-12-01'

Title extraction priority: <title> tag, then og:title. Author extraction checks both name="author" and property="article:author". Date extraction checks both name="date" and property="article:published_time".

Normalizing Imported Markdown

Clean up markdown from external sources that may have inconsistent formatting:

import{convertMarkdown}from'docling-node-ts';constmessy=`# Title#### Jumped Heading Level* Mixed+ List- MarkersClick [broken]() link.[Valid link](https://example.com)`;const{ markdown }=convertMarkdown(messy);// Heading levels normalized (#### becomes ##)// List markers standardized to -// Broken link text extracted without brackets// Excessive blank lines collapsed

HTML Table Conversion

Tables are converted to GitHub Flavored Markdown pipe tables with column normalization and pipe escaping:

import{convertHtml}from'docling-node-ts';consthtml=`<table> <thead> <tr><th>Product</th><th>Q1</th><th>Q2</th></tr> </thead> <tbody> <tr><td>Widget A</td><td>$1,200</td><td>$1,500</td></tr> <tr><td>Widget B</td><td>$800</td><td>$950</td></tr> </tbody></table>`;const{ markdown }=convertHtml(html);// | Product | Q1 | Q2 |// | --- | --- | --- |// | Widget A | $1,200 | $1,500 |// | Widget B | $800 | $950 |

Rows with fewer columns are padded with empty cells. Pipe characters (|) inside cell content are escaped as \|.

TypeScript

This package is written in TypeScript and ships type declarations (dist/index.d.ts) alongside the compiled JavaScript. All public types are exported from the package entry point:

importtype{ConversionResult,ConvertOptions,InputFormat,DocumentMetadata,ImageReference,PageContent,}from'docling-node-ts';

Compiled with strict: true, targeting ES2022 with CommonJS module output.

License

MIT

About

Convert documents to clean RAG-ready markdown in Node.js

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - SiluPanda/docling-node-ts: Convert documents to clean RAG-ready markdown in Node.js · GitHub
Skip to content

Repository files navigation

docling-node-ts

Zero-dependency document-to-markdown conversion for Node.js.

npm versionnpm downloadslicensenode

Convert HTML, plain text, and markdown documents into clean, structure-preserving markdown suitable for RAG (Retrieval-Augmented Generation) pipelines, knowledge base construction, and LLM ingestion. Accepts string or Buffer input, auto-detects the format, routes to the appropriate converter, extracts metadata and image references, and returns a typed ConversionResult. No external services, no Python runtime, no network calls -- everything runs locally in Node.js.


Installation

npm install docling-node-ts

Requires Node.js 18 or later.

Quick Start

import{convert}from'docling-node-ts';// Convert HTML to markdownconstresult=convert('<h1>Quarterly Report</h1><p>Revenue grew <strong>15%</strong> year-over-year.</p>');console.log(result.markdown);// # Quarterly Report//// Revenue grew **15%** year-over-year.console.log(result.metadata);// { wordCount: 5, headingCount: 1, imageCount: 0, readingTimeMinutes: 1 }console.log(result.durationMs);// 2
// Convert a Buffer with auto-detectionimport{readFileSync}from'fs';constbuf=readFileSync('report.html');const{ markdown, metadata, images, warnings }=convert(buf);

Features

  • HTML to Markdown -- Converts headings (h1-h6), paragraphs, bold, italic, strikethrough, inline code, links, images, ordered and unordered lists (including nested), GFM pipe tables, fenced code blocks with language hints, blockquotes, horizontal rules, <figure>/<figcaption>, and <sup>/<sub> elements.
  • Plain Text to Markdown -- Detects setext-style headings (underlined with === or ---), ALL CAPS headings, unordered and ordered lists, and paragraph breaks. Normalizes list markers and line endings.
  • Markdown Normalization -- Cleans and normalizes existing markdown: collapses excessive blank lines, standardizes list markers to -, normalizes heading levels to eliminate gaps, fixes broken links with empty hrefs, and ensures consistent spacing around headings.
  • Format Auto-Detection -- Detects the input format automatically using file extension, magic bytes (for Buffer inputs), and content analysis (HTML tags, markdown patterns). Supports explicit format override via options.
  • Metadata Extraction -- Returns word count, heading count, image count, and estimated reading time. For HTML inputs, extracts title, author, and date from <title>, <meta>, and Open Graph tags.
  • Image Reference Extraction -- Collects all image references from HTML with their id, alt text, and src path. Can be disabled with extractImages: false.
  • Binary Format Guidance -- Detects PDF, DOCX, and PPTX inputs (via magic bytes or extension) and returns informative messages with suggested packages (pdfjs-dist, mammoth, jszip) and code examples. No binary parsers are bundled to keep the dependency tree at zero.
  • HTML Sanitization -- Strips <script>, <style>, <noscript>, <iframe>, <svg>, <canvas>, <nav>, <footer>, <header>, and <aside> elements. Decodes HTML entities including numeric and hex character references.
  • Zero Dependencies -- No runtime dependencies. Only devDependencies for building and testing.

API Reference

convert(input, options?)

The primary conversion function. Accepts a string or Buffer, auto-detects the format (or uses the explicit format from options), converts to markdown, and returns a ConversionResult.

functionconvert(input: string|Buffer,options?: ConvertOptions): ConversionResult;

Parameters:

ParameterTypeDescription
inputstring | BufferThe document content to convert
optionsConvertOptionsOptional conversion settings

Returns:ConversionResult

import{convert}from'docling-node-ts';constresult=convert('<table><thead><tr><th>Name</th><th>Age</th></tr></thead><tbody><tr><td>Alice</td><td>30</td></tr></tbody></table>');console.log(result.markdown);// | Name | Age |// | --- | --- |// | Alice | 30 |

convertHtml(html)

Convenience function that converts HTML to markdown. Equivalent to calling convert(html, { format: 'html' }).

functionconvertHtml(html: string): ConversionResult;
import{convertHtml}from'docling-node-ts';const{ markdown }=convertHtml('<ul><li>First</li><li>Second</li></ul>');// - First// - Second

convertMarkdown(md)

Cleans and normalizes existing markdown. Standardizes list markers, normalizes heading levels, collapses blank lines, removes broken links, and ensures consistent formatting. Equivalent to calling convert(md, { format: 'markdown' }).

functionconvertMarkdown(md: string): ConversionResult;
import{convertMarkdown}from'docling-node-ts';const{ markdown }=convertMarkdown('# Title\n\n\n\n\n#### Skipped Level\n\n* Item');// # Title//// ## Skipped Level//// - Item

convertText(text)

Converts plain text to markdown. Detects headings, lists, and paragraph structure. Equivalent to calling convert(text, { format: 'text' }).

functionconvertText(text: string): ConversionResult;
import{convertText}from'docling-node-ts';const{ markdown }=convertText('INTRODUCTION\n\nSome body text.\n\n1) First step\n2) Second step');// ## INTRODUCTION//// Some body text.//// 1. First step// 2. Second step

detectFormat(input, fileName?)

Detects the format of a document from its content or file name.

Detection priority:

  1. File extension from fileName (.pdf, .docx, .pptx, .html, .htm, .xhtml, .txt, .md, .markdown)
  2. Magic bytes for Buffer inputs (%PDF for PDF, PK\x03\x04 for ZIP-based Office formats)
  3. Content analysis (HTML tags, markdown patterns)
  4. Default: 'text'
functiondetectFormat(input: string|Buffer,fileName?: string): InputFormat;
import{detectFormat}from'docling-node-ts';detectFormat('','report.pdf');// 'pdf'detectFormat('<html><body>Hi</body></html>');// 'html'detectFormat('# Title\n\n## Section');// 'markdown'detectFormat('Just plain text.');// 'text'constpdfBuffer=Buffer.from('%PDF-1.4 ...');detectFormat(pdfBuffer);// 'pdf'

extractMetadata(markdown)

Extracts metadata from a markdown string. Computes word count, heading count, image count, and estimated reading time.

functionextractMetadata(markdown: string): Pick<DocumentMetadata,'wordCount'|'headingCount'|'imageCount'|'readingTimeMinutes'>;
import{extractMetadata}from'docling-node-ts';constmeta=extractMetadata('# Title\n\nSome **bold** text with ![img](photo.png).\n');// { wordCount: 4, headingCount: 1, imageCount: 1, readingTimeMinutes: 1 }

Word counting strips markdown syntax (headings, bold/italic, code blocks, image references, links, blockquotes, horizontal rules, table pipes, and HTML tags) before counting. Reading time is calculated at 200 words per minute, rounded up, with a minimum of 1 minute.

Types

ConversionResult

The return type of all conversion functions.

interfaceConversionResult{/** The converted markdown string */markdown: string;/** Extracted document metadata */metadata: DocumentMetadata;/** Image references found in the document */images: ImageReference[];/** Per-page content breakdown (for paginated formats) */pages: PageContent[];/** Warnings generated during conversion */warnings: string[];/** Conversion duration in milliseconds */durationMs: number;}

ConvertOptions

Options for the convert function.

interfaceConvertOptions{/** Explicitly specify the input format (skips auto-detection) */format?: InputFormat;/** Whether to extract image references (default: true) */extractImages?: boolean;/** Whether to preserve document structure like headings and lists (default: true) */preserveStructure?: boolean;/** Maximum number of pages to process (for paginated formats) */maxPages?: number;/** Whether to insert page break markers (default: false) */pageBreaks?: boolean;/** File name hint for format detection */fileName?: string;}

InputFormat

Supported input format identifiers.

typeInputFormat='html'|'markdown'|'text'|'pdf'|'docx'|'pptx';

DocumentMetadata

Metadata extracted from a converted document.

interfaceDocumentMetadata{title?: string;author?: string;date?: string;pageCount?: number;wordCount: number;headingCount: number;imageCount: number;readingTimeMinutes: number;}

ImageReference

A reference to an image found in the document.

interfaceImageReference{/** Unique identifier for the image (e.g., "img-1") */id: string;/** Alt text for the image */alt: string;/** Source URL or path of the image */src: string;/** Page number where the image was found (if applicable) */page?: number;}

PageContent

Content of a single page in a paginated document.

interfacePageContent{/** Page number (1-based) */pageNumber: number;/** Markdown content of the page */markdown: string;/** Headings found on this page */headings: string[];}

Configuration

Format Override

Skip auto-detection by specifying the format explicitly:

constresult=convert(content,{format: 'html'});

File Name Hint

Provide a file name for extension-based format detection:

constresult=convert(buffer,{fileName: 'report.html'});

Disable Image Extraction

Suppress image reference collection:

constresult=convert(html,{extractImages: false});console.log(result.images);// []

Strip All Formatting

Produce plain text output with no markdown syntax:

constresult=convert('# Heading\n\n**bold** and *italic*',{format: 'markdown',preserveStructure: false,});console.log(result.markdown);// Heading//// bold and italic

Error Handling

All conversion functions are synchronous and do not throw under normal operation. Errors and edge cases are communicated through the warnings array in the ConversionResult.

Binary Formats

When a binary format (PDF, DOCX, PPTX) is detected, the library does not throw. Instead, it returns a ConversionResult with an informative markdown message describing the detected format, suggested external packages, and example code:

constresult=convert(pdfBuffer);console.log(result.warnings);// [// 'Binary format "pdf" detected. Install a dedicated parser for full support.',// 'Suggested packages: `pdfjs-dist`, `pdf-parse`, `pdf2json`'// ]

Unexpected Formats

If the detected format does not match any known converter, the input is treated as plain text and a warning is added:

// result.warnings: ['Unexpected format: xyz. Treating as plain text.']

Empty or Whitespace Input

Empty strings and whitespace-only input produce minimal output without errors:

constresult=convert('');console.log(result.markdown);// '\n'console.log(result.metadata.wordCount);// 0

Advanced Usage

RAG Pipeline Integration

Use docling-node-ts as the first stage in a document ingestion pipeline. The output markdown is designed for downstream chunking and embedding:

import{convert}from'docling-node-ts';functioningestDocument(html: string){const{ markdown, metadata, images, warnings }=convert(html);if(warnings.length>0){console.warn('Conversion warnings:',warnings);}// Chunk the markdown for embedding (e.g., with chunk-smart)// const chunks = chunkMarkdown(markdown, { maxTokens: 512 });return{ markdown, metadata, images };}

Processing Buffers from File Uploads

import{convert}from'docling-node-ts';functionhandleUpload(buffer: Buffer,originalFileName: string){constresult=convert(buffer,{fileName: originalFileName});return{markdown: result.markdown,title: result.metadata.title,wordCount: result.metadata.wordCount,readingTime: result.metadata.readingTimeMinutes,imageCount: result.images.length,};}

HTML Metadata Extraction

When converting HTML, the library extracts metadata from <head> elements:

import{convert}from'docling-node-ts';consthtml=`<html><head> <title>Annual Report 2024</title> <meta name="author" content="Finance Team"> <meta name="date" content="2024-12-01"> <meta property="og:title" content="Annual Report"></head><body> <h1>Annual Report</h1> <p>Revenue increased by 20%.</p></body></html>`;constresult=convert(html);console.log(result.metadata.title);// 'Annual Report 2024'console.log(result.metadata.author);// 'Finance Team'console.log(result.metadata.date);// '2024-12-01'

Title extraction priority: <title> tag, then og:title. Author extraction checks both name="author" and property="article:author". Date extraction checks both name="date" and property="article:published_time".

Normalizing Imported Markdown

Clean up markdown from external sources that may have inconsistent formatting:

import{convertMarkdown}from'docling-node-ts';constmessy=`# Title#### Jumped Heading Level* Mixed+ List- MarkersClick [broken]() link.[Valid link](https://example.com)`;const{ markdown }=convertMarkdown(messy);// Heading levels normalized (#### becomes ##)// List markers standardized to -// Broken link text extracted without brackets// Excessive blank lines collapsed

HTML Table Conversion

Tables are converted to GitHub Flavored Markdown pipe tables with column normalization and pipe escaping:

import{convertHtml}from'docling-node-ts';consthtml=`<table> <thead> <tr><th>Product</th><th>Q1</th><th>Q2</th></tr> </thead> <tbody> <tr><td>Widget A</td><td>$1,200</td><td>$1,500</td></tr> <tr><td>Widget B</td><td>$800</td><td>$950</td></tr> </tbody></table>`;const{ markdown }=convertHtml(html);// | Product | Q1 | Q2 |// | --- | --- | --- |// | Widget A | $1,200 | $1,500 |// | Widget B | $800 | $950 |

Rows with fewer columns are padded with empty cells. Pipe characters (|) inside cell content are escaped as \|.

TypeScript

This package is written in TypeScript and ships type declarations (dist/index.d.ts) alongside the compiled JavaScript. All public types are exported from the package entry point:

importtype{ConversionResult,ConvertOptions,InputFormat,DocumentMetadata,ImageReference,PageContent,}from'docling-node-ts';

Compiled with strict: true, targeting ES2022 with CommonJS module output.

License

MIT

About

Convert documents to clean RAG-ready markdown in Node.js

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - SiluPanda/docling-node-ts: Convert documents to clean RAG-ready markdown in Node.js · GitHub
Skip to content

Repository files navigation

docling-node-ts

Zero-dependency document-to-markdown conversion for Node.js.

npm versionnpm downloadslicensenode

Convert HTML, plain text, and markdown documents into clean, structure-preserving markdown suitable for RAG (Retrieval-Augmented Generation) pipelines, knowledge base construction, and LLM ingestion. Accepts string or Buffer input, auto-detects the format, routes to the appropriate converter, extracts metadata and image references, and returns a typed ConversionResult. No external services, no Python runtime, no network calls -- everything runs locally in Node.js.


Installation

npm install docling-node-ts

Requires Node.js 18 or later.

Quick Start

import{convert}from'docling-node-ts';// Convert HTML to markdownconstresult=convert('<h1>Quarterly Report</h1><p>Revenue grew <strong>15%</strong> year-over-year.</p>');console.log(result.markdown);// # Quarterly Report//// Revenue grew **15%** year-over-year.console.log(result.metadata);// { wordCount: 5, headingCount: 1, imageCount: 0, readingTimeMinutes: 1 }console.log(result.durationMs);// 2
// Convert a Buffer with auto-detectionimport{readFileSync}from'fs';constbuf=readFileSync('report.html');const{ markdown, metadata, images, warnings }=convert(buf);

Features

  • HTML to Markdown -- Converts headings (h1-h6), paragraphs, bold, italic, strikethrough, inline code, links, images, ordered and unordered lists (including nested), GFM pipe tables, fenced code blocks with language hints, blockquotes, horizontal rules, <figure>/<figcaption>, and <sup>/<sub> elements.
  • Plain Text to Markdown -- Detects setext-style headings (underlined with === or ---), ALL CAPS headings, unordered and ordered lists, and paragraph breaks. Normalizes list markers and line endings.
  • Markdown Normalization -- Cleans and normalizes existing markdown: collapses excessive blank lines, standardizes list markers to -, normalizes heading levels to eliminate gaps, fixes broken links with empty hrefs, and ensures consistent spacing around headings.
  • Format Auto-Detection -- Detects the input format automatically using file extension, magic bytes (for Buffer inputs), and content analysis (HTML tags, markdown patterns). Supports explicit format override via options.
  • Metadata Extraction -- Returns word count, heading count, image count, and estimated reading time. For HTML inputs, extracts title, author, and date from <title>, <meta>, and Open Graph tags.
  • Image Reference Extraction -- Collects all image references from HTML with their id, alt text, and src path. Can be disabled with extractImages: false.
  • Binary Format Guidance -- Detects PDF, DOCX, and PPTX inputs (via magic bytes or extension) and returns informative messages with suggested packages (pdfjs-dist, mammoth, jszip) and code examples. No binary parsers are bundled to keep the dependency tree at zero.
  • HTML Sanitization -- Strips <script>, <style>, <noscript>, <iframe>, <svg>, <canvas>, <nav>, <footer>, <header>, and <aside> elements. Decodes HTML entities including numeric and hex character references.
  • Zero Dependencies -- No runtime dependencies. Only devDependencies for building and testing.

API Reference

convert(input, options?)

The primary conversion function. Accepts a string or Buffer, auto-detects the format (or uses the explicit format from options), converts to markdown, and returns a ConversionResult.

functionconvert(input: string|Buffer,options?: ConvertOptions): ConversionResult;

Parameters:

ParameterTypeDescription
inputstring | BufferThe document content to convert
optionsConvertOptionsOptional conversion settings

Returns:ConversionResult

import{convert}from'docling-node-ts';constresult=convert('<table><thead><tr><th>Name</th><th>Age</th></tr></thead><tbody><tr><td>Alice</td><td>30</td></tr></tbody></table>');console.log(result.markdown);// | Name | Age |// | --- | --- |// | Alice | 30 |

convertHtml(html)

Convenience function that converts HTML to markdown. Equivalent to calling convert(html, { format: 'html' }).

functionconvertHtml(html: string): ConversionResult;
import{convertHtml}from'docling-node-ts';const{ markdown }=convertHtml('<ul><li>First</li><li>Second</li></ul>');// - First// - Second

convertMarkdown(md)

Cleans and normalizes existing markdown. Standardizes list markers, normalizes heading levels, collapses blank lines, removes broken links, and ensures consistent formatting. Equivalent to calling convert(md, { format: 'markdown' }).

functionconvertMarkdown(md: string): ConversionResult;
import{convertMarkdown}from'docling-node-ts';const{ markdown }=convertMarkdown('# Title\n\n\n\n\n#### Skipped Level\n\n* Item');// # Title//// ## Skipped Level//// - Item

convertText(text)

Converts plain text to markdown. Detects headings, lists, and paragraph structure. Equivalent to calling convert(text, { format: 'text' }).

functionconvertText(text: string): ConversionResult;
import{convertText}from'docling-node-ts';const{ markdown }=convertText('INTRODUCTION\n\nSome body text.\n\n1) First step\n2) Second step');// ## INTRODUCTION//// Some body text.//// 1. First step// 2. Second step

detectFormat(input, fileName?)

Detects the format of a document from its content or file name.

Detection priority:

  1. File extension from fileName (.pdf, .docx, .pptx, .html, .htm, .xhtml, .txt, .md, .markdown)
  2. Magic bytes for Buffer inputs (%PDF for PDF, PK\x03\x04 for ZIP-based Office formats)
  3. Content analysis (HTML tags, markdown patterns)
  4. Default: 'text'
functiondetectFormat(input: string|Buffer,fileName?: string): InputFormat;
import{detectFormat}from'docling-node-ts';detectFormat('','report.pdf');// 'pdf'detectFormat('<html><body>Hi</body></html>');// 'html'detectFormat('# Title\n\n## Section');// 'markdown'detectFormat('Just plain text.');// 'text'constpdfBuffer=Buffer.from('%PDF-1.4 ...');detectFormat(pdfBuffer);// 'pdf'

extractMetadata(markdown)

Extracts metadata from a markdown string. Computes word count, heading count, image count, and estimated reading time.

functionextractMetadata(markdown: string): Pick<DocumentMetadata,'wordCount'|'headingCount'|'imageCount'|'readingTimeMinutes'>;
import{extractMetadata}from'docling-node-ts';constmeta=extractMetadata('# Title\n\nSome **bold** text with ![img](photo.png).\n');// { wordCount: 4, headingCount: 1, imageCount: 1, readingTimeMinutes: 1 }

Word counting strips markdown syntax (headings, bold/italic, code blocks, image references, links, blockquotes, horizontal rules, table pipes, and HTML tags) before counting. Reading time is calculated at 200 words per minute, rounded up, with a minimum of 1 minute.

Types

ConversionResult

The return type of all conversion functions.

interfaceConversionResult{/** The converted markdown string */markdown: string;/** Extracted document metadata */metadata: DocumentMetadata;/** Image references found in the document */images: ImageReference[];/** Per-page content breakdown (for paginated formats) */pages: PageContent[];/** Warnings generated during conversion */warnings: string[];/** Conversion duration in milliseconds */durationMs: number;}

ConvertOptions

Options for the convert function.

interfaceConvertOptions{/** Explicitly specify the input format (skips auto-detection) */format?: InputFormat;/** Whether to extract image references (default: true) */extractImages?: boolean;/** Whether to preserve document structure like headings and lists (default: true) */preserveStructure?: boolean;/** Maximum number of pages to process (for paginated formats) */maxPages?: number;/** Whether to insert page break markers (default: false) */pageBreaks?: boolean;/** File name hint for format detection */fileName?: string;}

InputFormat

Supported input format identifiers.

typeInputFormat='html'|'markdown'|'text'|'pdf'|'docx'|'pptx';

DocumentMetadata

Metadata extracted from a converted document.

interfaceDocumentMetadata{title?: string;author?: string;date?: string;pageCount?: number;wordCount: number;headingCount: number;imageCount: number;readingTimeMinutes: number;}

ImageReference

A reference to an image found in the document.

interfaceImageReference{/** Unique identifier for the image (e.g., "img-1") */id: string;/** Alt text for the image */alt: string;/** Source URL or path of the image */src: string;/** Page number where the image was found (if applicable) */page?: number;}

PageContent

Content of a single page in a paginated document.

interfacePageContent{/** Page number (1-based) */pageNumber: number;/** Markdown content of the page */markdown: string;/** Headings found on this page */headings: string[];}

Configuration

Format Override

Skip auto-detection by specifying the format explicitly:

constresult=convert(content,{format: 'html'});

File Name Hint

Provide a file name for extension-based format detection:

constresult=convert(buffer,{fileName: 'report.html'});

Disable Image Extraction

Suppress image reference collection:

constresult=convert(html,{extractImages: false});console.log(result.images);// []

Strip All Formatting

Produce plain text output with no markdown syntax:

constresult=convert('# Heading\n\n**bold** and *italic*',{format: 'markdown',preserveStructure: false,});console.log(result.markdown);// Heading//// bold and italic

Error Handling

All conversion functions are synchronous and do not throw under normal operation. Errors and edge cases are communicated through the warnings array in the ConversionResult.

Binary Formats

When a binary format (PDF, DOCX, PPTX) is detected, the library does not throw. Instead, it returns a ConversionResult with an informative markdown message describing the detected format, suggested external packages, and example code:

constresult=convert(pdfBuffer);console.log(result.warnings);// [// 'Binary format "pdf" detected. Install a dedicated parser for full support.',// 'Suggested packages: `pdfjs-dist`, `pdf-parse`, `pdf2json`'// ]

Unexpected Formats

If the detected format does not match any known converter, the input is treated as plain text and a warning is added:

// result.warnings: ['Unexpected format: xyz. Treating as plain text.']

Empty or Whitespace Input

Empty strings and whitespace-only input produce minimal output without errors:

constresult=convert('');console.log(result.markdown);// '\n'console.log(result.metadata.wordCount);// 0

Advanced Usage

RAG Pipeline Integration

Use docling-node-ts as the first stage in a document ingestion pipeline. The output markdown is designed for downstream chunking and embedding:

import{convert}from'docling-node-ts';functioningestDocument(html: string){const{ markdown, metadata, images, warnings }=convert(html);if(warnings.length>0){console.warn('Conversion warnings:',warnings);}// Chunk the markdown for embedding (e.g., with chunk-smart)// const chunks = chunkMarkdown(markdown, { maxTokens: 512 });return{ markdown, metadata, images };}

Processing Buffers from File Uploads

import{convert}from'docling-node-ts';functionhandleUpload(buffer: Buffer,originalFileName: string){constresult=convert(buffer,{fileName: originalFileName});return{markdown: result.markdown,title: result.metadata.title,wordCount: result.metadata.wordCount,readingTime: result.metadata.readingTimeMinutes,imageCount: result.images.length,};}

HTML Metadata Extraction

When converting HTML, the library extracts metadata from <head> elements:

import{convert}from'docling-node-ts';consthtml=`<html><head> <title>Annual Report 2024</title> <meta name="author" content="Finance Team"> <meta name="date" content="2024-12-01"> <meta property="og:title" content="Annual Report"></head><body> <h1>Annual Report</h1> <p>Revenue increased by 20%.</p></body></html>`;constresult=convert(html);console.log(result.metadata.title);// 'Annual Report 2024'console.log(result.metadata.author);// 'Finance Team'console.log(result.metadata.date);// '2024-12-01'

Title extraction priority: <title> tag, then og:title. Author extraction checks both name="author" and property="article:author". Date extraction checks both name="date" and property="article:published_time".

Normalizing Imported Markdown

Clean up markdown from external sources that may have inconsistent formatting:

import{convertMarkdown}from'docling-node-ts';constmessy=`# Title#### Jumped Heading Level* Mixed+ List- MarkersClick [broken]() link.[Valid link](https://example.com)`;const{ markdown }=convertMarkdown(messy);// Heading levels normalized (#### becomes ##)// List markers standardized to -// Broken link text extracted without brackets// Excessive blank lines collapsed

HTML Table Conversion

Tables are converted to GitHub Flavored Markdown pipe tables with column normalization and pipe escaping:

import{convertHtml}from'docling-node-ts';consthtml=`<table> <thead> <tr><th>Product</th><th>Q1</th><th>Q2</th></tr> </thead> <tbody> <tr><td>Widget A</td><td>$1,200</td><td>$1,500</td></tr> <tr><td>Widget B</td><td>$800</td><td>$950</td></tr> </tbody></table>`;const{ markdown }=convertHtml(html);// | Product | Q1 | Q2 |// | --- | --- | --- |// | Widget A | $1,200 | $1,500 |// | Widget B | $800 | $950 |

Rows with fewer columns are padded with empty cells. Pipe characters (|) inside cell content are escaped as \|.

TypeScript

This package is written in TypeScript and ships type declarations (dist/index.d.ts) alongside the compiled JavaScript. All public types are exported from the package entry point:

importtype{ConversionResult,ConvertOptions,InputFormat,DocumentMetadata,ImageReference,PageContent,}from'docling-node-ts';

Compiled with strict: true, targeting ES2022 with CommonJS module output.

License

MIT

About

Convert documents to clean RAG-ready markdown in Node.js

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - SiluPanda/docling-node-ts: Convert documents to clean RAG-ready markdown in Node.js · GitHub
Skip to content

Repository files navigation

docling-node-ts

Zero-dependency document-to-markdown conversion for Node.js.

npm versionnpm downloadslicensenode

Convert HTML, plain text, and markdown documents into clean, structure-preserving markdown suitable for RAG (Retrieval-Augmented Generation) pipelines, knowledge base construction, and LLM ingestion. Accepts string or Buffer input, auto-detects the format, routes to the appropriate converter, extracts metadata and image references, and returns a typed ConversionResult. No external services, no Python runtime, no network calls -- everything runs locally in Node.js.


Installation

npm install docling-node-ts

Requires Node.js 18 or later.

Quick Start

import{convert}from'docling-node-ts';// Convert HTML to markdownconstresult=convert('<h1>Quarterly Report</h1><p>Revenue grew <strong>15%</strong> year-over-year.</p>');console.log(result.markdown);// # Quarterly Report//// Revenue grew **15%** year-over-year.console.log(result.metadata);// { wordCount: 5, headingCount: 1, imageCount: 0, readingTimeMinutes: 1 }console.log(result.durationMs);// 2
// Convert a Buffer with auto-detectionimport{readFileSync}from'fs';constbuf=readFileSync('report.html');const{ markdown, metadata, images, warnings }=convert(buf);

Features

  • HTML to Markdown -- Converts headings (h1-h6), paragraphs, bold, italic, strikethrough, inline code, links, images, ordered and unordered lists (including nested), GFM pipe tables, fenced code blocks with language hints, blockquotes, horizontal rules, <figure>/<figcaption>, and <sup>/<sub> elements.
  • Plain Text to Markdown -- Detects setext-style headings (underlined with === or ---), ALL CAPS headings, unordered and ordered lists, and paragraph breaks. Normalizes list markers and line endings.
  • Markdown Normalization -- Cleans and normalizes existing markdown: collapses excessive blank lines, standardizes list markers to -, normalizes heading levels to eliminate gaps, fixes broken links with empty hrefs, and ensures consistent spacing around headings.
  • Format Auto-Detection -- Detects the input format automatically using file extension, magic bytes (for Buffer inputs), and content analysis (HTML tags, markdown patterns). Supports explicit format override via options.
  • Metadata Extraction -- Returns word count, heading count, image count, and estimated reading time. For HTML inputs, extracts title, author, and date from <title>, <meta>, and Open Graph tags.
  • Image Reference Extraction -- Collects all image references from HTML with their id, alt text, and src path. Can be disabled with extractImages: false.
  • Binary Format Guidance -- Detects PDF, DOCX, and PPTX inputs (via magic bytes or extension) and returns informative messages with suggested packages (pdfjs-dist, mammoth, jszip) and code examples. No binary parsers are bundled to keep the dependency tree at zero.
  • HTML Sanitization -- Strips <script>, <style>, <noscript>, <iframe>, <svg>, <canvas>, <nav>, <footer>, <header>, and <aside> elements. Decodes HTML entities including numeric and hex character references.
  • Zero Dependencies -- No runtime dependencies. Only devDependencies for building and testing.

API Reference

convert(input, options?)

The primary conversion function. Accepts a string or Buffer, auto-detects the format (or uses the explicit format from options), converts to markdown, and returns a ConversionResult.

functionconvert(input: string|Buffer,options?: ConvertOptions): ConversionResult;

Parameters:

ParameterTypeDescription
inputstring | BufferThe document content to convert
optionsConvertOptionsOptional conversion settings

Returns:ConversionResult

import{convert}from'docling-node-ts';constresult=convert('<table><thead><tr><th>Name</th><th>Age</th></tr></thead><tbody><tr><td>Alice</td><td>30</td></tr></tbody></table>');console.log(result.markdown);// | Name | Age |// | --- | --- |// | Alice | 30 |

convertHtml(html)

Convenience function that converts HTML to markdown. Equivalent to calling convert(html, { format: 'html' }).

functionconvertHtml(html: string): ConversionResult;
import{convertHtml}from'docling-node-ts';const{ markdown }=convertHtml('<ul><li>First</li><li>Second</li></ul>');// - First// - Second

convertMarkdown(md)

Cleans and normalizes existing markdown. Standardizes list markers, normalizes heading levels, collapses blank lines, removes broken links, and ensures consistent formatting. Equivalent to calling convert(md, { format: 'markdown' }).

functionconvertMarkdown(md: string): ConversionResult;
import{convertMarkdown}from'docling-node-ts';const{ markdown }=convertMarkdown('# Title\n\n\n\n\n#### Skipped Level\n\n* Item');// # Title//// ## Skipped Level//// - Item

convertText(text)

Converts plain text to markdown. Detects headings, lists, and paragraph structure. Equivalent to calling convert(text, { format: 'text' }).

functionconvertText(text: string): ConversionResult;
import{convertText}from'docling-node-ts';const{ markdown }=convertText('INTRODUCTION\n\nSome body text.\n\n1) First step\n2) Second step');// ## INTRODUCTION//// Some body text.//// 1. First step// 2. Second step

detectFormat(input, fileName?)

Detects the format of a document from its content or file name.

Detection priority:

  1. File extension from fileName (.pdf, .docx, .pptx, .html, .htm, .xhtml, .txt, .md, .markdown)
  2. Magic bytes for Buffer inputs (%PDF for PDF, PK\x03\x04 for ZIP-based Office formats)
  3. Content analysis (HTML tags, markdown patterns)
  4. Default: 'text'
functiondetectFormat(input: string|Buffer,fileName?: string): InputFormat;
import{detectFormat}from'docling-node-ts';detectFormat('','report.pdf');// 'pdf'detectFormat('<html><body>Hi</body></html>');// 'html'detectFormat('# Title\n\n## Section');// 'markdown'detectFormat('Just plain text.');// 'text'constpdfBuffer=Buffer.from('%PDF-1.4 ...');detectFormat(pdfBuffer);// 'pdf'

extractMetadata(markdown)

Extracts metadata from a markdown string. Computes word count, heading count, image count, and estimated reading time.

functionextractMetadata(markdown: string): Pick<DocumentMetadata,'wordCount'|'headingCount'|'imageCount'|'readingTimeMinutes'>;
import{extractMetadata}from'docling-node-ts';constmeta=extractMetadata('# Title\n\nSome **bold** text with ![img](photo.png).\n');// { wordCount: 4, headingCount: 1, imageCount: 1, readingTimeMinutes: 1 }

Word counting strips markdown syntax (headings, bold/italic, code blocks, image references, links, blockquotes, horizontal rules, table pipes, and HTML tags) before counting. Reading time is calculated at 200 words per minute, rounded up, with a minimum of 1 minute.

Types

ConversionResult

The return type of all conversion functions.

interfaceConversionResult{/** The converted markdown string */markdown: string;/** Extracted document metadata */metadata: DocumentMetadata;/** Image references found in the document */images: ImageReference[];/** Per-page content breakdown (for paginated formats) */pages: PageContent[];/** Warnings generated during conversion */warnings: string[];/** Conversion duration in milliseconds */durationMs: number;}

ConvertOptions

Options for the convert function.

interfaceConvertOptions{/** Explicitly specify the input format (skips auto-detection) */format?: InputFormat;/** Whether to extract image references (default: true) */extractImages?: boolean;/** Whether to preserve document structure like headings and lists (default: true) */preserveStructure?: boolean;/** Maximum number of pages to process (for paginated formats) */maxPages?: number;/** Whether to insert page break markers (default: false) */pageBreaks?: boolean;/** File name hint for format detection */fileName?: string;}

InputFormat

Supported input format identifiers.

typeInputFormat='html'|'markdown'|'text'|'pdf'|'docx'|'pptx';

DocumentMetadata

Metadata extracted from a converted document.

interfaceDocumentMetadata{title?: string;author?: string;date?: string;pageCount?: number;wordCount: number;headingCount: number;imageCount: number;readingTimeMinutes: number;}

ImageReference

A reference to an image found in the document.

interfaceImageReference{/** Unique identifier for the image (e.g., "img-1") */id: string;/** Alt text for the image */alt: string;/** Source URL or path of the image */src: string;/** Page number where the image was found (if applicable) */page?: number;}

PageContent

Content of a single page in a paginated document.

interfacePageContent{/** Page number (1-based) */pageNumber: number;/** Markdown content of the page */markdown: string;/** Headings found on this page */headings: string[];}

Configuration

Format Override

Skip auto-detection by specifying the format explicitly:

constresult=convert(content,{format: 'html'});

File Name Hint

Provide a file name for extension-based format detection:

constresult=convert(buffer,{fileName: 'report.html'});

Disable Image Extraction

Suppress image reference collection:

constresult=convert(html,{extractImages: false});console.log(result.images);// []

Strip All Formatting

Produce plain text output with no markdown syntax:

constresult=convert('# Heading\n\n**bold** and *italic*',{format: 'markdown',preserveStructure: false,});console.log(result.markdown);// Heading//// bold and italic

Error Handling

All conversion functions are synchronous and do not throw under normal operation. Errors and edge cases are communicated through the warnings array in the ConversionResult.

Binary Formats

When a binary format (PDF, DOCX, PPTX) is detected, the library does not throw. Instead, it returns a ConversionResult with an informative markdown message describing the detected format, suggested external packages, and example code:

constresult=convert(pdfBuffer);console.log(result.warnings);// [// 'Binary format "pdf" detected. Install a dedicated parser for full support.',// 'Suggested packages: `pdfjs-dist`, `pdf-parse`, `pdf2json`'// ]

Unexpected Formats

If the detected format does not match any known converter, the input is treated as plain text and a warning is added:

// result.warnings: ['Unexpected format: xyz. Treating as plain text.']

Empty or Whitespace Input

Empty strings and whitespace-only input produce minimal output without errors:

constresult=convert('');console.log(result.markdown);// '\n'console.log(result.metadata.wordCount);// 0

Advanced Usage

RAG Pipeline Integration

Use docling-node-ts as the first stage in a document ingestion pipeline. The output markdown is designed for downstream chunking and embedding:

import{convert}from'docling-node-ts';functioningestDocument(html: string){const{ markdown, metadata, images, warnings }=convert(html);if(warnings.length>0){console.warn('Conversion warnings:',warnings);}// Chunk the markdown for embedding (e.g., with chunk-smart)// const chunks = chunkMarkdown(markdown, { maxTokens: 512 });return{ markdown, metadata, images };}

Processing Buffers from File Uploads

import{convert}from'docling-node-ts';functionhandleUpload(buffer: Buffer,originalFileName: string){constresult=convert(buffer,{fileName: originalFileName});return{markdown: result.markdown,title: result.metadata.title,wordCount: result.metadata.wordCount,readingTime: result.metadata.readingTimeMinutes,imageCount: result.images.length,};}

HTML Metadata Extraction

When converting HTML, the library extracts metadata from <head> elements:

import{convert}from'docling-node-ts';consthtml=`<html><head> <title>Annual Report 2024</title> <meta name="author" content="Finance Team"> <meta name="date" content="2024-12-01"> <meta property="og:title" content="Annual Report"></head><body> <h1>Annual Report</h1> <p>Revenue increased by 20%.</p></body></html>`;constresult=convert(html);console.log(result.metadata.title);// 'Annual Report 2024'console.log(result.metadata.author);// 'Finance Team'console.log(result.metadata.date);// '2024-12-01'

Title extraction priority: <title> tag, then og:title. Author extraction checks both name="author" and property="article:author". Date extraction checks both name="date" and property="article:published_time".

Normalizing Imported Markdown

Clean up markdown from external sources that may have inconsistent formatting:

import{convertMarkdown}from'docling-node-ts';constmessy=`# Title#### Jumped Heading Level* Mixed+ List- MarkersClick [broken]() link.[Valid link](https://example.com)`;const{ markdown }=convertMarkdown(messy);// Heading levels normalized (#### becomes ##)// List markers standardized to -// Broken link text extracted without brackets// Excessive blank lines collapsed

HTML Table Conversion

Tables are converted to GitHub Flavored Markdown pipe tables with column normalization and pipe escaping:

import{convertHtml}from'docling-node-ts';consthtml=`<table> <thead> <tr><th>Product</th><th>Q1</th><th>Q2</th></tr> </thead> <tbody> <tr><td>Widget A</td><td>$1,200</td><td>$1,500</td></tr> <tr><td>Widget B</td><td>$800</td><td>$950</td></tr> </tbody></table>`;const{ markdown }=convertHtml(html);// | Product | Q1 | Q2 |// | --- | --- | --- |// | Widget A | $1,200 | $1,500 |// | Widget B | $800 | $950 |

Rows with fewer columns are padded with empty cells. Pipe characters (|) inside cell content are escaped as \|.

TypeScript

This package is written in TypeScript and ships type declarations (dist/index.d.ts) alongside the compiled JavaScript. All public types are exported from the package entry point:

importtype{ConversionResult,ConvertOptions,InputFormat,DocumentMetadata,ImageReference,PageContent,}from'docling-node-ts';

Compiled with strict: true, targeting ES2022 with CommonJS module output.

License

MIT

About

Convert documents to clean RAG-ready markdown in Node.js

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages